"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, Trash2 } from "lucide-react"; import { beautyBusinessApi, type Organization } from "@/modules/beauty/services/beauty-business-api"; import { useTenantId } from "@/hooks/useTenantId"; import { Button, Dialog, Drawer, Input, EmptyState, FormField, ConfirmDialog, Select, } from "@/components/ds"; import { BeautyTablePage, BeautyStatusChip, businessFormatLabels } from "@/modules/beauty/design-system"; import { BeautyPageLoader, BeautyPageError } from "@/modules/beauty/pages/shared"; const createSchema = z.object({ code: z.string().min(1, "کد الزامی است"), name: z.string().min(1, "نام الزامی است"), description: z.string().optional(), business_format: z.enum(["salon", "clinic", "spa", "barbershop", "mixed"]).optional(), }); const editSchema = z.object({ name: z.string().min(1, "نام الزامی است"), description: z.string().optional(), status: z.enum(["draft", "active", "inactive", "suspended", "archived"]), }); const statusLabel: Record = { draft: "پیش‌نویس", active: "فعال", inactive: "غیرفعال", suspended: "معلق", archived: "آرشیو", }; export default function OrganizationsPage() { const { tenantId } = useTenantId(); const qc = useQueryClient(); const [createOpen, setCreateOpen] = useState(false); const [editRow, setEditRow] = useState(null); const [deleteId, setDeleteId] = useState(null); const listQ = useQuery({ queryKey: ["beauty", tenantId, "organizations"], queryFn: () => beautyBusinessApi.organizations.list(tenantId!), enabled: !!tenantId, }); const createForm = useForm>({ resolver: zodResolver(createSchema), defaultValues: { code: "", name: "", description: "", business_format: "salon" }, }); const editForm = useForm>({ resolver: zodResolver(editSchema), }); const invalidate = () => qc.invalidateQueries({ queryKey: ["beauty", tenantId, "organizations"] }); const createM = useMutation({ mutationFn: (d: z.infer) => beautyBusinessApi.organizations.create(tenantId!, d), onSuccess: async () => { toast.success("سازمان ایجاد شد"); setCreateOpen(false); createForm.reset(); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const updateM = useMutation({ mutationFn: (d: z.infer) => beautyBusinessApi.organizations.update(tenantId!, editRow!.id, { ...d, version: editRow!.version, }), onSuccess: async () => { toast.success("سازمان به‌روز شد"); setEditRow(null); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const deleteM = useMutation({ mutationFn: (id: string) => beautyBusinessApi.organizations.delete(tenantId!, id), onSuccess: async () => { toast.success("سازمان حذف شد"); setDeleteId(null); await invalidate(); }, onError: (e: Error) => toast.error(e.message), }); const openEdit = (row: Organization) => { setEditRow(row); editForm.reset({ name: row.name, description: row.description ?? "", status: row.status, }); }; if (!tenantId || listQ.isLoading) return ; if (listQ.error) { return listQ.refetch()} />; } return (
setCreateOpen(true)}> سازمان جدید } columns={[ { key: "code", header: "کد" }, { key: "name", header: "نام" }, { key: "business_format", header: "نوع", render: (r) => businessFormatLabels[String(r.business_format)] ?? String(r.business_format), }, { key: "status", header: "وضعیت", render: (r) => , }, { key: "actions", header: "عملیات", render: (r) => (
), }, ]} rows={(listQ.data ?? []) as unknown as Record[]} empty={ setCreateOpen(true)}>ایجاد سازمان} />} /> setCreateOpen(false)} title="سازمان جدید">
createM.mutate(d))}>
setEditRow(null)} title="ویرایش سازمان">
updateM.mutate(d))}>
setDeleteId(null)} onConfirm={() => deleteId && deleteM.mutate(deleteId)} title="حذف سازمان" description="سازمان به‌صورت نرم حذف می‌شود." confirmLabel="حذف" loading={deleteM.isPending} />
); }