Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 2x 2x 2x 2x 8x 5x 8x 1x 7x | /**
* EI-2574 — pure helpers extracted from `ChangeName.jsx`.
*
* Two layers:
* 1. Yup schema (`teacherNameValidationSchema`) — locks the form's
* validation contract: firstName + lastName required (1-25 chars,
* letter-class regex); middleName optional (≤25 chars, same regex).
* 2. Payload mapper (`buildTeacherFullnamePayload`) — camelCase form
* values → snake_case wire shape consumed by the
* `PATCH /v1/teacher/account/{teacherUUID}/update` endpoint.
*
* Extracted so the AIO scenarios are unit-testable without rendering
* MUI / Formik / Redux.
*/
import * as yup from "yup";
const NAME_REGEX = /^[a-zA-ZÀ-ÖØ-öø-ÿ '-]+$/;
const OPTIONAL_NAME_REGEX = /^[a-zA-ZÀ-ÖØ-öø-ÿ '-]*$/;
export const TEACHER_NAME_MAX_LENGTH = 25;
export const teacherNameValidationSchema = yup.object({
firstName: yup
.string()
.trim()
.min(1, "First name must be at least 1 character long")
.max(TEACHER_NAME_MAX_LENGTH, `First name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
.matches(NAME_REGEX, "First name contains invalid characters")
.required("First name is required"),
middleName: yup
.string()
.trim()
.max(TEACHER_NAME_MAX_LENGTH, `Middle name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
.matches(OPTIONAL_NAME_REGEX, "Middle name contains invalid characters"),
lastName: yup
.string()
.trim()
.min(1, "Last name must be at least 1 character long")
.max(TEACHER_NAME_MAX_LENGTH, `Last name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
.matches(NAME_REGEX, "Last name contains invalid characters")
.required("Last name is required"),
});
/**
* Form values (camelCase) → API payload (snake_case). Mirrors lines
* 89–93 of `ChangeName.jsx::clickSave`. Defensive: undefined
* middleName collapses to "" so the wire shape is stable.
*/
export function buildTeacherFullnamePayload(values) {
if (!values || typeof values !== "object") return null;
return {
first_name: values.firstName ?? "",
middle_name: values.middleName ?? "",
last_name: values.lastName ?? "",
};
}
/**
* Round-trip the API teacher record → form initial values (lines
* 105–109 of `ChangeName.jsx`). Pure so the prefill behavior is
* testable. Missing/undefined middle_name collapses to "" so the
* MUI TextField is always controlled.
*/
export function buildTeacherNameInitialValues(teacherData) {
if (!teacherData || typeof teacherData !== "object") {
return { firstName: "", middleName: "", lastName: "" };
}
return {
firstName: teacherData.first_name ?? "",
middleName: teacherData.middle_name ?? "",
lastName: teacherData.last_name ?? "",
};
}
|