62 lines
3.9 KiB
TypeScript
62 lines
3.9 KiB
TypeScript
"use client";
|
||
|
||
import { FormEvent, useState } from "react";
|
||
import { Banner, Button } from "@/components/admin/controls";
|
||
import { simulateRecommendations } from "../adapters/admin";
|
||
import { MetadataBagView } from "../components/RegistryBrowser";
|
||
import { friendlyMessage } from "../presentation";
|
||
|
||
export function AdminRecommendationSimulator() {
|
||
const [answers, setAnswers] = useState<Record<string, unknown>>({
|
||
business_type_code: "",
|
||
employees: 1,
|
||
branches: 1,
|
||
in_person_sales: false,
|
||
online_sales: false,
|
||
delivery: false,
|
||
booking: false,
|
||
loyalty: false,
|
||
});
|
||
const [result, setResult] = useState<Record<string, unknown> | null>(null);
|
||
const [error, setError] = useState("");
|
||
const [busy, setBusy] = useState(false);
|
||
|
||
const setAnswer = (key: string, value: unknown) => setAnswers((current) => ({ ...current, [key]: value }));
|
||
const run = async (event: FormEvent) => {
|
||
event.preventDefault();
|
||
setBusy(true);
|
||
setError("");
|
||
setResult(null);
|
||
const response = await simulateRecommendations(answers);
|
||
if (!response.ok) setError(friendlyMessage(response.message, "اجرای نمونه پیشنهاد انجام نشد. لطفاً دوباره تلاش کنید."));
|
||
else setResult(response.data && typeof response.data === "object" ? response.data as Record<string, unknown> : {});
|
||
setBusy(false);
|
||
};
|
||
|
||
return (
|
||
<section className="rounded-2xl border border-gray-100 bg-white p-5 shadow-sm">
|
||
<h3 className="text-base font-bold text-secondary">پیشنمایش پیشنهاد به مشتری</h3>
|
||
<p className="mt-1 text-xs text-gray-500">یک سناریوی واقعی بسازید و نتیجهای را که مشتری میبیند بررسی کنید.</p>
|
||
{error ? <div className="mt-3"><Banner variant="error">{error}</Banner></div> : null}
|
||
<form onSubmit={(event) => void run(event)} className="mt-5 space-y-5">
|
||
<div className="grid gap-4 sm:grid-cols-3">
|
||
<label className="block text-sm font-medium text-secondary">نوع کسبوکار<input value={String(answers.business_type_code || "")} onChange={(event) => setAnswer("business_type_code", event.target.value)} className="mt-1 w-full rounded-xl border border-gray-200 px-3 py-2.5" placeholder="مثلاً رستوران" /></label>
|
||
<label className="block text-sm font-medium text-secondary">تعداد پرسنل<input type="number" min={1} value={Number(answers.employees)} onChange={(event) => setAnswer("employees", Number(event.target.value))} className="mt-1 w-full rounded-xl border border-gray-200 px-3 py-2.5" /></label>
|
||
<label className="block text-sm font-medium text-secondary">تعداد شعبه<input type="number" min={1} value={Number(answers.branches)} onChange={(event) => setAnswer("branches", Number(event.target.value))} className="mt-1 w-full rounded-xl border border-gray-200 px-3 py-2.5" /></label>
|
||
</div>
|
||
<fieldset><legend className="text-sm font-semibold text-secondary">نیازهای کسبوکار</legend><div className="mt-3 grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
||
{[
|
||
["in_person_sales", "فروش حضوری"],
|
||
["online_sales", "فروش آنلاین"],
|
||
["delivery", "ارسال کالا"],
|
||
["booking", "مدیریت رزرو"],
|
||
["loyalty", "باشگاه مشتریان"],
|
||
].map(([key, label]) => <label key={key} className="flex cursor-pointer items-center gap-2 rounded-xl border border-gray-200 px-3 py-2.5 text-sm"><input type="checkbox" checked={Boolean(answers[key])} onChange={(event) => setAnswer(key, event.target.checked)} />{label}</label>)}
|
||
</div></fieldset>
|
||
<Button type="submit" loading={busy}>نمایش نتیجه پیشنهادی</Button>
|
||
</form>
|
||
{result ? <div className="mt-6"><MetadataBagView title="نتیجه قابل نمایش به مشتری" attributes={result} /></div> : null}
|
||
</section>
|
||
);
|
||
}
|