@raxonltd/raxon-core 1.0.4 → 1.0.8
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/feature/analytic-event/analytic.event.api.d.ts +13 -0
- package/dist/core/feature/analytic-event/analytic.event.api.d.ts.map +1 -0
- package/dist/core/feature/analytic-event/analytic.event.api.js +10 -0
- package/dist/core/feature/analytic-event/analytic.event.context.d.ts +8 -5
- package/dist/core/feature/analytic-event/analytic.event.context.d.ts.map +1 -1
- package/dist/core/feature/analytic-event/analytic.event.context.js +58 -84
- package/dist/core/feature/analytic-event/analytic.event.util.d.ts +8 -0
- package/dist/core/feature/analytic-event/analytic.event.util.d.ts.map +1 -0
- package/dist/core/feature/analytic-event/analytic.event.util.js +39 -0
- package/dist/core/feature/analytic-event/use.analytic.auto.d.ts +13 -0
- package/dist/core/feature/analytic-event/use.analytic.auto.d.ts.map +1 -0
- package/dist/core/feature/analytic-event/use.analytic.auto.js +81 -0
- package/dist/core/raxon.context.d.ts +3 -1
- package/dist/core/raxon.context.d.ts.map +1 -1
- package/dist/core/raxon.context.js +11 -12
- package/dist/core/util/nexine.axios.js +22 -0
- package/dist/core/view/view.checkout.d.ts +5 -1
- package/dist/core/view/view.checkout.d.ts.map +1 -1
- package/dist/core/view/view.checkout.js +265 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
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';
|
|
4
|
+
import { useRouter, useSearchParams } from 'next/navigation';
|
|
5
|
+
import { CheckCircle2, HelpCircle, Loader2, Package, XCircle } from 'lucide-react';
|
|
6
|
+
import { useState, useRef, useEffect, useMemo, useCallback, Suspense, createContext, useContext } from 'react';
|
|
7
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
7
8
|
import { useForm } from 'react-hook-form';
|
|
8
9
|
import { Input } from 'rizzui/input';
|
|
9
10
|
import { Button } from 'rizzui/button';
|
|
@@ -17,8 +18,10 @@ import { AddressSearchInput } from '../feature/address/form/address-search-input
|
|
|
17
18
|
import { formatAddressSummary, parsedAddressToFormFields } from '../feature/address/util/parse-google-place';
|
|
18
19
|
import { formatBasketItemVariantLine } from '../util/basket.item.display';
|
|
19
20
|
import { GeneralImage } from '../component/general.image';
|
|
20
|
-
import { AddressType, PaymentProvider, PaymentTerms } from '../interface/prisma.interface';
|
|
21
|
-
import { storeGarantiPaymentHtml } from '../util/garanti-payment';
|
|
21
|
+
import { AddressType, PaymentProvider, PaymentTerms, Status } from '../interface/prisma.interface';
|
|
22
|
+
import { consumeGarantiPaymentHtml, storeGarantiPaymentHtml, submitGarantiPaymentHtml } from '../util/garanti-payment';
|
|
23
|
+
import { useOrder } from '../feature/order/hook/use.order';
|
|
24
|
+
import { nexineAxios } from '../util/nexine.axios';
|
|
22
25
|
import { resolveClientIp } from '../util/client-ip';
|
|
23
26
|
import { CartPromoCodeSection } from '../feature/cart/component/cart.promo.code.section';
|
|
24
27
|
const addressFormDefaultValues = {
|
|
@@ -42,6 +45,23 @@ const addressFormDefaultValues = {
|
|
|
42
45
|
savedBillingAddressId: '',
|
|
43
46
|
addressSearch: '',
|
|
44
47
|
};
|
|
48
|
+
const CheckoutViewContext = createContext({
|
|
49
|
+
webReturnUrl: '/sepet/odeme',
|
|
50
|
+
});
|
|
51
|
+
function useCheckoutViewConfig() {
|
|
52
|
+
return useContext(CheckoutViewContext);
|
|
53
|
+
}
|
|
54
|
+
function resolveAbsoluteReturnUrl(webReturnUrl) {
|
|
55
|
+
if (/^https?:\/\//i.test(webReturnUrl))
|
|
56
|
+
return webReturnUrl;
|
|
57
|
+
if (typeof window === 'undefined')
|
|
58
|
+
return webReturnUrl;
|
|
59
|
+
return `${window.location.origin}${webReturnUrl.startsWith('/') ? webReturnUrl : `/${webReturnUrl}`}`;
|
|
60
|
+
}
|
|
61
|
+
function withCheckoutQuery(webReturnUrl, query) {
|
|
62
|
+
const separator = webReturnUrl.includes('?') ? '&' : '?';
|
|
63
|
+
return `${webReturnUrl}${separator}${query}`;
|
|
64
|
+
}
|
|
45
65
|
function formatAddressLine(addr) {
|
|
46
66
|
const name = addr.companyName || `${addr.firstName ?? ''} ${addr.lastName ?? ''}`.trim();
|
|
47
67
|
const street = addr.streetName ?? addr.fullAddress ?? '';
|
|
@@ -117,7 +137,7 @@ function ViewStep1({ onContinue }) {
|
|
|
117
137
|
const handleEmailBlur = () => {
|
|
118
138
|
void saveEmail(emailInput);
|
|
119
139
|
};
|
|
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?",
|
|
140
|
+
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 12?", _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
141
|
userEditedEmailRef.current = true;
|
|
122
142
|
setEmailInput(e.target.value);
|
|
123
143
|
}, 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 () => {
|
|
@@ -410,6 +430,7 @@ function ViewStep2({ onComplete, onBack }) {
|
|
|
410
430
|
}
|
|
411
431
|
function ViewStepCheckout({ onBack }) {
|
|
412
432
|
const router = useRouter();
|
|
433
|
+
const { webReturnUrl } = useCheckoutViewConfig();
|
|
413
434
|
const { cart, cartLoading, paymentMethod, deliveryMethod, bankAccount } = useRaxon();
|
|
414
435
|
const [payStartError, setPayStartError] = useState(null);
|
|
415
436
|
const [bankTransferError, setBankTransferError] = useState(null);
|
|
@@ -598,7 +619,7 @@ function ViewStepCheckout({ onBack }) {
|
|
|
598
619
|
return;
|
|
599
620
|
setPayStartError(null);
|
|
600
621
|
try {
|
|
601
|
-
const payReturnUrl =
|
|
622
|
+
const payReturnUrl = resolveAbsoluteReturnUrl(webReturnUrl);
|
|
602
623
|
const paymentResponse = await payMutation({ platform: 'web', webReturnUrl: payReturnUrl });
|
|
603
624
|
const ok = paymentResponse && typeof paymentResponse === 'object' && 'status' in paymentResponse && paymentResponse.status === true;
|
|
604
625
|
const info = paymentResponse && typeof paymentResponse === 'object' && 'info' in paymentResponse && paymentResponse.info && typeof paymentResponse.info === 'object'
|
|
@@ -618,12 +639,12 @@ function ViewStepCheckout({ onBack }) {
|
|
|
618
639
|
const garantiTransactionId = info && typeof info.transactionId === 'string' ? info.transactionId : null;
|
|
619
640
|
if (ok && provider === PaymentProvider.GARANTI && garantiHtml && garantiTransactionId) {
|
|
620
641
|
storeGarantiPaymentHtml(garantiTransactionId, garantiHtml);
|
|
621
|
-
router.push(
|
|
642
|
+
router.push(withCheckoutQuery(webReturnUrl, `type=pay&provider=garanti&transactionId=${encodeURIComponent(garantiTransactionId)}`));
|
|
622
643
|
return;
|
|
623
644
|
}
|
|
624
645
|
const token = info && typeof info.token === 'string' ? info.token : null;
|
|
625
646
|
if (ok && token) {
|
|
626
|
-
router.push(
|
|
647
|
+
router.push(withCheckoutQuery(webReturnUrl, `type=pay&token=${encodeURIComponent(token)}`));
|
|
627
648
|
}
|
|
628
649
|
else {
|
|
629
650
|
setPayStartError('Ödeme ekranı açılamadı. Lütfen tekrar deneyin.');
|
|
@@ -642,7 +663,234 @@ const CHECKOUT_STEP_LABELS = {
|
|
|
642
663
|
address: 'Adres',
|
|
643
664
|
checkout: 'Önizleme ve ödeme',
|
|
644
665
|
};
|
|
645
|
-
|
|
666
|
+
const PAYTR_IFRAME_ID = 'paytriframe';
|
|
667
|
+
const TERMINAL_FAILURE_STATUSES = new Set([
|
|
668
|
+
Status.REJECTED,
|
|
669
|
+
Status.ERROR,
|
|
670
|
+
Status.CANCELLED,
|
|
671
|
+
Status.TIMEOUT,
|
|
672
|
+
]);
|
|
673
|
+
function normalizeReturnMessage(raw) {
|
|
674
|
+
if (raw == null || raw === '')
|
|
675
|
+
return null;
|
|
676
|
+
try {
|
|
677
|
+
const d = decodeURIComponent(raw.replace(/\+/g, ' '));
|
|
678
|
+
return d.replace(/^['"]|['"]$/g, '').trim() || null;
|
|
679
|
+
}
|
|
680
|
+
catch {
|
|
681
|
+
return raw.replace(/^['"]|['"]$/g, '').trim() || null;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function shortenId(id) {
|
|
685
|
+
if (id.length <= 12)
|
|
686
|
+
return id;
|
|
687
|
+
return `${id.slice(0, 8)}…${id.slice(-4)}`;
|
|
688
|
+
}
|
|
689
|
+
async function fetchTransactionStatus(transactionId) {
|
|
690
|
+
const response = await nexineAxios.get(`/global/transcation/${transactionId}/status`);
|
|
691
|
+
return {
|
|
692
|
+
status: response.data?.status ?? null,
|
|
693
|
+
orderId: response.data?.orderId ?? null,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function runPaytrIframeResize() {
|
|
697
|
+
const w = window;
|
|
698
|
+
w.iFrameResize?.({}, `#${PAYTR_IFRAME_ID}`);
|
|
699
|
+
}
|
|
700
|
+
function CheckoutShellHeader() {
|
|
701
|
+
const { branch } = useRaxon();
|
|
702
|
+
return (_jsx("header", { className: "border-b border-gray-100 bg-white", children: _jsx("div", { className: "mx-auto flex max-w-3xl items-center justify-between px-4 py-5 sm:px-6", 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" }) }) }) }));
|
|
703
|
+
}
|
|
704
|
+
function CheckoutPayView() {
|
|
705
|
+
const searchParams = useSearchParams();
|
|
706
|
+
const { webReturnUrl } = useCheckoutViewConfig();
|
|
707
|
+
const token = searchParams.get('token');
|
|
708
|
+
const providerParam = searchParams.get('provider');
|
|
709
|
+
const transactionId = searchParams.get('transactionId');
|
|
710
|
+
const [garantiRedirectError, setGarantiRedirectError] = useState(null);
|
|
711
|
+
const [garantiRedirecting, setGarantiRedirecting] = useState(false);
|
|
712
|
+
const garantiSubmitRef = useRef(false);
|
|
713
|
+
const isGarantiRedirect = providerParam === 'garanti' &&
|
|
714
|
+
transactionId != null &&
|
|
715
|
+
transactionId.trim() !== '';
|
|
716
|
+
useEffect(() => {
|
|
717
|
+
if (!isGarantiRedirect || !transactionId || garantiSubmitRef.current)
|
|
718
|
+
return;
|
|
719
|
+
const html = consumeGarantiPaymentHtml(transactionId);
|
|
720
|
+
if (!html) {
|
|
721
|
+
setGarantiRedirectError('Garanti ödeme oturumu bulunamadı. Lütfen ödeme adımından tekrar deneyin.');
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
garantiSubmitRef.current = true;
|
|
725
|
+
setGarantiRedirecting(true);
|
|
726
|
+
try {
|
|
727
|
+
submitGarantiPaymentHtml(html);
|
|
728
|
+
}
|
|
729
|
+
catch {
|
|
730
|
+
garantiSubmitRef.current = false;
|
|
731
|
+
setGarantiRedirecting(false);
|
|
732
|
+
setGarantiRedirectError('Garanti ödeme sayfasına yönlendirilemedi. Lütfen tekrar deneyin.');
|
|
733
|
+
}
|
|
734
|
+
}, [isGarantiRedirect, transactionId]);
|
|
735
|
+
useEffect(() => {
|
|
736
|
+
if (!token)
|
|
737
|
+
return;
|
|
738
|
+
const scriptSelector = 'script[data-paytr-iframe-resizer]';
|
|
739
|
+
if (document.querySelector(scriptSelector)) {
|
|
740
|
+
runPaytrIframeResize();
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
const s = document.createElement('script');
|
|
744
|
+
s.src = 'https://www.paytr.com/js/iframeResizer.min.js';
|
|
745
|
+
s.async = true;
|
|
746
|
+
s.dataset.paytrIframeResizer = 'true';
|
|
747
|
+
s.onload = runPaytrIframeResize;
|
|
748
|
+
document.body.appendChild(s);
|
|
749
|
+
}, [token]);
|
|
750
|
+
if (isGarantiRedirect) {
|
|
751
|
+
if (garantiRedirectError) {
|
|
752
|
+
return (_jsx("div", { className: "min-h-screen bg-gray-50 flex flex-col items-center justify-center px-4", children: _jsxs("div", { className: "max-w-md w-full rounded-2xl border border-gray-100 bg-white p-10 text-center shadow-sm", children: [_jsx("h1", { className: "text-xl font-black uppercase tracking-tighter text-gray-900 mb-3", children: "Garanti \u00F6deme" }), _jsx("p", { className: "text-sm text-[#CF0A2C] mb-8 font-medium", children: garantiRedirectError }), _jsx(Link, { href: webReturnUrl, className: "inline-flex justify-center rounded-xl bg-[#CF0A2C] px-8 py-3.5 text-sm font-black uppercase tracking-widest text-white transition hover:bg-[#a80824]", children: "\u00D6demeye d\u00F6n" })] }) }));
|
|
753
|
+
}
|
|
754
|
+
return (_jsx("div", { className: "min-h-screen bg-gray-50 flex flex-col items-center justify-center px-4", children: _jsxs("div", { className: "max-w-md w-full rounded-2xl border border-gray-100 bg-white p-10 text-center shadow-sm", children: [_jsx("div", { className: "mx-auto mb-5 h-10 w-10 animate-spin rounded-full border-2 border-gray-200 border-t-[#CF0A2C]", "aria-hidden": true }), _jsx("span", { className: "text-sm font-black text-[#CF0A2C] uppercase tracking-widest", children: "Garanti" }), _jsx("h1", { className: "mt-2 text-xl font-black uppercase tracking-tighter text-gray-900 mb-3", children: garantiRedirecting ? 'Yönlendiriliyorsunuz' : 'Hazırlanıyor' }), _jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: "Garanti g\u00FCvenli \u00F6deme sayfas\u0131na aktar\u0131l\u0131yorsunuz. L\u00FCtfen bekleyin." })] }) }));
|
|
755
|
+
}
|
|
756
|
+
if (token) {
|
|
757
|
+
return (_jsx("div", { className: "min-h-screen bg-gray-50", children: _jsxs("div", { className: "max-w-3xl mx-auto px-4 py-10 sm:py-12", children: [_jsxs("div", { className: "mb-8 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between sm:gap-4", children: [_jsxs("div", { children: [_jsx("span", { className: "text-sm font-black text-[#CF0A2C] uppercase tracking-widest", children: "PayTR" }), _jsx("h1", { className: "mt-2 text-2xl font-black text-gray-900 uppercase tracking-tighter", children: "G\u00FCvenli \u00F6deme" })] }), _jsx(Link, { href: webReturnUrl, className: "text-xs font-black uppercase tracking-widest text-gray-900 border-b-2 border-black pb-1 self-start sm:self-auto hover:text-[#CF0A2C] hover:border-[#CF0A2C] transition-colors", children: "\u00D6deme sayfas\u0131na d\u00F6n" })] }), _jsx("div", { className: "rounded-2xl border border-gray-100 bg-white overflow-hidden shadow-sm", children: _jsx("div", { className: "p-2", children: _jsx("iframe", { title: "PayTR g\u00FCvenli \u00F6deme", src: `https://www.paytr.com/odeme/guvenli/${token}`, id: PAYTR_IFRAME_ID, frameBorder: 0, scrolling: "no", className: "w-full min-h-[480px] border-0 rounded-xl", onLoad: runPaytrIframeResize }) }) })] }) }));
|
|
758
|
+
}
|
|
759
|
+
return (_jsx("div", { className: "min-h-screen bg-gray-50 flex flex-col items-center justify-center px-4", children: _jsxs("div", { className: "max-w-md w-full rounded-2xl border border-gray-100 bg-white p-10 text-center shadow-sm", children: [_jsx("h1", { className: "text-xl font-black uppercase tracking-tighter text-gray-900 mb-3", children: "Ge\u00E7ersiz ba\u011Flant\u0131" }), _jsx("p", { className: "text-sm text-gray-600 mb-8 leading-relaxed", children: "\u00D6deme oturumu bulunamad\u0131. L\u00FCtfen \u00F6deme ad\u0131m\u0131ndan tekrar deneyin." }), _jsx(Link, { href: webReturnUrl, className: "inline-flex justify-center rounded-xl bg-[#CF0A2C] px-8 py-3.5 text-sm font-black uppercase tracking-widest text-white transition hover:bg-[#a80824]", children: "\u00D6demeye git" })] }) }));
|
|
760
|
+
}
|
|
761
|
+
function CheckoutResultView() {
|
|
762
|
+
const searchParams = useSearchParams();
|
|
763
|
+
const queryClient = useQueryClient();
|
|
764
|
+
const { webReturnUrl } = useCheckoutViewConfig();
|
|
765
|
+
const statusParam = searchParams.get('status');
|
|
766
|
+
const titleParam = normalizeReturnMessage(searchParams.get('title'));
|
|
767
|
+
const messageParam = normalizeReturnMessage(searchParams.get('message'));
|
|
768
|
+
const transactionId = searchParams.get('transactionId');
|
|
769
|
+
const paymentIdParam = searchParams.get('paymentId');
|
|
770
|
+
const orderIdParam = searchParams.get('orderId');
|
|
771
|
+
const isSuccess = statusParam === 'success';
|
|
772
|
+
const isFailure = statusParam === 'fail' || statusParam === 'error';
|
|
773
|
+
const hasValidStatus = isSuccess || isFailure;
|
|
774
|
+
const [phase, setPhase] = useState(() => {
|
|
775
|
+
if (isFailure)
|
|
776
|
+
return 'error';
|
|
777
|
+
if (isSuccess && orderIdParam)
|
|
778
|
+
return 'success';
|
|
779
|
+
if (isSuccess)
|
|
780
|
+
return 'loading';
|
|
781
|
+
return 'loading';
|
|
782
|
+
});
|
|
783
|
+
const [resolvedOrderId, setResolvedOrderId] = useState(orderIdParam);
|
|
784
|
+
const resolvedPaymentId = paymentIdParam;
|
|
785
|
+
const [errorMessage, setErrorMessage] = useState(isFailure ? messageParam ?? titleParam ?? 'Ödeme tamamlanamadı.' : null);
|
|
786
|
+
const intervalRef = useRef(null);
|
|
787
|
+
const pollFailCountRef = useRef(0);
|
|
788
|
+
const cartInvalidatedRef = useRef(false);
|
|
789
|
+
const clearPollInterval = useCallback(() => {
|
|
790
|
+
if (intervalRef.current != null) {
|
|
791
|
+
clearInterval(intervalRef.current);
|
|
792
|
+
intervalRef.current = null;
|
|
793
|
+
}
|
|
794
|
+
}, []);
|
|
795
|
+
const { detail } = useOrder();
|
|
796
|
+
const orderQuery = detail(resolvedOrderId ?? '');
|
|
797
|
+
const order = orderQuery.data;
|
|
798
|
+
useEffect(() => {
|
|
799
|
+
if (window.self !== window.top) {
|
|
800
|
+
window.top.location.href = window.location.href;
|
|
801
|
+
}
|
|
802
|
+
}, []);
|
|
803
|
+
useEffect(() => {
|
|
804
|
+
if (!isSuccess)
|
|
805
|
+
return;
|
|
806
|
+
if (orderIdParam) {
|
|
807
|
+
setResolvedOrderId(orderIdParam);
|
|
808
|
+
setPhase('success');
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
if (!transactionId) {
|
|
812
|
+
setErrorMessage('İşlem bilgisi bulunamadı.');
|
|
813
|
+
setPhase('error');
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
let cancelled = false;
|
|
817
|
+
setPhase('polling');
|
|
818
|
+
const tick = async () => {
|
|
819
|
+
try {
|
|
820
|
+
const { status: st, orderId } = await fetchTransactionStatus(transactionId);
|
|
821
|
+
pollFailCountRef.current = 0;
|
|
822
|
+
if (cancelled)
|
|
823
|
+
return;
|
|
824
|
+
if (orderId) {
|
|
825
|
+
setResolvedOrderId(orderId);
|
|
826
|
+
}
|
|
827
|
+
if (st === Status.COMPLETED) {
|
|
828
|
+
clearPollInterval();
|
|
829
|
+
if (!cartInvalidatedRef.current) {
|
|
830
|
+
cartInvalidatedRef.current = true;
|
|
831
|
+
await queryClient.invalidateQueries({ queryKey: ['organization', 'cart'] });
|
|
832
|
+
}
|
|
833
|
+
setPhase('success');
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
if (st != null && TERMINAL_FAILURE_STATUSES.has(st)) {
|
|
837
|
+
clearPollInterval();
|
|
838
|
+
setErrorMessage('Ödeme tamamlanamadı veya iptal edildi.');
|
|
839
|
+
setPhase('error');
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
catch {
|
|
843
|
+
pollFailCountRef.current += 1;
|
|
844
|
+
if (pollFailCountRef.current >= 5 && !cancelled) {
|
|
845
|
+
clearPollInterval();
|
|
846
|
+
setErrorMessage('Ödeme durumu alınamadı. Lütfen daha sonra siparişlerinizi kontrol edin.');
|
|
847
|
+
setPhase('error');
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
void tick();
|
|
852
|
+
intervalRef.current = setInterval(() => void tick(), 3000);
|
|
853
|
+
return () => {
|
|
854
|
+
cancelled = true;
|
|
855
|
+
clearPollInterval();
|
|
856
|
+
};
|
|
857
|
+
}, [isSuccess, transactionId, orderIdParam, clearPollInterval, queryClient]);
|
|
858
|
+
useEffect(() => {
|
|
859
|
+
if (phase !== 'success' || cartInvalidatedRef.current)
|
|
860
|
+
return;
|
|
861
|
+
cartInvalidatedRef.current = true;
|
|
862
|
+
void queryClient.invalidateQueries({ queryKey: ['organization', 'cart'] });
|
|
863
|
+
}, [phase, queryClient]);
|
|
864
|
+
const displayTitle = phase === 'success' ? (titleParam ?? 'Ödeme başarılı') : (titleParam ?? 'Ödeme başarısız');
|
|
865
|
+
const displayMessage = phase === 'success'
|
|
866
|
+
? (messageParam ?? 'Ödemeniz alındı. Siparişiniz işleme alınacaktır.')
|
|
867
|
+
: (errorMessage ?? messageParam ?? 'İşlem tamamlanamadı.');
|
|
868
|
+
const showOrderLoading = phase === 'success' && resolvedOrderId && orderQuery.isLoading;
|
|
869
|
+
return (_jsxs("div", { className: "min-h-screen bg-gray-50", children: [_jsx(CheckoutShellHeader, {}), _jsxs("main", { className: "mx-auto max-w-2xl px-4 py-10 sm:py-14", children: [(phase === 'loading' || phase === 'polling' || showOrderLoading) && (_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-10 text-center shadow-sm", children: [_jsx(Loader2, { className: "mx-auto mb-5 h-10 w-10 animate-spin text-[#CF0A2C]", "aria-hidden": true }), _jsx("h1", { className: "text-xl font-black uppercase tracking-tighter text-gray-900 mb-3", children: "\u00D6deme onaylan\u0131yor" }), _jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: "Sipari\u015Finiz olu\u015Fturuluyor. L\u00FCtfen bu sayfada kal\u0131n." })] })), phase === 'success' && !showOrderLoading && (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-8 sm:p-10 text-center shadow-sm", children: [_jsx("div", { className: "mx-auto mb-5 inline-flex h-16 w-16 items-center justify-center rounded-full bg-green-50 text-green-600", children: _jsx(CheckCircle2, { size: 32, "aria-hidden": true }) }), _jsx("h1", { className: "text-2xl font-black uppercase tracking-tighter text-gray-900 mb-2", children: displayTitle }), _jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: displayMessage })] }), _jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-6 shadow-sm space-y-4", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-[#CF0A2C]", children: "\u0130\u015Flem bilgileri" }), _jsxs("dl", { className: "space-y-3 text-sm", children: [resolvedPaymentId ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between sm:gap-4", children: [_jsx("dt", { className: "text-gray-500", children: "\u00D6deme no" }), _jsx("dd", { className: "font-mono font-medium text-gray-900 break-all", title: resolvedPaymentId, children: shortenId(resolvedPaymentId) })] })) : null, transactionId ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between sm:gap-4", children: [_jsx("dt", { className: "text-gray-500", children: "\u0130\u015Flem no" }), _jsx("dd", { className: "font-mono font-medium text-gray-900 break-all", title: transactionId, children: shortenId(transactionId) })] })) : null, resolvedOrderId ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between sm:gap-4", children: [_jsx("dt", { className: "text-gray-500", children: "Sipari\u015F no" }), _jsx("dd", { className: "font-medium text-gray-900", children: order?.orderNumber ? `#${order.orderNumber}` : shortenId(resolvedOrderId) })] })) : null, order?.totalPayAmount != null ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between sm:gap-4 border-t border-gray-100 pt-3", children: [_jsx("dt", { className: "text-gray-500", children: "\u00D6denen tutar" }), _jsx("dd", { className: "font-bold tabular-nums text-[#CF0A2C]", children: order.totalPayAmount.toTry() })] })) : null] })] }), order?.items && order.items.length > 0 ? (_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-6 shadow-sm", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-[#CF0A2C] mb-4", children: "Sipari\u015F \u00F6zeti" }), _jsx("ul", { className: "space-y-4", children: order.items.map(item => {
|
|
870
|
+
const imageSrc = item.productImage
|
|
871
|
+
? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${item.productImage.replace(/^\//, '')}`
|
|
872
|
+
: null;
|
|
873
|
+
return (_jsxs("li", { className: "flex gap-4", children: [_jsxs("div", { className: "relative h-16 w-16 shrink-0 overflow-hidden rounded-xl border border-gray-100 bg-gray-50", children: [imageSrc ? (_jsx("img", { src: imageSrc, alt: item.productName ?? item.title ?? 'Ürün', className: "h-full w-full object-cover" })) : (_jsx("div", { className: "flex h-full w-full items-center justify-center text-gray-300", children: _jsx(Package, { size: 24 }) })), _jsx("span", { className: "absolute -bottom-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-[#CF0A2C] text-[10px] font-black text-white", children: item.quantity })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-sm font-medium text-gray-900", children: item.productName ?? item.title }), item.unitName ? _jsx("p", { className: "text-xs text-gray-500 mt-0.5", children: item.unitName }) : null] })] }, item.id));
|
|
874
|
+
}) })] })) : null, _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row", children: [resolvedOrderId ? (_jsx(Link, { href: `/hesabim/siparislerim/${resolvedOrderId}`, className: "inline-flex flex-1 justify-center rounded-xl bg-[#CF0A2C] px-8 py-3.5 text-sm font-black uppercase tracking-widest text-white transition hover:bg-[#a80824]", children: "Sipari\u015Fi g\u00F6r\u00FCnt\u00FCle" })) : null, _jsx(Link, { href: "/", className: "inline-flex flex-1 justify-center rounded-xl border-2 border-gray-200 px-8 py-3.5 text-sm font-black uppercase tracking-widest text-gray-900 transition hover:border-gray-900", children: "Al\u0131\u015Fveri\u015Fe devam" })] })] })), phase === 'error' && (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-8 sm:p-10 text-center shadow-sm", children: [_jsx("div", { className: "mx-auto mb-5 inline-flex h-16 w-16 items-center justify-center rounded-full bg-red-50 text-[#CF0A2C]", children: _jsx(XCircle, { size: 32, "aria-hidden": true }) }), _jsx("h1", { className: "text-2xl font-black uppercase tracking-tighter text-gray-900 mb-2", children: displayTitle }), _jsx("p", { className: "text-sm text-gray-600 leading-relaxed", children: displayMessage })] }), (transactionId || resolvedPaymentId) && (_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-6 shadow-sm space-y-3 text-sm", children: [_jsx("p", { className: "text-xs font-black uppercase tracking-widest text-gray-500", children: "Referans bilgileri" }), transactionId ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between", children: [_jsx("span", { className: "text-gray-500", children: "\u0130\u015Flem no" }), _jsx("span", { className: "font-mono text-gray-900 break-all", title: transactionId, children: shortenId(transactionId) })] })) : null, resolvedPaymentId ? (_jsxs("div", { className: "flex flex-col gap-0.5 sm:flex-row sm:justify-between", children: [_jsx("span", { className: "text-gray-500", children: "\u00D6deme no" }), _jsx("span", { className: "font-mono text-gray-900 break-all", title: resolvedPaymentId, children: shortenId(resolvedPaymentId) })] })) : null] })), _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row", children: [_jsx(Link, { href: webReturnUrl, className: "inline-flex flex-1 justify-center rounded-xl bg-[#CF0A2C] px-8 py-3.5 text-sm font-black uppercase tracking-widest text-white transition hover:bg-[#a80824]", children: "\u00D6demeyi tekrar dene" }), _jsx(Link, { href: "/sepet", className: "inline-flex flex-1 justify-center rounded-xl border-2 border-gray-200 px-8 py-3.5 text-sm font-black uppercase tracking-widest text-gray-900 transition hover:border-gray-900", children: "Sepete d\u00F6n" })] })] })), !hasValidStatus && (_jsxs("div", { className: "rounded-2xl border border-gray-100 bg-white p-10 text-center shadow-sm", children: [_jsx("h1", { className: "text-xl font-black uppercase tracking-tighter text-gray-900 mb-3", children: "Ge\u00E7ersiz ba\u011Flant\u0131" }), _jsx("p", { className: "text-sm text-gray-600 mb-8 leading-relaxed", children: "\u00D6deme sonucu bulunamad\u0131. L\u00FCtfen \u00F6deme ad\u0131m\u0131ndan tekrar deneyin." }), _jsx(Link, { href: webReturnUrl, className: "inline-flex justify-center rounded-xl bg-[#CF0A2C] px-8 py-3.5 text-sm font-black uppercase tracking-widest text-white transition hover:bg-[#a80824]", children: "\u00D6demeye git" })] }))] })] }));
|
|
875
|
+
}
|
|
876
|
+
function CheckoutPageInner() {
|
|
877
|
+
const searchParams = useSearchParams();
|
|
878
|
+
const type = searchParams.get('type');
|
|
879
|
+
const statusParam = searchParams.get('status');
|
|
880
|
+
const token = searchParams.get('token');
|
|
881
|
+
const providerParam = searchParams.get('provider');
|
|
882
|
+
const transactionId = searchParams.get('transactionId');
|
|
883
|
+
const isPaymentResult = statusParam === 'success' || statusParam === 'fail' || statusParam === 'error';
|
|
884
|
+
const isPayFlow = type === 'pay' ||
|
|
885
|
+
Boolean(token) ||
|
|
886
|
+
(providerParam === 'garanti' && Boolean(transactionId?.trim()));
|
|
887
|
+
if (isPaymentResult)
|
|
888
|
+
return _jsx(CheckoutResultView, {});
|
|
889
|
+
if (isPayFlow)
|
|
890
|
+
return _jsx(CheckoutPayView, {});
|
|
891
|
+
return _jsx(CheckoutMainView, {});
|
|
892
|
+
}
|
|
893
|
+
function CheckoutMainView() {
|
|
646
894
|
const { cart, branch } = useRaxon();
|
|
647
895
|
const [checkoutStep, setCheckoutStep] = useState('contact');
|
|
648
896
|
const [confirmedContactEmail, setConfirmedContactEmail] = useState('');
|
|
@@ -682,3 +930,10 @@ export default function PaymentPage() {
|
|
|
682
930
|
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
931
|
}) }), _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
932
|
}
|
|
933
|
+
function CheckoutPageFallback() {
|
|
934
|
+
return (_jsx("div", { className: "min-h-screen bg-gray-50 flex items-center justify-center", children: _jsx(Loader2, { className: "h-10 w-10 animate-spin text-[#CF0A2C]", "aria-label": "Y\u00FCkleniyor" }) }));
|
|
935
|
+
}
|
|
936
|
+
export default function PaymentPage({ webReturnUrl = '/sepet/odeme' }) {
|
|
937
|
+
return (_jsx(CheckoutViewContext.Provider, { value: { webReturnUrl }, children: _jsx(Suspense, { fallback: _jsx(CheckoutPageFallback, {}), children: _jsx(CheckoutPageInner, {}) }) }));
|
|
938
|
+
}
|
|
939
|
+
export { PaymentPage as CheckoutView };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export * from './core/raxon.context';
|
|
2
2
|
export { nexineAxios } from './core/util/nexine.axios';
|
|
3
|
+
export { AnalyticEventProvider, useAnalyticEvent } from './core/feature/analytic-event/analytic.event.context';
|
|
4
|
+
export type { AnalyticEventProviderProps } from './core/feature/analytic-event/analytic.event.context';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AAC/G,YAAY,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC"}
|
package/dist/index.js
CHANGED