import { useEffect } from 'react'; import { Drawer, Button, Group, Stack, Text, LoadingOverlay, Box, Select, TextInput, NumberInput, Switch, Divider, } from '@mantine/core'; import { useForm, Controller } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { notifications } from '@mantine/notifications'; import { modals } from '@mantine/modals'; import { apiClient } from '../../api/client'; import type { InventoryItem, InventoryItemType } from '../../api/types'; const font = "'Montserrat', Arial, sans-serif"; const teal = '#008286'; const charcoal = '#58595b'; const TYPE_OPTIONS: { value: InventoryItemType; label: string }[] = [ { value: 'uniforma', label: 'Uniformă' }, { value: 'halat', label: 'Halat' }, { value: 'ciupici', label: 'Ciupici' }, { value: 'vesta', label: 'Vestă' }, { value: 'aparat_telefon', label: 'Aparat telefon' }, { value: 'alte', label: 'Altele' }, ]; const schema = z.object({ sku: z.string().min(1, 'Câmp obligatoriu'), name: z.string().min(1, 'Câmp obligatoriu'), type: z.enum(['uniforma', 'halat', 'ciupici', 'vesta', 'aparat_telefon', 'alte']), size: z.string().optional(), color: z.string().optional(), pricePerUnit: z.string().optional(), stockQty: z.number().int().min(0, 'Stocul nu poate fi negativ'), active: z.boolean(), }); type FormValues = z.infer; interface Props { inventoryItem: InventoryItem | null; opened: boolean; onClose: () => void; } export function InventoryDrawer({ inventoryItem, opened, onClose }: Props) { const isEdit = !!inventoryItem; const qc = useQueryClient(); const { handleSubmit, control, reset, formState: { errors, isSubmitting } } = useForm({ resolver: zodResolver(schema), defaultValues: { sku: '', name: '', type: 'uniforma', size: '', color: '', pricePerUnit: '', stockQty: 0, active: true, }, }); useEffect(() => { if (inventoryItem) { reset({ sku: inventoryItem.sku, name: inventoryItem.name, type: inventoryItem.type, size: inventoryItem.size ?? '', color: inventoryItem.color ?? '', pricePerUnit: inventoryItem.pricePerUnit ?? '', stockQty: inventoryItem.stockQty, active: inventoryItem.active, }); } else { reset({ sku: '', name: '', type: 'uniforma', size: '', color: '', pricePerUnit: '', stockQty: 0, active: true, }); } }, [inventoryItem, opened, reset]); const mutation = useMutation({ mutationFn: (data: FormValues) => { const price = data.pricePerUnit ? Number(data.pricePerUnit) : undefined; const payload = { sku: data.sku, name: data.name, type: data.type, size: data.size || undefined, color: data.color || undefined, pricePerUnit: Number.isFinite(price) ? price : undefined, stockQty: data.stockQty, active: data.active, }; return isEdit ? apiClient.patch(`/inventory/${inventoryItem.id}`, payload) : apiClient.post('/inventory', payload); }, onSuccess: () => { void qc.invalidateQueries({ queryKey: ['inventory'] }); notifications.show({ color: 'medpark', title: 'Salvat', message: isEdit ? 'Articol actualizat.' : 'Articol creat.', }); onClose(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { message?: string } } })?.response?.data?.message ?? 'Eroare'; notifications.show({ color: 'red', title: 'Eroare', message: msg }); }, }); const deleteMutation = useMutation({ mutationFn: () => apiClient.delete(`/inventory/${inventoryItem!.id}`), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['inventory'] }); notifications.show({ color: 'medpark', title: 'Șters', message: 'Articol șters.' }); onClose(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { message?: string } } })?.response?.data?.message ?? 'Eroare'; notifications.show({ color: 'red', title: 'Eroare', message: msg }); }, }); function confirmDelete() { if (!inventoryItem) return; modals.openConfirmModal({ title: Șterge articol, children: ( Ești sigur că vrei să ștergi articolul {inventoryItem.sku} — {inventoryItem.name}? Această acțiune nu poate fi anulată. ), labels: { confirm: 'Șterge', cancel: 'Anulează' }, confirmProps: { color: 'red' }, onConfirm: () => deleteMutation.mutate(), }); } const section = (label: string) => ( {label}} labelPosition="left" my={12} /> ); return ( {isEdit ? 'Editare articol' : 'Articol nou'}} styles={{ header: { borderBottom: `2px solid ${teal}` } }} >
mutation.mutate(d))}> {section('Identificare')} ( )} /> (