Skip to content

Conversation

@Yemyam
Copy link
Contributor

@Yemyam Yemyam commented Jan 15, 2026

Update invite user and agency modals to match Figma designs

Frontend Changes:

  • Implemented invite modal design from figma
  • Affiliated Agency dropdown now only shows for Agency member role
  • Updated User and Home icons to accept custom stroke colors
  • Added an org role select in the user invite form

NOTE:

  • The agency invite form is currently just hooked up with createOrganization
  • App role (not org role) is not being handled by inviteUser, every user is being added to the db as a driver.

Summary by CodeRabbit

  • New Features

    • Two-step invite flow: choose User or Agency, then complete the corresponding invite form.
    • New Agency invite form with validation for name and slug.
    • Enhanced User invite form with role selection and conditional organization assignment.
  • UI Improvements

    • Increased modal footer spacing for improved layout.
    • Icon components updated for consistent, customizable strokes.

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Implements a two-step invite flow (select invite type → show corresponding modal form), adds InviteAgencyForm, expands InviteUserForm validation/role logic, introduces createOrganization mutation, updates modal lifecycle/handlers, and adds stroke props to Home/User SVG components. No public API signature changes.

Changes

Cohort / File(s) Summary
Admin Dashboard Invitation Flow
src/app/_components/admincomponents/admin-dashboard.tsx
Replaces single invite modal with type-selection then specific form modals; adds inviteType state, handleInviteTypeSelect, handleUserConfirm, handleAgencyConfirm, and createOrganization mutation; refetches organizations and resets modal state on success.
New Agency Form Component
src/app/_components/admincomponents/invite-agency-form.tsx
Adds InviteAgencyForm component with name and slug inputs wired to a Mantine form prop and client-side validation.
User Form Enhancements
src/app/_components/admincomponents/invite-user-form.tsx
Adds role selection, handleRoleChange, conditional organization select based on role, enhanced email/role/org validation, UI relabeling and layout adjustments.
Icon Stroke Customization
src/assets/icons/home.tsx, src/assets/icons/user.tsx
Adds stroke prop (default #434343) to SVG components and replaces hard-coded stroke values with the prop; removes duplicated/opacity variants.
Modal Footer Spacing
src/app/_components/common/modal/modal.tsx
Adjusts default footer spacing from mt="md" to mt="xl".
Backend Invite Comment
src/server/api/routers/organizations.ts
Minor inline comment change clarifying invitee name behavior; no functional API/signature changes.

Sequence Diagram(s)

sequenceDiagram
    actor Admin
    participant Dashboard
    participant Modal
    participant Form
    participant Mutation
    participant API

    Admin->>Dashboard: Click "Invite New"
    Dashboard->>Modal: Open type-selection modal
    Admin->>Modal: Select "User" or "Agency"
    Modal->>Form: Render InviteUserForm or InviteAgencyForm
    Admin->>Form: Fill fields and submit
    Form->>Mutation: call inviteUserMutation / createOrganization
    Mutation->>API: HTTP request (inviteUser / createOrganization)
    API-->>Mutation: Response (success/error)
    Mutation->>Dashboard: onSuccess -> refetch orgs, close modal
    Dashboard->>Admin: Updated UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • promatty
  • themaxboucher
  • JustinTan-1
  • burtonjong
  • wesleylui
  • jason-duong4509
  • tanvimahal
  • Lujarios

Poem

🐰 A button clicked beneath moon's glow,

Two little paths decide where to go.
Forms flutter in with fields neat and spry,
Invites hop off — a carrot-fueled sky. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title "Sanc 64 update the invitations frontend" is related to the main changes, which involve updating the invite user and agency modal components to match Figma designs and restructuring the invitation flow.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SANC-64-update-the-invitations-frontend

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Yemyam Yemyam force-pushed the SANC-64-update-the-invitations-frontend branch from bb0a87e to 80fc82c Compare January 15, 2026 04:41
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/app/_components/admincomponents/admin-dashboard.tsx`:
- Line 115: Remove the debug console.log by deleting the line
console.log("submit user", submitData); in the admin-dashboard component (where
submitData is handled) inside admin-dashboard.tsx; if persistent logging is
needed replace it with the app's structured logger call (e.g., using
processLogger or a provided logging utility) or handle the data silently by
returning/setting state, but do not leave console.log in the production
component.
- Line 127: Remove the debug console.log call that prints agencyForm.values in
the submit handler; locate the line console.log("submit agency",
agencyForm.values) inside the admin dashboard submit routine (the agency form
submit function in admin-dashboard.tsx) and delete it (or replace with a proper
structured logger if required by project logging conventions), ensuring no
leftover debug output remains.
- Around line 35-45: The onSuccess handler for createAgencyMutation assumes its
parameter `data` is non-null; add a null-check or non-null assertion before
accessing `data.name` in the onSuccess callback of
api.organization.createOrganization.useMutation (the createAgencyMutation
onSuccess handler) — e.g., return early or guard if `!data`, or assert `data!`
if you’re certain success always provides data, then keep the notify.success,
agencyForm.reset(), setShowInviteModal(false) and organizations.refetch() calls
only when data is present.

In `@src/app/_components/admincomponents/invite-user-form.tsx`:
- Line 100: The fallback is applied after mapping so it never runs; change the
expression to apply the fallback to organizations before mapping, e.g. replace
data={organizations.map(... ) ?? NO_ORGS_DATA} with data={(organizations ??
NO_ORGS_DATA).map(org => ({ value: org.id, label: org.name }))} so the
NO_ORGS_DATA fallback is used when organizations is null/undefined.
🧹 Nitpick comments (4)
src/server/api/routers/organizations.ts (1)

100-106: Consider validating organizationRole conditionally with organizationId.

When organizationId is not provided, organizationRole is still required but ignored (lines 141-149). Consider using Zod's .refine() or discriminated unions to enforce that organizationRole is only required when organizationId is present, or make organizationRole optional as well.

♻️ Suggested schema refinement
     .input(
       z.object({
         name: z.string().min(1),
         email: z.string().email(),
-        organizationRole: z.nativeEnum(OrganizationRole),
+        organizationRole: z.nativeEnum(OrganizationRole).optional(),
         organizationId: z.string().optional(),
-      }),
+      }).refine(
+        (data) => !data.organizationId || data.organizationRole,
+        { message: "organizationRole is required when organizationId is provided", path: ["organizationRole"] }
+      ),
     )

Then update the addMember call:

       if (input.organizationId) {
+        if (!input.organizationRole) {
+          throw new TRPCError({
+            code: "BAD_REQUEST",
+            message: "organizationRole is required when organizationId is provided",
+          });
+        }
         await auth.api.addMember({
src/app/_components/admincomponents/invite-agency-form.tsx (1)

5-12: Consider renaming the interface to avoid shadowing the component name.

Both the interface (InviteAgencyForm) and the component (InviteAgencyForm) share the same name, which can cause confusion and potential import issues. Consider renaming the interface to InviteAgencyFormValues or AgencyFormData.

♻️ Suggested rename
-interface InviteAgencyForm {
+interface InviteAgencyFormValues {
   name: string;
   slug: string;
 }

 interface InviteAgencyFormProps {
-  form: UseFormReturnType<InviteAgencyForm>;
+  form: UseFormReturnType<InviteAgencyFormValues>;
 }
src/app/_components/admincomponents/admin-dashboard.tsx (2)

57-62: Consider importing the shared email regex.

The email regex is already defined in src/types/validation.ts. Importing it would reduce duplication and ensure consistency.

Proposed fix
+import { emailRegex } from "@/types/validation";
...
       email: (value) => {
         if (value.trim().length === 0) return "Email is required";
-        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
         if (!emailRegex.test(value)) return "Invalid email address";
         return null;
       },

131-136: Consider resetting form values on modal close.

Currently only errors are cleared, but form values persist. If a user partially fills the form and closes the modal, stale data will remain when reopening. Consider also calling form.reset() or resetting inviteType to ensure a clean state.

Proposed fix
   const handleCloseModal = () => {
-    userForm.clearErrors();
-    agencyForm.clearErrors();
+    userForm.reset();
+    agencyForm.reset();
     setShowInviteModal(false);
     setInviteType(null);
   };
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 527ad0b and bb0a87e.

📒 Files selected for processing (7)
  • src/app/_components/admincomponents/admin-dashboard.tsx
  • src/app/_components/admincomponents/invite-agency-form.tsx
  • src/app/_components/admincomponents/invite-user-form.tsx
  • src/app/_components/common/modal/modal.tsx
  • src/assets/icons/home.tsx
  • src/assets/icons/user.tsx
  • src/server/api/routers/organizations.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-23T05:44:37.925Z
Learnt from: tanvimahal
Repo: Code-the-Change-YYC/salvationarmy PR: 25
File: src/server/api/routers/organizations.ts:38-38
Timestamp: 2025-12-23T05:44:37.925Z
Learning: In this codebase's TRPC protectedProcedure context, ctx.session has a nested structure containing both a session object and a user object. To access activeOrganizationId, use ctx.session.session.activeOrganizationId (not ctx.session.activeOrganizationId).

Applied to files:

  • src/server/api/routers/organizations.ts
🧬 Code graph analysis (2)
src/app/_components/common/modal/modal.tsx (1)
src/app/_components/common/modal/modaltests.tsx (3)
  • setCustomFooterOpen (153-153)
  • setCustomFooterOpen (158-158)
  • simpleOpen (19-306)
src/app/_components/admincomponents/admin-dashboard.tsx (7)
src/trpc/react.tsx (1)
  • api (25-25)
src/lib/notifications.ts (1)
  • notify (13-58)
src/types/validation.ts (1)
  • emailRegex (10-10)
src/app/_components/common/button/Button.tsx (1)
  • Button (41-80)
src/app/_components/common/modal/modal.tsx (1)
  • Modal (24-70)
src/app/_components/admincomponents/invite-user-form.tsx (1)
  • InviteUserForm (29-108)
src/app/_components/admincomponents/invite-agency-form.tsx (1)
  • InviteAgencyForm (14-38)
🪛 GitHub Actions: CI
src/app/_components/admincomponents/admin-dashboard.tsx

[error] 37-37: yarn tsc --noEmit: TypeScript error TS18047: 'data' is possibly 'null'.

🪛 GitHub Check: ci
src/app/_components/admincomponents/admin-dashboard.tsx

[failure] 37-37:
'data' is possibly 'null'.

🔇 Additional comments (10)
src/app/_components/common/modal/modal.tsx (1)

42-51: LGTM!

The increased margin (mt="xl") provides better visual separation between modal content and footer actions, aligning with the updated Figma designs.

src/assets/icons/user.tsx (1)

4-35: LGTM!

The stroke prop addition enables flexible customization while maintaining backward compatibility with the default #434343 color. The consolidated path structure is cleaner than the previous implementation with duplicate paths.

src/assets/icons/home.tsx (1)

4-35: LGTM!

Consistent implementation with the User icon. The stroke prop customization pattern across icons enables unified styling in the modal invitation flow.

src/server/api/routers/organizations.ts (2)

125-131: LGTM on the name field integration.

The name field is properly validated at input and correctly passed to signUpEmail. This ensures invited users have a name set from the start.


141-149: Behavior is intentional: non-MEMBER roles are created without organization association.

The code correctly implements the design where only users with the MEMBER role are associated with an organization. Frontend validation enforces this by requiring organizationId only for MEMBER role and clearing it for non-member roles (ADMIN, DRIVER). When organizationId is omitted or not provided for other roles, the user is created successfully without organization membership, which is the expected behavior.

src/app/_components/admincomponents/invite-agency-form.tsx (2)

14-37: LGTM on component structure.

The form component follows Mantine's recommended patterns with form.key() for React keys and getInputProps() for field binding. The layout is clean and accessible with proper labels.


28-34: Slug validation and format guidance already exist in the parent form.

The form validation is implemented in admin-dashboard.tsx (lines 81-84) with a regex pattern /^[a-z0-9-]+$/ that enforces lowercase letters, numbers, and hyphens. The validation error message clearly communicates the required format: "Slug must only contain lowercase letters, numbers, and hyphens". Additionally, the field label already provides a format example ("Agency Slug (ex: my-org)"). No changes are needed.

Likely an incorrect or invalid review comment.

src/app/_components/admincomponents/invite-user-form.tsx (1)

23-27: Verify: OWNER role labeled as "Driver" is intentional.

The mapping of OrganizationRole.OWNER to the label "Driver" appears semantically unusual. Please confirm this aligns with the business logic and Figma designs. If "Driver" is indeed a distinct role concept, consider renaming the enum value for clarity.

src/app/_components/admincomponents/admin-dashboard.tsx (2)

147-186: Approve: Two-step invitation flow is well-structured.

The type selection modal cleanly separates concerns with clear UX. The showDefaultFooter={false} correctly hides the confirm/cancel buttons since selection is done via the type buttons. The onConfirm={() => {}} no-op is acceptable here since confirmation isn't needed for this step.


188-228: LGTM: Form modals properly integrated.

The conditional rendering of user/agency modals based on inviteType, with appropriate loading states and form passing, is correctly implemented.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

submitData.organizationId = userForm.values.organizationId;
}

console.log("submit user", submitData);
Copy link

@coderabbitai coderabbitai bot Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove debug console.log statement.

This appears to be a debug artifact that should be removed before merging.

Proposed fix
-    console.log("submit user", submitData);
     inviteUserMutation.mutate(submitData);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log("submit user", submitData);
inviteUserMutation.mutate(submitData);
🤖 Prompt for AI Agents
In `@src/app/_components/admincomponents/admin-dashboard.tsx` at line 115, Remove
the debug console.log by deleting the line console.log("submit user",
submitData); in the admin-dashboard component (where submitData is handled)
inside admin-dashboard.tsx; if persistent logging is needed replace it with the
app's structured logger call (e.g., using processLogger or a provided logging
utility) or handle the data silently by returning/setting state, but do not
leave console.log in the production component.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove console log

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@promatty Thanks for confirming! 👍


// todo: handle case where admin permissions are given within the organization
console.log("submit", form.values);
console.log("submit agency", agencyForm.values);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove debug console.log statement.

Same as above - debug statement should be removed.

Proposed fix
-    console.log("submit agency", agencyForm.values);
     createAgencyMutation.mutate(agencyForm.values);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log("submit agency", agencyForm.values);
createAgencyMutation.mutate(agencyForm.values);
🤖 Prompt for AI Agents
In `@src/app/_components/admincomponents/admin-dashboard.tsx` at line 127, Remove
the debug console.log call that prints agencyForm.values in the submit handler;
locate the line console.log("submit agency", agencyForm.values) inside the admin
dashboard submit routine (the agency form submit function in
admin-dashboard.tsx) and delete it (or replace with a proper structured logger
if required by project logging conventions), ensuring no leftover debug output
remains.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/server/api/routers/organizations.ts`:
- Around line 99-106: The inviteUser adminProcedure input schema currently
allows any organizationRole with an optional organizationId; update the Zod
schema for inviteUser to enforce the frontend contract by adding a .refine() on
the object: require organizationId when organizationRole ===
OrganizationRole.MEMBER (and optionally reject organizationId for non-MEMBER
roles if you prefer strictness). Reference the inviteUser input object and
OrganizationRole enum when adding the refine so validation fails if MEMBER is
missing organizationId (or if non-MEMBER includes one, depending on chosen
strictness).
♻️ Duplicate comments (2)
src/app/_components/admincomponents/admin-dashboard.tsx (2)

115-116: Remove debug console.log statement.

This debug statement should be removed before merging.


127-128: Remove debug console.log statement.

This debug statement should be removed before merging.

🧹 Nitpick comments (4)
src/server/api/routers/organizations.ts (1)

110-119: Consider removing redundant authorization check.

This manual role check duplicates the protection already provided by adminProcedure. While defense-in-depth is valid, consider whether this adds value or just maintenance overhead.

src/app/_components/admincomponents/admin-dashboard.tsx (3)

57-62: Import shared email regex from validation module.

The email regex is duplicated here. Consider importing from src/types/validation.ts which already exports emailRegex to maintain a single source of truth.

♻️ Proposed fix
+import { emailRegex } from "@/types/validation";

Then in the validation:

       email: (value) => {
         if (value.trim().length === 0) return "Email is required";
-        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
         if (!emailRegex.test(value)) return "Invalid email address";
         return null;
       },

147-159: Remove unnecessary onConfirm prop.

Since showDefaultFooter={false}, the onConfirm={() => {}} is never invoked. Consider removing it for clarity, unless the Modal component requires it.

♻️ Proposed fix
         <Modal
           opened={showInviteModal}
           onClose={handleCloseModal}
-          onConfirm={() => {}}
           title={

209-228: Clarify modal title: "Create" vs "Invite" an Agency.

The modal title says "Invite an Agency" but the action creates an organization via createOrganization. Consider changing the title to "Create an Agency" or "Add an Agency" to more accurately reflect the action.

♻️ Proposed fix
           title={
             <Box fw={600} fz="xl">
-              Invite an Agency
+              Create an Agency
             </Box>
           }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb0a87e and 80fc82c.

📒 Files selected for processing (5)
  • src/app/_components/admincomponents/admin-dashboard.tsx
  • src/app/_components/admincomponents/invite-agency-form.tsx
  • src/assets/icons/home.tsx
  • src/assets/icons/user.tsx
  • src/server/api/routers/organizations.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/assets/icons/home.tsx
  • src/app/_components/admincomponents/invite-agency-form.tsx
  • src/assets/icons/user.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-23T05:44:37.925Z
Learnt from: tanvimahal
Repo: Code-the-Change-YYC/salvationarmy PR: 25
File: src/server/api/routers/organizations.ts:38-38
Timestamp: 2025-12-23T05:44:37.925Z
Learning: In this codebase's TRPC protectedProcedure context, ctx.session has a nested structure containing both a session object and a user object. To access activeOrganizationId, use ctx.session.session.activeOrganizationId (not ctx.session.activeOrganizationId).

Applied to files:

  • src/server/api/routers/organizations.ts
🧬 Code graph analysis (2)
src/server/api/routers/organizations.ts (1)
src/lib/auth.ts (1)
  • auth (10-116)
src/app/_components/admincomponents/admin-dashboard.tsx (7)
src/trpc/react.tsx (1)
  • api (25-25)
src/lib/notifications.ts (1)
  • notify (13-58)
src/types/validation.ts (1)
  • emailRegex (10-10)
src/app/_components/common/button/Button.tsx (1)
  • Button (41-80)
src/app/_components/common/modal/modal.tsx (1)
  • Modal (24-70)
src/app/_components/admincomponents/invite-user-form.tsx (1)
  • InviteUserForm (29-108)
src/app/_components/admincomponents/invite-agency-form.tsx (1)
  • InviteAgencyForm (14-38)
🔇 Additional comments (4)
src/server/api/routers/organizations.ts (1)

141-149: LGTM! Conditional organization membership is correctly implemented.

The logic correctly gates addMember on the presence of organizationId, allowing user creation without immediate organization membership when appropriate.

src/app/_components/admincomponents/admin-dashboard.tsx (3)

35-45: LGTM! Null-safety addressed.

The optional chaining data?.name ?? "Agency" correctly handles the potentially null data response.


73-88: LGTM! Agency form validation is well-implemented.

The slug validation correctly enforces URL-safe format with lowercase letters, numbers, and hyphens.


90-117: LGTM! Submission data correctly prepared.

The conditional inclusion of organizationId only for MEMBER role aligns well with the backend changes that gate addMember on the presence of organizationId.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 99 to 134
inviteUser: adminProcedure
.input(
z.object({
name: z.string().min(1),
email: z.string().email(),
organizationRole: z.nativeEnum(OrganizationRole),
organizationId: z.string(),
organizationId: z.string().optional(),
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd src/server/api/routers && wc -l organizations.ts

Repository: Code-the-Change-YYC/salvationarmy

Length of output: 97


🏁 Script executed:

cd src/server/api/routers && sed -n '90,160p' organizations.ts

Repository: Code-the-Change-YYC/salvationarmy

Length of output: 2216


🏁 Script executed:

rg "organizationRole" --type=ts -B 3 -A 3 | head -100

Repository: Code-the-Change-YYC/salvationarmy

Length of output: 7374


Enforce the relationship between organizationRole and organizationId in the schema.

The frontend shows that organizationId is conditionally required only when organizationRole is MEMBER. However, the schema accepts any combination, allowing organizationRole (required) without organizationId when the role is non-MEMBER, even though the API won't use it. Use Zod's .refine() to enforce that organizationId is required when organizationRole is MEMBER, or adjust the schema to reflect that non-MEMBER roles should not include organizationId at all.

🤖 Prompt for AI Agents
In `@src/server/api/routers/organizations.ts` around lines 99 - 106, The
inviteUser adminProcedure input schema currently allows any organizationRole
with an optional organizationId; update the Zod schema for inviteUser to enforce
the frontend contract by adding a .refine() on the object: require
organizationId when organizationRole === OrganizationRole.MEMBER (and optionally
reject organizationId for non-MEMBER roles if you prefer strictness). Reference
the inviteUser input object and OrganizationRole enum when adding the refine so
validation fails if MEMBER is missing organizationId (or if non-MEMBER includes
one, depending on chosen strictness).

@Yemyam Yemyam force-pushed the SANC-64-update-the-invitations-frontend branch from 80fc82c to 4329fdd Compare January 15, 2026 04:54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file, what is the distinction between the invite types of "user", "agency" and null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using invite type to determine which modal to display. "user" for the user modal, "agency" for the agency modal, and null for the selection modal to select between inviting a user and agency.

Copy link
Contributor

@burtonjong burtonjong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's some confusion about these organization roles

Maybe we can hop on a call and i can explain it better if you still don't understand from my comments.

We would use these organizations in the future for these example cases:

not everyone in the salvation army navigation center should be able to invite new agencies. This could be done by appointing ADMINs (org role) and MEMBERs (org role) that have different permissions. Admins will be able to send invitations, and members wont be able to

Or even for drivers, ADMIN drivers will be able to see ALL bookings whereas MEMBER drivers won't, and only bookings assigned to them, etc.

@vercel
Copy link

vercel bot commented Feb 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
salvationarmy Ready Ready Preview, Comment Feb 4, 2026 7:54pm

// todo: handle case where admin permissions are given within the organization
console.log("submit", form.values);
const formValues = agencyForm.getValues();
console.log("submit agency", formValues);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove console log

submitData.organizationId = userForm.values.organizationId;
}

console.log("submit user", submitData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove console log

<Stack gap="md">
<Box fw={500} fz="lg">
User Information
<Box fw={600} fz="lg" c="#8B2635">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this color is hardcoded here a few times. can we import from the global scss file instead

Comment on lines +52 to +56
withAsterisk
label="Email Address (Gmail only)"
placeholder="Example@gmail.com"
key={form.key("email")}
{...form.getInputProps("email")}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we only accept gmail again?

Comment on lines +57 to +61
email: (value) => {
if (value.trim().length === 0) return "Email is required";
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) return "Invalid email address";
return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have email regex in a shared function already. also, if we are only allowing gmail then the regex should also adjust for this

@burtonjong
Copy link
Contributor

@Yemyam I think once you address matthews comments and then change the "invite agency" to "create agency" this looks good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants