"use client"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { Plus, Pencil, Archive, Star } from "lucide-react"; import { accountingApi, type Currency } from "@/lib/accounting-api"; import { useTenantId } from "@/hooks/useTenantId"; import { PageHeader, Button, Dialog, ConfirmDialog, Input, Label, FieldError, DataTable, EmptyState, LoadingState, ErrorState, Badge, Drawer, Checkbox, } from "@/components/ds"; const createSchema = z.object({ code: z.string().length(3, "کد ارز ۳ حرفی است"), name: z.string().min(1, "نام الزامی است"), symbol: z.string().optional(), is_base: z.boolean().optional(), }); const editSchema = z.object({ name: z.string().min(1, "نام الزامی است"), symbol: z.string().optional(), }); export default function CurrenciesPage() { const { tenantId } = useTenantId(); const qc = useQueryClient(); const [createOpen, setCreateOpen] = useState(false); const [selected, setSelected] = useState(null); const [archiveId, setArchiveId] = useState(null); const createForm = useForm>({ resolver: zodResolver(createSchema), defaultValues: { code: "IRR", name: "ریال", symbol: "﷼", is_base: false }, }); const editForm = useForm>({ resolver: zodResolver(editSchema), }); const listQ = useQuery({ queryKey: ["accounting", tenantId, "currencies"], queryFn: () => accountingApi.currencies.list(tenantId!), enabled: !!tenantId, }); const invalidate = async () => { await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "currencies"] }); }; const createM = useMutation({ mutationFn: (d: z.infer) => accountingApi.currencies.create(tenantId!, d), onSuccess: async () => { toast.success("ارز ایجاد شد"); setCreateOpen(false); createForm.reset({ code: "", name: "", symbol: "", is_base: false }); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const updateM = useMutation({ mutationFn: (d: z.infer) => accountingApi.currencies.update(tenantId!, selected!.id, d), onSuccess: async () => { toast.success("ارز به‌روز شد"); setSelected(null); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const setBaseM = useMutation({ mutationFn: (id: string) => accountingApi.currencies.setBase(tenantId!, id), onSuccess: async () => { toast.success("ارز پایه تنظیم شد"); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const archiveM = useMutation({ mutationFn: (id: string) => accountingApi.currencies.archive(tenantId!, id), onSuccess: async () => { toast.success("ارز آرشیو شد"); setArchiveId(null); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); if (!tenantId || listQ.isLoading) return ; if (listQ.error) return listQ.refetch()} />; return (
setCreateOpen(true)}> ارز جدید } /> (r.is_base ? پایه : "—"), }, { key: "is_active", header: "فعال", render: (r) => r.is_active ? فعال : آرشیو, }, { key: "actions", header: "عملیات", render: (r) => { const id = String(r.id); const active = Boolean(r.is_active); const isBase = Boolean(r.is_base); return (
{active && !isBase ? ( ) : null} {active && !isBase ? ( ) : null}
); }, }, ]} rows={(listQ.data ?? []) as unknown as Record[]} empty={ setCreateOpen(true)}>ایجاد ارز} />} /> setCreateOpen(false)} title="ایجاد ارز">
createM.mutate(d))}>
{createForm.formState.errors.code?.message}
{createForm.formState.errors.name?.message}
setSelected(null)} title="ویرایش ارز" description={selected ? `${selected.code} — ${selected.name}` : undefined} >
updateM.mutate(d))}>
{editForm.formState.errors.name?.message}
setArchiveId(null)} onConfirm={() => archiveId && archiveM.mutate(archiveId)} title="آرشیو ارز؟" description="ارز آرشیو شده دیگر در تراکنش‌های جدید قابل انتخاب نیست." confirmLabel="آرشیو" danger loading={archiveM.isPending} />
); }