initial booking
This commit is contained in:
102
src/lib/bookingStore.ts
Normal file
102
src/lib/bookingStore.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
'use client';
|
||||
|
||||
import { create } from 'zustand';
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
|
||||
// Persist booking form state across page navigations (e.g. when the user
|
||||
// switches language mid-flow). sessionStorage so it's per-tab and cleared
|
||||
// when the tab closes. Bumping STORE_VERSION invalidates old persisted state.
|
||||
const STORE_VERSION = 1;
|
||||
|
||||
export type Step = 'products' | 'details' | 'pickup' | 'review';
|
||||
|
||||
export type BookingFormState = {
|
||||
step: Step;
|
||||
quantities: Record<string, number>;
|
||||
contactName: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
orgName: string;
|
||||
orgNumber: string;
|
||||
address: string;
|
||||
postalCode: string;
|
||||
city: string;
|
||||
country: string;
|
||||
pickupSlotId: string | null;
|
||||
notes: string;
|
||||
confirm: boolean;
|
||||
};
|
||||
|
||||
type BookingFormActions = {
|
||||
setStep: (step: Step) => void;
|
||||
setQuantity: (productId: string, qty: number) => void;
|
||||
patch: (partial: Partial<BookingFormState>) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
const initial: BookingFormState = {
|
||||
step: 'products',
|
||||
quantities: {},
|
||||
contactName: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
orgName: '',
|
||||
orgNumber: '',
|
||||
address: '',
|
||||
postalCode: '',
|
||||
city: '',
|
||||
country: 'SE',
|
||||
pickupSlotId: null,
|
||||
notes: '',
|
||||
confirm: false,
|
||||
};
|
||||
|
||||
export const useBookingStore = create<BookingFormState & BookingFormActions>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
...initial,
|
||||
setStep: (step) => set({ step }),
|
||||
setQuantity: (productId, qty) =>
|
||||
set((s) => {
|
||||
const q = { ...s.quantities };
|
||||
if (qty <= 0) delete q[productId];
|
||||
else q[productId] = Math.min(999, Math.floor(qty));
|
||||
return { quantities: q };
|
||||
}),
|
||||
patch: (partial) => set(partial as BookingFormState),
|
||||
reset: () => set({ ...initial }),
|
||||
}),
|
||||
{
|
||||
name: 'boka-gasol247:booking-form',
|
||||
version: STORE_VERSION,
|
||||
storage: createJSONStorage(() =>
|
||||
typeof window === 'undefined'
|
||||
? // SSR no-op
|
||||
{
|
||||
getItem: () => null,
|
||||
setItem: () => {},
|
||||
removeItem: () => {},
|
||||
}
|
||||
: window.sessionStorage,
|
||||
),
|
||||
// Don't persist `confirm` (re-check each session) or `step` if user
|
||||
// hasn't started filling anything. Keeps the experience clean if they
|
||||
// close and reopen a tab with stale state.
|
||||
partialize: (s) => ({
|
||||
step: s.step,
|
||||
quantities: s.quantities,
|
||||
contactName: s.contactName,
|
||||
email: s.email,
|
||||
phone: s.phone,
|
||||
orgName: s.orgName,
|
||||
orgNumber: s.orgNumber,
|
||||
address: s.address,
|
||||
postalCode: s.postalCode,
|
||||
city: s.city,
|
||||
country: s.country,
|
||||
pickupSlotId: s.pickupSlotId,
|
||||
notes: s.notes,
|
||||
}),
|
||||
},
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user