Users now fill legal name, national ID, economic code, address and contacts instead of generic setting key/value ops documents. Co-authored-by: Cursor <cursoragent@cursor.com>
180 lines
6.6 KiB
TypeScript
180 lines
6.6 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect } from "react";
|
||
import { useForm } from "react-hook-form";
|
||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||
import { toast } from "sonner";
|
||
import { accountingApi } from "@/lib/accounting-api";
|
||
import { useTenantId } from "@/hooks/useTenantId";
|
||
import {
|
||
PageHeader,
|
||
LoadingState,
|
||
ErrorState,
|
||
Card,
|
||
CardContent,
|
||
CardHeader,
|
||
CardTitle,
|
||
Button,
|
||
Input,
|
||
FormField,
|
||
} from "@/components/ds";
|
||
|
||
type CompanyForm = {
|
||
legal_name: string;
|
||
trade_name: string;
|
||
national_id: string;
|
||
economic_code: string;
|
||
registration_number: string;
|
||
postal_code: string;
|
||
province: string;
|
||
city: string;
|
||
address: string;
|
||
phone: string;
|
||
mobile: string;
|
||
email: string;
|
||
website: string;
|
||
ceo_name: string;
|
||
accountant_name: string;
|
||
};
|
||
|
||
const EMPTY: CompanyForm = {
|
||
legal_name: "",
|
||
trade_name: "",
|
||
national_id: "",
|
||
economic_code: "",
|
||
registration_number: "",
|
||
postal_code: "",
|
||
province: "",
|
||
city: "",
|
||
address: "",
|
||
phone: "",
|
||
mobile: "",
|
||
email: "",
|
||
website: "",
|
||
ceo_name: "",
|
||
accountant_name: "",
|
||
};
|
||
|
||
export default function CompanySettingsPage() {
|
||
const { tenantId } = useTenantId();
|
||
const qc = useQueryClient();
|
||
const form = useForm<CompanyForm>({ defaultValues: EMPTY });
|
||
|
||
const profileQ = useQuery({
|
||
queryKey: ["accounting", tenantId, "company-profile"],
|
||
queryFn: () => accountingApi.setup.getCompanyProfile(tenantId!),
|
||
enabled: !!tenantId,
|
||
});
|
||
|
||
useEffect(() => {
|
||
if (profileQ.data) {
|
||
form.reset({ ...EMPTY, ...profileQ.data });
|
||
}
|
||
}, [profileQ.data, form]);
|
||
|
||
const saveM = useMutation({
|
||
mutationFn: (data: CompanyForm) => accountingApi.setup.updateCompanyProfile(tenantId!, data),
|
||
onSuccess: async () => {
|
||
toast.success("اطلاعات شرکت ذخیره شد");
|
||
await qc.invalidateQueries({ queryKey: ["accounting", tenantId, "company-profile"] });
|
||
},
|
||
onError: (e: Error) => toast.error(e.message),
|
||
});
|
||
|
||
if (!tenantId || profileQ.isLoading) return <LoadingState />;
|
||
if (profileQ.error) {
|
||
return <ErrorState message={profileQ.error.message} onRetry={() => profileQ.refetch()} />;
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<PageHeader
|
||
title="اطلاعات شرکت"
|
||
description="مشخصات حقوقی و تماس شرکت برای چاپ اسناد، گزارشها و اظهارنامهها. فقط فیلدهایی که دارید را پر کنید."
|
||
/>
|
||
|
||
<form className="space-y-6" onSubmit={form.handleSubmit((d) => saveM.mutate(d))}>
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>هویت حقوقی</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="grid gap-4 sm:grid-cols-2">
|
||
<FormField label="نام قانونی شرکت" hint="همان نام ثبتشده در روزنامه رسمی">
|
||
<Input placeholder="مثال: شرکت بازرگانی آفتاب سپاهان" {...form.register("legal_name")} />
|
||
</FormField>
|
||
<FormField label="نام تجاری / برند" hint="اگر با نام قانونی فرق دارد">
|
||
<Input placeholder="مثال: آفتابمارکت" {...form.register("trade_name")} />
|
||
</FormField>
|
||
<FormField label="شناسه ملی" hint="۱۱ رقم برای اشخاص حقوقی">
|
||
<Input dir="ltr" placeholder="1400xxxxxxx" {...form.register("national_id")} />
|
||
</FormField>
|
||
<FormField label="کد اقتصادی" hint="برای فاکتور رسمی و مالیات">
|
||
<Input dir="ltr" placeholder="کد اقتصادی" {...form.register("economic_code")} />
|
||
</FormField>
|
||
<FormField label="شماره ثبت" hint="شماره ثبت در اداره ثبت شرکتها">
|
||
<Input dir="ltr" placeholder="مثال: ۱۲۳۴۵۶" {...form.register("registration_number")} />
|
||
</FormField>
|
||
<FormField label="کد پستی" hint="۱۰ رقم">
|
||
<Input dir="ltr" placeholder="xxxxxxxxxx" {...form.register("postal_code")} />
|
||
</FormField>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>آدرس و تماس</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="grid gap-4 sm:grid-cols-2">
|
||
<FormField label="استان">
|
||
<Input placeholder="مثال: خراسان رضوی" {...form.register("province")} />
|
||
</FormField>
|
||
<FormField label="شهر">
|
||
<Input placeholder="مثال: تربت حیدریه" {...form.register("city")} />
|
||
</FormField>
|
||
<div className="sm:col-span-2">
|
||
<FormField label="آدرس کامل">
|
||
<Input placeholder="خیابان، پلاک، واحد…" {...form.register("address")} />
|
||
</FormField>
|
||
</div>
|
||
<FormField label="تلفن ثابت">
|
||
<Input dir="ltr" placeholder="051-xxxxx" {...form.register("phone")} />
|
||
</FormField>
|
||
<FormField label="موبایل">
|
||
<Input dir="ltr" placeholder="09xxxxxxxxx" {...form.register("mobile")} />
|
||
</FormField>
|
||
<FormField label="ایمیل">
|
||
<Input dir="ltr" type="email" placeholder="info@example.com" {...form.register("email")} />
|
||
</FormField>
|
||
<FormField label="وبسایت">
|
||
<Input dir="ltr" placeholder="https://…" {...form.register("website")} />
|
||
</FormField>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>اشخاص مرتبط (اختیاری)</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="grid gap-4 sm:grid-cols-2">
|
||
<FormField label="نام مدیرعامل / مدیر مسئول">
|
||
<Input {...form.register("ceo_name")} />
|
||
</FormField>
|
||
<FormField label="نام حسابدار مسئول">
|
||
<Input {...form.register("accountant_name")} />
|
||
</FormField>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<div className="flex flex-wrap justify-end gap-2">
|
||
<Button type="button" variant="outline" disabled={saveM.isPending} onClick={() => profileQ.refetch()}>
|
||
بازخوانی
|
||
</Button>
|
||
<Button type="submit" disabled={saveM.isPending}>
|
||
ذخیره اطلاعات شرکت
|
||
</Button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
);
|
||
}
|