Skip to content

Commit 4c8448d

Browse files
committed
fix: updated validatortypes
1 parent 3b0e731 commit 4c8448d

File tree

7 files changed

+43
-17
lines changed

7 files changed

+43
-17
lines changed

packages/core/src/components/question/Question.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const Question: React.FC<QuestionProps> = ({ model, style }) => {
6565
questionModel={model}
6666
{...model.inputProperties ?? {}}
6767
/>
68-
{model.validationResult?.message !== "" && <ErrorMessage message={model.validationResult?.message} />}
68+
{typeof (model.validationResult?.message) !== "undefined" && model.validationResult?.message !== "" && <ErrorMessage message={model.validationResult?.message} />}
6969
</div>
7070
);
7171
}

packages/core/src/services/QuickFormServices.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import { InputPropertiesTypes, QuestionModel, QuickFormModel } from "../model";
44
import { QuickFormDefinition } from "../model";
55
import { QuestionJsonModel } from "../model/json-definitions/JsonDataModels";
66
import { InputComponentType } from "./defaults/DefaultInputTypeResolver";
7+
import { QuickformState } from "../state";
78

89
export type HeadingNumberDisplayProvider = () => boolean;
910
export type QuickFormModelTransformer = (data: QuickFormDefinition, payload: any) => QuickFormModel;
1011
export type QuestionTransformer = (key: string, question: QuestionJsonModel, value?: any, visible?: { type: string; rule: string; }) => QuestionModel;
1112
export type InputTypePropertiesTransformer = (questionJsonModel: QuestionJsonModel) => InputPropertiesTypes | undefined;
1213
export type RegisterInputTypeComponent = (key: string, component: InputComponentType) => void;
13-
export type InputValidator = <TProps extends InputPropertiesTypes>(questionModel: QuestionModel<TProps>) => Promise<ValidationResult>;
14+
export type InputValidator = <TProps extends InputPropertiesTypes>(questionModel: QuestionModel<TProps>, state: QuickformState) => Promise<ValidationResult>;
1415
export interface IQuickFormLogger {
1516
log(body: string, ...args: any[]): void;
1617
warn(body: string, ...args: any[]): void;

packages/core/src/services/defaults/DefaultInputValidator.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ValidationResult } from "../../model/ValidationResult";
22
import { InputPropertiesTypes, QuestionModel } from "../../model";
33
import { registerQuickFormService } from "../QuickFormServices";
4+
import { QuickformState } from "../../state";
45

