@raxonltd/raxon-core 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/context/cart.context.d.ts +4 -9
- package/dist/core/context/cart.context.d.ts.map +1 -1
- package/dist/core/context/cart.context.js +18 -29
- package/dist/core/context/security.context.d.ts +4 -10
- package/dist/core/context/security.context.d.ts.map +1 -1
- package/dist/core/context/security.context.js +25 -32
- package/dist/core/feature/address/form/address-search-input.d.ts +1 -1
- package/dist/core/feature/address/hook/use.addres.d.ts +2 -2
- package/dist/core/feature/address/hook/use.addres.js +1 -1
- package/dist/core/feature/address/hook/use.address-autocomplete.d.ts +2 -2
- package/dist/core/feature/address/hook/use.address-autocomplete.js +1 -1
- package/dist/core/feature/address/util/parse-google-place.d.ts +2 -2
- package/dist/core/feature/article/hook/use.article.d.ts +2 -2
- package/dist/core/feature/article/hook/use.article.js +1 -1
- package/dist/core/feature/attribute/hook/use.attribute.d.ts +2 -2
- package/dist/core/feature/attribute/hook/use.attribute.js +1 -1
- package/dist/core/feature/auth/hook/use.auth.js +1 -1
- package/dist/core/feature/auth/modal/modal.auth.js +4 -4
- package/dist/core/feature/auth/view/view.login.js +1 -1
- package/dist/core/feature/auth/view/view.register.js +1 -1
- package/dist/core/feature/bank-account/hook/use.bank.account.d.ts +2 -2
- package/dist/core/feature/bank-account/hook/use.bank.account.js +1 -1
- package/dist/core/feature/cart/component/cart.order.summary.d.ts +1 -1
- package/dist/core/feature/cart/component/cart.order.summary.js +1 -1
- package/dist/core/feature/cart/component/cart.promo.code.section.js +5 -5
- package/dist/core/feature/cart/hook/use.cart.d.ts +7 -3
- package/dist/core/feature/cart/hook/use.cart.d.ts.map +1 -1
- package/dist/core/feature/cart/hook/use.cart.js +12 -3
- package/dist/core/feature/cart/util/basket-pay.response.js +1 -1
- package/dist/core/feature/cart/util/cart-optimistic.d.ts +1 -1
- package/dist/core/feature/cart/util/cart-optimistic.js +1 -1
- package/dist/core/feature/collection/hook/use.collection.d.ts +2 -2
- package/dist/core/feature/collection/hook/use.collection.js +1 -1
- package/dist/core/feature/delivery-method/hook/use.delivery.method.d.ts +1 -1
- package/dist/core/feature/delivery-method/hook/use.delivery.method.js +2 -2
- package/dist/core/feature/delivery-method/util/checkout.delivery.method.d.ts +1 -1
- package/dist/core/feature/faq/hook/use.faq.d.ts +2 -2
- package/dist/core/feature/faq/hook/use.faq.js +1 -1
- package/dist/core/feature/favorite/hook/use.favorite.d.ts +2 -2
- package/dist/core/feature/favorite/hook/use.favorite.js +1 -1
- package/dist/core/feature/form-submit/hook/use.form.submit.js +1 -1
- package/dist/core/feature/invoice/hook/use.invoice.d.ts +2 -2
- package/dist/core/feature/invoice/hook/use.invoice.js +1 -1
- package/dist/core/feature/newsletter/hook/use.newsletter.d.ts +1 -1
- package/dist/core/feature/newsletter/hook/use.newsletter.js +1 -1
- package/dist/core/feature/newsletter/modal/modal.newsletter.product.d.ts +1 -1
- package/dist/core/feature/newsletter/modal/modal.newsletter.product.js +3 -3
- package/dist/core/feature/order/hook/use.order.d.ts +2 -2
- package/dist/core/feature/order/hook/use.order.js +1 -1
- package/dist/core/feature/payment-method/checkout.payment.options.d.ts +1 -1
- package/dist/core/feature/payment-method/checkout.payment.options.js +1 -1
- package/dist/core/feature/payment-method/hook/use.payment.method.d.ts +2 -2
- package/dist/core/feature/payment-method/hook/use.payment.method.js +1 -1
- package/dist/core/feature/product/hook/use.product.d.ts +3 -3
- package/dist/core/feature/product/hook/use.product.js +2 -2
- package/dist/core/feature/profile/hook/use.profile.d.ts +1 -1
- package/dist/core/feature/profile/hook/use.profile.js +1 -1
- package/dist/core/feature/promo-code/hook/use.promo.code.d.ts +1 -1
- package/dist/core/feature/promo-code/hook/use.promo.code.js +1 -1
- package/dist/core/interface/inventory.interface.d.ts +1 -1
- package/dist/core/raxon.context.d.ts +13 -10
- package/dist/core/raxon.context.d.ts.map +1 -1
- package/dist/core/raxon.context.js +28 -21
- package/dist/core/util/garanti-payment.d.ts +1 -1
- package/dist/core/util/garanti-payment.js +1 -1
- package/dist/core/view/view.checkout.d.ts +2 -0
- package/dist/core/view/view.checkout.d.ts.map +1 -0
- package/dist/core/view/view.checkout.js +684 -0
- package/dist/hook.d.ts +19 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +18 -0
- package/dist/index.d.ts +2 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -22
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/view.d.ts +2 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +1 -0
- package/package.json +35 -13
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { HelpCircle } from 'lucide-react';
|
|
6
|
+
import { useState, useRef, useEffect, useMemo } from 'react';
|
|
7
|
+
import { useForm } from 'react-hook-form';
|
|
8
|
+
import { Input } from 'rizzui/input';
|
|
9
|
+
import { Button } from 'rizzui/button';
|
|
10
|
+
import { useRaxon } from '../raxon.context';
|
|
11
|
+
import { LOGIN_SUCCESS_EVENT } from '../feature/auth/hook/use.auth';
|
|
12
|
+
import { ModalAuth } from '../feature/auth/modal/modal.auth';
|
|
13
|
+
import { useCart } from '../feature/cart/hook/use.cart';
|
|
14
|
+
import { useAddress } from '../feature/address/hook/use.addres';
|
|
15
|
+
import { useAddressAutocomplete } from '../feature/address/hook/use.address-autocomplete';
|
|
16
|
+
import { AddressSearchInput } from '../feature/address/form/address-search-input';
|
|
17
|
+
import { formatAddressSummary, parsedAddressToFormFields } from '../feature/address/util/parse-google-place';
|
|
18
|
+
import { formatBasketItemVariantLine } from '../util/basket.item.display';
|
|
19
|
+
import { GeneralImage } from '../component/general.image';
|
|
20
|
+
import { AddressType, PaymentProvider, PaymentTerms } from '../interface/prisma.interface';
|
|
21
|
+
import { storeGarantiPaymentHtml } from '../util/garanti-payment';
|
|
22
|
+
import { resolveClientIp } from '../util/client-ip';
|
|
23
|
+
import { CartPromoCodeSection } from '../feature/cart/component/cart.promo.code.section';
|
|
24
|
+
const addressFormDefaultValues = {
|
|
25
|
+
firstName: '',
|
|
26
|
+
lastName: '',
|
|
27
|
+
phone: '',
|
|
28
|
+
street: '',
|
|
29
|
+
buildingNumber: '',
|
|
30
|
+
apartmentNumber: '',
|
|
31
|
+
postalCode: '',
|
|
32
|
+
province: '',
|
|
33
|
+
district: '',
|
|
34
|
+
newsletter: false,
|
|
35
|
+
billingAddressDifferent: false,
|
|
36
|
+
billingFullName: '',
|
|
37
|
+
billingTaxNumber: '',
|
|
38
|
+
billingProvince: '',
|
|
39
|
+
billingDistrict: '',
|
|
40
|
+
billingStreet: '',
|
|
41
|
+
savedDeliveryAddressId: '',
|
|
42
|
+
savedBillingAddressId: '',
|
|
43
|
+
addressSearch: '',
|
|
44
|
+
};
|
|
45
|
+
function formatAddressLine(addr) {
|
|
46
|
+
const name = addr.companyName || `${addr.firstName ?? ''} ${addr.lastName ?? ''}`.trim();
|
|
47
|
+
const street = addr.streetName ?? addr.fullAddress ?? '';
|
|
48
|
+
const location = [addr.administrativeAreaLevel2, addr.administrativeAreaLevel1].filter(Boolean).join(', ');
|
|
49
|
+
return { name, street, location, postalCode: addr.postalCode, taxNumber: addr.taxNumber };
|
|
50
|
+
}
|
|
51
|
+
function pickDefaultDeliveryAddress(addresses) {
|
|
52
|
+
return addresses.find(addr => addr.type === AddressType.DELIVERY) ?? addresses[0];
|
|
53
|
+
}
|
|
54
|
+
function ViewStep1({ onContinue }) {
|
|
55
|
+
const { cart, profile, isAuthenticated, isGuest } = useRaxon();
|
|
56
|
+
const modalAuthRef = useRef(null);
|
|
57
|
+
const [emailInput, setEmailInput] = useState('');
|
|
58
|
+
const [emailError, setEmailError] = useState(null);
|
|
59
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
60
|
+
const lastSavedEmailRef = useRef('');
|
|
61
|
+
const saveInFlightRef = useRef(null);
|
|
62
|
+
const userEditedEmailRef = useRef(false);
|
|
63
|
+
const updateBasketMutation = useCart().update();
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const fromCart = cart?.email?.trim() || '';
|
|
66
|
+
const fromProfile = isAuthenticated && !isGuest ? profile?.email?.trim() || '' : '';
|
|
67
|
+
const resolved = fromCart || fromProfile;
|
|
68
|
+
if (fromCart) {
|
|
69
|
+
lastSavedEmailRef.current = fromCart;
|
|
70
|
+
}
|
|
71
|
+
if (!resolved || userEditedEmailRef.current)
|
|
72
|
+
return;
|
|
73
|
+
setEmailInput(resolved);
|
|
74
|
+
}, [cart?.email, profile?.email, isAuthenticated, isGuest]);
|
|
75
|
+
const isValidEmail = (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
76
|
+
const saveEmail = (email) => {
|
|
77
|
+
if (saveInFlightRef.current)
|
|
78
|
+
return saveInFlightRef.current;
|
|
79
|
+
const promise = (async () => {
|
|
80
|
+
const trimmed = email.trim();
|
|
81
|
+
if (!trimmed) {
|
|
82
|
+
setEmailError('E-posta adresi zorunludur.');
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (!isValidEmail(trimmed)) {
|
|
86
|
+
setEmailError('Geçerli bir e-posta adresi giriniz.');
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (trimmed === lastSavedEmailRef.current)
|
|
90
|
+
return true;
|
|
91
|
+
if (!cart?.id) {
|
|
92
|
+
setEmailError('Sepet bulunamadı. Lütfen sayfayı yenileyin.');
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
setEmailError(null);
|
|
96
|
+
setIsSaving(true);
|
|
97
|
+
try {
|
|
98
|
+
await updateBasketMutation.mutateAsync({ id: cart.id, email: trimmed });
|
|
99
|
+
lastSavedEmailRef.current = trimmed;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
setEmailError('E-posta kaydedilemedi. Lütfen tekrar deneyin.');
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
setIsSaving(false);
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
saveInFlightRef.current = promise;
|
|
111
|
+
void promise.finally(() => {
|
|
112
|
+
if (saveInFlightRef.current === promise)
|
|
113
|
+
saveInFlightRef.current = null;
|
|
114
|
+
});
|
|
115
|
+
return promise;
|
|
116
|
+
};
|
|
117
|
+
const handleEmailBlur = () => {
|
|
118
|
+
void saveEmail(emailInput);
|
|
119
|
+
};
|
|
120
|
+
return (_jsxs(_Fragment, { children: [_jsx(ModalAuth, { ref: modalAuthRef }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900", children: "\u0130leti\u015Fim" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Sipari\u015F onay\u0131 ve kargo bilgileri bu adrese g\u00F6nderilir." })] }), !isGuest && isAuthenticated ? (_jsx("p", { className: "text-sm text-gray-600", children: _jsx("button", { type: "button", className: "font-medium text-[#CF0A2C] hover:underline", onClick: () => modalAuthRef.current?.open('login'), children: "Hesab\u0131n\u0131zla giri\u015F yapt\u0131n\u0131z" }) })) : (_jsxs("p", { className: "text-sm text-gray-600", children: ["Hesab\u0131n\u0131z var m\u0131?", ' ', _jsx("button", { type: "button", className: "font-medium text-[#CF0A2C] hover:underline", onClick: () => modalAuthRef.current?.open('login'), children: "Giri\u015F yap" }), ' veya ', _jsx("button", { type: "button", className: "font-medium text-[#CF0A2C] hover:underline", onClick: () => modalAuthRef.current?.open('register'), children: "kay\u0131t ol" })] })), _jsx(Input, { type: "email", label: "E-posta", placeholder: "ornek@email.com", value: emailInput, onChange: e => {
|
|
121
|
+
userEditedEmailRef.current = true;
|
|
122
|
+
setEmailInput(e.target.value);
|
|
123
|
+
}, onBlur: handleEmailBlur, size: "lg", className: "rounded-xl", required: true }), isSaving ? _jsx("p", { className: "text-xs text-gray-500", children: "Kaydediliyor\u2026" }) : null, emailError ? _jsx("p", { className: "text-sm text-red-600", children: emailError }) : null, _jsx(Button, { type: "button", size: "lg", className: "w-full rounded-xl bg-[#CF0A2C] font-semibold text-white hover:bg-[#a80824]", disabled: !emailInput.trim() || isSaving, onClick: async () => {
|
|
124
|
+
const ok = await saveEmail(emailInput);
|
|
125
|
+
if (ok)
|
|
126
|
+
onContinue(emailInput.trim());
|
|
127
|
+
}, children: "Devam et" })] })] }));
|
|
128
|
+
}
|
|
129
|
+
function ViewStep2({ onComplete, onBack }) {
|
|
130
|
+
const { cart } = useRaxon();
|
|
131
|
+
const deliveryFormHydratedKeyRef = useRef(null);
|
|
132
|
+
const addressBasketSyncRef = useRef(null);
|
|
133
|
+
const { query: addressSearchQuery, setQuery: setAddressSearchQuery, onUserQueryChange: onAddressSearchQueryChange, results: addressSearchResults, isSearching: isAddressSearching, showResults: showAddressSearchResults, setShowResults: setShowAddressSearchResults, selectPlace: selectAddressPlace, resetSearch: resetAddressSearch, } = useAddressAutocomplete();
|
|
134
|
+
const updateBasketMutation = useCart().update();
|
|
135
|
+
const { data: addressesPayload } = useAddress().fetch();
|
|
136
|
+
const savedAddresses = addressesPayload?.data ?? [];
|
|
137
|
+
const addressForm = useForm({
|
|
138
|
+
defaultValues: addressFormDefaultValues,
|
|
139
|
+
});
|
|
140
|
+
const { register, handleSubmit, watch, setValue, getValues, reset, setError, clearErrors, formState: { errors, isSubmitting }, } = addressForm;
|
|
141
|
+
const billingAddressDifferent = watch('billingAddressDifferent');
|
|
142
|
+
const savedDeliveryAddressId = watch('savedDeliveryAddressId');
|
|
143
|
+
const savedBillingAddressId = watch('savedBillingAddressId');
|
|
144
|
+
const provinceField = register('province', { required: 'İl giriniz' });
|
|
145
|
+
const districtField = register('district', { required: 'İlçe giriniz' });
|
|
146
|
+
const billingProvinceField = register('billingProvince', {
|
|
147
|
+
required: billingAddressDifferent ? 'İl giriniz' : false,
|
|
148
|
+
});
|
|
149
|
+
const billingDistrictField = register('billingDistrict', {
|
|
150
|
+
required: billingAddressDifferent ? 'İlçe giriniz' : false,
|
|
151
|
+
});
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const d = cart?.deliveryAddress;
|
|
154
|
+
if (!cart || !d?.id)
|
|
155
|
+
return;
|
|
156
|
+
const hydrateKey = `${cart.id}:${d.id}`;
|
|
157
|
+
if (deliveryFormHydratedKeyRef.current === hydrateKey)
|
|
158
|
+
return;
|
|
159
|
+
deliveryFormHydratedKeyRef.current = hydrateKey;
|
|
160
|
+
reset({
|
|
161
|
+
...addressFormDefaultValues,
|
|
162
|
+
firstName: d.firstName ?? '',
|
|
163
|
+
lastName: d.lastName ?? '',
|
|
164
|
+
phone: d.phoneNumber ?? '',
|
|
165
|
+
street: d.streetName ?? d.fullAddress ?? '',
|
|
166
|
+
buildingNumber: d.buildingName ?? '',
|
|
167
|
+
apartmentNumber: d.apartmentNumber ?? '',
|
|
168
|
+
postalCode: d.postalCode ?? '',
|
|
169
|
+
province: d.administrativeAreaLevel1 ?? '',
|
|
170
|
+
district: d.administrativeAreaLevel2 ?? '',
|
|
171
|
+
savedDeliveryAddressId: d.id,
|
|
172
|
+
});
|
|
173
|
+
setAddressSearchQuery(formatAddressSummary(d));
|
|
174
|
+
}, [cart, cart?.deliveryAddress?.id, reset, setAddressSearchQuery]);
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
if (cart?.deliveryAddress?.id)
|
|
177
|
+
return;
|
|
178
|
+
if (!addressesPayload?.data?.length)
|
|
179
|
+
return;
|
|
180
|
+
const defaultAddress = pickDefaultDeliveryAddress(addressesPayload.data);
|
|
181
|
+
if (!defaultAddress)
|
|
182
|
+
return;
|
|
183
|
+
const hydrateKey = `saved:${defaultAddress.id}`;
|
|
184
|
+
if (deliveryFormHydratedKeyRef.current === hydrateKey)
|
|
185
|
+
return;
|
|
186
|
+
deliveryFormHydratedKeyRef.current = hydrateKey;
|
|
187
|
+
reset({
|
|
188
|
+
...addressFormDefaultValues,
|
|
189
|
+
firstName: defaultAddress.firstName ?? '',
|
|
190
|
+
lastName: defaultAddress.lastName ?? '',
|
|
191
|
+
phone: defaultAddress.phoneNumber ?? '',
|
|
192
|
+
street: defaultAddress.streetName ?? defaultAddress.fullAddress ?? '',
|
|
193
|
+
buildingNumber: defaultAddress.buildingName ?? '',
|
|
194
|
+
apartmentNumber: defaultAddress.apartmentNumber ?? '',
|
|
195
|
+
postalCode: defaultAddress.postalCode ?? '',
|
|
196
|
+
province: defaultAddress.administrativeAreaLevel1 ?? '',
|
|
197
|
+
district: defaultAddress.administrativeAreaLevel2 ?? '',
|
|
198
|
+
savedDeliveryAddressId: defaultAddress.id,
|
|
199
|
+
});
|
|
200
|
+
setAddressSearchQuery(formatAddressSummary(defaultAddress));
|
|
201
|
+
}, [addressesPayload?.data, cart?.deliveryAddress?.id, reset, setAddressSearchQuery]);
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (updateBasketMutation.isPending)
|
|
204
|
+
return;
|
|
205
|
+
if (!cart?.id || cart?.deliveryAddress?.id)
|
|
206
|
+
return;
|
|
207
|
+
if (!addressesPayload?.data?.length)
|
|
208
|
+
return;
|
|
209
|
+
const defaultAddress = pickDefaultDeliveryAddress(addressesPayload.data);
|
|
210
|
+
if (!defaultAddress?.id)
|
|
211
|
+
return;
|
|
212
|
+
const syncKey = `${cart.id}:${defaultAddress.id}`;
|
|
213
|
+
if (addressBasketSyncRef.current === syncKey)
|
|
214
|
+
return;
|
|
215
|
+
addressBasketSyncRef.current = syncKey;
|
|
216
|
+
updateBasketMutation.mutate({
|
|
217
|
+
id: cart.id,
|
|
218
|
+
deliveryAddressId: defaultAddress.id,
|
|
219
|
+
invoiceAddressId: defaultAddress.id,
|
|
220
|
+
});
|
|
221
|
+
}, [cart?.id, cart?.deliveryAddress?.id, addressesPayload?.data, updateBasketMutation.isPending, updateBasketMutation.mutate]);
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
const invoiceId = cart?.invoiceAddress?.id;
|
|
224
|
+
const deliveryId = cart?.deliveryAddress?.id;
|
|
225
|
+
if (!invoiceId || !deliveryId)
|
|
226
|
+
return;
|
|
227
|
+
if (invoiceId === deliveryId)
|
|
228
|
+
return;
|
|
229
|
+
setValue('billingAddressDifferent', true);
|
|
230
|
+
const matched = savedAddresses.find(a => a.id === invoiceId);
|
|
231
|
+
if (matched) {
|
|
232
|
+
setValue('savedBillingAddressId', matched.id);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const inv = cart.invoiceAddress;
|
|
236
|
+
setValue('billingFullName', inv.companyName ?? `${inv.firstName ?? ''} ${inv.lastName ?? ''}`.trim());
|
|
237
|
+
setValue('billingTaxNumber', inv.taxNumber ?? '');
|
|
238
|
+
setValue('billingProvince', inv.administrativeAreaLevel1 ?? '');
|
|
239
|
+
setValue('billingDistrict', inv.administrativeAreaLevel2 ?? '');
|
|
240
|
+
setValue('billingStreet', inv.streetName ?? inv.description ?? '');
|
|
241
|
+
}, [cart?.invoiceAddress?.id, cart?.deliveryAddress?.id, savedAddresses, setValue]);
|
|
242
|
+
const applyParsedAddressToForm = (fields) => {
|
|
243
|
+
setValue('street', fields.street);
|
|
244
|
+
setValue('buildingNumber', fields.buildingNumber);
|
|
245
|
+
setValue('apartmentNumber', fields.apartmentNumber);
|
|
246
|
+
setValue('postalCode', fields.postalCode);
|
|
247
|
+
setValue('province', fields.provinceName);
|
|
248
|
+
setValue('district', fields.districtName);
|
|
249
|
+
};
|
|
250
|
+
const handleSelectGoogleAddress = async (placeId) => {
|
|
251
|
+
clearErrors('addressSearch');
|
|
252
|
+
const prediction = addressSearchResults.find(r => r.place_id === placeId);
|
|
253
|
+
if (!prediction)
|
|
254
|
+
return;
|
|
255
|
+
const parsed = await selectAddressPlace(prediction);
|
|
256
|
+
if (!parsed) {
|
|
257
|
+
setError('addressSearch', { type: 'manual', message: 'Adres bilgileri alınamadı. Lütfen tekrar deneyin.' });
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
applyParsedAddressToForm(parsedAddressToFormFields(parsed));
|
|
261
|
+
setValue('savedDeliveryAddressId', '');
|
|
262
|
+
};
|
|
263
|
+
const handleAddressSearchQueryChange = (value) => {
|
|
264
|
+
onAddressSearchQueryChange(value);
|
|
265
|
+
clearErrors('addressSearch');
|
|
266
|
+
if (!value.trim()) {
|
|
267
|
+
resetAddressSearch();
|
|
268
|
+
setValue('street', '');
|
|
269
|
+
setValue('buildingNumber', '');
|
|
270
|
+
setValue('apartmentNumber', '');
|
|
271
|
+
setValue('postalCode', '');
|
|
272
|
+
setValue('province', '');
|
|
273
|
+
setValue('district', '');
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const handleSelectSavedAddress = (addr) => {
|
|
277
|
+
reset({
|
|
278
|
+
...getValues(),
|
|
279
|
+
firstName: addr.firstName ?? '',
|
|
280
|
+
lastName: addr.lastName ?? '',
|
|
281
|
+
phone: addr.phoneNumber ?? '',
|
|
282
|
+
street: addr.streetName ?? addr.fullAddress ?? '',
|
|
283
|
+
buildingNumber: addr.buildingName ?? '',
|
|
284
|
+
apartmentNumber: addr.apartmentNumber ?? '',
|
|
285
|
+
postalCode: addr.postalCode ?? '',
|
|
286
|
+
province: addr.administrativeAreaLevel1 ?? '',
|
|
287
|
+
district: addr.administrativeAreaLevel2 ?? '',
|
|
288
|
+
savedDeliveryAddressId: addr.id,
|
|
289
|
+
});
|
|
290
|
+
setAddressSearchQuery(formatAddressSummary(addr));
|
|
291
|
+
};
|
|
292
|
+
const handleSelectBillingAddress = (addr) => {
|
|
293
|
+
setValue('savedBillingAddressId', addr.id);
|
|
294
|
+
setValue('billingFullName', addr.companyName ?? `${addr.firstName ?? ''} ${addr.lastName ?? ''}`.trim());
|
|
295
|
+
setValue('billingTaxNumber', addr.taxNumber ?? '');
|
|
296
|
+
setValue('billingProvince', addr.administrativeAreaLevel1 ?? '');
|
|
297
|
+
setValue('billingDistrict', addr.administrativeAreaLevel2 ?? '');
|
|
298
|
+
setValue('billingStreet', addr.streetName ?? addr.fullAddress ?? '');
|
|
299
|
+
};
|
|
300
|
+
const buildDeliveryAddress = (data) => {
|
|
301
|
+
const fullAddr = [data.street, data.buildingNumber, data.apartmentNumber].filter(Boolean).join(', ');
|
|
302
|
+
const phoneDigits = data.phone.replace(/\D/g, '').replace(/^90/, '');
|
|
303
|
+
return {
|
|
304
|
+
title: 'Teslimat',
|
|
305
|
+
type: AddressType.DELIVERY,
|
|
306
|
+
firstName: data.firstName,
|
|
307
|
+
lastName: data.lastName,
|
|
308
|
+
phoneNumber: phoneDigits || data.phone,
|
|
309
|
+
postalCode: data.postalCode,
|
|
310
|
+
administrativeAreaLevel1: data.province.trim(),
|
|
311
|
+
administrativeAreaLevel2: data.district.trim(),
|
|
312
|
+
administrativeAreaLevel3: '',
|
|
313
|
+
fullAddress: fullAddr,
|
|
314
|
+
streetName: data.street,
|
|
315
|
+
buildingName: data.buildingNumber || null,
|
|
316
|
+
apartmentNumber: data.apartmentNumber || null,
|
|
317
|
+
country: 'Türkiye',
|
|
318
|
+
countryCode: 'TR',
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
const buildInvoiceAddress = (data) => {
|
|
322
|
+
const phoneDigits = data.phone.replace(/\D/g, '').replace(/^90/, '');
|
|
323
|
+
return {
|
|
324
|
+
title: 'Fatura',
|
|
325
|
+
type: AddressType.INVOICE,
|
|
326
|
+
companyName: data.billingFullName,
|
|
327
|
+
taxNumber: data.billingTaxNumber,
|
|
328
|
+
phoneNumber: phoneDigits || data.phone,
|
|
329
|
+
postalCode: data.postalCode,
|
|
330
|
+
administrativeAreaLevel1: data.billingProvince.trim(),
|
|
331
|
+
administrativeAreaLevel2: data.billingDistrict.trim(),
|
|
332
|
+
administrativeAreaLevel3: '',
|
|
333
|
+
fullAddress: data.billingStreet,
|
|
334
|
+
streetName: data.billingStreet,
|
|
335
|
+
country: 'Türkiye',
|
|
336
|
+
countryCode: 'TR',
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
const handleAddressSubmit = async (data) => {
|
|
340
|
+
if (!cart?.id)
|
|
341
|
+
return;
|
|
342
|
+
clearErrors('root');
|
|
343
|
+
try {
|
|
344
|
+
const deliveryAddressPayload = buildDeliveryAddress(data);
|
|
345
|
+
const useDeliveryId = data.savedDeliveryAddressId || null;
|
|
346
|
+
const useInvoiceId = data.billingAddressDifferent ? data.savedBillingAddressId || null : useDeliveryId;
|
|
347
|
+
const basketPayload = { id: cart.id };
|
|
348
|
+
if (useDeliveryId) {
|
|
349
|
+
basketPayload.deliveryAddressId = useDeliveryId;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
basketPayload.deliveryAddress = deliveryAddressPayload;
|
|
353
|
+
}
|
|
354
|
+
if (data.billingAddressDifferent) {
|
|
355
|
+
if (useInvoiceId) {
|
|
356
|
+
basketPayload.invoiceAddressId = useInvoiceId;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
basketPayload.invoiceAddress = buildInvoiceAddress(data);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
else if (useDeliveryId) {
|
|
363
|
+
basketPayload.invoiceAddressId = useDeliveryId;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
basketPayload.invoiceAddress = deliveryAddressPayload;
|
|
367
|
+
}
|
|
368
|
+
await updateBasketMutation.mutateAsync(basketPayload);
|
|
369
|
+
onComplete();
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
setError('root', { type: 'server', message: 'Adres kaydedilemedi. Lütfen bilgileri kontrol edip tekrar deneyin.' });
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
return (_jsxs("form", { onSubmit: handleSubmit(handleAddressSubmit), className: "space-y-6", children: [savedAddresses.length > 0 && (_jsxs("div", { children: [_jsx("label", { className: "rizzui-input-label block text-sm mb-1.5 font-medium", children: "\u00D6nerilen teslimat adresi" }), _jsxs("select", { value: savedDeliveryAddressId || (cart?.deliveryAddress?.id ?? ''), onChange: e => {
|
|
376
|
+
if (!e.target.value) {
|
|
377
|
+
setValue('savedDeliveryAddressId', '');
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const addr = savedAddresses.find(a => a.id === e.target.value);
|
|
381
|
+
if (addr)
|
|
382
|
+
handleSelectSavedAddress(addr);
|
|
383
|
+
}, className: "rizzui-input-container peer flex h-10 w-full items-center rounded-lg border border-gray-200 bg-white px-3.5 py-2 text-sm transition-all focus:border-[#CF0A2C] focus:outline-none focus:ring-2 focus:ring-[#CF0A2C]/25", children: [_jsx("option", { value: "", children: "Yeni adres girin" }), savedAddresses.map(addr => (_jsxs("option", { value: addr.id, children: [`${addr.firstName ?? ''} ${addr.lastName ?? ''}`.trim(), addr.administrativeAreaLevel2 ? ` — ${addr.administrativeAreaLevel2}, ${addr.administrativeAreaLevel1}` : ''] }, addr.id)))] })] })), _jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900 mb-1", children: "Teslimat adresi" }), _jsx("p", { className: "text-sm text-gray-500 mb-4", children: "Adresinizi aratarak h\u0131zl\u0131ca doldurabilir veya a\u015Fa\u011F\u0131daki alanlar\u0131 manuel girebilirsiniz." }), _jsx("div", { className: "mb-4", children: _jsx(AddressSearchInput, { query: addressSearchQuery, onQueryChange: handleAddressSearchQueryChange, results: addressSearchResults, isSearching: isAddressSearching, showResults: showAddressSearchResults, onShowResultsChange: setShowAddressSearchResults, onSelect: placeId => void handleSelectGoogleAddress(placeId), error: errors.addressSearch?.message, label: "Adres ara", placeholder: "Mahalle, cadde, sokak veya posta kodu yaz\u0131n\u2026", noResultsText: "Sonu\u00E7 bulunamad\u0131" }) }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Input, { ...register('firstName', { required: true }), label: "Ad", placeholder: "Ad", size: "lg", required: true, error: errors.firstName?.message }), _jsx(Input, { ...register('lastName', { required: true }), label: "Soyad", placeholder: "Soyad", size: "lg", required: true, error: errors.lastName?.message })] }), _jsx(Input, { ...register('street', { required: true }), label: "Mahalle, cadde, sokak vb.", placeholder: "Mahalle, cadde, sokak vb.", size: "lg", required: true, error: errors.street?.message }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Input, { ...register('buildingNumber'), label: "Apartman no", placeholder: "Apartman / bina no", size: "lg" }), _jsx(Input, { ...register('apartmentNumber'), label: "Daire no", placeholder: "Daire no", size: "lg" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Input, { ...register('postalCode', { required: true }), label: "Posta Kodu", placeholder: "Posta Kodu", size: "lg", required: true, error: errors.postalCode?.message }), _jsx(Input, { ...provinceField, onChange: e => {
|
|
384
|
+
provinceField.onChange(e);
|
|
385
|
+
setValue('savedDeliveryAddressId', '');
|
|
386
|
+
}, label: "\u0130l", placeholder: "\u0130l", size: "lg", required: true, error: errors.province?.message })] }), _jsx("div", { className: "grid grid-cols-2 gap-4", children: _jsx(Input, { ...districtField, onChange: e => {
|
|
387
|
+
districtField.onChange(e);
|
|
388
|
+
setValue('savedDeliveryAddressId', '');
|
|
389
|
+
}, label: "\u0130l\u00E7e", placeholder: "\u0130l\u00E7e", size: "lg", required: true, error: errors.district?.message }) }), _jsxs("div", { children: [_jsx("label", { className: "rizzui-input-label block text-sm mb-1.5 font-medium", children: "Telefon *" }), _jsxs("div", { className: "relative", children: [_jsxs("div", { className: "absolute left-3 top-1/2 -translate-y-1/2 flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-gray-700", children: "\uD83C\uDDF9\uD83C\uDDF7" }), _jsx("span", { className: "text-sm text-gray-700", children: "+90" })] }), _jsx(Input, { ...register('phone', { required: true }), type: "tel", placeholder: "Telefon", size: "lg", className: "pl-20", required: true, error: errors.phone?.message })] })] })] })] }), _jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900 mb-2", children: "Fatura adresi" }), _jsxs("div", { className: "flex items-start gap-2 mb-4", children: [_jsx("input", { type: "checkbox", id: "billingAddressDifferent", ...register('billingAddressDifferent'), className: "mt-1 h-4 w-4 rounded border-gray-300 text-[#CF0A2C] focus:ring-[#CF0A2C]" }), _jsx("label", { htmlFor: "billingAddressDifferent", className: "cursor-pointer text-sm text-gray-700", children: "Fatura adresi farkl\u0131 olsun" })] }), billingAddressDifferent && (_jsxs("div", { className: "mt-4 space-y-4 rounded-xl border border-gray-200 bg-white p-4", children: [savedAddresses.length > 0 && (_jsxs("div", { children: [_jsx("label", { className: "rizzui-input-label block text-sm mb-1.5 font-medium", children: "\u00D6nerilen fatura adresi" }), _jsxs("select", { value: savedBillingAddressId || (cart?.invoiceAddress?.id !== cart?.deliveryAddress?.id ? (cart?.invoiceAddress?.id ?? '') : ''), onChange: e => {
|
|
390
|
+
if (!e.target.value) {
|
|
391
|
+
setValue('savedBillingAddressId', '');
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const addr = savedAddresses.find(a => a.id === e.target.value);
|
|
395
|
+
if (addr)
|
|
396
|
+
handleSelectBillingAddress(addr);
|
|
397
|
+
}, className: "rizzui-input-container peer flex h-10 w-full items-center rounded-lg border border-gray-200 bg-white px-3.5 py-2 text-sm transition-all focus:border-[#CF0A2C] focus:outline-none focus:ring-2 focus:ring-[#CF0A2C]/25", children: [_jsx("option", { value: "", children: "Manuel girin" }), savedAddresses.map(addr => (_jsxs("option", { value: addr.id, children: [addr.companyName || `${addr.firstName ?? ''} ${addr.lastName ?? ''}`.trim(), addr.administrativeAreaLevel2 ? ` — ${addr.administrativeAreaLevel2}, ${addr.administrativeAreaLevel1}` : ''] }, addr.id)))] })] })), _jsx("p", { className: "text-sm text-gray-600", children: "Fatura bilgileri (\u015Fah\u0131s ad\u0131 veya firma unvan\u0131, vergi numaras\u0131 ve adres)" }), _jsx(Input, { ...register('billingFullName', {
|
|
398
|
+
required: billingAddressDifferent ? 'Ad / Firma adı zorunludur' : false,
|
|
399
|
+
}), label: "Ad / Firma ad\u0131", placeholder: "\u015Eah\u0131s i\u00E7in ad soyad, \u015Firket i\u00E7in firma unvan\u0131", size: "lg", required: billingAddressDifferent, error: errors.billingFullName?.message }), _jsx(Input, { ...register('billingTaxNumber', {
|
|
400
|
+
required: billingAddressDifferent ? 'Vergi numarası zorunludur' : false,
|
|
401
|
+
}), label: "Vergi numaras\u0131", placeholder: "10 veya 11 haneli vergi numaras\u0131", size: "lg", required: billingAddressDifferent, error: errors.billingTaxNumber?.message }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Input, { ...billingProvinceField, onChange: e => {
|
|
402
|
+
billingProvinceField.onChange(e);
|
|
403
|
+
setValue('savedBillingAddressId', '');
|
|
404
|
+
}, label: "\u0130l", placeholder: "\u0130l", size: "lg", required: billingAddressDifferent, error: errors.billingProvince?.message }), _jsx(Input, { ...billingDistrictField, onChange: e => {
|
|
405
|
+
billingDistrictField.onChange(e);
|
|
406
|
+
setValue('savedBillingAddressId', '');
|
|
407
|
+
}, label: "\u0130l\u00E7e", placeholder: "\u0130l\u00E7e", size: "lg", required: billingAddressDifferent, error: errors.billingDistrict?.message })] }), _jsx(Input, { ...register('billingStreet', {
|
|
408
|
+
required: billingAddressDifferent ? 'Açık adres zorunludur' : false,
|
|
409
|
+
}), label: "A\u00E7\u0131k adres", placeholder: "Mahalle, cadde, sokak, bina no, daire no", size: "lg", required: billingAddressDifferent, error: errors.billingStreet?.message })] }))] }), _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("input", { type: "checkbox", ...register('newsletter'), id: "newsletter", className: "mt-1 h-4 w-4 rounded border-gray-300 text-[#CF0A2C] focus:ring-[#CF0A2C]" }), _jsxs("label", { htmlFor: "newsletter", className: "text-sm text-gray-700 flex items-center gap-1", children: ["Beni haberlerden ve \u00F6zel tekliflerden haberdar et", _jsx(HelpCircle, { className: "w-4 h-4 text-gray-400" })] })] }), errors.root?.message ? _jsx("p", { className: "text-sm text-red-600", children: errors.root.message }) : null, _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row", children: [_jsx(Button, { type: "button", size: "lg", variant: "outline", className: "rounded-xl border-2 border-gray-200 font-semibold text-gray-900 hover:border-gray-900", onClick: onBack, children: "Geri" }), _jsx(Button, { type: "submit", size: "lg", className: "flex-1 rounded-xl bg-[#CF0A2C] font-semibold text-white hover:bg-[#a80824]", disabled: isSubmitting, children: isSubmitting ? 'Kaydediliyor…' : 'Devam et' })] })] }));
|
|
410
|
+
}
|
|
411
|
+
function ViewStepCheckout({ onBack }) {
|
|
412
|
+
const router = useRouter();
|
|
413
|
+
const { cart, cartLoading, paymentMethod, deliveryMethod, bankAccount } = useRaxon();
|
|
414
|
+
const [payStartError, setPayStartError] = useState(null);
|
|
415
|
+
const [bankTransferError, setBankTransferError] = useState(null);
|
|
416
|
+
const [selectedBankAccountId, setSelectedBankAccountId] = useState(null);
|
|
417
|
+
const paymentDefaultRef = useRef(false);
|
|
418
|
+
const deliveryDefaultRef = useRef(false);
|
|
419
|
+
const addressBasketSyncRef = useRef(false);
|
|
420
|
+
const updateBasketMutation = useCart().update();
|
|
421
|
+
const { data: addressesPayload, isLoading: addressesLoading } = useAddress().fetch();
|
|
422
|
+
const { mutateAsync: payMutation, isPending: payMutationPending } = useCart().pay();
|
|
423
|
+
const { mutateAsync: createTransferCode, isPending: transferCodePending } = useCart().createTransferCode();
|
|
424
|
+
const selectedPaymentMethod = paymentMethod.find(m => m.id === cart?.paymentMethod?.id);
|
|
425
|
+
const isBankTransfer = selectedPaymentMethod?.provider === PaymentProvider.BANK_TRANSFER &&
|
|
426
|
+
selectedPaymentMethod?.paymentTerms === PaymentTerms.BANK_TRANSFER;
|
|
427
|
+
const payAmount = cart?.info?.payPrice?.pay ?? 0;
|
|
428
|
+
const bankTransferCode = cart?.bankTransferCode;
|
|
429
|
+
const hasValidTransferCode = Boolean(bankTransferCode?.id) &&
|
|
430
|
+
bankTransferCode != null &&
|
|
431
|
+
Math.abs((bankTransferCode.amount ?? 0) - payAmount) < 0.01;
|
|
432
|
+
useEffect(() => {
|
|
433
|
+
void resolveClientIp();
|
|
434
|
+
}, []);
|
|
435
|
+
useEffect(() => {
|
|
436
|
+
setPayStartError(null);
|
|
437
|
+
setBankTransferError(null);
|
|
438
|
+
if (!isBankTransfer) {
|
|
439
|
+
setSelectedBankAccountId(null);
|
|
440
|
+
}
|
|
441
|
+
}, [cart?.paymentMethod?.id, isBankTransfer]);
|
|
442
|
+
useEffect(() => {
|
|
443
|
+
if (!isBankTransfer)
|
|
444
|
+
return;
|
|
445
|
+
if (bankTransferCode?.bankAccount?.id) {
|
|
446
|
+
setSelectedBankAccountId(bankTransferCode.bankAccount.id);
|
|
447
|
+
}
|
|
448
|
+
}, [isBankTransfer, bankTransferCode?.bankAccount?.id]);
|
|
449
|
+
const handleBankAccountSelect = async (account) => {
|
|
450
|
+
if (!isBankTransfer || !cart?.id || transferCodePending || updateBasketMutation.isPending)
|
|
451
|
+
return;
|
|
452
|
+
setSelectedBankAccountId(account.id);
|
|
453
|
+
setBankTransferError(null);
|
|
454
|
+
if (hasValidTransferCode &&
|
|
455
|
+
bankTransferCode?.bankAccount?.id === account.id) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
try {
|
|
459
|
+
const code = await createTransferCode({
|
|
460
|
+
amount: payAmount,
|
|
461
|
+
bankAccountId: account.id,
|
|
462
|
+
});
|
|
463
|
+
await updateBasketMutation.mutateAsync({
|
|
464
|
+
id: cart.id,
|
|
465
|
+
bankTransferCodeId: code.id,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
setBankTransferError('Transfer kodu oluşturulamadı. Lütfen tekrar deneyin.');
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
useEffect(() => {
|
|
473
|
+
paymentDefaultRef.current = false;
|
|
474
|
+
deliveryDefaultRef.current = false;
|
|
475
|
+
addressBasketSyncRef.current = false;
|
|
476
|
+
}, [cart?.id]);
|
|
477
|
+
const savedAddresses = addressesPayload?.data ?? [];
|
|
478
|
+
const defaultSavedAddress = savedAddresses.length ? pickDefaultDeliveryAddress(savedAddresses) : undefined;
|
|
479
|
+
useEffect(() => {
|
|
480
|
+
if (updateBasketMutation.isPending)
|
|
481
|
+
return;
|
|
482
|
+
if (!cart?.id || cart?.deliveryAddress?.id)
|
|
483
|
+
return;
|
|
484
|
+
if (!defaultSavedAddress?.id)
|
|
485
|
+
return;
|
|
486
|
+
if (addressBasketSyncRef.current)
|
|
487
|
+
return;
|
|
488
|
+
addressBasketSyncRef.current = true;
|
|
489
|
+
updateBasketMutation.mutate({
|
|
490
|
+
id: cart.id,
|
|
491
|
+
deliveryAddressId: defaultSavedAddress.id,
|
|
492
|
+
invoiceAddressId: defaultSavedAddress.id,
|
|
493
|
+
});
|
|
494
|
+
}, [cart?.id, cart?.deliveryAddress?.id, defaultSavedAddress?.id, updateBasketMutation.isPending, updateBasketMutation.mutate]);
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
if (updateBasketMutation.isPending)
|
|
497
|
+
return;
|
|
498
|
+
if (!cart?.id)
|
|
499
|
+
return;
|
|
500
|
+
const list = paymentMethod;
|
|
501
|
+
if (!list?.length || paymentDefaultRef.current)
|
|
502
|
+
return;
|
|
503
|
+
if (cart?.paymentMethod?.id) {
|
|
504
|
+
paymentDefaultRef.current = true;
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
paymentDefaultRef.current = true;
|
|
508
|
+
updateBasketMutation.mutate({ id: cart.id, paymentMethodId: list[0].id });
|
|
509
|
+
}, [paymentMethod, cart?.id, cart?.paymentMethod?.id, updateBasketMutation.isPending, updateBasketMutation.mutate]);
|
|
510
|
+
useEffect(() => {
|
|
511
|
+
if (updateBasketMutation.isPending)
|
|
512
|
+
return;
|
|
513
|
+
if (!cart?.id)
|
|
514
|
+
return;
|
|
515
|
+
const list = deliveryMethod;
|
|
516
|
+
if (!list?.length || deliveryDefaultRef.current)
|
|
517
|
+
return;
|
|
518
|
+
if (cart?.deliveryMethod?.id) {
|
|
519
|
+
deliveryDefaultRef.current = true;
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
deliveryDefaultRef.current = true;
|
|
523
|
+
updateBasketMutation.mutate({ id: cart.id, deliveryMethodId: list[0].id });
|
|
524
|
+
}, [deliveryMethod, cart?.id, cart?.deliveryMethod?.id, updateBasketMutation.isPending, updateBasketMutation.mutate]);
|
|
525
|
+
const delivery = cart?.deliveryAddress ?? defaultSavedAddress ?? undefined;
|
|
526
|
+
const invoice = cart?.invoiceAddress;
|
|
527
|
+
const invoiceSameAsDelivery = delivery?.id && invoice?.id === delivery.id;
|
|
528
|
+
const deliveryLine = delivery ? formatAddressLine(delivery) : null;
|
|
529
|
+
const invoiceLine = invoice && !invoiceSameAsDelivery ? formatAddressLine(invoice) : null;
|
|
530
|
+
const isAddressLoading = !deliveryLine && (cartLoading || addressesLoading || updateBasketMutation.isPending);
|
|
531
|
+
const paymentBlockers = useMemo(() => {
|
|
532
|
+
const blockers = [];
|
|
533
|
+
if (cartLoading) {
|
|
534
|
+
blockers.push('Sepet yükleniyor…');
|
|
535
|
+
return blockers;
|
|
536
|
+
}
|
|
537
|
+
if (!cart?.email?.trim()) {
|
|
538
|
+
blockers.push('E-posta adresi girilmedi.');
|
|
539
|
+
}
|
|
540
|
+
if (!cart?.deliveryAddress) {
|
|
541
|
+
if (isAddressLoading) {
|
|
542
|
+
blockers.push('Teslimat adresi hazırlanıyor…');
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
blockers.push('Teslimat adresi eklenmedi.');
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (paymentMethod.length === 0) {
|
|
549
|
+
blockers.push('Ödeme yöntemi bulunamadı.');
|
|
550
|
+
}
|
|
551
|
+
else if (!cart?.paymentMethod?.id) {
|
|
552
|
+
blockers.push('Ödeme yöntemi seçin.');
|
|
553
|
+
}
|
|
554
|
+
if (deliveryMethod.length === 0) {
|
|
555
|
+
blockers.push('Teslimat yöntemi bulunamadı.');
|
|
556
|
+
}
|
|
557
|
+
else if (!cart?.deliveryMethod?.id) {
|
|
558
|
+
blockers.push('Teslimat yöntemi seçin.');
|
|
559
|
+
}
|
|
560
|
+
if (isBankTransfer) {
|
|
561
|
+
if (bankAccount.length === 0) {
|
|
562
|
+
blockers.push('Havale için tanımlı banka hesabı bulunamadı.');
|
|
563
|
+
}
|
|
564
|
+
else if (!hasValidTransferCode) {
|
|
565
|
+
if (!selectedBankAccountId && !bankTransferCode?.bankAccount?.id) {
|
|
566
|
+
blockers.push('Devam etmek için bir banka hesabı seçin.');
|
|
567
|
+
}
|
|
568
|
+
else if (transferCodePending || updateBasketMutation.isPending) {
|
|
569
|
+
blockers.push('Transfer kodu hazırlanıyor…');
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
blockers.push('Transfer kodu oluşturulamadı. Banka hesabını tekrar seçin.');
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return blockers;
|
|
577
|
+
}, [
|
|
578
|
+
cart?.email,
|
|
579
|
+
cart?.deliveryAddress,
|
|
580
|
+
cart?.paymentMethod?.id,
|
|
581
|
+
cart?.deliveryMethod?.id,
|
|
582
|
+
cartLoading,
|
|
583
|
+
isAddressLoading,
|
|
584
|
+
paymentMethod.length,
|
|
585
|
+
deliveryMethod.length,
|
|
586
|
+
isBankTransfer,
|
|
587
|
+
bankAccount.length,
|
|
588
|
+
hasValidTransferCode,
|
|
589
|
+
selectedBankAccountId,
|
|
590
|
+
bankTransferCode?.bankAccount?.id,
|
|
591
|
+
transferCodePending,
|
|
592
|
+
updateBasketMutation.isPending,
|
|
593
|
+
]);
|
|
594
|
+
const canCompletePayment = paymentBlockers.length === 0;
|
|
595
|
+
const isPaymentButtonDisabled = !canCompletePayment || payMutationPending || transferCodePending;
|
|
596
|
+
const handlePaymentSubmit = async () => {
|
|
597
|
+
if (!canCompletePayment)
|
|
598
|
+
return;
|
|
599
|
+
setPayStartError(null);
|
|
600
|
+
try {
|
|
601
|
+
const payReturnUrl = `${window.location.origin}/sepet/odeme/sonuc`;
|
|
602
|
+
const paymentResponse = await payMutation({ platform: 'web', webReturnUrl: payReturnUrl });
|
|
603
|
+
const ok = paymentResponse && typeof paymentResponse === 'object' && 'status' in paymentResponse && paymentResponse.status === true;
|
|
604
|
+
const info = paymentResponse && typeof paymentResponse === 'object' && 'info' in paymentResponse && paymentResponse.info && typeof paymentResponse.info === 'object'
|
|
605
|
+
? paymentResponse.info
|
|
606
|
+
: null;
|
|
607
|
+
if (isBankTransfer) {
|
|
608
|
+
const orderId = info && typeof info.orderId === 'string' ? info.orderId : null;
|
|
609
|
+
if (ok && orderId) {
|
|
610
|
+
router.push(`/hesabim/siparislerim/${orderId}`);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
setPayStartError('Sipariş oluşturulamadı. Lütfen tekrar deneyin.');
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const provider = info && typeof info.provider === 'string' ? info.provider : null;
|
|
617
|
+
const garantiHtml = info && typeof info.html === 'string' ? info.html : null;
|
|
618
|
+
const garantiTransactionId = info && typeof info.transactionId === 'string' ? info.transactionId : null;
|
|
619
|
+
if (ok && provider === PaymentProvider.GARANTI && garantiHtml && garantiTransactionId) {
|
|
620
|
+
storeGarantiPaymentHtml(garantiTransactionId, garantiHtml);
|
|
621
|
+
router.push(`/sepet/odeme/pay?provider=garanti&transactionId=${encodeURIComponent(garantiTransactionId)}`);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
const token = info && typeof info.token === 'string' ? info.token : null;
|
|
625
|
+
if (ok && token) {
|
|
626
|
+
router.push(`/sepet/odeme/pay?token=${encodeURIComponent(token)}`);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
setPayStartError('Ödeme ekranı açılamadı. Lütfen tekrar deneyin.');
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
catch {
|
|
633
|
+
setPayStartError('Ödeme başlatılırken bir hata oluştu.');
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900", children: "Sipari\u015F \u00F6zeti" }), _jsx("p", { className: "mt-1 text-sm text-gray-500", children: "Adres bilgilerinizi kontrol edin ve \u00F6deme y\u00F6ntemini se\u00E7in." })] }), isAddressLoading ? (_jsx("p", { className: "text-sm text-gray-500", children: "Sepet g\u00FCncelleniyor\u2026" })) : !deliveryLine ? (_jsx("p", { className: "text-sm text-amber-700 rounded-xl border border-amber-200 bg-amber-50 p-4", children: "Teslimat adresi hen\u00FCz eklenmedi." })) : (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4 space-y-1", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-[#CF0A2C]", children: "Teslimat adresi" }), _jsx("p", { className: "text-sm font-medium text-gray-900", children: deliveryLine.name }), _jsx("p", { className: "text-sm text-gray-600", children: deliveryLine.street }), _jsx("p", { className: "text-sm text-gray-600", children: [deliveryLine.location, deliveryLine.postalCode].filter(Boolean).join(' · ') })] })), invoiceLine ? (_jsxs("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4 space-y-1", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-[#CF0A2C]", children: "Fatura adresi" }), _jsx("p", { className: "text-sm font-medium text-gray-900", children: invoiceLine.name }), invoiceLine.taxNumber ? _jsxs("p", { className: "text-sm text-gray-600", children: ["VKN: ", invoiceLine.taxNumber] }) : null, _jsx("p", { className: "text-sm text-gray-600", children: invoiceLine.street }), _jsx("p", { className: "text-sm text-gray-600", children: [invoiceLine.location, invoiceLine.postalCode].filter(Boolean).join(' · ') })] })) : deliveryLine ? (_jsx("p", { className: "text-sm text-gray-500", children: "Fatura adresi teslimat adresi ile ayn\u0131." })) : null, _jsxs("div", { className: "rounded-xl border border-gray-100 bg-white p-4 space-y-2", children: [_jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Ara toplam" }), _jsx("span", { className: "font-semibold tabular-nums", children: (cart?.info?.basePrice?.total ?? 0).toTry() })] }), (cart?.info?.delivery?.pay ?? 0) > 0 ? (_jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Kargo" }), _jsx("span", { className: "font-semibold tabular-nums", children: cart?.info?.delivery?.pay?.toTry() })] })) : null, _jsxs("div", { className: "flex justify-between border-t border-gray-100 pt-2 text-sm", children: [_jsx("span", { className: "font-semibold text-gray-900", children: "Toplam" }), _jsx("span", { className: "font-bold tabular-nums text-[#CF0A2C]", children: (cart?.info?.payPrice?.pay ?? 0).toTry() })] })] }), _jsxs("div", { className: "border-t border-gray-100 pt-6", children: [_jsx("h2", { className: "text-base font-semibold text-gray-900 mb-3", children: "Teslimat y\u00F6ntemi" }), _jsx("div", { className: "space-y-2", children: deliveryMethod.map((method) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-gray-100 bg-white p-4 shadow-sm transition-colors hover:border-gray-200 has-[:checked]:border-[#CF0A2C] has-[:checked]:ring-2 has-[:checked]:ring-[#CF0A2C]/20", children: [_jsx("input", { type: "radio", name: "deliveryMethod", value: method.id, checked: cart?.deliveryMethod?.id === method.id, onChange: () => cart?.id && updateBasketMutation.mutate({ id: cart.id, deliveryMethodId: method.id }), disabled: updateBasketMutation.isPending, className: "mt-0.5 h-4 w-4 shrink-0 border-gray-300 text-[#CF0A2C] focus:ring-[#CF0A2C]" }), _jsx("span", { className: "flex flex-col gap-0.5 min-w-0", children: _jsx("span", { className: "text-sm font-medium text-gray-900", children: method.name }) })] }, method.id))) })] }), _jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900 mb-3", children: "\u00D6deme y\u00F6ntemi" }), _jsx("div", { className: "space-y-2", children: paymentMethod.map((method) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-gray-100 bg-white p-4 shadow-sm transition-colors hover:border-gray-200 has-[:checked]:border-[#CF0A2C] has-[:checked]:ring-2 has-[:checked]:ring-[#CF0A2C]/20", children: [_jsx("input", { type: "radio", name: "payment", value: method.id, checked: cart?.paymentMethod?.id === method.id, onChange: () => cart?.id && updateBasketMutation.mutate({ id: cart.id, paymentMethodId: method.id }), disabled: updateBasketMutation.isPending, className: "mt-0.5 h-4 w-4 shrink-0 border-gray-300 text-[#CF0A2C] focus:ring-[#CF0A2C]" }), _jsxs("span", { className: "flex flex-col gap-0.5 min-w-0", children: [_jsx("span", { className: "text-sm font-medium text-gray-900", children: method.name }), method.description ? _jsx("span", { className: "text-xs text-gray-600", children: method.description }) : null] })] }, method.id))) })] }), isBankTransfer ? (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-base font-semibold text-gray-900 mb-3", children: "Banka hesab\u0131" }), bankAccount.length === 0 ? (_jsx("p", { className: "text-sm text-amber-700 rounded-xl border border-amber-200 bg-amber-50 p-4", children: "Havale i\u00E7in tan\u0131ml\u0131 banka hesab\u0131 bulunamad\u0131." })) : (_jsx("div", { className: "space-y-2", children: bankAccount.map((account) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-gray-100 bg-white p-4 shadow-sm transition-colors hover:border-gray-200 has-[:checked]:border-[#CF0A2C] has-[:checked]:ring-2 has-[:checked]:ring-[#CF0A2C]/20", children: [_jsx("input", { type: "radio", name: "bankAccount", value: account.id, checked: selectedBankAccountId === account.id, onChange: () => void handleBankAccountSelect(account), disabled: transferCodePending || updateBasketMutation.isPending, className: "mt-0.5 h-4 w-4 shrink-0 border-gray-300 text-[#CF0A2C] focus:ring-[#CF0A2C]" }), _jsxs("span", { className: "flex flex-col gap-0.5 min-w-0", children: [_jsx("span", { className: "text-sm font-medium text-gray-900", children: account.bankName }), account.accountHolderName ? (_jsx("span", { className: "text-xs text-gray-600", children: account.accountHolderName })) : null, account.IBAN && account.IBAN !== '-' ? (_jsx("span", { className: "text-xs font-mono text-gray-500", children: account.IBAN })) : null] })] }, account.id))) }))] }), transferCodePending || updateBasketMutation.isPending ? (_jsx("p", { className: "text-sm text-gray-500", children: "Transfer kodu haz\u0131rlan\u0131yor\u2026" })) : null, bankTransferError ? (_jsx("p", { className: "text-sm text-red-600", role: "alert", children: bankTransferError })) : null, hasValidTransferCode && bankTransferCode ? (_jsxs("div", { className: "rounded-xl border border-[#CF0A2C]/20 bg-[#CF0A2C]/5 p-4 space-y-3", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-[#CF0A2C]", children: "Havale bilgileri" }), _jsxs("div", { className: "space-y-2 text-sm", children: [_jsxs("div", { children: [_jsx("p", { className: "text-gray-500", children: "Banka" }), _jsx("p", { className: "font-medium text-gray-900", children: bankTransferCode.bankAccount.bankName })] }), bankTransferCode.bankAccount.IBAN && bankTransferCode.bankAccount.IBAN !== '-' ? (_jsxs("div", { children: [_jsx("p", { className: "text-gray-500", children: "IBAN" }), _jsx("p", { className: "font-mono font-medium text-gray-900", children: bankTransferCode.bankAccount.IBAN })] })) : null, bankTransferCode.bankAccount.accountHolderName ? (_jsxs("div", { children: [_jsx("p", { className: "text-gray-500", children: "Al\u0131c\u0131 ad\u0131" }), _jsx("p", { className: "font-medium text-gray-900", children: bankTransferCode.bankAccount.accountHolderName })] })) : null, _jsxs("div", { children: [_jsx("p", { className: "text-gray-500", children: "Tutar" }), _jsx("p", { className: "font-bold tabular-nums text-[#CF0A2C]", children: (bankTransferCode.amount ?? 0).toTry() })] }), _jsxs("div", { className: "rounded-lg bg-white p-3 border border-[#CF0A2C]/20", children: [_jsx("p", { className: "text-xs text-gray-500", children: "Transfer kodu (a\u00E7\u0131klama alan\u0131na yaz\u0131n)" }), _jsx("p", { className: "text-lg font-black tracking-wider text-[#CF0A2C]", children: bankTransferCode.code })] })] }), _jsx("p", { className: "text-xs text-gray-600", children: "Havaleyi yapt\u0131ktan sonra \"Sipari\u015Fi tamamla\" butonuna bas\u0131n. \u00D6demeniz onayland\u0131\u011F\u0131nda sipari\u015Finiz i\u015Fleme al\u0131n\u0131r." })] })) : isBankTransfer && bankAccount.length > 0 ? (_jsx("p", { className: "text-sm text-gray-500", children: "Devam etmek i\u00E7in bir banka hesab\u0131 se\u00E7in." })) : null] })) : null, payStartError && (_jsx("p", { className: "text-sm text-red-600", role: "alert", children: payStartError })), paymentBlockers.length > 0 && !payMutationPending ? (_jsxs("div", { className: "rounded-xl border border-red-200 bg-red-50 p-4", role: "alert", children: [_jsx("p", { className: "text-sm font-medium text-red-800", children: "\u00D6deme tamamlanam\u0131yor:" }), _jsx("ul", { className: "mt-1.5 list-inside list-disc space-y-0.5 text-sm text-red-600", children: paymentBlockers.map(message => (_jsx("li", { children: message }, message))) })] })) : null, _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row", children: [_jsx(Button, { type: "button", size: "lg", variant: "outline", className: "rounded-xl border-2 border-gray-200 font-semibold text-gray-900 hover:border-gray-900", onClick: onBack, children: "Geri" }), _jsx(Button, { type: "button", size: "lg", className: `flex-1 rounded-xl font-black uppercase tracking-widest shadow-md ${isPaymentButtonDisabled
|
|
637
|
+
? 'cursor-not-allowed bg-gray-300 text-gray-500 hover:bg-gray-300 hover:shadow-md'
|
|
638
|
+
: 'bg-[#CF0A2C] text-white hover:bg-[#a80824] hover:shadow-lg'}`, onClick: handlePaymentSubmit, disabled: isPaymentButtonDisabled, children: payMutationPending ? 'Yönlendiriliyor…' : isBankTransfer ? 'Siparişi tamamla' : 'Ödemeyi tamamla' })] })] }));
|
|
639
|
+
}
|
|
640
|
+
const CHECKOUT_STEP_LABELS = {
|
|
641
|
+
contact: 'İletişim',
|
|
642
|
+
address: 'Adres',
|
|
643
|
+
checkout: 'Önizleme ve ödeme',
|
|
644
|
+
};
|
|
645
|
+
export default function PaymentPage() {
|
|
646
|
+
const { cart, branch } = useRaxon();
|
|
647
|
+
const [checkoutStep, setCheckoutStep] = useState('contact');
|
|
648
|
+
const [confirmedContactEmail, setConfirmedContactEmail] = useState('');
|
|
649
|
+
useEffect(() => {
|
|
650
|
+
const fromCart = cart?.email?.trim() || '';
|
|
651
|
+
if (fromCart)
|
|
652
|
+
setConfirmedContactEmail(fromCart);
|
|
653
|
+
}, [cart?.email]);
|
|
654
|
+
useEffect(() => {
|
|
655
|
+
const hasContactEmail = Boolean(cart?.email?.trim() || confirmedContactEmail);
|
|
656
|
+
if (!hasContactEmail && checkoutStep !== 'contact') {
|
|
657
|
+
setCheckoutStep('contact');
|
|
658
|
+
}
|
|
659
|
+
}, [cart?.email, confirmedContactEmail, checkoutStep]);
|
|
660
|
+
useEffect(() => {
|
|
661
|
+
const handleLoginSuccess = () => window.location.reload();
|
|
662
|
+
window.addEventListener(LOGIN_SUCCESS_EVENT, handleLoginSuccess);
|
|
663
|
+
return () => window.removeEventListener(LOGIN_SUCCESS_EVENT, handleLoginSuccess);
|
|
664
|
+
}, []);
|
|
665
|
+
return (_jsxs("div", { className: "min-h-screen overflow-x-hidden bg-gray-50", children: [_jsx("header", { className: "border-b border-gray-100 bg-white", children: _jsxs("div", { className: "mx-auto flex max-w-7xl items-center justify-between px-4 py-5 sm:px-6 lg:px-8", children: [_jsx(Link, { href: "/", className: "flex flex-col items-start gap-1", children: _jsx(GeneralImage, { quality: 85, src: branch?.logoMedia?.relativePath ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${branch.logoMedia.relativePath}` : '', alt: branch?.tradingName ?? 'Logo', width: 120, height: 36, className: "h-7 w-auto object-contain" }) }), _jsx(Link, { href: "/sepet", className: "text-xs font-black uppercase tracking-widest text-gray-900 transition-colors hover:text-[#CF0A2C]", children: "Sepete d\u00F6n" })] }) }), _jsx("div", { className: "mx-auto max-w-7xl px-4 py-10 sm:px-6 sm:py-14 lg:px-8", children: _jsxs("div", { className: "grid grid-cols-1 gap-10 lg:grid-cols-[2fr_1fr] lg:gap-14", children: [_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-6 shadow-sm sm:p-8", children: [_jsx("nav", { className: "mb-8 flex flex-wrap gap-2", "aria-label": "\u00D6deme ad\u0131mlar\u0131", children: ['contact', 'address', 'checkout'].map((step, index) => {
|
|
666
|
+
const stepOrder = ['contact', 'address', 'checkout'].indexOf(checkoutStep);
|
|
667
|
+
const isActive = checkoutStep === step;
|
|
668
|
+
const isDone = index < stepOrder;
|
|
669
|
+
return (_jsxs("span", { className: `rounded-full px-3 py-1 text-xs font-semibold ${isActive
|
|
670
|
+
? 'bg-[#CF0A2C] text-white'
|
|
671
|
+
: isDone
|
|
672
|
+
? 'bg-[#CF0A2C]/10 text-[#CF0A2C]'
|
|
673
|
+
: 'bg-gray-100 text-gray-500'}`, children: [index + 1, ". ", CHECKOUT_STEP_LABELS[step]] }, step));
|
|
674
|
+
}) }), checkoutStep === 'contact' && (_jsx(ViewStep1, { onContinue: email => {
|
|
675
|
+
setConfirmedContactEmail(email);
|
|
676
|
+
setCheckoutStep('address');
|
|
677
|
+
} })), checkoutStep === 'address' && (_jsx(ViewStep2, { onComplete: () => setCheckoutStep('checkout'), onBack: () => setCheckoutStep('contact') })), checkoutStep === 'checkout' && _jsx(ViewStepCheckout, { onBack: () => setCheckoutStep('address') })] }), _jsx("div", { children: _jsxs("div", { className: "sticky top-8 rounded-2xl border border-gray-100 bg-white p-6 shadow-sm lg:top-24 lg:p-8", children: [_jsx("span", { className: "text-sm font-black text-[#CF0A2C] uppercase tracking-widest", children: "\u00D6zet" }), _jsx("h2", { className: "mt-2 text-xl font-black text-gray-900 uppercase tracking-tighter", children: "Sipari\u015F \u00F6zeti" }), _jsx("div", { className: "my-6 space-y-5", children: cart?.items?.map(item => {
|
|
678
|
+
const linePay = item.linePay ?? 0;
|
|
679
|
+
const listGross = (item.lineTotal ?? 0) + (item.lineTax ?? 0);
|
|
680
|
+
const showListStrike = listGross - linePay > 0.01;
|
|
681
|
+
const variantLine = formatBasketItemVariantLine(item);
|
|
682
|
+
return (_jsxs("div", { className: "flex gap-4", children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx("img", { src: item.images?.[0] ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${item.images[0]}` : 'https://placehold.co/80x80/f3f4f6/9ca3af?text=Ürün', alt: item.product.name, className: "h-20 w-20 rounded-xl border border-gray-100 object-cover" }), _jsx("div", { className: "absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-[#CF0A2C] text-[11px] font-black text-white shadow-sm", children: item.quantity })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h3", { className: "text-sm font-medium text-gray-900", children: item.product.name }), variantLine ? (_jsx("p", { className: "mt-1 text-xs text-gray-500", children: variantLine })) : null, _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [showListStrike ? (_jsx("span", { className: "text-xs text-gray-400 line-through tabular-nums", children: listGross.toTry() })) : null, _jsx("span", { className: "text-sm font-bold tabular-nums text-[#CF0A2C]", children: linePay.toTry() })] })] })] }, item.id));
|
|
683
|
+
}) }), _jsxs("div", { className: "space-y-3 border-t border-gray-100 pt-5", children: [_jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsxs("span", { className: "flex items-center gap-1 text-gray-600", children: ["Ara toplam", _jsx(HelpCircle, { className: "h-4 w-4 text-gray-400" })] }), _jsx("span", { className: "font-semibold tabular-nums text-gray-900", children: (cart?.info?.basePrice?.total ?? 0).toTry() })] }), cart?.info?.tax && cart.info.tax.length > 0 ? (_jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "KDV" }), _jsx("span", { className: "font-semibold tabular-nums text-gray-900", children: cart.info.tax.reduce((acc, curr) => acc + curr.tax, 0).toTry() })] })) : null, (cart?.info?.delivery?.pay ?? 0) > 0 ? (_jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsx("span", { className: "text-gray-600", children: "Kargo" }), _jsx("span", { className: "font-semibold tabular-nums text-gray-900", children: cart?.info?.delivery?.pay?.toTry() })] })) : null, (cart?.info?.discount?.pay ?? 0) > 0 ? (_jsxs("div", { className: "flex items-center justify-between text-sm", children: [_jsx("span", { className: "font-bold text-[#CF0A2C]", children: "\u0130ndirim" }), _jsxs("span", { className: "font-semibold tabular-nums text-[#CF0A2C]", children: ["-", cart?.info?.discount?.pay?.toTry()] })] })) : null, _jsxs("div", { className: "flex flex-col gap-2 pt-1", children: [_jsx(CartPromoCodeSection, { variant: "checkout" }), _jsx("button", { type: "button", className: "text-left text-xs font-black uppercase tracking-widest text-gray-600 underline-offset-2 transition-colors hover:text-[#CF0A2C] hover:underline", children: "Sipari\u015F notu ekle" })] }), _jsxs("div", { className: "flex items-center justify-between border-t border-gray-100 pt-5", children: [_jsx("span", { className: "text-sm font-black uppercase tracking-widest text-gray-900", children: "Toplam" }), _jsx("span", { className: "text-xl font-black tabular-nums text-[#CF0A2C]", children: (cart?.info?.payPrice?.pay ?? 0).toTry() })] })] })] }) })] }) })] }));
|
|
684
|
+
}
|