103 lines
2.7 KiB
TypeScript
103 lines
2.7 KiB
TypeScript
'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,
|
|
}),
|
|
},
|
|
),
|
|
);
|