upgraded cart add function

This commit is contained in:
Jelaletdin12
2025-12-24 15:43:27 +05:00
parent 2b46d525f2
commit d3ed4d1901
9 changed files with 224 additions and 126 deletions

View File

@@ -326,7 +326,7 @@ export default function CartItemCard({ item, onUpdate }: CartItemCardProps) {
<Card className="p-4 shadow-none border">
<div className="flex flex-col sm:flex-row gap-4">
<div className="flex gap-4 flex-1">
<div className="relative w-[88px] h-[117px] rounded-xl border overflow-hidden flex-shrink-0">
<div className="relative w-[88px] h-[117px] rounded-xl border overflow-hidden shrink-0">
<Image
src={getImageSrc()}
alt={item.product.name}

View File

@@ -16,6 +16,7 @@ import { Input } from "@/components/ui/input";
import DeliveryTypeSelector from "./DeliveryTypeSelector";
import { useTranslations } from "next-intl";
import type { DeliveryType, PaymentType, Province } from "@/lib/types/api";
import { useState } from "react";
interface OrderBillingItem {
title: string;
@@ -83,17 +84,59 @@ export default function OrderSummary({
isLoading,
}: OrderSummaryProps) {
const t = useTranslations();
const [showValidation, setShowValidation] = useState(false);
const provincesForSelectedRegion = selectedRegion
? regionGroups[selectedRegion] || []
: [];
const phoneDigits = phone.replace(/\D/g, "");
const isPhoneValid = phoneDigits.length === 11;
const isFormValid =
selectedRegion && selectedProvince && paymentType && phone && name;
selectedRegion &&
selectedProvince &&
paymentType &&
isPhoneValid &&
name.trim() !== "" &&
lastName.trim() !== "";
const handlePhoneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const input = e.target.value;
const prefix = "+993 ";
if (input.length < prefix.length) {
onPhoneChange(prefix);
return;
}
const digitsOnly = input.substring(prefix.length).replace(/\D/g, "");
const limitedDigits = digitsOnly.substring(0, 8);
let formattedPhone = prefix;
if (limitedDigits.length > 0) {
formattedPhone += limitedDigits.substring(0, 2);
if (limitedDigits.length > 2) {
formattedPhone += " " + limitedDigits.substring(2);
}
}
onPhoneChange(formattedPhone);
};
const handleCompleteOrderClick = () => {
setShowValidation(true);
if (isFormValid) {
onCompleteOrder();
}
};
return (
<Card className="w-full md:w-[380px] p-4 md:p-6 rounded-xl h-fit sticky top-20">
{/* Customer Information */}
<div className="">
<div className="mb-6">
<h3 className="text-lg font-semibold mb-3">
{t("customer_information")}
</h3>
@@ -107,8 +150,13 @@ export default function OrderSummary({
value={name}
onChange={(e) => onNameChange(e.target.value)}
placeholder={t("name")}
className="rounded-lg"
className={`rounded-lg ${
showValidation && name.trim() === "" ? "border-red-500" : ""
}`}
/>
{showValidation && name.trim() === "" && (
<p className="text-xs text-red-500 mt-1">Bu alan zorunludur</p>
)}
</div>
<div>
<Label className="text-sm font-medium mb-2 block">
@@ -119,8 +167,13 @@ export default function OrderSummary({
value={lastName}
onChange={(e) => onLastNameChange(e.target.value)}
placeholder={t("last_name")}
className="rounded-lg"
className={`rounded-lg ${
showValidation && lastName.trim() === "" ? "border-red-500" : ""
}`}
/>
{showValidation && lastName.trim() === "" && (
<p className="text-xs text-red-500 mt-1">Bu alan zorunludur</p>
)}
</div>
<div>
<Label className="text-sm font-medium mb-2 block">
@@ -129,16 +182,23 @@ export default function OrderSummary({
<Input
type="tel"
value={phone}
onChange={(e) => onPhoneChange(e.target.value)}
placeholder={t("phone")}
className="rounded-lg"
onChange={handlePhoneChange}
placeholder="+993 61 097651"
className={`rounded-lg ${
showValidation && !isPhoneValid ? "border-red-500" : ""
}`}
/>
{showValidation && !isPhoneValid && (
<p className="text-xs text-red-500 mt-1">
Telefon 8 rakamdan oluşmalıdır
</p>
)}
</div>
</div>
</div>
{/* Payment Type */}
<div className="">
<div className="mb-6">
<h3 className="text-lg font-semibold mb-3">{t("payment_type")}</h3>
<div className="flex gap-2">
{paymentTypes.map((type) => (
@@ -147,6 +207,8 @@ export default function OrderSummary({
className={`flex-1 cursor-pointer transition-all ${
paymentType?.id === type.id
? "border-2 border-[#005bff] bg-blue-50"
: showValidation && !paymentType
? "border-2 border-red-500"
: "border-2 border-gray-200"
}`}
onClick={() => onPaymentTypeChange(type)}
@@ -163,16 +225,13 @@ export default function OrderSummary({
</Card>
))}
</div>
{showValidation && !paymentType && (
<p className="text-xs text-red-500 mt-1">Ödeme türü seçiniz</p>
)}
</div>
{/* Delivery Type */}
{/* <DeliveryTypeSelector
selectedType={deliveryType}
onSelect={onDeliveryTypeChange}
/> */}
{/* Region Selection */}
<div className="">
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">
{t("choose_region")}
</Label>
@@ -189,7 +248,11 @@ export default function OrderSummary({
<RadioGroupItem
value={regionCode}
id={`region-${regionCode}`}
className="border-2 border-gray-400 data-[state=checked]:border-[#005bff] data-[state=checked]:bg-white"
className={`border-2 ${
showValidation && !selectedRegion
? "border-red-500"
: "border-gray-400"
} data-[state=checked]:border-[#005bff] data-[state=checked]:bg-white`}
/>
<Label
htmlFor={`region-${regionCode}`}
@@ -200,11 +263,14 @@ export default function OrderSummary({
</div>
))}
</RadioGroup>
{showValidation && !selectedRegion && (
<p className="text-xs text-red-500 mt-1">Bölge seçiniz</p>
)}
</div>
{/* Province Selection */}
{selectedRegion && provincesForSelectedRegion.length > 0 && (
<div className="">
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">
{t("choose_address")}
</Label>
@@ -212,7 +278,11 @@ export default function OrderSummary({
value={selectedProvince?.toString() || ""}
onValueChange={(value) => onProvinceChange(parseInt(value))}
>
<SelectTrigger className="rounded-lg w-full">
<SelectTrigger
className={`rounded-lg w-full ${
showValidation && !selectedProvince ? "border-red-500" : ""
}`}
>
<SelectValue placeholder={t("choose_address")} />
</SelectTrigger>
<SelectContent>
@@ -223,11 +293,14 @@ export default function OrderSummary({
))}
</SelectContent>
</Select>
{showValidation && !selectedProvince && (
<p className="text-xs text-red-500 mt-1">Adres seçiniz</p>
)}
</div>
)}
{/* Note */}
<div className="">
<div className="mb-6">
<Label className="text-lg font-semibold mb-3 block">{t("note")}</Label>
<Textarea
value={note}
@@ -253,7 +326,7 @@ export default function OrderSummary({
<Separator className="my-4" />
<div className="flex justify-between items-center ">
<div className="flex justify-between items-center mb-6">
<span className="text-lg font-semibold">
{order.billing.footer.title}:
</span>
@@ -263,8 +336,8 @@ export default function OrderSummary({
</div>
<Button
onClick={onCompleteOrder}
disabled={!isFormValid || isLoading}
onClick={handleCompleteOrderClick}
disabled={isLoading}
className="w-full rounded-lg cursor-pointer bg-[#005bff] hover:bg-[#004dcc] h-12 text-lg font-bold disabled:opacity-50"
size="lg"
>