added debounce to - + buttons

This commit is contained in:
Jelaletdin12
2025-11-16 23:37:21 +05:00
parent f867896817
commit 4fe0fb3d4e
52 changed files with 2548 additions and 2253 deletions

View File

@@ -1,37 +1,58 @@
"use client"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Textarea } from "@/components/ui/textarea"
import { Separator } from "@/components/ui/separator"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import DeliveryTypeSelector from "./DeliveryTypeSelector"
import type { Order, Province, DeliveryType, CartTranslations, PaymentType } from "../types"
"use client";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import DeliveryTypeSelector from "./DeliveryTypeSelector";
import { useTranslations } from "next-intl";
import type { DeliveryType, PaymentType, Province } from "@/lib/types/api";
interface OrderBillingItem {
title: string;
value: string;
}
interface OrderBilling {
body: OrderBillingItem[];
footer: {
title: string;
value: string;
};
}
interface OrderSummaryProps {
order: Order
translations: CartTranslations
paymentType: PaymentType | null
deliveryType: DeliveryType
selectedRegion: string
selectedProvince: number | null
note: string
regionGroups: Record<string, Province[]>
availableRegions: string[]
paymentTypes: PaymentType[]
onPaymentTypeChange: (type: PaymentType) => void
onDeliveryTypeChange: (type: DeliveryType) => void
onRegionChange: (regionCode: string) => void
onProvinceChange: (provinceId: number) => void
onNoteChange: (note: string) => void
onCompleteOrder: () => void
isLoading: boolean
order: {
id: number;
billing: OrderBilling;
};
paymentType: PaymentType | null;
deliveryType: DeliveryType;
selectedRegion: string;
selectedProvince: number | null;
note: string;
regionGroups: Record<string, Province[]>;
availableRegions: string[];
paymentTypes: PaymentType[];
onPaymentTypeChange: (type: PaymentType) => void;
onDeliveryTypeChange: (type: DeliveryType) => void;
onRegionChange: (regionCode: string) => void;
onProvinceChange: (provinceId: number) => void;
onNoteChange: (note: string) => void;
onCompleteOrder: () => void;
isLoading: boolean;
}
export default function OrderSummary({
order,
translations: t,
paymentType,
deliveryType,
selectedRegion,
@@ -48,29 +69,35 @@ export default function OrderSummary({
onCompleteOrder,
isLoading,
}: OrderSummaryProps) {
const provincesForSelectedRegion = selectedRegion ? regionGroups[selectedRegion] || [] : []
const isFormValid = selectedRegion && selectedProvince && paymentType
const t = useTranslations();
const provincesForSelectedRegion = selectedRegion
? regionGroups[selectedRegion] || []
: [];
const isFormValid = selectedRegion && selectedProvince && paymentType;
return (
<Card className="w-full md:w-[380px] p-6 rounded-xl h-fit sticky top-20">
{/* Payment Type */}
<div className="mb-6">
<h3 className="text-lg font-semibold mb-3">{t.paymentType}</h3>
<h3 className="text-lg font-semibold mb-3">{t("payment_type")}</h3>
<div className="flex gap-2">
{paymentTypes.map((type) => (
<Card
key={type.id}
className={`flex-1 cursor-pointer transition-all ${
paymentType?.id === type.id
? "border-2 border-[#005bff] bg-blue-50"
paymentType?.id === type.id
? "border-2 border-[#005bff] bg-blue-50"
: "border-2 border-gray-200"
}`}
onClick={() => onPaymentTypeChange(type)}
>
<div className="flex flex-col items-center justify-center p-4 gap-2">
<span className={`text-xs font-medium ${
paymentType?.id === type.id ? "text-[#005bff]" : ""
}`}>
<span
className={`text-xs font-medium ${
paymentType?.id === type.id ? "text-[#005bff]" : ""
}`}
>
{type.name}
</span>
</div>
@@ -80,21 +107,22 @@ export default function OrderSummary({
</div>
{/* Delivery Type */}
<DeliveryTypeSelector
selectedType={deliveryType}
onSelect={onDeliveryTypeChange}
translations={t}
<DeliveryTypeSelector
selectedType={deliveryType}
onSelect={onDeliveryTypeChange}
/>
{/* Region Selection */}
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">{t.selectRegion}</Label>
<RadioGroup
value={selectedRegion}
<Label className="text-lg font-semibold mb-3 block">
{t("choose_region")}
</Label>
<RadioGroup
value={selectedRegion}
onValueChange={(value) => {
onRegionChange(value)
onProvinceChange(null as any)
}}
onRegionChange(value);
onProvinceChange(null as any);
}}
className="flex flex-wrap gap-4"
>
{availableRegions.map((regionCode) => (
@@ -104,7 +132,10 @@ export default function OrderSummary({
id={`region-${regionCode}`}
className="border-2 border-gray-400 data-[state=checked]:border-[#005bff] data-[state=checked]:bg-white"
/>
<Label htmlFor={`region-${regionCode}`} className="cursor-pointer uppercase">
<Label
htmlFor={`region-${regionCode}`}
className="cursor-pointer uppercase"
>
{regionCode}
</Label>
</div>
@@ -115,13 +146,15 @@ export default function OrderSummary({
{/* Province Selection */}
{selectedRegion && provincesForSelectedRegion.length > 0 && (
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">{t.selectAddress}</Label>
<Select
value={selectedProvince?.toString() || ""}
<Label className="text-lg font-semibold mb-3 block">
{t("choose_address")}
</Label>
<Select
value={selectedProvince?.toString() || ""}
onValueChange={(value) => onProvinceChange(parseInt(value))}
>
<SelectTrigger className="rounded-xl">
<SelectValue placeholder={t.selectAddress} />
<SelectValue placeholder={t("choose_address")} />
</SelectTrigger>
<SelectContent>
{provincesForSelectedRegion.map((province) => (
@@ -136,20 +169,23 @@ export default function OrderSummary({
{/* Note */}
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">{t.note}</Label>
<Label className="text-lg font-semibold mb-3 block">{t("note")}</Label>
<Textarea
value={note}
onChange={(e) => onNoteChange(e.target.value)}
className="rounded-xl resize-none"
rows={3}
placeholder={t.note}
placeholder={t("note")}
/>
</div>
{/* Billing */}
<div className="space-y-2 mb-4">
{order.billing.body.map((item, index) => (
<div key={index} className="flex justify-between text-base font-medium">
<div
key={index}
className="flex justify-between text-base font-medium"
>
<span>{item.title}:</span>
<span>{item.value}</span>
</div>
@@ -159,8 +195,12 @@ export default function OrderSummary({
<Separator className="my-4" />
<div className="flex justify-between items-center mb-6">
<span className="text-lg font-semibold">{order.billing.footer.title}:</span>
<span className="text-lg font-bold text-green-600">{order.billing.footer.value}</span>
<span className="text-lg font-semibold">
{order.billing.footer.title}:
</span>
<span className="text-lg font-bold text-green-600">
{order.billing.footer.value}
</span>
</div>
<Button
@@ -169,8 +209,8 @@ export default function OrderSummary({
className="w-full rounded-xl bg-[#005bff] hover:bg-[#004dcc] h-12 text-lg font-bold disabled:opacity-50"
size="lg"
>
{isLoading ? `${t.placeOrder}...` : t.placeOrder}
{isLoading ? `${t("order")}...` : t("order")}
</Button>
</Card>
)
}
);
}