106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
import { StepId } from '../value-objects/StepId';
|
|
import { SessionState } from '../value-objects/SessionState';
|
|
import type { IDomainValidationService } from '@gridpilot/shared/domain';
|
|
import { Result } from '../../../shared/result/Result';
|
|
|
|
export interface ValidationResult {
|
|
isValid: boolean;
|
|
error?: string;
|
|
}
|
|
|
|
export interface StepTransitionValidationInput {
|
|
currentStep: StepId;
|
|
nextStep: StepId;
|
|
state: SessionState;
|
|
}
|
|
|
|
export interface StepTransitionValidationResult extends ValidationResult {}
|
|
|
|
const STEP_DESCRIPTIONS: Record<number, string> = {
|
|
1: 'Navigate to Hosted Racing page',
|
|
2: 'Click Create a Race',
|
|
3: 'Fill Race Information',
|
|
4: 'Configure Server Details',
|
|
5: 'Set Admins',
|
|
6: 'Add Admin (Modal)',
|
|
7: 'Set Time Limits',
|
|
8: 'Set Cars',
|
|
9: 'Add a Car (Modal)',
|
|
10: 'Set Car Classes',
|
|
11: 'Set Track',
|
|
12: 'Add a Track (Modal)',
|
|
13: 'Configure Track Options',
|
|
14: 'Set Time of Day',
|
|
15: 'Configure Weather',
|
|
16: 'Set Race Options',
|
|
17: 'Track Conditions (STOP - Manual Submit Required)',
|
|
};
|
|
|
|
export class StepTransitionValidator
|
|
implements
|
|
IDomainValidationService<StepTransitionValidationInput, StepTransitionValidationResult, Error>
|
|
{
|
|
validate(input: StepTransitionValidationInput): Result<StepTransitionValidationResult, Error> {
|
|
try {
|
|
const { currentStep, nextStep, state } = input;
|
|
const result = StepTransitionValidator.canTransition(currentStep, nextStep, state);
|
|
return Result.ok(result);
|
|
} catch (error) {
|
|
return Result.err(
|
|
error instanceof Error
|
|
? error
|
|
: new Error(`Step transition validation failed: ${String(error)}`),
|
|
);
|
|
}
|
|
}
|
|
static canTransition(
|
|
currentStep: StepId,
|
|
nextStep: StepId,
|
|
state: SessionState
|
|
): ValidationResult {
|
|
if (!state.isInProgress()) {
|
|
return {
|
|
isValid: false,
|
|
error: 'Session must be in progress to transition steps',
|
|
};
|
|
}
|
|
|
|
if (currentStep.equals(nextStep)) {
|
|
return {
|
|
isValid: false,
|
|
error: 'Already at this step',
|
|
};
|
|
}
|
|
|
|
if (nextStep.value < currentStep.value) {
|
|
return {
|
|
isValid: false,
|
|
error: 'Cannot move backward - steps must progress forward only',
|
|
};
|
|
}
|
|
|
|
if (nextStep.value !== currentStep.value + 1) {
|
|
return {
|
|
isValid: false,
|
|
error: 'Cannot skip steps - must progress sequentially',
|
|
};
|
|
}
|
|
|
|
return { isValid: true };
|
|
}
|
|
|
|
static validateModalStepTransition(
|
|
currentStep: StepId,
|
|
nextStep: StepId
|
|
): ValidationResult {
|
|
return { isValid: true };
|
|
}
|
|
|
|
static shouldStopAtStep18(nextStep: StepId): boolean {
|
|
return nextStep.isFinalStep();
|
|
}
|
|
|
|
static getStepDescription(step: StepId): string {
|
|
return STEP_DESCRIPTIONS[step.value] || `Step ${step.value}`;
|
|
}
|
|
} |