Files
thrilltrack-explorer/src-old/lib/deletionDialogMachine.ts

92 lines
2.4 KiB
TypeScript

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
);
};