userManagementUx.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. const BRANCH_ID_RE = /^NL\d+$/;
  2. const BRANCH_ID_CAPTURE_RE = /^NL(\d+)$/i;
  3. export const MASKED_PASSWORD_VALUE = "••••••";
  4. function normalizeComparableText(value) {
  5. return String(value ?? "")
  6. .trim()
  7. .toLowerCase();
  8. }
  9. export function normalizeUsernameForConfirmation(value) {
  10. return normalizeComparableText(value);
  11. }
  12. export function isUsernameConfirmationMatch({
  13. expectedUsername,
  14. typedUsername,
  15. }) {
  16. const expected = normalizeUsernameForConfirmation(expectedUsername);
  17. const typed = normalizeUsernameForConfirmation(typedUsername);
  18. return Boolean(expected) && expected === typed;
  19. }
  20. export function normalizeBranchIdInput(value) {
  21. return String(value ?? "")
  22. .trim()
  23. .toUpperCase();
  24. }
  25. export function normalizeBranchNumberInput(value) {
  26. const raw = String(value ?? "").trim();
  27. if (!raw) return "";
  28. const digits = raw.replace(/\D+/g, "");
  29. if (!digits) return "";
  30. // Keep "0" as a valid numeric value but collapse leading zeros.
  31. return digits.replace(/^0+(?=\d)/, "");
  32. }
  33. export function formatBranchIdFromNumberInput(value) {
  34. const numberPart = normalizeBranchNumberInput(value);
  35. if (!numberPart) return "";
  36. return `NL${numberPart.padStart(2, "0")}`;
  37. }
  38. export function extractBranchNumberInputFromBranchId(branchId) {
  39. const match = BRANCH_ID_CAPTURE_RE.exec(normalizeBranchIdInput(branchId));
  40. if (!match) return "";
  41. return match[1];
  42. }
  43. export function isValidBranchIdFormat(value) {
  44. return BRANCH_ID_RE.test(normalizeBranchIdInput(value));
  45. }
  46. /**
  47. * Decides branch existence UX state for branch-role create/edit forms.
  48. *
  49. * Rules:
  50. * - Only relevant when role is "branch" and a branchId was entered.
  51. * - If branch list is available (status=ready), unknown branchIds block submit.
  52. * - If branch list failed to load (status=error), do not block submit (fail-open).
  53. */
  54. export function evaluateBranchExistence({
  55. role,
  56. branchId,
  57. branchesStatus,
  58. availableBranchIds,
  59. }) {
  60. const isBranchRole = String(role ?? "").trim() === "branch";
  61. const normalizedBranchId = normalizeBranchIdInput(branchId);
  62. const hasBranchId = Boolean(normalizedBranchId);
  63. const listReady =
  64. branchesStatus === "ready" && Array.isArray(availableBranchIds);
  65. const listError = branchesStatus === "error";
  66. const normalizedAvailable = listReady
  67. ? availableBranchIds.map(normalizeBranchIdInput).filter(Boolean)
  68. : [];
  69. const branchExists =
  70. isBranchRole && hasBranchId && listReady
  71. ? normalizedAvailable.includes(normalizedBranchId)
  72. : null;
  73. const hasUnknownBranch =
  74. isBranchRole && hasBranchId && listReady && branchExists === false;
  75. return {
  76. isBranchRole,
  77. normalizedBranchId,
  78. hasBranchId,
  79. listReady,
  80. listError,
  81. branchExists,
  82. hasUnknownBranch,
  83. shouldBlockSubmit: Boolean(hasUnknownBranch),
  84. };
  85. }
  86. export function hasTemporaryPassword(value) {
  87. return typeof value === "string" && value.length > 0;
  88. }
  89. export function getDisplayedTemporaryPassword({
  90. temporaryPassword,
  91. isVisible = false,
  92. }) {
  93. if (isVisible && hasTemporaryPassword(temporaryPassword)) {
  94. return temporaryPassword;
  95. }
  96. return MASKED_PASSWORD_VALUE;
  97. }