"use client"; import { useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Plus } from "lucide-react"; import { toast } from "sonner"; import { z } from "zod"; import { accountingApi } from "@/lib/accounting-api"; import { useTenantId } from "@/hooks/useTenantId"; import { formatMoney } from "@/lib/utils"; import { Badge, Button, Card, CardContent, CardHeader, CardTitle, DataTable, DatePicker, Dialog, EmptyState, ErrorState, FormField, Input, JalaliDateText, LoadingState, MoneyInput, PageHeader, Select, StatCard, Textarea, } from "@/components/ds"; const today = () => new Date().toISOString().slice(0, 10); const requiredText = z.string().min(1, "این فیلد الزامی است"); function Actions({ onCancel, pending, submitLabel = "ذخیره", }: { onCancel: () => void; pending: boolean; submitLabel?: string; }) { return (
); } const employeeSchema = z.object({ employee_code: requiredText, first_name: requiredText, last_name: requiredText, base_salary: requiredText, department_id: z.string(), }); export function PayrollEmployeesPage() { const { tenantId } = useTenantId(); const qc = useQueryClient(); const [open, setOpen] = useState(false); const form = useForm>({ resolver: zodResolver(employeeSchema), defaultValues: { employee_code: "", first_name: "", last_name: "", base_salary: "0", department_id: "" }, }); const employeesQ = useQuery({ queryKey: ["accounting", tenantId, "payroll-employees"], queryFn: () => accountingApi.payroll.listEmployees(tenantId!), enabled: !!tenantId, }); const departmentsQ = useQuery({ queryKey: ["accounting", tenantId, "payroll-departments"], queryFn: () => accountingApi.payroll.listDepartments(tenantId!), enabled: !!tenantId, }); const createM = useMutation({ mutationFn: (values: z.infer) => accountingApi.payroll.createEmployee(tenantId!, { ...values, department_id: values.department_id || undefined, }), onSuccess: async () => { toast.success("کارمند ثبت شد"); setOpen(false); form.reset(); await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "payroll-employees"] }); }, onError: (error: Error) => toast.error(error.message), }); if (!tenantId || employeesQ.isLoading || departmentsQ.isLoading) return ; if (employeesQ.error || departmentsQ.error) { const error = employeesQ.error || departmentsQ.error; return { employeesQ.refetch(); departmentsQ.refetch(); }} />; } return (
setOpen(true)}>کارمند جدید} /> []} empty={} /> setOpen(false)} title="ثبت کارمند" size="lg">
createM.mutate(v))}> setOpen(false)} pending={createM.isPending} />
); } const policySchema = z.object({ code: requiredText, name: requiredText, policy_type: requiredText, rules_config: requiredText.refine((value) => { try { JSON.parse(value); return true; } catch { return false; } }, "JSON معتبر وارد کنید"), }); export function CompliancePoliciesPage() { const { tenantId } = useTenantId(); const qc = useQueryClient(); const [open, setOpen] = useState(false); const form = useForm>({ resolver: zodResolver(policySchema), defaultValues: { code: "", name: "", policy_type: "", rules_config: "{}" }, }); const listQ = useQuery({ queryKey: ["accounting", tenantId, "compliance-policies"], queryFn: () => accountingApi.compliance.listPolicies(tenantId!), enabled: !!tenantId, }); const createM = useMutation({ mutationFn: (values: z.infer) => accountingApi.compliance.createPolicy(tenantId!, values), onSuccess: async () => { toast.success("سیاست ثبت شد"); setOpen(false); form.reset(); await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "compliance-policies"] }); }, onError: (error: Error) => toast.error(error.message), }); if (!tenantId || listQ.isLoading) return ; if (listQ.error) return listQ.refetch()} />; return (
setOpen(true)}>سیاست جدید} /> {r.is_active ? "فعال" : "غیرفعال"} }, ]} rows={listQ.data as unknown as Record[]} empty={} /> setOpen(false)} title="سیاست جدید" size="lg">
createM.mutate(v))}>