Skip to main content
Version: 1.0.0

Additional Components & Reference

Author: Carmine Antonio Bonavoglia Creation Date: 10/11/2025
Last Reviewer: Carmine Antonio Bonavoglia Last Updated: 10/11/2025

Component Hierarchy & Architecture

Profile Page (Parent)

├─ PersonalInformation
│ └─ Read-only user info (name, email, company, role)

├─ ChangePassword
│ └─ Form with:
│ ├─ Current password
│ ├─ New password (validation)
│ └─ Save with Firebase re-authentication

├─ NotificationsSection
│ └─ 8 notification groups:
│ ├─ Admin
│ ├─ Catalogue
│ ├─ Orders
│ ├─ Subscription
│ ├─ Support
│ ├─ Teams
│ ├─ Weekly 3D Assets
│ └─ Weekly 3D Modelling

├─ TeamsSection (COMPLEX - "My Teams")
│ ├─ State Management:
│ │ ├─ editingTeam (which team in edit mode)
│ │ ├─ editingTeamName (buffered name edit)
│ │ ├─ pendingChanges (role changes: {email → newRole})
│ │ ├─ originalTeamData (for cancel restoration)
│ │ ├─ isAddMemberModalOpen (modal visibility)
│ │ ├─ addMemberTeamId (selected team)
│ │ ├─ deleteConfirmVisible (confirmation dialog)
│ │ └─ memberToDelete ({teamId, memberEmail})
│ │
│ ├─ Team Card (per team):
│ │ ├─ Team name (editable in edit mode)
│ │ ├─ Status badge
│ │ ├─ Member count
│ │ ├─ Created date
│ │ ├─ Subscription info
│ │ ├─ Members table with:
│ │ │ ├─ First/Last Name
│ │ │ ├─ Role (select dropdown in edit mode)
│ │ │ ├─ Status (Active/Pending)
│ │ │ ├─ Joined date
│ │ │ └─ Actions (dropdown: Remove/Resend Invite)
│ │ └─ Buttons: Edit/Add Member (or Save/Cancel in edit mode)
│ │
│ ├─ Add Member Modal (AddMemberModal)
│ │ ├─ Radio toggle: "Invite New User" / "Add Existing User"
│ │ ├─ New user form:
│ │ │ ├─ First Name
│ │ │ ├─ Last Name
│ │ │ ├─ Email prefix (+ domain from Client doc)
│ │ │ └─ Team Admin checkbox
│ │ ├─ Existing user select:
│ │ │ ├─ Dropdown of available profiles
│ │ │ └─ Team Admin checkbox
│ │ ├─ Confirmation modal:
│ │ │ └─ Confirm + Firebase function call
│ │ └─ Email sending via Firebase Cloud Function
│ │
│ └─ Delete Confirmation Modal
│ └─ Remove member + send notifications

├─ TeamSection (SECONDARY - Team Members View)
│ └─ Simple table of team members:
│ ├─ Avatar (with role-based color)
│ ├─ Name
│ ├─ Subscription count
│ ├─ Catalogue count
│ ├─ Role
│ └─ Actions (view details → MemberDetailsModal)

├─ MemberDetailsModal
│ ├─ Member info card:
│ │ ├─ Avatar + name/email
│ │ ├─ Role (select in edit mode)
│ │ └─ Edit button
│ │
│ ├─ Catalogues section:
│ │ ├─ Assigned catalogues table
│ │ ├─ Add Catalogues button (in edit mode)
│ │ └─ Remove buttons (in edit mode)
│ │
│ ├─ Subscriptions section:
│ │ └─ Auto-calculated based on assigned catalogues
│ │
│ ├─ AddCatalogueModal (nested)
│ │ └─ Multi-select table of unassigned catalogues
│ │
│ └─ Tutorial panel (right side)

├─ AssociatedBrands
│ └─ Subscriptions table:
│ ├─ Subscription Type
│ ├─ Start/End dates
│ ├─ Days left
│ ├─ Name
│ ├─ Services (tags)
│ ├─ % Consumed
│ └─ Status

└─ MFASetup
└─ Firebase Phone Auth:
├─ Phone number input
├─ Send verification code
├─ Verify code
└─ Enable MFA

AssociatedBrands Component

