Skip to main content
Version: 1.0.0

Notifications

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

NotificationsSection Component

Purpose

Display and manage role-based notification preferences grouped by category.

Features

  1. Load preferences on mount — Fetch user's notification settings
  2. Group toggle — Switch all notifications in a group on/off
  3. API sync — Each toggle calls updateNotificationPreferences() for each key
  4. Role filtering — Only show groups the user has access to (via preferences.hasOwnProperty(key))
  5. State restoration — On error, restore previous preferences

Notification Groups (8 Groups)

const NOTIFICATION_GROUPS = {
Admin: {
description: "Receive email notifications for administrative tasks...",
notificationKeys: [
"sendQuotationRequestEmailHttp",
"catalogOrderRejectionNotification",
"processSupportRequest",
],
},
Catalogue: {
description:
"Receive email notifications when new catalogues are published",
notificationKeys: ["newCatalogueHasBeenPublished"],
},
Orders: {
description: "Receive email notifications about quotations and orders",
notificationKeys: [
"sendQuotationRequestEmailHttpConfirmation",
"sendQuotationEmail",
"processCatalogOrderHttp",
],
},
Subscription: {
description:
"Receive email notifications about licence status and renewals",
notificationKeys: [
"licenseHasExpired",
"licenseHasBeenRenewed",
"subscriptionsMail",
],
},
Support: {
description:
"Receive email notifications when you submit support requests",
notificationKeys: ["processSupportRequestConfirmation"],
},
Teams: {
description:
"Receive email notifications about team invitations and member changes",
notificationKeys: [
"inviteMemberTeam",
"deletedMemberTeam",
"roleChangedMemberTeam",
],
},
"Weekly 3D Assets": {
description:
"Receive a weekly report on published variants and 3D assets",
notificationKeys: ["weeklyPublishedVariantsReport"],
},
"Weekly 3D Modelling": {
description:
"Receive a weekly report on assigned SKUs for 3D modelling",
notificationKeys: ["weeklySkuAssigned"],
},
};

Notification Groups Detail

Admin Group

  • sendQuotationRequestEmailHttp — New quotation requests
  • catalogOrderRejectionNotification — Order rejection notifications
  • processSupportRequest — Support request processing

Catalogue Group

  • newCatalogueHasBeenPublished — New catalogue publications

Orders Group

  • sendQuotationRequestEmailHttpConfirmation — Quotation confirmations
  • sendQuotationEmail — Quotation details
  • processCatalogOrderHttp — Order processing

Subscription Group

  • licenseHasExpired — License expiration alerts
  • licenseHasBeenRenewed — License renewal notifications
  • subscriptionsMail — Subscription status updates

Support Group

  • processSupportRequestConfirmation — Support ticket confirmations

Teams Group

  • inviteMemberTeam — Team invitation notifications
  • deletedMemberTeam — Member removal notifications
  • roleChangedMemberTeam — Role change notifications

Weekly 3D Assets Group

  • weeklyPublishedVariantsReport — Weekly variant reports

Weekly 3D Modelling Group

  • weeklySkuAssigned — Weekly SKU assignment reports

Layout

  • Group name + description
  • Toggle switch (currently disabled - for display only)
  • Dividers between groups
  • Empty state if no notifications accessible

Component State Management

const [preferences, setPreferences] = useState({}); // User's notification preferences
const [loading, setLoading] = useState(true); // Loading state
const [hasError, setHasError] = useState(false); // Error state
const [lastLoadedPreferences, setLastLoadedPreferences] = useState({}); // For rollback

Workflow: Load User Preferences

Step 1: Mount Component

useEffect(() => {
const loadPreferences = async () => {
try {
setLoading(true);
const userPrefs = await fetchNotificationPreferences(userId);
setPreferences(userPrefs);
setLastLoadedPreferences(userPrefs); // Store for rollback
} catch (error) {
console.error('Error loading preferences:', error);
setHasError(true);
} finally {
setLoading(false);
}
};

loadPreferences();
}, [userId]);

Workflow: Toggle Notification Group

Step 1: User Clicks Toggle

const handleGroupToggle = async (groupName, isEnabled) => {
const group = NOTIFICATION_GROUPS[groupName];

try {
// Update each notification key in the group
for (const key of group.notificationKeys) {
await updateNotificationPreferences(userId, key, isEnabled);
}

// Update local state
const updatedPrefs = { ...preferences };
group.notificationKeys.forEach(key => {
updatedPrefs[key] = isEnabled;
});
setPreferences(updatedPrefs);

message.success(`${groupName} notifications ${isEnabled ? 'enabled' : 'disabled'}`);
} catch (error) {
console.error('Error updating preferences:', error);
message.error('Failed to update notification preferences');

// Rollback to previous state
setPreferences(lastLoadedPreferences);
}
};

UI Display Logic

Determine Group Status:

const isGroupEnabled = (groupName) => {
const group = NOTIFICATION_GROUPS[groupName];
return group.notificationKeys.every(key => preferences[key] === true);
};

const isGroupPartiallyEnabled = (groupName) => {
const group = NOTIFICATION_GROUPS[groupName];
const enabledCount = group.notificationKeys.filter(
key => preferences[key] === true
).length;
return enabledCount > 0 && enabledCount < group.notificationKeys.length;
};

Render Group UI:

{NOTIFICATION_GROUPS.map((groupName, group) => (
<div key={groupName}>
<Row justify="space-between" align="middle">
<Col>
<Typography.Title level={5}>{groupName}</Typography.Title>
<Typography.Text type="secondary">
{group.description}
</Typography.Text>
</Col>
<Col>
<Switch
checked={isGroupEnabled(groupName)}
indeterminate={isGroupPartiallyEnabled(groupName)}
onChange={(checked) => handleGroupToggle(groupName, checked)}
/>
</Col>
</Row>
<Divider />
</div>
))}

Role-Based Filtering

Only show groups user has access to:

const visibleGroups = Object.keys(NOTIFICATION_GROUPS).filter(groupName => {
const group = NOTIFICATION_GROUPS[groupName];
// User sees group if they have at least one key in preferences
return group.notificationKeys.some(key => key in preferences);
});

Error Handling

Error TypeUser FeedbackRecovery
Load preferences failsShow error messageRetry button to reload
Toggle failsError toastRollback to previous state
Network timeout"Connection lost" messageAuto-retry with exponential backoff
Permission denied"You don't have access"None (disable all toggles)

Edge Cases

Edge Case 1: Group Partially Enabled

Admin group has 3 notifications:
- Quotation requests: ✓ ENABLED
- Order rejection: ✗ DISABLED
- Support request: ✓ ENABLED

Result: Switch shows INDETERMINATE state (partial)
Action: User clicking toggle → ALL notifications in group toggle

Edge Case 2: No Preferences Found

User has no preference document
→ Show empty state
→ All toggles appear disabled
→ User can enable groups → Creates preference document

Edge Case 3: Preference Key Missing

Group has 3 keys but user only has 2 in preferences
→ Compare: preferences.hasOwnProperty(key)
→ Show only accessible notifications
→ Partial toggle behavior