export type DeletionStep = 'warning' | 'confirm' | 'code'; export type DeletionDialogState = { step: DeletionStep; confirmationCode: string; codeReceived: boolean; scheduledDate: string; isLoading: boolean; error: string | null; }; export type DeletionDialogAction = | { type: 'CONTINUE_TO_CONFIRM' } | { type: 'GO_BACK_TO_WARNING' } | { type: 'REQUEST_DELETION'; payload: { scheduledDate: string } } | { type: 'UPDATE_CODE'; payload: { code: string } } | { type: 'TOGGLE_CODE_RECEIVED' } | { type: 'SET_LOADING'; payload: boolean } | { type: 'SET_ERROR'; payload: string | null } | { type: 'RESET' }; export const initialState: DeletionDialogState = { step: 'warning', confirmationCode: '', codeReceived: false, scheduledDate: '', isLoading: false, error: null }; export function deletionDialogReducer( state: DeletionDialogState, action: DeletionDialogAction ): DeletionDialogState { switch (action.type) { case 'CONTINUE_TO_CONFIRM': return { ...state, step: 'confirm' }; case 'GO_BACK_TO_WARNING': return { ...state, step: 'warning', error: null }; case 'REQUEST_DELETION': return { ...state, step: 'code', scheduledDate: action.payload.scheduledDate, isLoading: false, error: null }; case 'UPDATE_CODE': // Only allow digits, max 6 const sanitized = action.payload.code.replace(/\D/g, '').slice(0, 6); return { ...state, confirmationCode: sanitized }; case 'TOGGLE_CODE_RECEIVED': return { ...state, codeReceived: !state.codeReceived }; case 'SET_LOADING': return { ...state, isLoading: action.payload }; case 'SET_ERROR': return { ...state, error: action.payload, isLoading: false }; case 'RESET': return initialState; default: // Exhaustive check const _exhaustive: never = action; return state; } } // Validation helpers export const canProceedToConfirm = (state: DeletionDialogState): boolean => { return state.step === 'warning' && !state.isLoading; }; export const canRequestDeletion = (state: DeletionDialogState): boolean => { return state.step === 'confirm' && !state.isLoading; }; export const canConfirmDeletion = (state: DeletionDialogState): boolean => { return ( state.step === 'code' && state.confirmationCode.length === 6 && state.codeReceived && !state.isLoading ); };