TorbatYar/frontend/modules/commercial/features/admin-recommendations.tsx

62 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { 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>
);
}