Purpose

Display user's subscription/brand associations with consumption tracking.

Props

{
loading: boolean,
subscriptions: Array<{
subscriptionType: string,
startDate: Date,
endDate: Date,
store: string,
service_list: Array<string>,
status: string
}>,
percentageData: Array<{
bandwidthDetails: { totalBandWidth: string },
consumptionLimit: number
}>
}

Table Columns

ColumnRender Logic
Subscription TypeText
Start DatetoLocaleDateString()
End DatetoLocaleDateString()
Days Leftdayjs(endDate).diff(dayjs(), 'day') or "Expired"
NameText
ServicesTag array (blue)
% Consumed(totalBandwidth / consumptionLimit * 100).toFixed(2)% → Red if >100%
StatusGreen tag "Active" or Red "Expired" based on endDate < now

Features

  • Subscription tracking — Display all active/expired subscriptions
  • Consumption display — Show bandwidth/data consumption percentage
  • Date formatting — Locale-specific date display
  • Service tags — Color-coded service indicators
  • Days remaining — Calculate and display days until expiration

MFASetup Component

Purpose

Enable Firebase Phone-based multi-factor authentication.

Features

  1. Firebase Phone Auth — Uses Firebase Authentication with phone verification
  2. reCAPTCHA v3 — Invisible verification (currently in testing mode)
  3. Verify email first — Check auth.currentUser.emailVerified before enabling MFA
  4. Two-step flow:
    • Input phone + send verification code
    • Input received code + verify + enable MFA

Implementation Notes

  • auth.appVerificationDisabledForTesting = true enables testing without phone
  • reCAPTCHA container: <div id="recaptcha-container" style={{ display: "none" }} />
  • Verification ID stored in window.verificationId
  • PhoneAuthProvider + multiFactor(user).enroll() enroll phone factor

Currently Disabled UI

The MFA setup UI is commented out in the current implementation:

{
/* All UI is hidden */
}
// The button, alert, and entire MFA form are commented out

Workflow: Enable MFA

Step 1: Verify Email

const verifyEmail = async () => {
const user = auth.currentUser;
if (!user.emailVerified) {
await sendEmailVerification(user);
message.info('Please verify your email first');
return false;
}
return true;
};

Step 2: Request Phone Verification

const handleSendVerificationCode = async (phoneNumber) => {
try {
// Create reCAPTCHA verifier
const verifier = new RecaptchaVerifier('recaptcha-container', {
size: 'invisible'
}, auth);

const confirmationResult = await signInWithPhoneNumber(
auth,
phoneNumber,
verifier
);

window.confirmationResult = confirmationResult;
message.success('Verification code sent');
} catch (error) {
message.error('Failed to send verification code');
}
};

Step 3: Verify Code & Enroll

const handleVerifyCode = async (code) => {
try {
const credential = await window.confirmationResult.confirm(code);

// Enroll phone as MFA factor
const user = auth.currentUser;
const phoneAuthProvider = new PhoneAuthProvider(auth);

await multiFactor(user).enroll(
phoneAuthProvider.credential(credential)
);

message.success('MFA enabled successfully');
} catch (error) {
message.error('Invalid code or verification failed');
}
};

Integration Points & Dependencies

API Services

import {
fetchNotificationPreferences,
updateNotificationPreferences,
updateTeamName,
updateMemberRole,
removeMemberFromTeam,
addMemberToTeam,
addExistingMemberToTeam,
fetchAvailableClientProfiles,
fetchClientCatalogues,
updateProfileDetails,
fetchTeamMembers,
} from "../../services/api/profileApi";

import {
createTeamNotification,
notifyAllTeamAdmins,
} from "../../services/api/notificationService";

import { getSubscriptions } from "../../services/api/subscriptionApi";

Firebase

import { auth } from "../../data/base";
import { doc, getDoc } from "firebase/firestore";
import {
updatePassword,
reauthenticateWithCredential,
EmailAuthProvider,
PhoneAuthProvider,
RecaptchaVerifier,
multiFactor,
sendEmailVerification,
signInWithPhoneNumber,
} from "firebase/auth";

Utilities

import { secureGetItem } from "../../data/utils";

