From 8d3cbb8aba78f208a47616839b106bf01c1a1573 Mon Sep 17 00:00:00 2001 From: Floke Date: Fri, 9 Jan 2026 17:40:48 +0000 Subject: [PATCH] =?UTF-8?q?competitor-analysis/components/EditableCard.tsx?= =?UTF-8?q?=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/EditableCard.tsx | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 competitor-analysis/components/EditableCard.tsx diff --git a/competitor-analysis/components/EditableCard.tsx b/competitor-analysis/components/EditableCard.tsx new file mode 100644 index 00000000..d2d0b37d --- /dev/null +++ b/competitor-analysis/components/EditableCard.tsx @@ -0,0 +1,129 @@ +import React, { useState } from 'react'; + +interface Item { + [key: string]: any; +} + +interface FieldConfig { + key: string; + label: string; + type: 'text' | 'textarea'; +} + +interface EditableCardProps { + title: string; + items: T[]; + onItemsChange: (items: T[]) => void; + fieldConfigs: FieldConfig[]; + newItemTemplate: T; + renderDisplay: (item: T, index: number) => React.ReactNode; + showAddButton?: boolean; + t: { + add: string; + cancel: string; + save: string; + } +} + +const PencilIcon = () => ( + +); +const TrashIcon = () => ( + +); + +export const EditableCard = ({ title, items, onItemsChange, fieldConfigs, newItemTemplate, renderDisplay, showAddButton, t }: EditableCardProps) => { + const [editingIndex, setEditingIndex] = useState(null); + const [editItem, setEditItem] = useState(null); + + const handleEdit = (index: number) => { + setEditingIndex(index); + setEditItem({ ...items[index] }); + }; + + const handleSave = () => { + if (editingIndex !== null && editItem) { + const newItems = [...items]; + newItems[editingIndex] = editItem; + onItemsChange(newItems); + setEditingIndex(null); + setEditItem(null); + } + }; + + const handleCancel = () => { + setEditingIndex(null); + setEditItem(null); + }; + + const handleRemove = (index: number) => { + onItemsChange(items.filter((_, i) => i !== index)); + }; + + const handleAdd = () => { + onItemsChange([...items, newItemTemplate]); + setEditingIndex(items.length); + setEditItem(newItemTemplate); + }; + + const handleInputChange = (key: string, value: string) => { + if (editItem) { + setEditItem({ ...editItem, [key]: value }); + } + }; + + const inputClasses = "w-full bg-light-secondary dark:bg-brand-secondary text-light-text dark:text-brand-text border border-light-accent dark:border-brand-accent rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-highlight"; + + return ( +
+
+

{title}

+ {(showAddButton ?? true) && ( + + )} +
+
+ {items.map((item, index) => ( +
+ {editingIndex === index && editItem ? ( +
+ {fieldConfigs.map(field => ( +
+ + {field.type === 'textarea' ? ( +