56
const validateText = (output: any): ValidationResult => {
67
const text = typeof output === 'string' ? output.trim() : '';
@@ -50,7 +51,7 @@ const validatePhone = async (output: any): Promise<ValidationResult> => {
5051
};
5152

5253
type ValidatorMap = {
53-
[inputType: string]: (output: any, properties?: any) => Promise<ValidationResult>;
54+
[inputType: string]: ValidatorFunction<any, any, QuestionModel<any>, QuickformState>;
5455
};
5556

5657
const validatorMap: ValidatorMap = {
@@ -60,7 +61,7 @@ const validatorMap: ValidatorMap = {
6061
multilinetext: (output: any) => Promise.resolve(validateMultilineText(output))
6162
};
6263

63-
const validateQuestionOutput = async <TProps extends InputPropertiesTypes>(questionModel: QuestionModel<TProps>): Promise<ValidationResult> => {
64+
const validateQuestionOutput = async <TProps extends InputPropertiesTypes>(questionModel: QuestionModel<TProps>, state: QuickformState): Promise<ValidationResult> => {
6465
const validator = validatorMap[questionModel.inputType];
6566
if (!validator) {
6667
// This is to support if no validation is created for inputtype.. defaults to validated..
@@ -73,11 +74,13 @@ const validateQuestionOutput = async <TProps extends InputPropertiesTypes>(quest
7374
});
7475
}
7576

76-
return await validator(questionModel.output, questionModel.inputProperties);
77+
return await validator(questionModel.output, questionModel.inputProperties, questionModel,state);
7778
};
7879

79-
export const registerInputTypeValidator = (key: string, validator: (output: any, properties?: any) => Promise<ValidationResult>) => {
80-
validatorMap[key] = validator;
80+
export type ValidatorFunction<TAnswer, TInputProps, TQuestionModel extends QuestionModel<TInputProps>, TQuickFormState extends QuickformState> = (output: TAnswer, properties: TInputProps, questionModel: TQuestionModel, state: TQuickFormState) => Promise<ValidationResult>;
81+
82+
export const registerInputTypeValidator = <TAnswer, TInputProps, TQuestionModel extends QuestionModel<TInputProps>, TQuickFormState extends QuickformState>(key: string, validator: ValidatorFunction<TAnswer, TInputProps, TQuestionModel, TQuickFormState>) => {
83+
validatorMap[key] = validator as ValidatorFunction<any, any, QuestionModel<any>, QuickformState>;
8184
};
8285

8386
registerQuickFormService("inputValidator", validateQuestionOutput);

packages/core/src/state/QuickformProvider.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { QuickFormTokens, defineQuickFormTokens } from "../style/quickFormTokens
77
import { QuickFormDefinition } from "../model";
88
import { resolveQuickFormService } from "../services/QuickFormServices";
99
import { kbaQuickFormTokens } from "../style/kbaQuickFormTokens";
10+
import { isFirstQInCurrentSlide } from "../utils/isFirstQuestionInSlide";
1011

1112
type QuickFormProviderProps = {
1213
children: React.ReactNode;
@@ -47,10 +48,7 @@ export const QuickFormProvider: React.FC<QuickFormProviderProps> = (
4748
}
4849
const setIntroVisited = () => { dispatch({ type: 'SET_INTRO_VISITED' }) };
4950
const setErrorMsg = (msg: string) => { dispatch({ type: "SET_ERROR_MSG", msg: msg }) };
50-
const isFirstQuestionInCurrentSlide = (questionLogicalName: string) => {
51-
const currSlide = state.slides[state.currIdx];
52-
return currSlide.questions && currSlide.questions.length > 0 && currSlide.questions[0].logicalName === questionLogicalName && currSlide.questions[0].visited !== true;
53-
}
51+
const isFirstQuestionInCurrentSlide = (questionLogicalName: string) => { return isFirstQInCurrentSlide(questionLogicalName, state); }
5452
const getCurrentSlide = () => (state.slides[state.currIdx]);
5553

5654
return (

packages/core/src/state/action-handlers/QuestionActionHandler.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ export class QuestionActionHandler {
6868
};
6969

7070
static startQuestionValidation = (state: QuickformState, logicalName: string, timestamp: number) => {
71-
const currentValidationResult = findQuestionByLogicalName(logicalName, getAllQuestions(state.slides)).validationResult;
71+
const currentValidationResult = findQuestionByLogicalName(logicalName, getAllQuestions(state.slides))?.validationResult;
7272

7373
return this.updateQuestionProperties(state, logicalName, {
7474
validationResult: { ...currentValidationResult, timestamp: timestamp, isValidating: true, isValid: false }
7575
});
7676
};
7777

7878
static updateQuestionValidation = (state: QuickformState, logicalName: string, validationResult: ValidationResult, timestamp: number) => {
79-
const currentValidationResult = findQuestionByLogicalName(logicalName, getAllQuestions(state.slides)).validationResult;
80-
if (currentValidationResult.timestamp !== timestamp) {
79+
const currentValidationResult = findQuestionByLogicalName(logicalName, getAllQuestions(state.slides))?.validationResult;
80+
if (currentValidationResult?.timestamp !== timestamp) {
8181
return state;
8282
}
8383
return this.updateQuestionProperties(state, logicalName, {
@@ -87,6 +87,13 @@ export class QuestionActionHandler {
8787

8888
static async validateInput(state: QuickformState, logicalName: string): Promise<ValidationResult> {
8989
const questionRef = findQuestionByKey(logicalName, getAllQuestions(state.slides));
90-
return await QuestionActionHandler.inputValidator(questionRef);
90+
if (!questionRef) {
91+
return {
92+
isValid: false,
93+
message: 'Question not valid',
94+
validatedOutput: ''
95+
}
96+
}
97+
return await QuestionActionHandler.inputValidator(questionRef, state);
9198
}
9299
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { QuickformState } from "../state";
2+
3+
/**
4+
* Determines if the provided question is the first in the current slide and if it should receive autofocus.
5+
* The method checks if any question on the slide has been visited, and if so, it will not autofocus the first question.
6+
* @param questionLogicalName The logical name of the question to check.
7+
* @returns boolean indicating if the question is the first and should be autofocused.
8+
*/
9+
export const isFirstQInCurrentSlide = (questionLogicalName: string, state: QuickformState): boolean => {
10+
const currSlide = state.slides[state.currIdx];
11+
if (currSlide.questions && currSlide.questions.length > 0) {
12+
const isFirstQuestion = currSlide.questions[0].logicalName === questionLogicalName;
13+
const anyQuestionVisited = currSlide.questions.some(q => q.visited);
14+
return isFirstQuestion && !anyQuestionVisited;
15+
}
16+
return false;
17+
}

packages/inputs/select/src/dropdown-options-list/dropdown-select-option/DropdownSelectOption.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { MouseEventHandler, ReactNode } from "react";
22
import classNames from "classnames";
33
import styles from "./DropdownSelectOption.module.css";
44
import { makeStyles, mergeClasses } from "@griffel/react";
5-
import { quickformtokens } from "@eavfw/quickform-core/src/style/quickformtokens";
65
import { Checkmark } from "@eavfw/quickform-core/src/components/icons";
76
import { shorthands } from "@fluentui/react-components";
7+
import { quickformtokens } from "@eavfw/quickform-core/src/style/quickFormTokensDefinition";
88

99
type DropdownSelectOptionProps = {
1010
readonly isSelected?: boolean;
@@ -35,7 +35,7 @@ const useDropDownSelectOptionStyles = makeStyles({
3535
color: quickformtokens.onSurface,
3636
backgroundColor: 'transparent',
3737

38-
...shorthands.border('1px', 'solid', quickformtokens.borderColor),
38+
...shorthands.border('1px', 'solid', quickformtokens.primary),
3939
...shorthands.borderRadius('5px'),
4040
':hover': {
4141
color: quickformtokens.onSurface,

0 commit comments

Comments
 (0)