import { useState, useRef, type ReactNode } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useAlert } from "../context/AlertContext"; import { useAuth } from "../context/AuthContext"; import { motion, AnimatePresence } from "framer-motion"; import ConfirmModal from "../components/ConfirmModal"; import FormField from "../components/FormField"; import Forbidden from "../components/Forbidden"; import RichEditor from "../components/RichEditor"; import useModalLock from "../hooks/useModalLock"; import { offerTemplatesOptions } from "../lib/queries/offers"; import { Skeleton } from "boneyard-js/react"; import OffersTemplatesFixture from "../fixtures/OffersTemplatesFixture"; import apiFetch from "../utils/api"; const API_BASE = "/api/admin"; interface ItemTemplate { id: number; name: string; description: string; default_price: number; category: string; } interface ScopeSection { _key: string; title: string; title_cz: string; content: string; } interface ScopeTemplate { id: number; name: string; sections?: ScopeSection[]; } interface ItemForm { name: string; description: string; default_price: number; category: string; } interface ScopeForm { name: string; sections: ScopeSection[]; } export default function OffersTemplates() { const { hasPermission } = useAuth(); const [activeTab, setActiveTab] = useState<"items" | "scopes">("items"); if (!hasPermission("settings.manage")) return ; return (

Šablony

Šablony položek a rozsahu projektu

{activeTab === "items" ? : }
); } // --- Item Templates Tab --- function ItemTemplatesTab() { const alert = useAlert(); const queryClient = useQueryClient(); const { data: templates = [], isPending } = useQuery( offerTemplatesOptions("items"), ) as { data: ItemTemplate[]; isPending: boolean }; const [showModal, setShowModal] = useState(false); const [editingTemplate, setEditingTemplate] = useState( null, ); const [saving, setSaving] = useState(false); const [form, setForm] = useState({ name: "", description: "", default_price: 0, category: "", }); const [deleteConfirm, setDeleteConfirm] = useState<{ show: boolean; template: ItemTemplate | null; }>({ show: false, template: null }); const [deleting, setDeleting] = useState(false); useModalLock(showModal); const openCreate = () => { setEditingTemplate(null); setForm({ name: "", description: "", default_price: 0, category: "" }); setShowModal(true); }; const openEdit = (t: ItemTemplate) => { setEditingTemplate(t); setForm({ name: t.name || "", description: t.description || "", default_price: t.default_price || 0, category: t.category || "", }); setShowModal(true); }; const handleSubmit = async () => { if (!form.name.trim()) { alert.error("Název šablony je povinný"); return; } setSaving(true); try { const body = editingTemplate ? { ...form, id: editingTemplate.id } : form; const response = await apiFetch( `${API_BASE}/offers-templates?action=item`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }, ); const result = await response.json(); if (result.success) { setShowModal(false); await new Promise((r) => setTimeout(r, 300)); alert.success(result.message); queryClient.invalidateQueries({ queryKey: ["offer-templates"] }); } else { alert.error(result.error); } } catch { alert.error("Chyba připojení"); } finally { setSaving(false); } }; const handleDelete = async () => { if (!deleteConfirm.template) return; setDeleting(true); try { const response = await apiFetch( `${API_BASE}/offers-templates?action=item&id=${deleteConfirm.template.id}`, { method: "DELETE" }, ); const result = await response.json(); if (result.success) { setDeleteConfirm({ show: false, template: null }); alert.success(result.message); queryClient.invalidateQueries({ queryKey: ["offer-templates"] }); } else { alert.error(result.error); } } catch { alert.error("Chyba připojení"); } finally { setDeleting(false); } }; return ( } > <>

Šablony položek ({templates.length})

{templates.length === 0 ? (

Zatím žádné šablony položek.

) : (
{templates.map((t) => ( ))}
Název Popis Cena Kategorie Akce
{t.name} {t.description || "—"} {Number(t.default_price).toFixed(2)} {t.category || "—"}
)}
{/* Item Template Modal */} {showModal && (
setShowModal(false)} />

{editingTemplate ? "Upravit šablonu" : "Nová šablona položky"}

setForm((p) => ({ ...p, name: e.target.value })) } className="admin-form-input" />