This commit is contained in:
Samandar Turgunboyev
2025-11-01 19:12:38 +05:00
parent 4e9b2f3bd8
commit 193d01ed51
27 changed files with 1300 additions and 120 deletions

View File

@@ -0,0 +1,140 @@
"use client";
import { payAgency } from "@/pages/finance/lib/api";
import { Button } from "@/shared/ui/button";
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/shared/ui/dialog";
import { Input } from "@/shared/ui/input";
import { Label } from "@/shared/ui/label";
import { useMutation } from "@tanstack/react-query";
import { Loader2 } from "lucide-react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
interface PayDialogProps {
open: boolean;
onClose: () => void;
agencyId: number;
}
interface PayFormValues {
amount: string; // formatted value (e.g. "1 200 000")
note: string;
}
// Narxni formatlovchi funksiya
function formatPrice(value: number | string): string {
const num = Number(value.toString().replace(/\D/g, ""));
if (isNaN(num)) return "";
return num.toLocaleString("ru-RU");
}
export function PayDialog({ open, onClose, agencyId }: PayDialogProps) {
const { t } = useTranslation();
const form = useForm<PayFormValues>({
defaultValues: {
amount: "",
note: "",
},
});
const { mutate, isPending } = useMutation({
mutationFn: ({
body,
}: {
body: {
travel_agency: number;
amount: number;
note: string;
};
}) => payAgency({ body }),
onSuccess: () => {
onClose();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
richColors: true,
position: "top-center",
});
},
});
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value.replace(/\D/g, "");
const formatted = formatPrice(raw);
form.setValue("amount", formatted);
};
const handleSubmit = async (values: PayFormValues) => {
const cleanAmount = Number(
values.amount.replace(/\s/g, "").replace(/,/g, ""),
);
mutate({
body: {
amount: cleanAmount,
note: values.note,
travel_agency: agencyId,
},
});
};
return (
<Dialog open={open} onOpenChange={onClose}>
<DialogContent className="sm:max-w-md text-white bg-gray-900">
<DialogHeader>
<DialogTitle>{t("Qolgan summani tolash")}</DialogTitle>
</DialogHeader>
<form
onSubmit={form.handleSubmit(handleSubmit)}
className="space-y-4 py-2"
>
{/* Summani kiritish */}
<div className="space-y-2">
<Label htmlFor="amount">{t("Summani kiriting")}</Label>
<Input
id="amount"
inputMode="numeric"
placeholder="1 200 000"
value={form.watch("amount")}
onChange={handleAmountChange}
/>
{form.formState.errors.amount && (
<p className="text-red-400 text-sm">
{t("Summani togri kiriting")}
</p>
)}
</div>
{/* Izoh */}
<div className="space-y-2">
<Label htmlFor="note">{t("Izoh")}</Label>
<Input
id="note"
type="text"
placeholder={t("Izoh kiriting") || ""}
{...form.register("note")}
/>
</div>
{/* Tugmalar */}
<DialogFooter className="flex justify-end gap-3 pt-4">
<Button type="button" variant="outline" onClick={onClose}>
{t("Bekor qilish")}
</Button>
<Button type="submit" disabled={isPending}>
{isPending ? <Loader2 className="animate-spin" /> : t("Tolash")}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}