Ant Design Components Used

  • Modal, Form, Input, Button, Table, Select, Tag, Badge
  • Avatar, Spin, Alert, Divider, Row, Col, Card, Typography
  • Radio, Checkbox, Switch, Dropdown
  • DatePicker, TimePicker, Progress
  • Tooltip, Popover, Popconfirm

Key Patterns & Anti-Patterns

✅ Good Patterns

  1. Buffered State for Edits — Role changes staged in pendingChanges before save

    • Allows user to make multiple changes and save once
    • Preserves original data for cancel restoration
  2. Deep Copy for CanceloriginalTeamData stores deep copy for restoration

    • Prevents accidental mutations
    • Enables safe rollback on cancel
  3. Notification Orchestration — Two-level notifications (member + admins)

    • Direct notification to affected member
    • Broadcast notification to all admins
    • Non-blocking on failure
  4. Optimistic Updates — UI updates before API call, rolls back on error

    • Better UX (instant feedback)
    • Rollback on network/server error
  5. Conditional RBAC — Permission checks before rendering edit controls

    • Prevents unauthorized actions at UI level
    • Server-side validation still required
  6. Hierarchical Role Mapping — Clear server → display role conversion

    • Centralized role transformation logic
    • Easy to modify role hierarchy

⚠️ Complexity Notes

  1. Modal Coordination — Multiple nested modals (AddMemberModal, ConfirmInvitationModal, AddCatalogueModal)

    • Require careful state tracking
    • Complex event flow and callbacks
    • Risk of state inconsistency
  2. Subscription Recalculation — useEffect dependency chain can lead to infinite loops

    • Mitigated with isFirstEditRender flag
    • Watch out for circular dependencies
  3. Notification Errors Non-Fatal — Notifications may fail silently

    • Operation completes but user doesn't receive email
    • Log errors for debugging but don't block
  4. Email Domain from Client — Tight coupling to Client document structure

    • If Client doc structure changes, AddMemberModal breaks
    • Consider abstraction layer

⚠️ Anti-Patterns to Avoid

  1. Direct Firestore Updates — Always use API wrapper services

    • Easier to test and mock
    • Centralized error handling
  2. Rendering in useEffect — Use state to trigger re-renders

    • Avoid setState in useEffect without dependencies
    • Watch for infinite loops
  3. Missing Error Boundaries — Always catch async errors

    • User won't know operation failed
    • Silent failures are hard to debug
  4. Race Conditions — Multiple async operations can conflict

    • Example: User saves while editing roles
    • Use debouncing or request queuing

Performance Considerations

Lazy Loading

  • Fetch team data only on component mount
  • Load notifications preferences on demand
  • Images loaded only when modal opens

Memoization

const mappedTeams = useMemo(() => {
return teams.map(team => ({
...team,
displayRole: mapRole(team.role)
}));
}, [teams]);

Pagination

  • Large team lists should paginate
  • Consider virtual scrolling for 100+ members
  • Limit API results per request

Caching

  • Cache notification preferences locally
  • Use React Query or SWR for data synchronization
  • Implement cache invalidation on updates

Testing Strategy

Unit Tests

  • Test role mapping logic
  • Test notification preference calculations
  • Test error handling

Integration Tests

  • Test full team member add workflow
  • Test role change workflow
  • Test password change flow

E2E Tests

  • User adds team member end-to-end
  • User edits member roles end-to-end
  • User manages notifications end-to-end

Profile folder components:

  • /src/components/Profile/PersonalInformation.js
  • /src/components/Profile/ChangePassword.js
  • /src/components/Profile/NotificationsSection.js
  • /src/components/Profile/TeamsSection.js ← Most complex
  • /src/components/Profile/TeamSection.js
  • /src/components/Profile/AddMemberModal.js ← Complex modal
  • /src/components/Profile/MemberDetailsModal.js ← Complex modal
  • /src/components/Profile/AssociatedBrands.js
  • /src/components/Profile/MFASetup.js
  • /src/components/Profile/BrandIdentity/

API services:

  • /src/services/api/profileApi.js
  • /src/services/api/notificationService.js
  • /src/services/api/subscriptionApi.js

Theme & utilities:

  • /src/theme/theme.js
  • /src/data/utils.js (secureGetItem)
  • /src/data/base.js (Firebase config)