import { useState } from 'react' import { useAlert } from '../context/AlertContext' import { useAuth } from '../context/AuthContext' import { Link } from 'react-router-dom' import Forbidden from '../components/Forbidden' import { motion } from 'framer-motion' import ConfirmModal from '../components/ConfirmModal' import apiFetch from '../utils/api' import { formatCurrency, formatDate, czechPlural } from '../utils/formatters' import SortIcon from '../components/SortIcon' import useTableSort from '../hooks/useTableSort' import useListData from '../hooks/useListData' import Pagination from '../components/Pagination' const API_BASE = '/api/admin' const STATUS_LABELS: Record = { prijata: 'Přijatá', v_realizaci: 'V realizaci', dokoncena: 'Dokončená', stornovana: 'Stornována' } const STATUS_CLASSES: Record = { prijata: 'admin-badge-order-prijata', v_realizaci: 'admin-badge-order-realizace', dokoncena: 'admin-badge-order-dokoncena', stornovana: 'admin-badge-order-stornovana' } interface Order { id: number order_number: string quotation_id: number quotation_number: string customer_name: string status: string created_at: string total: number currency: string invoice_id?: number } export default function Orders() { const alert = useAlert() const { hasPermission } = useAuth() const { sort, order, handleSort, activeSort } = useTableSort('order_number') const [search, setSearch] = useState('') const [page, setPage] = useState(1) const [deleteConfirm, setDeleteConfirm] = useState<{ show: boolean; order: Order | null }>({ show: false, order: null }) const [deleting, setDeleting] = useState(false) const [deleteFiles, setDeleteFiles] = useState(false) const { items: orders, loading, initialLoad, pagination, refetch: fetchData } = useListData('orders', { search, sort, order, page, errorMsg: 'Nepodařilo se načíst objednávky' }) if (!hasPermission('orders.view')) return const handleDelete = async () => { if (!deleteConfirm.order) return setDeleting(true) try { const response = await apiFetch(`${API_BASE}/orders/${deleteConfirm.order.id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ delete_files: deleteFiles }), }) const result = await response.json() if (result.success) { setDeleteConfirm({ show: false, order: null }) setDeleteFiles(false) alert.success(result.message || 'Objednávka byla smazána') fetchData() } else { alert.error(result.error || 'Nepodařilo se smazat objednávku') } } catch { alert.error('Chyba připojení') } finally { setDeleting(false) } } if (initialLoad) { return (
{[0, 1, 2, 3, 4].map(i => (
))}
) } return (

Objednávky

{pagination?.total ?? orders.length} {czechPlural(pagination?.total ?? orders.length, 'objednávka', 'objednávky', 'objednávek')}

{ setSearch(e.target.value); setPage(1) }} className="admin-form-input" placeholder="Hledat podle čísla, nabídky, projektu nebo zákazníka..." />
{orders.length === 0 ? (

Zatím nejsou žádné objednávky.

Objednávky se vytvářejí z nabídek.

) : (
{(orders as Order[]).map((o) => ( ))}
handleSort('order_number')}> Číslo Nabídka Zákazník handleSort('status')}> Stav handleSort('created_at')}> Datum Celkem Akce
{o.order_number} {o.quotation_number} {o.customer_name || '—'} {STATUS_LABELS[o.status] || o.status} {formatDate(o.created_at)} {formatCurrency(o.total, o.currency)}
{o.invoice_id ? ( F ) : hasPermission('invoices.create') && ( )} {hasPermission('orders.delete') && ( )}
)}
{ setDeleteConfirm({ show: false, order: null }) setDeleteFiles(false) }} onConfirm={handleDelete} title="Smazat objednávku" message={ <> Opravdu chcete smazat objednávku "{deleteConfirm.order?.order_number}"? Bude smazán i přidružený projekt. Tato akce je nevratná. } confirmText="Smazat" cancelText="Zrušit" type="danger" loading={deleting} />
) }