context/order: split into files

This commit is contained in:
vchikalkin 2025-04-10 11:37:27 +03:00
parent 4143151cbb
commit 8c8a588dfc
5 changed files with 137 additions and 122 deletions

View File

@ -1,122 +0,0 @@
'use client';
import { createContext, type PropsWithChildren, useMemo, useReducer, useState } from 'react';
type Action = { payload: Steps; type: 'SET_STEP' } | { type: 'NEXT_STEP' } | { type: 'PREV_STEP' };
type ContextType = {
clientId: null | string;
date: Date;
masterId: null | string;
nextStep: () => void;
prevStep: () => void;
serviceId: null | string;
setClientId: (clientId: null | string) => void;
setDate: (date: Date) => void;
setMasterId: (customerId: null | string) => void;
setServiceId: (serviceId: null | string) => void;
setStep: (step: Steps) => void;
setTime: (time: string) => void;
step: Steps;
time: null | string;
};
type State = { step: Steps };
type Steps = 'client-select' | 'datetime-select' | 'master-select' | 'service-select' | 'success';
const stepsSequence: Steps[] = [
'master-select',
'client-select',
'service-select',
'datetime-select',
'success',
];
function stepsReducer(state: State, action: Action): State {
switch (action.type) {
case 'NEXT_STEP': {
const currentIndex = stepsSequence.indexOf(state.step);
const nextIndex = currentIndex + 1;
const nextStep = stepsSequence[nextIndex];
return nextStep ? { ...state, step: nextStep } : state;
}
case 'PREV_STEP': {
const currentIndex = stepsSequence.indexOf(state.step);
const previousIndex = currentIndex - 1;
const previousStep = stepsSequence[previousIndex];
return previousStep ? { ...state, step: previousStep } : state;
}
case 'SET_STEP': {
return { ...state, step: action.payload };
}
default:
return state;
}
}
function useEntityState() {
const [entityId, setEntityId] = useState<null | string>(null);
return { entityId, setEntityId };
}
function useStep() {
const [state, dispatch] = useReducer(stepsReducer, { step: 'master-select' });
const setStep = (payload: Steps) => dispatch({ payload, type: 'SET_STEP' });
const nextStep = () => dispatch({ type: 'NEXT_STEP' });
const previousStep = () => dispatch({ type: 'PREV_STEP' });
return { nextStep, prevStep: previousStep, setStep, ...state };
}
export const OrderContext = createContext<ContextType>({} as ContextType);
export function OrderContextProvider({ children }: Readonly<PropsWithChildren>) {
const { entityId: masterId, setEntityId: setMasterId } = useEntityState();
const { entityId: serviceId, setEntityId: setServiceId } = useEntityState();
const { entityId: clientId, setEntityId: setClientId } = useEntityState();
const [date, setDate] = useState<Date>(new Date());
const [time, setTime] = useState<null | string>(null);
const { nextStep, prevStep, setStep, step } = useStep();
const value = useMemo(
() => ({
clientId,
date,
masterId,
nextStep,
prevStep,
serviceId,
setClientId,
setDate,
setMasterId,
setServiceId,
setStep,
setTime,
step,
time,
}),
[
clientId,
date,
masterId,
nextStep,
prevStep,
serviceId,
setClientId,
setMasterId,
setServiceId,
setStep,
step,
time,
],
);
return <OrderContext.Provider value={value}>{children}</OrderContext.Provider>;
}

View File

@ -0,0 +1,19 @@
'use client';
import { stepsReducer } from './reducer';
import { type Steps } from './types';
import { useReducer, useState } from 'react';
export function useEntityState() {
const [entityId, setEntityId] = useState<null | string>(null);
return { entityId, setEntityId };
}
export function useStep() {
const [state, dispatch] = useReducer(stepsReducer, { step: 'master-select' });
const setStep = (payload: Steps) => dispatch({ payload, type: 'SET_STEP' });
const nextStep = () => dispatch({ type: 'NEXT_STEP' });
const previousStep = () => dispatch({ type: 'PREV_STEP' });
return { nextStep, prevStep: previousStep, setStep, ...state };
}

View File

@ -0,0 +1,52 @@
'use client';
import { useEntityState, useStep } from './hooks';
import { type ContextType } from './types';
import { createContext, type PropsWithChildren, useMemo, useState } from 'react';
export const OrderContext = createContext<ContextType>({} as ContextType);
export function OrderContextProvider({ children }: Readonly<PropsWithChildren>) {
const { entityId: masterId, setEntityId: setMasterId } = useEntityState();
const { entityId: serviceId, setEntityId: setServiceId } = useEntityState();
const { entityId: clientId, setEntityId: setClientId } = useEntityState();
const [date, setDate] = useState<Date>(new Date());
const [time, setTime] = useState<null | string>(null);
const { nextStep, prevStep, setStep, step } = useStep();
const value = useMemo(
() => ({
clientId,
date,
masterId,
nextStep,
prevStep,
serviceId,
setClientId,
setDate,
setMasterId,
setServiceId,
setStep,
setTime,
step,
time,
}),
[
clientId,
date,
masterId,
nextStep,
prevStep,
serviceId,
setClientId,
setMasterId,
setServiceId,
setStep,
step,
time,
],
);
return <OrderContext.Provider value={value}>{children}</OrderContext.Provider>;
}

View File

@ -0,0 +1,36 @@
import { type Action, type State, type Steps } from './types';
const stepsSequence: Steps[] = [
'master-select',
'client-select',
'service-select',
'datetime-select',
'success',
];
export function stepsReducer(state: State, action: Action): State {
switch (action.type) {
case 'NEXT_STEP': {
const currentIndex = stepsSequence.indexOf(state.step);
const nextIndex = currentIndex + 1;
const nextStep = stepsSequence[nextIndex];
return nextStep ? { ...state, step: nextStep } : state;
}
case 'PREV_STEP': {
const currentIndex = stepsSequence.indexOf(state.step);
const previousIndex = currentIndex - 1;
const previousStep = stepsSequence[previousIndex];
return previousStep ? { ...state, step: previousStep } : state;
}
case 'SET_STEP': {
return { ...state, step: action.payload };
}
default:
return state;
}
}

View File

@ -0,0 +1,30 @@
export type Action =
| { payload: Steps; type: 'SET_STEP' }
| { type: 'NEXT_STEP' }
| { type: 'PREV_STEP' };
export type ContextType = {
clientId: null | string;
date: Date;
masterId: null | string;
nextStep: () => void;
prevStep: () => void;
serviceId: null | string;
setClientId: (clientId: null | string) => void;
setDate: (date: Date) => void;
setMasterId: (customerId: null | string) => void;
setServiceId: (serviceId: null | string) => void;
setStep: (step: Steps) => void;
setTime: (time: string) => void;
step: Steps;
time: null | string;
};
export type State = { step: Steps };
export type Steps =
| 'client-select'
| 'datetime-select'
| 'master-select'
| 'service-select'
| 'success';