pass order store via context
This commit is contained in:
parent
e6f2e6ccaf
commit
7e886172f2
@ -7,9 +7,9 @@ import {
|
||||
ServiceSelect,
|
||||
SubmitButton,
|
||||
} from './components';
|
||||
import { useProfileQuery } from '@/hooks/profile';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { type JSX, useEffect } from 'react';
|
||||
import { OrderStoreProvider, useOrderStore } from '@/stores/order';
|
||||
import { withContext } from '@/utils/context';
|
||||
import { type JSX } from 'react';
|
||||
|
||||
const STEP_COMPONENTS: Record<string, JSX.Element> = {
|
||||
'client-select': <ClientsGrid />,
|
||||
@ -18,14 +18,8 @@ const STEP_COMPONENTS: Record<string, JSX.Element> = {
|
||||
'service-select': <ServiceSelect />,
|
||||
};
|
||||
|
||||
export function OrderForm() {
|
||||
const { data: customer } = useProfileQuery();
|
||||
export const OrderForm = withContext(OrderStoreProvider)(function () {
|
||||
const step = useOrderStore((store) => store.step);
|
||||
const initStepSequence = useOrderStore((store) => store.initStepSequence);
|
||||
|
||||
useEffect(() => {
|
||||
initStepSequence(customer?.role);
|
||||
}, [customer?.role, initStepSequence]);
|
||||
|
||||
return (
|
||||
<div className="space-y-4 [&>*]:px-4">
|
||||
@ -36,7 +30,7 @@ export function OrderForm() {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function getStepComponent(step: string) {
|
||||
return STEP_COMPONENTS[step] ?? null;
|
||||
|
||||
18
apps/web/stores/order/context.tsx
Normal file
18
apps/web/stores/order/context.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
'use client';
|
||||
import { useInitialState } from './hooks';
|
||||
import { createOrderStore } from './store';
|
||||
import { createContext, type PropsWithChildren, useRef } from 'react';
|
||||
|
||||
export type OrderStoreApi = ReturnType<typeof createOrderStore>;
|
||||
|
||||
export const OrderStoreContext = createContext<OrderStoreApi | undefined>(undefined);
|
||||
|
||||
export function OrderStoreProvider({ children }: Readonly<PropsWithChildren>) {
|
||||
const storeRef = useRef<null | OrderStoreApi>(null);
|
||||
const initialState = useInitialState();
|
||||
if (storeRef.current === null) {
|
||||
storeRef.current = createOrderStore(initialState);
|
||||
}
|
||||
|
||||
return <OrderStoreContext value={storeRef.current}>{children}</OrderStoreContext>;
|
||||
}
|
||||
40
apps/web/stores/order/hooks.tsx
Normal file
40
apps/web/stores/order/hooks.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
/* eslint-disable canonical/id-match */
|
||||
'use client';
|
||||
import { OrderStoreContext } from './context';
|
||||
import { type OrderStore, type Steps } from './types';
|
||||
import { useProfileQuery } from '@/hooks/profile';
|
||||
import { Enum_Customer_Role } from '@repo/graphql/types';
|
||||
import { useContext } from 'react';
|
||||
import { useStore } from 'zustand';
|
||||
|
||||
export const MASTER_STEPS: Steps[] = [
|
||||
'master-select',
|
||||
'client-select',
|
||||
'service-select',
|
||||
'datetime-select',
|
||||
'success',
|
||||
];
|
||||
|
||||
export const CLIENT_STEPS: Steps[] = MASTER_STEPS.filter((step) => step !== 'client-select');
|
||||
|
||||
export function useInitialState() {
|
||||
const { data } = useProfileQuery();
|
||||
const role = data?.role;
|
||||
const steps = role === Enum_Customer_Role.Master ? MASTER_STEPS : CLIENT_STEPS;
|
||||
const initialStep = steps[0];
|
||||
|
||||
return {
|
||||
_stepSequence: steps,
|
||||
step: initialStep,
|
||||
} as OrderStore;
|
||||
}
|
||||
|
||||
export const useOrderStore = <T,>(selector: (store: OrderStore) => T): T => {
|
||||
const orderStoreContext = useContext(OrderStoreContext);
|
||||
|
||||
if (!orderStoreContext) {
|
||||
throw new Error(`useOrderStore must be used within OrderStoreProvider`);
|
||||
}
|
||||
|
||||
return useStore(orderStoreContext, selector);
|
||||
};
|
||||
@ -1 +1,2 @@
|
||||
export * from './store';
|
||||
export * from './context';
|
||||
export { useOrderStore } from './hooks';
|
||||
|
||||
@ -1,52 +1,37 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/* eslint-disable canonical/id-match */
|
||||
import { type OrderStore, type Steps } from './types';
|
||||
import { Enum_Customer_Role } from '@repo/graphql/types';
|
||||
import { create } from 'zustand';
|
||||
import { type OrderStore } from './types';
|
||||
import { createStore } from 'zustand';
|
||||
|
||||
const MASTER_STEPS: Steps[] = [
|
||||
'master-select',
|
||||
'client-select',
|
||||
'service-select',
|
||||
'datetime-select',
|
||||
'success',
|
||||
];
|
||||
export function createOrderStore(initState: OrderStore) {
|
||||
return createStore<OrderStore>((set, get) => ({
|
||||
...initState,
|
||||
_stepSequence: [],
|
||||
clientId: null,
|
||||
date: new Date(),
|
||||
|
||||
const CLIENT_STEPS: Steps[] = MASTER_STEPS.filter((step) => step !== 'client-select');
|
||||
masterId: null,
|
||||
nextStep: () => {
|
||||
const { _stepSequence, step } = get();
|
||||
const index = _stepSequence.indexOf(step);
|
||||
const next = _stepSequence[index + 1];
|
||||
if (next) set({ step: next });
|
||||
},
|
||||
|
||||
export const useOrderStore = create<OrderStore>((set, get) => ({
|
||||
_stepSequence: [],
|
||||
clientId: null,
|
||||
date: new Date(),
|
||||
initStepSequence: (role) => {
|
||||
const steps = role === Enum_Customer_Role.Master ? MASTER_STEPS : CLIENT_STEPS;
|
||||
const initialStep = steps[0];
|
||||
set({ _stepSequence: steps, step: initialStep });
|
||||
},
|
||||
masterId: null,
|
||||
nextStep: () => {
|
||||
const { _stepSequence, step } = get();
|
||||
const index = _stepSequence.indexOf(step);
|
||||
const next = _stepSequence[index + 1];
|
||||
if (next) set({ step: next });
|
||||
},
|
||||
prevStep: () => {
|
||||
const { _stepSequence, step } = get();
|
||||
const index = _stepSequence.indexOf(step);
|
||||
const previous = _stepSequence[index - 1];
|
||||
if (previous) set({ step: previous });
|
||||
},
|
||||
|
||||
serviceId: null,
|
||||
setClientId: (id) => set({ clientId: id }),
|
||||
setDate: (date) => set({ date }),
|
||||
setMasterId: (id) => set({ masterId: id }),
|
||||
setServiceId: (id) => set({ serviceId: id }),
|
||||
setStep: (step) => set({ step }),
|
||||
|
||||
setTime: (time) => set({ time }),
|
||||
|
||||
step: 'master-select',
|
||||
|
||||
time: null,
|
||||
}));
|
||||
prevStep: () => {
|
||||
const { _stepSequence, step } = get();
|
||||
const index = _stepSequence.indexOf(step);
|
||||
const previous = _stepSequence[index - 1];
|
||||
if (previous) set({ step: previous });
|
||||
},
|
||||
serviceId: null,
|
||||
setClientId: (id) => set({ clientId: id }),
|
||||
setDate: (date) => set({ date }),
|
||||
setMasterId: (id) => set({ masterId: id }),
|
||||
setServiceId: (id) => set({ serviceId: id }),
|
||||
setStep: (step) => set({ step }),
|
||||
setTime: (time) => set({ time }),
|
||||
step: 'master-select',
|
||||
time: null,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
import { type Enum_Customer_Role } from '@repo/graphql/types';
|
||||
|
||||
export type OrderStore = {
|
||||
_stepSequence: Steps[];
|
||||
clientId: null | string;
|
||||
date: Date;
|
||||
initStepSequence: (role: Enum_Customer_Role | undefined) => void;
|
||||
masterId: null | string;
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user