Files
guilan-ace-frontend/src/components/CouponDialogFa.tsx
Amirhossein Khalili dacbd3a328
Some checks failed
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled
initial commit
2026-05-19 20:58:15 +03:30

137 lines
4.8 KiB
TypeScript
Raw 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.
import * as React from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { cn, formatNumberPersian, formatToman, resolveErrorMessage } from "@/lib/utils";
type RawVerifyResult = {
discount_amount: number;
final_price: number;
};
type Normalized = {
valid: boolean;
discount_amount: number;
final_price: number;
message_fa: string;
};
type Props = {
open: boolean;
onOpenChange: (v: boolean) => void;
basePrice: number; // مبلغ اولیه رویداد
onVerifyCouponRaw: (code: string) => Promise<RawVerifyResult>;
onContinue: (coupon?: string, finalPrice?: number) => void; // ادامه‌ی جریان ثبت‌نام/پرداخت
};
export default function CouponDialogFa({
open,
onOpenChange,
basePrice,
onVerifyCouponRaw,
onContinue,
}: Props) {
const [code, setCode] = React.useState("");
const [verifying, setVerifying] = React.useState(false);
const [res, setRes] = React.useState<Normalized | null>(null);
// اگر نتیجه نداریم، قیمت نهایی = قیمت پایه
const finalPrice = res?.final_price ?? basePrice / 10;
const handleVerify = async () => {
if (!code) return;
try {
setVerifying(true);
// فراخوانی تابع خام که فقط خروجی بک‌اند را می‌دهد
const raw = await onVerifyCouponRaw(code);
// --- نرمالایز داخل همین کامپوننت ---
setRes({
valid: true,
discount_amount: (raw.discount_amount ?? 0) / 10,
final_price: (raw.final_price ?? basePrice) / 10,
message_fa: "کد تخفیف با موفقیت اعمال شد",
});
} catch (error) {
setRes({
valid: false,
discount_amount: 0,
final_price: basePrice / 10, // برگرداندن قیمت به حالت اولیه
message_fa: resolveErrorMessage(error, "کد تخفیف معتبر نیست"),
});
} finally {
setVerifying(false);
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md" dir="rtl">
<DialogHeader>
<DialogTitle>کد تخفیف</DialogTitle>
</DialogHeader>
<div className="grid gap-4 text-right">
<div className="grid gap-2">
<Label htmlFor="coupon">کد تخفیف (اختیاری)</Label>
<div className="flex gap-2">
<Input
id="coupon"
value={code}
onChange={(e) => setCode(e.target.value)}
placeholder="مثلاً OFF20"
className="text-right"
/>
<Button variant="secondary" disabled={!code || verifying} onClick={handleVerify}>
{verifying ? "در حال بررسی..." : "بررسی کد"}
</Button>
</div>
{/* پیام زیر اینپوت: موفق/نامعتبر */}
{res && (
<p className={cn("text-sm", res.valid ? "text-emerald-600" : "text-destructive")}>
{res.message_fa}
</p>
)}
</div>
<div className="rounded-md border p-3 space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground">قیمت اولیه</span>
<span className="font-medium">{formatToman(basePrice)}</span>
</div>
{res?.discount_amount ? (
<div className="flex items-center justify-between">
<span className="text-muted-foreground">تخفیف</span>
<span className="font-medium">
- {formatNumberPersian(res.discount_amount)} تومان
</span>
</div>
) : null}
<div className="flex items-center justify-between border-t pt-2">
<span className="text-muted-foreground">قیمت نهایی</span>
<span className="font-semibold">{formatNumberPersian(finalPrice)} تومان</span>
</div>
</div>
</div>
<DialogFooter className="sm:justify-start">
<div className="flex w-full items-center justify-end gap-2">
<Button variant="outline" onClick={() => onOpenChange(false)}>انصراف</Button>
<Button
onClick={() => onContinue(code || undefined, finalPrice)}
disabled={verifying /* در حال بررسی که هستیم، ادامه غیرفعال باشد */}
>
ادامه و پرداخت
</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
);
}