const BRANCH_ID_RE = /^NL\d+$/; const BRANCH_ID_CAPTURE_RE = /^NL(\d+)$/i; export const MASKED_PASSWORD_VALUE = "••••••"; function normalizeComparableText(value) { return String(value ?? "") .trim() .toLowerCase(); } export function normalizeUsernameForConfirmation(value) { return normalizeComparableText(value); } export function isUsernameConfirmationMatch({ expectedUsername, typedUsername, }) { const expected = normalizeUsernameForConfirmation(expectedUsername); const typed = normalizeUsernameForConfirmation(typedUsername); return Boolean(expected) && expected === typed; } export function normalizeBranchIdInput(value) { return String(value ?? "") .trim() .toUpperCase(); } export function normalizeBranchNumberInput(value) { const raw = String(value ?? "").trim(); if (!raw) return ""; const digits = raw.replace(/\D+/g, ""); if (!digits) return ""; // Keep "0" as a valid numeric value but collapse leading zeros. return digits.replace(/^0+(?=\d)/, ""); } export function formatBranchIdFromNumberInput(value) { const numberPart = normalizeBranchNumberInput(value); if (!numberPart) return ""; return `NL${numberPart.padStart(2, "0")}`; } export function extractBranchNumberInputFromBranchId(branchId) { const match = BRANCH_ID_CAPTURE_RE.exec(normalizeBranchIdInput(branchId)); if (!match) return ""; return match[1]; } export function isValidBranchIdFormat(value) { return BRANCH_ID_RE.test(normalizeBranchIdInput(value)); } /** * Decides branch existence UX state for branch-role create/edit forms. * * Rules: * - Only relevant when role is "branch" and a branchId was entered. * - If branch list is available (status=ready), unknown branchIds block submit. * - If branch list failed to load (status=error), do not block submit (fail-open). */ export function evaluateBranchExistence({ role, branchId, branchesStatus, availableBranchIds, }) { const isBranchRole = String(role ?? "").trim() === "branch"; const normalizedBranchId = normalizeBranchIdInput(branchId); const hasBranchId = Boolean(normalizedBranchId); const listReady = branchesStatus === "ready" && Array.isArray(availableBranchIds); const listError = branchesStatus === "error"; const normalizedAvailable = listReady ? availableBranchIds.map(normalizeBranchIdInput).filter(Boolean) : []; const branchExists = isBranchRole && hasBranchId && listReady ? normalizedAvailable.includes(normalizedBranchId) : null; const hasUnknownBranch = isBranchRole && hasBranchId && listReady && branchExists === false; return { isBranchRole, normalizedBranchId, hasBranchId, listReady, listError, branchExists, hasUnknownBranch, shouldBlockSubmit: Boolean(hasUnknownBranch), }; } export function hasTemporaryPassword(value) { return typeof value === "string" && value.length > 0; } export function getDisplayedTemporaryPassword({ temporaryPassword, isVisible = false, }) { if (isVisible && hasTemporaryPassword(temporaryPassword)) { return temporaryPassword; } return MASKED_PASSWORD_VALUE; }