import { useState } from "react"; import { Modal, Button, Form, ListGroup, Alert } from "react-bootstrap"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faTrashCan } from "@fortawesome/free-regular-svg-icons"; import { faPen, faPlus, faUpRightFromSquare, faXmark } from "@fortawesome/free-solid-svg-icons"; import { addStore, deleteStore, updateStore, Store } from "../../../../types"; import { getStoreUrls, storeUrlLabel } from "../../utils/storeUrls"; type Props = { isOpen: boolean; onClose: () => void; stores: Store[]; onStoresChanged: (stores: Store[]) => void; }; /** Rozpracovaná editace obchodu — původní název slouží k jeho identifikaci na serveru. */ type EditState = { originalName: string; name: string; urls: string[]; }; /** Vstupní pole pro URL nabídek — vždy alespoň jedno prázdné, aby bylo kam psát. */ function toUrlInputs(urls: string[]): string[] { return urls.length > 0 ? urls : ['']; } export default function StoreAdminModal({ isOpen, onClose, stores, onStoresChanged }: Readonly) { const [newName, setNewName] = useState(''); // Jeden podnik může být dostupný přes více dovozových služeb — proto seznam URL const [newUrls, setNewUrls] = useState(['']); const [edit, setEdit] = useState(null); const [heslo, setHeslo] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const addUrlRow = (urls: string[]) => [...urls, '']; const removeUrlRow = (urls: string[], index: number) => urls.length === 1 ? [''] : urls.filter((_, i) => i !== index); const setUrlAt = (urls: string[], index: number, value: string) => urls.map((u, i) => (i === index ? value : u)); /** Zpracuje odpověď API — vrací true při úspěchu. Chybu z API hlásí globální toaster. */ const applyResult = (res: { data?: unknown; error?: unknown }): boolean => { if (res.error) { return false; } if (res.data) { onStoresChanged(res.data as Store[]); return true; } return false; }; const handleAdd = async () => { if (!newName.trim()) return; setError(null); setLoading(true); try { const urls = newUrls.map(u => u.trim()).filter(Boolean); const res = await addStore({ body: { name: newName.trim(), urls: urls.length > 0 ? urls : undefined, heslo } }); if (applyResult(res)) { setNewName(''); setNewUrls(['']); } } catch (e: any) { setError(e.message || 'Nastala chyba'); } finally { setLoading(false); } }; const startEdit = (store: Store) => { setError(null); setEdit({ originalName: store.name, name: store.name, urls: toUrlInputs(store.urls ?? []) }); }; const handleSaveEdit = async () => { if (!edit || !edit.name.trim()) return; setError(null); setLoading(true); try { const res = await updateStore({ body: { name: edit.originalName, newName: edit.name.trim(), urls: edit.urls.map(u => u.trim()).filter(Boolean), heslo, }, }); if (applyResult(res)) { setEdit(null); } } catch (e: any) { setError(e.message || 'Nastala chyba'); } finally { setLoading(false); } }; const handleRemove = async (name: string) => { setError(null); setLoading(true); try { const res = await deleteStore({ body: { name, heslo } }); if (applyResult(res) && edit?.originalName === name) { setEdit(null); } } catch (e: any) { setError(e.message || 'Nastala chyba'); } finally { setLoading(false); } }; /** Řádky se vstupy pro URL — používá se pro přidání i pro editaci obchodu. */ const renderUrlInputs = (urls: string[], onChange: (urls: string[]) => void, onSubmit: () => void) => ( <> {urls.map((url, index) => (
onChange(setUrlAt(urls, index, e.target.value))} onKeyDown={e => { e.stopPropagation(); if (e.key === 'Enter') onSubmit(); }} />
))} ); return (

Správa obchodů

{error && ( setError(null)} dismissible> {error} )} Admin heslo setHeslo(e.target.value)} onKeyDown={e => e.stopPropagation()} />
Přidat obchod
setNewName(e.target.value)} onKeyDown={e => { e.stopPropagation(); if (e.key === 'Enter') handleAdd(); }} /> {renderUrlInputs(newUrls, setNewUrls, handleAdd)}
Aktuální seznam
{stores.length === 0 ? (

Žádné obchody v seznamu

) : ( {stores.map(s => { const urls = getStoreUrls(s); const isEditing = edit?.originalName === s.name; if (isEditing) { return ( setEdit({ ...edit, name: e.target.value })} onKeyDown={e => { e.stopPropagation(); if (e.key === 'Enter') handleSaveEdit(); }} /> {renderUrlInputs(edit.urls, next => setEdit({ ...edit, urls: next }), handleSaveEdit)}
); } return (
{s.name}
{urls.length > 0 && ( {urls.map(url => ( {storeUrlLabel(url)} ))} )}
startEdit(s)} style={{ cursor: 'pointer' }} /> handleRemove(s.name)} style={{ cursor: 'pointer' }} />
); })}
)}
); }