TorbatYar/frontend/modules/delivery/features/settings.tsx
Mortezakoohjani 7978970783 feat(delivery): add Torbat Driver frontend module with real API wiring.
Ship the delivery platform UI under modules/delivery with thin app routes, BFF proxy, CRUD for phase 10.0-10.1 APIs, and capability-gated future screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 12:02:01 +03:30

74 lines
3.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { useTenantId } from "@/hooks/useTenantId";
import { deliveryApi } from "@/modules/delivery/services/delivery-api";
import { DeliveryPageLoader, DeliveryPageError } from "@/modules/delivery/pages/shared";
import { PageHeader, Card, CardContent, Button, Input, FormField } from "@/components/ds";
import { DeliveryBreadcrumbs } from "@/modules/delivery/components/DeliveryBreadcrumbs";
import { useDeliveryLookups } from "@/modules/delivery/hooks/useDeliveryCapabilities";
export const SettingsPage = function DeliverySettingsPage() {
const { tenantId } = useTenantId();
const qc = useQueryClient();
const lookups = useDeliveryLookups(tenantId);
const [key, setKey] = useState("");
const [value, setValue] = useState("");
const [orgId, setOrgId] = useState("");
const listQ = useQuery({
queryKey: ["delivery", tenantId, "settings"],
queryFn: () => deliveryApi.settings.list(tenantId!),
enabled: !!tenantId,
});
const saveM = useMutation({
mutationFn: () => deliveryApi.settings.upsert(tenantId!, {
organization_id: orgId || null,
key,
value: JSON.parse(value || "{}"),
}),
onSuccess: () => {
toast.success("تنظیمات ذخیره شد");
qc.invalidateQueries({ queryKey: ["delivery", tenantId, "settings"] });
},
onError: (e: Error) => toast.error(e.message),
});
if (!tenantId || listQ.isLoading || lookups.isLoading) return <DeliveryPageLoader />;
if (listQ.error) return <DeliveryPageError error={listQ.error} onRetry={() => listQ.refetch()} />;
return (
<div className="space-y-6">
<DeliveryBreadcrumbs current="تنظیمات" />
<PageHeader title="تنظیمات" description="کلید-مقدار tenant-scoped." />
<Card>
<CardContent className="space-y-4 p-4">
<FormField label="سازمان (اختیاری)">
<select className="w-full rounded-xl border px-3 py-2" value={orgId} onChange={(e) => setOrgId(e.target.value)}>
<option value=""></option>
{lookups.data?.organizations.map((o) => (
<option key={String(o.id)} value={String(o.id)}>{String(o.name)}</option>
))}
</select>
</FormField>
<FormField label="کلید"><Input value={key} onChange={(e) => setKey(e.target.value)} /></FormField>
<FormField label="مقدار (JSON)"><Input value={value} onChange={(e) => setValue(e.target.value)} placeholder='{"enabled":true}' /></FormField>
<Button onClick={() => saveM.mutate()} loading={saveM.isPending}>ذخیره</Button>
</CardContent>
</Card>
<div className="grid gap-2">
{(listQ.data ?? []).map((s) => (
<Card key={String(s.id)}><CardContent className="p-3 text-sm">
<strong>{String(s.key)}</strong>
<pre className="mt-1 overflow-x-auto text-xs">{JSON.stringify(s.value, null, 2)}</pre>
</CardContent></Card>
))}
</div>
</div>
);
};
export default SettingsPage;