create-brainerce-store 1.2.0 → 1.3.0
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/index.js +1 -1
- package/package.json +1 -1
- package/templates/nextjs/base/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts +26 -0
- package/templates/nextjs/base/src/app/checkout/page.tsx +151 -17
- package/templates/nextjs/base/src/app/order-confirmation/page.tsx +198 -191
- package/templates/nextjs/base/src/components/checkout/delivery-method-step.tsx +62 -0
- package/templates/nextjs/base/src/components/checkout/payment-step.tsx +292 -124
- package/templates/nextjs/base/src/components/checkout/pickup-step.tsx +195 -0
- package/templates/nextjs/base/src/components/checkout/tax-display.tsx +62 -62
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "create-brainerce-store",
|
|
34
|
-
version: "1.2.
|
|
34
|
+
version: "1.2.1",
|
|
35
35
|
description: "Scaffold a production-ready e-commerce storefront connected to Brainerce",
|
|
36
36
|
bin: {
|
|
37
37
|
"create-brainerce-store": "dist/index.js"
|
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Apple Pay domain verification for Grow (Meshulam) payment provider
|
|
2
|
+
// This file must be accessible at /.well-known/apple-developer-merchantid-domain-association
|
|
3
|
+
// See: https://developer.apple.com/documentation/apple_pay_on_the_web/setting_up_your_server
|
|
4
|
+
|
|
5
|
+
import { NextResponse } from 'next/server';
|
|
6
|
+
|
|
7
|
+
// Production domain verification content from Grow/Meshulam
|
|
8
|
+
const PRODUCTION_VERIFICATION =
|
|
9
|
+
'7B227073704964223A2231344636453432313941364637443346353446454633434638423534424630323337344445383438373643463936304544434643313836383831344136353933222C2276657273696F6E223A312C22637265617465644F6E223A313632323635363735313134342C227369676E6174757265223A2233303830303630393261383634383836663730643031303730326130383033303830303230313031333130663330306430363039363038363438303136353033303430323031303530303330383030363039326138363438383666373064303130373031303030306130383033303832303365333330383230333838613030333032303130323032303834633330343134393531396435343336333030613036303832613836343863653364303430333032333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333933303335333133383330333133333332333533373561313730643332333433303335333133363330333133333332333533373561333035663331323533303233303630333535303430333063316336353633363332643733366437303264363237323666366236353732326437333639363736653566353534333334326435303532346634343331313433303132303630333535303430623063306236393466353332303533373937333734363536643733333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303463323135373765646562643663376232323138663638646437303930613132313864633762306264366632633238336438343630393564393461663461353431316238333432306564383131663334303765383333333166316335346333663765623332323064366261643564346566663439323839383933653763306631336133383230323131333038323032306433303063303630333535316431333031303166663034303233303030333031663036303335353164323330343138333031363830313432336632343963343466393365346566323765366334663632383663336661326262666432653462333034353036303832623036303130353035303730313031303433393330333733303335303630383262303630313035303530373330303138363239363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363536313639363336313333333033323330383230313164303630333535316432303034383230313134333038323031313033303832303130633036303932613836343838366637363336343035303133303831666533303831633330363038326230363031303530353037303230323330383162363063383162333532363536633639363136653633363532303666366532303734363836393733323036333635373237343639363636393633363137343635323036323739323036313665373932303730363137323734373932303631373337333735366436353733323036313633363336353730373436313665363336353230366636363230373436383635323037343638363536653230363137303730366336393633363136323663363532303733373436313665363436313732363432303734363537323664373332303631366536343230363336663665363436393734363936663665373332303666363632303735373336353263323036333635373237343639363636393633363137343635323037303666366336393633373932303631366536343230363336353732373436393636363936333631373436393666366532303730373236313633373436393633363532303733373436313734363536643635366537343733326533303336303630383262303630313035303530373032303131363261363837343734373033613266326637373737373732653631373037303663363532653633366636643266363336353732373436393636363936333631373436353631373537343638366637323639373437393266333033343036303335353164316630343264333032623330323961303237613032353836323336383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635363136393633363133333265363337323663333031643036303335353164306530343136303431343934353764623666643537343831383638393839373632663765353738353037653739623538323433303065303630333535316430663031303166663034303430333032303738303330306630363039326138363438383666373633363430363164303430323035303033303061303630383261383634386365336430343033303230333439303033303436303232313030626530393537316665373165316537333562353565356166616362346337326665623434356633303138353232326337323531303032623631656264366635353032323130306431386233353061356464366464366562313734363033356231316562326365383763666133653661663663626438333830383930646338326364646161363333303832303265653330383230323735613030333032303130323032303834393664326662663361393864613937333030613036303832613836343863653364303430333032333036373331316233303139303630333535303430333063313234313730373036633635323035323666366637343230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313334333033353330333633323333333433363333333035613137306433323339333033353330333633323333333433363333333035613330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034663031373131383431396437363438356435316135653235383130373736653838306132656664653762616534646530386466633462393365313333353664353636356233356165323264303937373630643232346537626261303866643736313763653838636237366262363637306265633865383239383466663534343561333831663733303831663433303436303630383262303630313035303530373031303130343361333033383330333630363038326230363031303530353037333030313836326136383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353732366636663734363336313637333333303164303630333535316430653034313630343134323366323439633434663933653465663237653663346636323836633366613262626664326534623330306630363033353531643133303130316666303430353330303330313031666633303166303630333535316432333034313833303136383031346262623064656131353833333838396161343861393964656265626465626166646163623234616233303337303630333535316431663034333033303265333032636130326161303238383632363638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363537323666366637343633363136373333326536333732366333303065303630333535316430663031303166663034303430333032303130363330313030363061326138363438383666373633363430363032306530343032303530303330306130363038326138363438636533643034303330323033363730303330363430323330336163663732383335313136393962313836666233356333353663613632626666343137656464393066373534646132386562656631396338313565343262373839663839386637396235393966393864353431306438663964653963326665303233303332326464353434323162306133303537373663356466333338336239303637666431373763326332313664393634666336373236393832313236663534663837613764316239396362396230393839323136313036393930663039393231643030303033313832303138643330383230313839303230313031333038313836333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353330323038346333303431343935313964353433363330306430363039363038363438303136353033303430323031303530306130383139353330313830363039326138363438383666373064303130393033333130623036303932613836343838366637306430313037303133303163303630393261383634383836663730643031303930353331306631373064333233313330333633303332333133373335333933313331356133303261303630393261383634383836663730643031303933343331316433303162333030643036303936303836343830313635303330343032303130353030613130613036303832613836343863653364303430333032333032663036303932613836343838366637306430313039303433313232303432306336396639373432383733363263303562396665616635646239663138373231633534383062643065373463373765363731326231636463616538346465363933303061303630383261383634386365336430343033303230343438333034363032323130306230383561316530323462323936323530323332363562363762356263376136353339393338653635633065326237366131343732363533366535336433393830323231303063666530333937626562623439623662336637386634346637386432336631343861663964326264383566633564386433326239663736316439326363316633303030303030303030303030227D';
|
|
10
|
+
|
|
11
|
+
// Development/sandbox domain verification content
|
|
12
|
+
const DEVELOPMENT_VERIFICATION =
|
|
13
|
+
'7B227073704964223A2231434145453235393330453932373535413231423330364239373833394330393833423031463145384543413646434531374532463439343146463246304231222C2276657273696F6E223A312C22637265617465644F6E223A313633393938323131323934372C227369676E6174757265223A223330383030363039326138363438383666373064303130373032613038303330383030323031303133313066333030643036303936303836343830313635303330343032303130353030333038303036303932613836343838366637306430313037303130303030613038303330383230336533333038323033383861303033303230313032303230383463333034313439353139643534333633303061303630383261383634386365336430343033303233303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133393330333533313338333033313333333233353337356131373064333233343330333533313336333033313333333233353337356133303566333132353330323330363033353530343033306331633635363336333264373336643730326436323732366636623635373232643733363936373665356635353433333432643530353234663434333131343330313230363033353530343062306330623639343635333230353337393733373436353664373333313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346332313537376564656264366337623232313866363864643730393061313231386463376230626436663263323833643834363039356439346166346135343131623833343230656438313166333430376538333333316631633534633366376562333232306436626164356434656666343932383938393365376330663133613338323032313133303832303230643330306330363033353531643133303130316666303430323330303033303166303630333535316432333034313833303136383031343233663234396334346639336534656632376536633466363238366333666132626266643265346233303435303630383262303630313035303530373031303130343339333033373330333530363038326230363031303530353037333030313836323936383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353631363936333631333333303332333038323031316430363033353531643230303438323031313433303832303131303330383230313063303630393261383634383836663736333634303530313330383166653330383163333036303832623036303130353035303730323032333038316236306338316233353236353663363936313665363336353230366636653230373436383639373332303633363537323734363936363639363336313734363532303632373932303631366537393230373036313732373437393230363137333733373536643635373332303631363336333635373037343631366536333635323036663636323037343638363532303734363836353665323036313730373036633639363336313632366336353230373337343631366536343631373236343230373436353732366437333230363136653634323036333666366536343639373436393666366537333230366636363230373537333635326332303633363537323734363936363639363336313734363532303730366636633639363337393230363136653634323036333635373237343639363636393633363137343639366636653230373037323631363337343639363336353230373337343631373436353664363536653734373332653330333630363038326230363031303530353037303230313136326136383734373437303361326632663737373737373265363137303730366336353265363336663664326636333635373237343639363636393633363137343635363137353734363836663732363937343739326633303334303630333535316431663034326433303262333032396130323761303235383632333638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363536313639363336313333326536333732366333303164303630333535316430653034313630343134393435376462366664353734383138363839383937363266376535373835303765373962353832343330306530363033353531643066303130316666303430343033303230373830333030663036303932613836343838366637363336343036316430343032303530303330306130363038326138363438636533643034303330323033343930303330343630323231303062653039353731666537316531653733356235356535616661636234633732666562343435663330313835323232633732353130303262363165626436663535303232313030643138623335306135646436646436656231373436303335623131656232636538376366613365366166366362643833383038393064633832636464616136333330383230326565333038323032373561303033303230313032303230383439366432666266336139386461393733303061303630383261383634386365336430343033303233303637333131623330313930363033353530343033306331323431373037303663363532303532366636663734323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333433303335333033363332333333343336333333303561313730643332333933303335333033363332333333343336333333303561333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303466303137313138343139643736343835643531613565323538313037373665383830613265666465376261653464653038646663346239336531333335366435363635623335616532326430393737363064323234653762626130386664373631376365383863623736626236363730626563386538323938346666353434356133383166373330383166343330343630363038326230363031303530353037303130313034336133303338333033363036303832623036303130353035303733303031383632613638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635373236663666373436333631363733333330316430363033353531643065303431363034313432336632343963343466393365346566323765366334663632383663336661326262666432653462333030663036303335353164313330313031666630343035333030333031303166663330316630363033353531643233303431383330313638303134626262306465613135383333383839616134386139396465626562646562616664616362323461623330333730363033353531643166303433303330326533303263613032616130323838363236363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353732366636663734363336313637333332653633373236633330306530363033353531643066303130316666303430343033303230313036333031303036306132613836343838366637363336343036303230653034303230353030333030613036303832613836343863653364303430333032303336373030333036343032333033616366373238333531313639396231383666623335633335366361363262666634313765646439306637353464613238656265663139633831356534326237383966383938663739623539396639386435343130643866396465396332666530323330333232646435343432316230613330353737366335646633333833623930363766643137376332633231366439363466633637323639383231323666353466383761376431623939636239623039383932313631303639393066303939323164303030303331383230313863333038323031383830323031303133303831383633303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303633363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333032303834633330343134393531396435343336333030643036303936303836343830313635303330343032303130353030613038313935333031383036303932613836343838366637306430313039303333313062303630393261383634383836663730643031303730313330316330363039326138363438383666373064303130393035333130663137306433323331333133323332333033303336333333353331333235613330326130363039326138363438383666373064303130393334333131643330316233303064303630393630383634383031363530333034303230313035303061313061303630383261383634386365336430343033303233303266303630393261383634383836663730643031303930343331323230343230326531313362373864353534386366376263393961306435663330663066653861376538326639363961613039303963343939366537306432386230356537663330306130363038326138363438636533643034303330323034343733303435303232313030633965663438663437393162623732656565646337386564633562306133376633383863623564326262366337653766323762646461646462306564353438623032323030333265316537356363653432303334323666393363656338323666663738383833636564326635343463326232326266363266343961363731396464303362303030303030303030303030227D';
|
|
14
|
+
|
|
15
|
+
export async function GET() {
|
|
16
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
17
|
+
const content = isDev ? DEVELOPMENT_VERIFICATION : PRODUCTION_VERIFICATION;
|
|
18
|
+
|
|
19
|
+
return new NextResponse(content, {
|
|
20
|
+
status: 200,
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'text/plain',
|
|
23
|
+
'Cache-Control': 'public, max-age=86400',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
ShippingRate,
|
|
10
10
|
SetShippingAddressDto,
|
|
11
11
|
ShippingDestinations,
|
|
12
|
+
PickupLocation,
|
|
12
13
|
} from 'brainerce';
|
|
13
14
|
import { formatPrice } from 'brainerce';
|
|
14
15
|
import { getClient } from '@/lib/brainerce';
|
|
@@ -16,12 +17,14 @@ import { useStoreInfo, useAuth, useCart } from '@/providers/store-provider';
|
|
|
16
17
|
import { CheckoutForm } from '@/components/checkout/checkout-form';
|
|
17
18
|
import { ShippingStep } from '@/components/checkout/shipping-step';
|
|
18
19
|
import { PaymentStep } from '@/components/checkout/payment-step';
|
|
20
|
+
import { DeliveryMethodStep } from '@/components/checkout/delivery-method-step';
|
|
21
|
+
import { PickupStep } from '@/components/checkout/pickup-step';
|
|
19
22
|
import { TaxDisplay } from '@/components/checkout/tax-display';
|
|
20
23
|
import { ReservationCountdown } from '@/components/cart/reservation-countdown';
|
|
21
24
|
import { LoadingSpinner } from '@/components/shared/loading-spinner';
|
|
22
25
|
import { cn } from '@/lib/utils';
|
|
23
26
|
|
|
24
|
-
type CheckoutStep = 'address' | 'shipping' | 'payment';
|
|
27
|
+
type CheckoutStep = 'method' | 'address' | 'shipping' | 'pickup' | 'payment';
|
|
25
28
|
|
|
26
29
|
function CheckoutContent() {
|
|
27
30
|
const searchParams = useSearchParams();
|
|
@@ -38,6 +41,8 @@ function CheckoutContent() {
|
|
|
38
41
|
const [initializing, setInitializing] = useState(true);
|
|
39
42
|
const [error, setError] = useState<string | null>(null);
|
|
40
43
|
const [destinations, setDestinations] = useState<ShippingDestinations | null>(null);
|
|
44
|
+
const [pickupLocations, setPickupLocations] = useState<PickupLocation[]>([]);
|
|
45
|
+
const [deliveryType, setDeliveryType] = useState<'shipping' | 'pickup'>('shipping');
|
|
41
46
|
|
|
42
47
|
// Check for returning from canceled payment
|
|
43
48
|
const canceled = searchParams.get('canceled') === 'true';
|
|
@@ -50,25 +55,33 @@ function CheckoutContent() {
|
|
|
50
55
|
setError(null);
|
|
51
56
|
const client = getClient();
|
|
52
57
|
|
|
53
|
-
// Fetch shipping destinations
|
|
58
|
+
// Fetch shipping destinations and pickup locations in parallel
|
|
54
59
|
client
|
|
55
60
|
.getShippingDestinations()
|
|
56
61
|
.then(setDestinations)
|
|
57
62
|
.catch(() => {});
|
|
58
63
|
|
|
64
|
+
const locations = await client.getPickupLocations().catch(() => [] as PickupLocation[]);
|
|
65
|
+
setPickupLocations(locations);
|
|
66
|
+
|
|
59
67
|
// If returning with existing checkout ID, resume it
|
|
60
68
|
if (existingCheckoutId) {
|
|
61
69
|
const existing = await client.getCheckout(existingCheckoutId);
|
|
62
70
|
setCheckout(existing);
|
|
63
71
|
|
|
64
72
|
// Determine step based on checkout state
|
|
65
|
-
if (existing.
|
|
73
|
+
if (existing.deliveryType === 'pickup' && existing.pickupLocation) {
|
|
74
|
+
setDeliveryType('pickup');
|
|
75
|
+
setStep('payment');
|
|
76
|
+
} else if (existing.shippingAddress && existing.shippingRateId) {
|
|
66
77
|
setStep('payment');
|
|
67
78
|
} else if (existing.shippingAddress) {
|
|
68
79
|
// Fetch shipping rates
|
|
69
80
|
const rates = await client.getShippingRates(existing.id);
|
|
70
81
|
setShippingRates(rates);
|
|
71
82
|
setStep('shipping');
|
|
83
|
+
} else if (locations.length > 0) {
|
|
84
|
+
setStep('method');
|
|
72
85
|
}
|
|
73
86
|
return;
|
|
74
87
|
}
|
|
@@ -92,6 +105,11 @@ function CheckoutContent() {
|
|
|
92
105
|
} else {
|
|
93
106
|
setError('Your cart is empty.');
|
|
94
107
|
}
|
|
108
|
+
|
|
109
|
+
// If pickup locations exist, start with delivery method selection
|
|
110
|
+
if (locations.length > 0) {
|
|
111
|
+
setStep('method');
|
|
112
|
+
}
|
|
95
113
|
} catch (err) {
|
|
96
114
|
const message = err instanceof Error ? err.message : 'Failed to initialize checkout';
|
|
97
115
|
setError(message);
|
|
@@ -149,6 +167,60 @@ function CheckoutContent() {
|
|
|
149
167
|
}
|
|
150
168
|
}
|
|
151
169
|
|
|
170
|
+
// Handle delivery method selection
|
|
171
|
+
async function handleDeliveryTypeSelect(method: 'shipping' | 'pickup') {
|
|
172
|
+
if (!checkout) return;
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
setLoading(true);
|
|
176
|
+
setError(null);
|
|
177
|
+
setDeliveryType(method);
|
|
178
|
+
const client = getClient();
|
|
179
|
+
|
|
180
|
+
await client.setDeliveryType(checkout.id, method);
|
|
181
|
+
|
|
182
|
+
if (method === 'shipping') {
|
|
183
|
+
setStep('address');
|
|
184
|
+
} else {
|
|
185
|
+
setStep('pickup');
|
|
186
|
+
}
|
|
187
|
+
} catch (err) {
|
|
188
|
+
const message = err instanceof Error ? err.message : 'Failed to set delivery method';
|
|
189
|
+
setError(message);
|
|
190
|
+
} finally {
|
|
191
|
+
setLoading(false);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Handle pickup location selection
|
|
196
|
+
async function handlePickupSelect(
|
|
197
|
+
locationId: string,
|
|
198
|
+
customerInfo: { email: string; firstName?: string; lastName?: string; phone?: string }
|
|
199
|
+
) {
|
|
200
|
+
if (!checkout) return;
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
setLoading(true);
|
|
204
|
+
setError(null);
|
|
205
|
+
const client = getClient();
|
|
206
|
+
|
|
207
|
+
const updated = await client.selectPickupLocation(checkout.id, {
|
|
208
|
+
pickupRateId: locationId,
|
|
209
|
+
email: customerInfo.email,
|
|
210
|
+
firstName: customerInfo.firstName,
|
|
211
|
+
lastName: customerInfo.lastName,
|
|
212
|
+
phone: customerInfo.phone,
|
|
213
|
+
});
|
|
214
|
+
setCheckout(updated);
|
|
215
|
+
setStep('payment');
|
|
216
|
+
} catch (err) {
|
|
217
|
+
const message = err instanceof Error ? err.message : 'Failed to select pickup location';
|
|
218
|
+
setError(message);
|
|
219
|
+
} finally {
|
|
220
|
+
setLoading(false);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
152
224
|
if (initializing) {
|
|
153
225
|
return (
|
|
154
226
|
<div className="flex min-h-[60vh] items-center justify-center">
|
|
@@ -190,11 +262,25 @@ function CheckoutContent() {
|
|
|
190
262
|
);
|
|
191
263
|
}
|
|
192
264
|
|
|
193
|
-
const steps: { key: CheckoutStep; label: string
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
265
|
+
const steps: { key: CheckoutStep; label: string }[] =
|
|
266
|
+
pickupLocations.length > 0
|
|
267
|
+
? deliveryType === 'pickup'
|
|
268
|
+
? [
|
|
269
|
+
{ key: 'method', label: 'Method' },
|
|
270
|
+
{ key: 'pickup', label: 'Pickup' },
|
|
271
|
+
{ key: 'payment', label: 'Payment' },
|
|
272
|
+
]
|
|
273
|
+
: [
|
|
274
|
+
{ key: 'method', label: 'Method' },
|
|
275
|
+
{ key: 'address', label: 'Address' },
|
|
276
|
+
{ key: 'shipping', label: 'Shipping' },
|
|
277
|
+
{ key: 'payment', label: 'Payment' },
|
|
278
|
+
]
|
|
279
|
+
: [
|
|
280
|
+
{ key: 'address', label: 'Address' },
|
|
281
|
+
{ key: 'shipping', label: 'Shipping' },
|
|
282
|
+
{ key: 'payment', label: 'Payment' },
|
|
283
|
+
];
|
|
198
284
|
|
|
199
285
|
const currentStepIndex = steps.findIndex((s) => s.key === step);
|
|
200
286
|
|
|
@@ -247,7 +333,7 @@ function CheckoutContent() {
|
|
|
247
333
|
/>
|
|
248
334
|
</svg>
|
|
249
335
|
) : (
|
|
250
|
-
|
|
336
|
+
index + 1
|
|
251
337
|
)}
|
|
252
338
|
</div>
|
|
253
339
|
<span
|
|
@@ -275,10 +361,29 @@ function CheckoutContent() {
|
|
|
275
361
|
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
|
|
276
362
|
{/* Main content */}
|
|
277
363
|
<div className="lg:col-span-2">
|
|
278
|
-
{/*
|
|
364
|
+
{/* Delivery Method */}
|
|
365
|
+
{step === 'method' && (
|
|
366
|
+
<div>
|
|
367
|
+
<h2 className="text-foreground mb-4 text-lg font-semibold">Delivery Method</h2>
|
|
368
|
+
<DeliveryMethodStep onSelect={handleDeliveryTypeSelect} />
|
|
369
|
+
</div>
|
|
370
|
+
)}
|
|
371
|
+
|
|
372
|
+
{/* Address */}
|
|
279
373
|
{step === 'address' && (
|
|
280
374
|
<div>
|
|
281
|
-
<
|
|
375
|
+
<div className="mb-4 flex items-center justify-between">
|
|
376
|
+
<h2 className="text-foreground text-lg font-semibold">Shipping Address</h2>
|
|
377
|
+
{pickupLocations.length > 0 && (
|
|
378
|
+
<button
|
|
379
|
+
type="button"
|
|
380
|
+
onClick={() => setStep('method')}
|
|
381
|
+
className="text-primary text-sm hover:underline"
|
|
382
|
+
>
|
|
383
|
+
Change method
|
|
384
|
+
</button>
|
|
385
|
+
)}
|
|
386
|
+
</div>
|
|
282
387
|
<CheckoutForm
|
|
283
388
|
onSubmit={handleAddressSubmit}
|
|
284
389
|
loading={loading}
|
|
@@ -326,17 +431,39 @@ function CheckoutContent() {
|
|
|
326
431
|
</div>
|
|
327
432
|
)}
|
|
328
433
|
|
|
329
|
-
{/*
|
|
434
|
+
{/* Pickup */}
|
|
435
|
+
{step === 'pickup' && (
|
|
436
|
+
<div>
|
|
437
|
+
<div className="mb-4 flex items-center justify-between">
|
|
438
|
+
<h2 className="text-foreground text-lg font-semibold">Pickup Location</h2>
|
|
439
|
+
<button
|
|
440
|
+
type="button"
|
|
441
|
+
onClick={() => setStep('method')}
|
|
442
|
+
className="text-primary text-sm hover:underline"
|
|
443
|
+
>
|
|
444
|
+
Change method
|
|
445
|
+
</button>
|
|
446
|
+
</div>
|
|
447
|
+
<PickupStep
|
|
448
|
+
locations={pickupLocations}
|
|
449
|
+
onSelect={handlePickupSelect}
|
|
450
|
+
loading={loading}
|
|
451
|
+
initialEmail={checkout?.email || ''}
|
|
452
|
+
/>
|
|
453
|
+
</div>
|
|
454
|
+
)}
|
|
455
|
+
|
|
456
|
+
{/* Payment */}
|
|
330
457
|
{step === 'payment' && checkout && (
|
|
331
458
|
<div>
|
|
332
459
|
<div className="mb-4 flex items-center justify-between">
|
|
333
460
|
<h2 className="text-foreground text-lg font-semibold">Payment</h2>
|
|
334
461
|
<button
|
|
335
462
|
type="button"
|
|
336
|
-
onClick={() => setStep('shipping')}
|
|
463
|
+
onClick={() => setStep(deliveryType === 'pickup' ? 'pickup' : 'shipping')}
|
|
337
464
|
className="text-primary text-sm hover:underline"
|
|
338
465
|
>
|
|
339
|
-
Change shipping
|
|
466
|
+
{deliveryType === 'pickup' ? 'Change pickup' : 'Change shipping'}
|
|
340
467
|
</button>
|
|
341
468
|
</div>
|
|
342
469
|
|
|
@@ -430,11 +557,18 @@ function CheckoutContent() {
|
|
|
430
557
|
</div>
|
|
431
558
|
)}
|
|
432
559
|
|
|
433
|
-
{parseFloat(checkout.shippingAmount) > 0
|
|
560
|
+
{(parseFloat(checkout.shippingAmount) > 0 ||
|
|
561
|
+
checkout.deliveryType === 'pickup') && (
|
|
434
562
|
<div className="flex items-center justify-between">
|
|
435
|
-
<span className="text-muted-foreground">
|
|
563
|
+
<span className="text-muted-foreground">
|
|
564
|
+
{checkout.deliveryType === 'pickup' ? 'Pickup' : 'Shipping'}
|
|
565
|
+
</span>
|
|
436
566
|
<span className="text-foreground">
|
|
437
|
-
{
|
|
567
|
+
{parseFloat(checkout.shippingAmount) === 0
|
|
568
|
+
? 'Free'
|
|
569
|
+
: (formatPrice(parseFloat(checkout.shippingAmount), {
|
|
570
|
+
currency,
|
|
571
|
+
}) as string)}
|
|
438
572
|
</span>
|
|
439
573
|
</div>
|
|
440
574
|
)}
|