Overview

The Non-Operational Day Management System is a comprehensive feature within the audit administration platform that enables organizations to manage when auditors, sites, and the entire organization are not operational. The system operates at three distinct levels:

  • Organization Level: Global non-operational days that affect all sites and auditors
  • Site Level: Site-specific non-operational days that override organization settings
  • User Level: Individual auditor non-operational day assignments

Key Features

  • Multi-Level Hierarchy: Organization → Site → User level off-days management
  • Dashboard Analytics: Comprehensive metrics and visualization for non-operational patterns
  • Bulk Operations: Mass assignment and management of off-days
  • Calendar Integration: Visual calendar interface for date selection and management
  • Real-time Updates: Live synchronization across all interfaces
  • Permission-based Access: Role-based access control for different management levels

Architecture

The Non-Operational Day Management System follows a sophisticated multi-layered architecture designed to handle complex organizational hierarchies and real-time data synchronization:

System Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                          PRESENTATION LAYER                        │
├─────────────────┬─────────────────┬─────────────────────────────────┤
│   Organization  │   Site Level    │        Auditor Level            │
│     Level       │                 │                                 │
├─────────────────┼─────────────────┼─────────────────────────────────┤
│ • Firebase      │ • Redux State   │ • REST API                      │
│   Connection    │   Management    │   Integration                   │
│ • Direct        │ • Custom Hooks  │ • Complex Data                  │
│   Firestore     │ • Saga          │   Transformation                │
│   Updates       │   Middleware    │ • User Assignment               │
└─────────────────┴─────────────────┴─────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         BUSINESS LOGIC LAYER                       │
├─────────────────────────────────────────────────────────────────────┤
│ • Permission-based Access Control                                  │
│ • Data Hierarchy Management (Organization → Site → User)           │
│ • Calendar Integration & Date Processing                           │
│ • Real-time Synchronization Logic                                  │
│ • Complex Query Parameter Management                               │
└─────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                           DATA LAYER                               │
├─────────────────┬─────────────────┬─────────────────────────────────┤
│   Firestore     │   REST APIs     │        Local State              │
│   Collections   │                 │                                 │
├─────────────────┼─────────────────┼─────────────────────────────────┤
│ • Organization  │ • User Off-Days │ • Component State               │
│   Off-Days      │   Management    │ • Form State                    │
│ • Real-time     │ • Dashboard     │ • UI State                      │
│   Updates       │   Analytics     │ • Cache Management              │
│                 │ • Site Off-Days │                                 │
└─────────────────┴─────────────────┴─────────────────────────────────┘

Data Flow Architecture

The system implements three distinct data flow patterns based on the operational level:

1. Organization Level Data Flow

[Firestore] ←→ [React-Redux-Firebase] ←→ [OffDaysManager] ←→ [OffDaysDatePicker]
     ↑                                                              ↑
     └─────────────── Real-time Updates ──────────────────────────┘

2. Site Level Data Flow

[REST API] → [Redux Action] → [Saga Middleware] → [Reducer] → [Hook] → [Component]
     ↑                                                                      ↓
     └─────────────────── API Calls ←──────────────────────────────────────┘

3. Auditor Level Data Flow

[REST API] ←→ [Service Layer] ←→ [Component State] ←→ [Date Picker Component]
     ↑                                                         ↓
     └── Complex Data Transformation & User Assignment ←──────┘

Key Architectural Components

Frontend Architecture

  • React Components: Modular, reusable components with clear separation of concerns
  • Styled Components: CSS-in-JS for consistent theming and responsive design
  • Redux State Management: Centralized state for site-level operations
  • Custom Hooks: Encapsulation of business logic and API interactions
  • React-Redux-Firebase: Real-time Firestore integration for organization data

State Management Strategy

  • Organization Level: Firebase real-time updates via react-redux-firebase
  • Site Level: Redux with saga middleware for complex async operations
  • User Level: Local component state with API integration
  • Dashboard: Composite state management with multiple data sources

Data Storage Strategy

  • Firestore Collections:
    • organizationOffDay: Organization-wide off-days
    • Real-time synchronization across all clients
  • REST API Endpoints:
    • /users/off-days: User-specific off-day management
    • /sites/off-days/{siteID}: Site-specific configurations
    • /users/off-days/count: Dashboard metrics
    • /users/off-days/upcoming: Schedule analytics

Permission & Access Control Architecture

graph TB
    A[User Authentication] --> B{Permission Check}
    B --> C[Admin Non-Operational Days Access]
    C --> D{Level Access}
    D --> E[Organization Level]
    D --> F[Site Level] 
    D --> G[User Level]
    E --> H[Full Calendar Management]
    F --> I[Site Override Capability]
    G --> J[Individual Assignment]

Component Hierarchy

Layout
├── AdminPage
    ├── OffDaysManager (Organization)
    │   ├── OffDaysHeader
    │   └── OffDaysDatePicker (Shared)
    ├── OffDaysManager (Auditor)
    │   ├── OffDaysHeader  
    │   └── OffDaysDatePicker (Auditor-specific)
    ├── SiteOffDays
    │   ├── Toggle Switch
    │   ├── useSiteOffDays Hook
    │   └── OffDaysDatePicker (Shared)
    └── OffDaysDashboard
        ├── UserMetrics (75% width)
        ├── OffDaysTable (75% width)
        ├── TotalNonOffDays (25% width)
        └── UpcomingSchedule (25% width)

Technology Stack Integration

Core Technologies

  • React 17+: Component framework with hooks
  • TypeScript: Type safety and development tooling
  • Styled Components: CSS-in-JS styling solution
  • Redux Toolkit: State management with standardized patterns
  • Redux-Saga: Side effect management for complex async flows

UI/UX Libraries

  • React-Dates: Advanced calendar picker with customization
  • Chart.js: Data visualization for analytics dashboard
  • React-Select: Advanced select components with search/filter
  • @nimbly-technologies/audit-component: Internal component library

Data & API Integration

  • Firebase SDK: Firestore integration and authentication
  • React-Redux-Firebase: Firebase-Redux binding
  • Fetch API: REST endpoint communication
  • @nimbly-technologies/nimbly-common: Shared type definitions

Scalability & Performance Considerations

Optimization Strategies

  • Lazy Loading: Code splitting for route-based components
  • Memoization: React.memo and useMemo for expensive computations
  • Debounced Search: Reduced API calls for search functionality
  • Pagination: Table data loaded in chunks of 10 items
  • Responsive Calendars: Dynamic month count based on screen size

Data Management Efficiency

  • Real-time Updates: Only for organization-level changes requiring immediate sync
  • Cached Responses: Component-level caching for frequently accessed data
  • Optimistic Updates: UI updates before API confirmation
  • Selective Rendering: Custom cell renderers for table performance

Core Components

The Non-Operational Day Management System is built using a sophisticated component architecture that enables multi-level management across organization, site, and user levels.

Organization Level Components

OffDaysManager (Organization)

File: src/components/offdays/OffDaysManager.tsx

The organization-level off-days manager provides comprehensive calendar management for organization-wide non-operational days.

Key Features:

  • Real-time Firestore Integration: Direct connection to Firebase for immediate synchronization
  • Organization-wide Scope: Changes affect all sites and users unless overridden
  • Redux Integration: Connected to Firebase state via react-redux-firebase
  • Permission Validation: Checks userAccess.admin['non-operational-days'].all.permissions

Technical Implementation:

interface OffDays {
  organization: string;
  siteKey?: string;
  dates: Dates; // { [date: string]: boolean }
}

State Management:

  • Uses firestoreConnect for real-time data binding
  • Firestore collection: organizationOffDay
  • Local state for temporary changes before save
  • Optimistic UI updates with error handling

Business Logic:

  • Date management with moment.js integration
  • Validation of date selections
  • Bulk save operations with transaction support
  • Error monitoring with Monitoring.logEvent

Site Level Components

SiteOffDays Component

File: src/components/sites/SiteOffDays/SiteOffDays.tsx

Site-specific off-days management that can override organization settings.

Key Features:

  • Toggle-based Enable/Disable: Visual slider to activate site-specific off-days
  • Organization Override: When enabled, site off-days take precedence
  • Visual Inheritance: Shows organization off-days as dots on the calendar
  • Redux-Saga Integration: Complex async state management

Component Structure:

const SiteOffDays = ({ organizationOffDay, siteKey }) => {
  const [
    { isFetchLoading, isUpsertLoading, siteOffDays },
    { handleOffDayToggle, handleChangeOffDay, handleSubmitOffDay }
  ] = useSiteOffDays({
    siteID: siteKey,
    onFetchError, onUpsertError, onUpsertSuccess
  });
}

useSiteOffDays Custom Hook

File: src/components/sites/SiteOffDays/hook/useSiteOffDays.ts

Encapsulates all site off-days business logic and state management.

Hook Features:

  • Loading State Management: Separate states for fetch and upsert operations
  • Error Handling: Comprehensive error callbacks with i18n support
  • Data Transformation: Converts array format to boolean object mapping
  • Redux Integration: Dispatches actions and manages saga lifecycle

Return Interface:

type UseSiteOffDaysReturnType = [
  {
    isFetchLoading: boolean;
    isUpsertLoading: boolean;
    siteOffDays: ProcessedSiteOffDays;
  },
  {
    handleOffDayToggle: () => void;
    handleChangeOffDay: (newOffDays: OffDays) => void;
    handleSubmitOffDay: () => void;
  }
];

User Level Components

OffDaysManager (Auditor)

File: src/components/auditors/offDaysManager/OffDaysManager.tsx

Manages individual auditor off-day assignments with complex user-date mapping.

Key Features:

  • Multi-User Assignment: Multiple users can be assigned to the same date
  • Complex Data Transformation: Converts between date-user and user-date mappings
  • REST API Integration: Uses /users/off-days endpoint
  • Differential Updates: Tracks added and removed users for efficient API calls

Data Transformation Logic:

// Frontend Format: { [date]: [userID1, userID2] }
const frontendFormat = {
  '2024-01-15': ['user1', 'user2'],
  '2024-01-16': ['user3']
};
 
// API Format: [{ user1: ['2024-01-15'] }, { user2: ['2024-01-15'] }]
const apiFormat = [
  { user1: ['2024-01-15'] },
  { user2: ['2024-01-15'] },
  { user3: ['2024-01-16'] }
];

API Integration:

  • Fetch: GET /users/off-days - Retrieves current assignments
  • Save: POST /users/off-days - Updates assignments with differential logic
  • Error Handling: Comprehensive error states with monitoring

OffDaysDatePicker (Auditor-specific)

File: src/components/auditors/offDaysManager/offDaysDatePicker.tsx

Specialized calendar picker for auditor assignments with user management interface.

Features:

  • User Selection Interface: Shows assigned user counts per date
  • Multi-User Support: Assign multiple auditors to single dates
  • Visual Indicators: Different styling for assigned vs available dates
  • User Management: Add/remove users from specific dates

Shared Components

OffDaysDatePicker (Shared)

File: src/components/global/OffDaysDatePicker/OffDaysDatePicker.tsx

Highly sophisticated calendar component used across organization and site levels.

Advanced Features:

  • Responsive Design: Dynamic month count (1-2) based on screen width
  • Year Navigation: Select dropdown with range 2019-2025
  • Dual View: Calendar grid + selected dates list
  • Organization Inheritance: Shows org off-days as dots on site calendars
  • Custom Styling: Extensive CSS customization for calendar appearance

Technical Specifications:

interface OffDayProps {
  type: 'site' | 'organization';
  organizationOffDay: OffDays;
  siteOffDay?: OffDays;
  handleUpdateOffDay: (offDays: OffDays) => void;
}

Responsive Behavior:

  • Desktop (>1275px): 2-month view
  • Tablet (992-1275px): 1-month view
  • Mobile (<992px): 2-month view (if >682px), 1-month view (if <682px)

Calendar Customization:

  • react-dates Integration: DayPickerSingleDateController
  • Custom Navigation: Back/forward arrows with custom styling
  • Highlighting Logic: Different states for selected, highlighted, and blocked dates
  • Tooltip Support: Hover information for organization off-days

Dashboard Components

OffDaysDashboard

File: src/components/auditors/offDaysDashboard/OffDaysDashboard.tsx

Main dashboard layout with analytics and management capabilities.

Layout Structure:

  • 75% Main Area: UserMetrics + OffDaysTable
  • 25% Sidebar: TotalNonOffDays + UpcomingSchedule
  • Responsive Design: Tailwind CSS classes for consistent layout

UserMetrics Widget

File: src/components/auditors/offDaysDashboard/UserMetrics.tsx

Displays real-time user count metrics across different time periods.

Metrics Displayed:

  • Today: Current day off-duty count
  • This Week: Weekly off-duty count
  • This Month: Monthly off-duty count
  • This Year: Annual off-duty count

API Integration:

  • Endpoint: GET /users/off-days/count
  • Response Format: UserCountI { today, week, month, year }
  • Loading State: Skeleton loading with spinner
  • Error Handling: Graceful fallback to zero values

OffDaysTable Component

File: src/components/auditors/offDaysDashboard/OffDaysTable.tsx

Advanced data table with dual view modes and comprehensive filtering.

View Modes:

  1. User-wise View: Groups by user, shows their off-days
  2. Date-wise View: Groups by date, shows affected users

Advanced Features:

  • Segmented View Toggle: Switch between user-wise and date-wise views
  • Advanced Filtering: Multi-select filters for users, sites, departments, date ranges
  • Calendar Integration: Date picker for date-wise view with visual indicators
  • Search Functionality: Debounced search with 500ms delay
  • Pagination: 10 items per page with navigation controls
  • Sorting: Multi-column sorting with visual indicators

Filter Configuration:

const filterConfigs: FilterConfig[] = [
  { name: 'user', type: FilterFieldType.MULTI_SELECT },
  { name: 'date', type: FilterFieldType.DATE_RANGE_PRESET },
  { name: 'sites', type: FilterFieldType.MULTI_SELECT },
  { name: 'departments', type: FilterFieldType.MULTI_SELECT }
];

Integration Points:

  • Issue Tracking: Links to issues page with date/user filters
  • Schedule Details: Modal views for schedule information
  • User Management: Navigation to user off-days management

TotalNonOffDays Chart

File: src/components/auditors/offDaysDashboard/TotalNonOffDays.tsx

Interactive chart displaying monthly non-operational day trends.

Chart Features:

  • Chart.js Integration: Line chart with gradient fill
  • Month Selection: Dropdown for 2020-2026 range
  • Gradient Styling: Purple gradient matching brand colors
  • Responsive Design: Maintains aspect ratio across devices

API Integration:

  • Endpoint: GET /users/off-days/userOffDaysPerMonth
  • Query Parameter: yearMonth (YYYY-MM format)
  • Data Processing: Sorts dates and formats for chart display

UpcomingSchedule Widget

File: src/components/auditors/offDaysDashboard/UpcomingSchedule.tsx

Displays upcoming scheduled off-days categorized by time periods.

Categories:

  • Today: Users scheduled off today
  • This Week: Users scheduled off this week
  • Next Week: Users scheduled off next week (labeled as “This Month”)

UI Elements:

  • Profile Icons: Visual user representation
  • Scrollable List: Accommodates long user lists
  • Empty State: “No upcoming schedules” message

API Integration:

  • Endpoint: GET /users/off-days/upcoming
  • Response: UpcomingScheduleI { today[], thisWeek[], nextWeek[] }

ScheduleListModal & ScheduleDetailModal

Files:

Purpose: Provide detailed schedule information with drill-down capability.

Navigation Flow:

  1. User clicks schedule count in table
  2. ScheduleListModal opens with schedule list
  3. User selects specific schedule
  4. ScheduleDetailModal opens with detailed information
  5. User can navigate back to list or close entirely

Component Integration Patterns

Shared State Management

// Organization Level - Firebase Real-time
const organizationOffDay = getVal(state.firestore.data, '@organizationManagerOrganizationOffDay');
 
// Site Level - Redux State
const { siteOffDays } = useSelector((state: RootState) => state.siteOffDays);
 
// User Level - Local State
const [tempOrganizationOffDay, setTempOrganizationOffDay] = useState<Dates>({});

Error Handling Patterns

  • Firestore: Uses isLoaded() checks and loading states
  • REST API: Try-catch blocks with Monitoring.logEvent
  • Redux: Error states in reducers with saga error handling
  • User Feedback: Toast notifications for all operations

Performance Optimization

  • Code Splitting: Lazy loading for all page components
  • Memoization: useMemo for expensive table data calculations
  • Debouncing: Search inputs to reduce API calls
  • Selective Rendering: Custom table cell renderers for efficiency

API Endpoints

The Non-Operational Day Management System integrates with multiple API layers and data storage systems. This section provides comprehensive documentation of all endpoints, their implementations, and integration patterns.

User Off-Days API

GET /users/off-days

Purpose: Retrieve current user off-day assignments
Service File: src/services/auditorOffDays/auditorOffDays.service.ts
Component Usage: src/components/auditors/offDaysManager/OffDaysManager.tsx:41

Authentication: Firebase Token Required
Method: GET
Headers:

{
  Authorization: string // Firebase JWT token
}

Response Format:

{
  data: {
    userIDs: Array<{ [userID: string]: string[] }> // User ID mapped to array of dates
  }
}

Response Example:

{
  "data": {
    "userIDs": [
      { "user123": ["2024-01-15", "2024-01-16"] },
      { "user456": ["2024-01-15", "2024-01-20"] }
    ]
  }
}

Business Logic:

  • Fetches all user assignments across all dates
  • Used for initial load and refresh operations
  • Data transformation occurs client-side to convert to date-user mapping

POST /users/off-days

Purpose: Update user off-day assignments with differential logic
Service File: src/services/auditorOffDays/auditorOffDays.service.ts
Component Usage: src/components/auditors/offDaysManager/OffDaysManager.tsx:79

Authentication: Firebase Token Required
Method: POST
Headers:

{
  Authorization: string,
  'Content-Type': 'application/json'
}

Request Body:

{
  userIDs: Array<{ [userID: string]: string[] }> // Complete user assignments
}

Request Example:

{
  "userIDs": [
    { "user123": ["2024-01-15", "2024-01-16"] },
    { "user456": ["2024-01-15"] },
    { "user789": [] } // Empty array removes all assignments
  ]
}

Complex Business Logic:

  • Differential Updates: Compares current state vs new state
  • Removal Logic: Empty arrays signal complete removal of user assignments
  • Bulk Operations: Handles multiple user updates in single request
  • Data Transformation: Converts from date-user mapping to user-date mapping

Error Handling:

  • HTTP 200: Success with data refresh
  • Other status codes: Error toast with monitoring log

GET /users/off-days/count

Purpose: Retrieve user count metrics for dashboard
Service File: src/services/auditorOffDays/auditorOffDays.service.ts:11
Component Usage: src/components/auditors/offDaysDashboard/UserMetrics.tsx:22

Authentication: Firebase Token Required
Method: GET
Headers:

{
  Authorization: string
}

Response Format:

interface UserCountI {
  today: number;
  week: number;
  month: number;
  year: number;
}

Response Example:

{
  "data": {
    "today": 5,
    "week": 12,
    "month": 45,
    "year": 150
  }
}

Metrics Calculation:

  • Today: Users with off-days on current date
  • Week: Users with off-days in current week
  • Month: Users with off-days in current month
  • Year: Users with off-days in current year

GET /users/off-days/upcoming

Purpose: Retrieve upcoming scheduled off-days for dashboard widget
Service File: src/services/auditorOffDays/auditorOffDays.service.ts:32
Component Usage: src/components/auditors/offDaysDashboard/UpcomingSchedule.tsx:24

Authentication: Firebase Token Required
Method: GET

Response Format:

interface UpcomingScheduleI {
  today: string[];    // User names
  thisWeek: string[]; // User names
  nextWeek: string[]; // User names (labeled as "This Month" in UI)
}

Response Example:

{
  "data": {
    "today": ["John Doe", "Jane Smith"],
    "thisWeek": ["Mike Johnson", "Sarah Wilson"],
    "nextWeek": ["David Brown", "Lisa Davis"]
  }
}

Business Logic:

  • Returns user names (not IDs) for display
  • Categorizes by time periods for dashboard organization
  • Used for upcoming schedule widget in dashboard sidebar

GET /users/off-days/userOffDaysPerMonth

Purpose: Retrieve monthly non-operational day statistics for chart visualization
Service File: src/services/auditorOffDays/auditorOffDays.service.ts:53
Component Usage: src/components/auditors/offDaysDashboard/TotalNonOffDays.tsx:84

Authentication: Firebase Token Required
Method: GET
Query Parameters:

{
  yearMonth: string // Format: "YYYY-MM"
}

Request Example:

GET /users/off-days/userOffDaysPerMonth?yearMonth=2024-01

Response Format:

interface MonthlyNonOpsI {
  [date: string]: number; // Date (YYYY-MM-DD) mapped to user count
}

Response Example:

{
  "data": {
    "2024-01-01": 3,
    "2024-01-02": 5,
    "2024-01-15": 8,
    "2024-01-31": 2
  }
}

Chart Integration:

  • Data processed for Chart.js line chart
  • Dates sorted chronologically for timeline visualization
  • Gradient fill styling applied for visual appeal

GET /users/off-days/userOffDaysData

Purpose: Retrieve paginated off-days data for dashboard table
Service File: src/services/auditorOffDays/auditorOffDays.service.ts:77
Component Usage: src/components/auditors/offDaysDashboard/OffDaysTable.tsx:332

Authentication: Firebase Token Required
Method: GET
Query Parameters:

// User-wise View Parameters
{
  type: 'user';
  department?: string[];
  site?: string[];
  users?: string[];
  startDate?: string; // YYYY-MM-DD
  endDate?: string;   // YYYY-MM-DD
  search?: string;
  sortBy?: string;
  order?: 'asc' | 'desc';
  limit?: number;
  page?: number;
}
 
// Date-wise View Parameters
{
  type: 'date';
  dates?: string[]; // Array of YYYY-MM-DD dates
  sortBy?: string;
  order?: 'asc' | 'desc';
  limit?: number;
  page?: number;
}

Request Examples:

// User-wise view
GET /users/off-days/userOffDaysData?type=user&search=john&sortBy=name&order=asc&limit=10&page=1

// Date-wise view
GET /users/off-days/userOffDaysData?type=date&dates=2024-01-15,2024-01-16&limit=10&page=1

Response Format:

interface NonOpsDataI {
  docs: NonOpsDocsI[];
  limit?: number | string;
  page?: number | string;
  totalDocs?: number;
  totalPages?: number;
}
 
interface NonOpsDocsI {
  userID?: string;
  name?: string;
  data: NonOpsDetailDataI[];
  date?: string; // For date-wise view
}
 
interface NonOpsDetailDataI {
  date?: string;
  issueCount: number;
  scheduleCount: number;
  scheduleData: ScheduleDataI[];
  userId?: string;
  name?: string;
}

Advanced Features:

  • Dual View Support: User-wise and date-wise grouping
  • Complex Filtering: Multi-dimensional filtering capabilities
  • Pagination: Server-side pagination with metadata
  • Search Integration: Full-text search across user names
  • Schedule Integration: Links to schedule and issue data

Site Off-Days API

GET /sites/off-days/{siteID}

Purpose: Retrieve site-specific off-days configuration
Service File: src/services/siteOffDays/siteOffDays.service.ts:19
Component Usage: Via Redux Action src/reducers/site/siteOffDays/siteOffDays.action.ts

Authentication: Firebase Token Required
Method: GET
Path Parameters:

{
  siteID: string
}

Response Format:

interface SiteOffdayMongo {
  organizationID: string;
  siteID: string;
  dates: string[]; // Array of date strings
  disabled: boolean;
  createdAt?: Date;
  updatedAt?: Date;
}

Response Example:

{
  "data": {
    "organizationID": "org123",
    "siteID": "site456",
    "dates": ["2024-01-15", "2024-01-16", "2024-01-20"],
    "disabled": false,
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-10T00:00:00.000Z"
  }
}

Integration Pattern:

  • Called via Redux saga middleware
  • Response processed through custom hook
  • Data transformation from array to boolean mapping occurs client-side

PUT /sites/off-days/{siteID}

Purpose: Create or update site-specific off-days configuration
Service File: src/services/siteOffDays/siteOffDays.service.ts:6
Component Usage: Via Redux Action src/reducers/site/siteOffDays/siteOffDays.action.ts

Authentication: Firebase Token Required
Method: PUT
Path Parameters:

{
  siteID: string
}

Request Body:

Partial<SiteOffdayMongo> {
  organizationID?: string;
  siteID?: string;
  dates?: string[];
  disabled?: boolean;
}

Request Example:

{
  "organizationID": "org123",
  "siteID": "site456",
  "dates": ["2024-01-15", "2024-01-16"],
  "disabled": false
}

Response Format:

{
  data: string; // Success message
}

Error Handling:

Business Logic:

  • Upsert Operation: Creates new or updates existing configuration
  • Toggle Support: Enables/disables site-specific off-days
  • Organization Override: When enabled, overrides organization-level settings

Firestore Integration

Organization Off-Days Collection

Collection: organizationOffDay
Document ID: Organization ID
Access Pattern: Real-time subscription via react-redux-firebase
Component Usage: src/components/offdays/OffDaysManager.tsx:142

Document Structure:

{
  organization: string;
  dates: { [dateString: string]: boolean };
  updatedBy: string; // User UID
  updatedAt: Timestamp;
}

Document Example:

{
  "organization": "org123",
  "dates": {
    "2024-01-15": true,
    "2024-01-16": true,
    "2024-01-20": true
  },
  "updatedBy": "user456",
  "updatedAt": { "_seconds": 1704153600, "_nanoseconds": 0 }
}

Real-time Features:

  • Automatic Synchronization: Changes propagate immediately to all connected clients
  • Optimistic Updates: UI updates immediately, rolls back on error
  • Conflict Resolution: Last-write-wins with timestamp tracking

Security Rules:

  • Authentication required
  • Permission validation via userAccess.admin['non-operational-days'].all.permissions

API Integration Patterns

Authentication Flow

// Consistent authentication across all APIs
const token = await API.getFirebaseToken();
const headers = { Authorization: token };

Error Handling Strategy

// REST APIs
try {
  const response = await fetch(url, options);
  if (response.status === 200) {
    const data = await response.json();
    return data.data;
  } else {
    throw new Error('API Error');
  }
} catch (error) {
  Monitoring.logEvent('APIError', error);
  return Promise.reject(error);
}
 
// Firestore
try {
  await ref.set(data, { merge: false });
  toast.success(t('success.message'));
} catch (error) {
  Monitoring.logEvent('FirestoreError', error);
  toast.error(t('error.message'));
}

Data Transformation Patterns

// API to Frontend (User Off-Days)
const frontendFormat = userIDs.reduce((acc, userObj) => {
  Object.entries(userObj).forEach(([userID, dates]) => {
    dates.forEach(date => {
      if (!acc[date]) acc[date] = [];
      acc[date].push(userID);
    });
  });
  return acc;
}, {});
 
// Frontend to API (User Off-Days)
const apiFormat = Object.entries(frontendData).reduce((acc, [date, userIDs]) => {
  userIDs.forEach(userID => {
    const existingUser = acc.find(item => item[userID]);
    if (existingUser) {
      existingUser[userID].push(date);
    } else {
      acc.push({ [userID]: [date] });
    }
  });
  return acc;
}, []);
 
// Site Off-Days (Array to Boolean Mapping)
const processedDates = apiDates.reduce((map, date) => {
  map[date] = true;
  return map;
}, {});

API Performance Considerations

Caching Strategy

  • Component Level: Local state caching for UI responsiveness
  • Request Debouncing: 500ms delay for search operations
  • Pagination: 10 items per page to reduce payload size

Request Optimization

  • Batch Operations: Single request for multiple user updates
  • Differential Updates: Only send changed data
  • Query Parameter Validation: Client-side validation before API calls

Error Recovery

  • Automatic Retry: Network error retry with exponential backoff
  • Graceful Degradation: Fallback to cached data when APIs fail
  • User Feedback: Toast notifications for all operation states

Database Schema

The Non-Operational Day Management System utilizes a hybrid data storage approach combining Firestore for real-time organization data and MongoDB for complex relational operations.

Firestore Collections

organizationOffDay Collection

Collection Path: /organizationOffDay/{organizationID}
Purpose: Real-time organization-wide off-days management
Access Pattern: Document per organization with real-time subscriptions

Document Schema:

interface OrganizationOffDay {
  organization: string;           // Organization identifier
  dates: { [date: string]: boolean }; // Date mapping { "2024-01-15": true }
  updatedBy: string;             // User UID who made the change
  updatedAt: Timestamp;          // Firestore timestamp
  createdAt?: Timestamp;         // Optional creation timestamp
}

Document Example:

{
  "organization": "org_nimbly_123",
  "dates": {
    "2024-01-15": true,
    "2024-01-16": true,
    "2024-02-14": true,
    "2024-12-25": true
  },
  "updatedBy": "user_abc123",
  "updatedAt": {
    "_seconds": 1704153600,
    "_nanoseconds": 123456789
  },
  "createdAt": {
    "_seconds": 1704067200,
    "_nanoseconds": 0
  }
}

Indexing Strategy:

  • Primary Index: Document ID (organization)
  • Compound Index: organization + updatedAt (for audit trails)
  • TTL Index: None (permanent data)

Security Rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /organizationOffDay/{organizationId} {
      allow read, write: if request.auth != null 
        && hasPermission(resource, 'non-operational-days');
    }
  }
}

Real-time Subscriptions:

  • Connection Pattern: react-redux-firebase with automatic reconnection
  • Update Strategy: Optimistic updates with rollback on failure
  • Conflict Resolution: Last-write-wins with timestamp validation

MongoDB Collections (API Backend)

User Off-Days Collection

Collection: userOffDays
Purpose: Individual user off-day assignments
Database: Audit Admin MongoDB

Document Schema:

interface UserOffDay {
  _id: ObjectId;                 // MongoDB document ID
  organizationID: string;        // Organization reference
  userID: string;               // User identifier
  dates: string[];              // Array of ISO date strings
  createdAt: Date;              // Creation timestamp
  updatedAt: Date;              // Last update timestamp
  createdBy: string;            // User who created the assignment
  updatedBy: string;            // User who last updated
}

Document Example:

{
  "_id": { "$oid": "507f1f77bcf86cd799439011" },
  "organizationID": "org_nimbly_123",
  "userID": "user_auditor_456",
  "dates": [
    "2024-01-15",
    "2024-01-16",
    "2024-02-20"
  ],
  "createdAt": { "$date": "2024-01-01T00:00:00.000Z" },
  "updatedAt": { "$date": "2024-01-10T00:00:00.000Z" },
  "createdBy": "admin_user_789",
  "updatedBy": "admin_user_789"
}

Indexing Strategy:

// Primary indexes
db.userOffDays.createIndex({ "organizationID": 1, "userID": 1 }, { unique: true });
db.userOffDays.createIndex({ "organizationID": 1, "dates": 1 });
db.userOffDays.createIndex({ "updatedAt": -1 });
 
// Compound indexes for dashboard queries
db.userOffDays.createIndex({ 
  "organizationID": 1, 
  "dates": 1, 
  "userID": 1 
});
 
// Text search index
db.userOffDays.createIndex({
  "userID": "text",
  "createdBy": "text",
  "updatedBy": "text"
});

Aggregation Pipelines:

// User count metrics pipeline
const userCountPipeline = [
  { $match: { organizationID: "org_nimbly_123" } },
  { $unwind: "$dates" },
  { $addFields: {
    dateObj: { $dateFromString: { dateString: "$dates" } }
  }},
  { $group: {
    _id: null,
    today: { $sum: { $cond: [
      { $eq: [{ $dayOfYear: "$dateObj" }, { $dayOfYear: new Date() }] },
      1, 0
    ]}},
    week: { $sum: { $cond: [
      { $gte: ["$dateObj", startOfWeek] },
      1, 0
    ]}},
    month: { $sum: { $cond: [
      { $gte: ["$dateObj", startOfMonth] },
      1, 0
    ]}},
    year: { $sum: { $cond: [
      { $gte: ["$dateObj", startOfYear] },
      1, 0
    ]}}
  }}
];
 
// Monthly statistics pipeline
const monthlyStatsPipeline = [
  { $match: { 
    organizationID: "org_nimbly_123",
    dates: { $regex: "^2024-01" }
  }},
  { $unwind: "$dates" },
  { $group: {
    _id: "$dates",
    userCount: { $sum: 1 }
  }},
  { $sort: { "_id": 1 } }
];

Site Off-Days Collection

Collection: siteOffDays
Purpose: Site-specific off-day configurations
Database: Audit Admin MongoDB

Document Schema:

interface SiteOffDay {
  _id: ObjectId;                 // MongoDB document ID
  organizationID: string;        // Organization reference
  siteID: string;               // Site identifier
  dates: string[];              // Array of ISO date strings
  disabled: boolean;            // Enable/disable toggle
  createdAt: Date;              // Creation timestamp
  updatedAt: Date;              // Last update timestamp
  createdBy: string;            // User who created
  updatedBy: string;            // User who last updated
}

Document Example:

{
  "_id": { "$oid": "507f1f77bcf86cd799439012" },
  "organizationID": "org_nimbly_123",
  "siteID": "site_downtown_789",
  "dates": [
    "2024-01-15",
    "2024-03-17",
    "2024-07-04"
  ],
  "disabled": false,
  "createdAt": { "$date": "2024-01-01T00:00:00.000Z" },
  "updatedAt": { "$date": "2024-01-15T00:00:00.000Z" },
  "createdBy": "site_admin_456",
  "updatedBy": "site_admin_456"
}

Indexing Strategy:

// Unique site configuration per organization
db.siteOffDays.createIndex({ 
  "organizationID": 1, 
  "siteID": 1 
}, { unique: true });
 
// Query optimization indexes
db.siteOffDays.createIndex({ "organizationID": 1, "disabled": 1 });
db.siteOffDays.createIndex({ "updatedAt": -1 });

Relational Data Patterns

User Schedule Integration

Purpose: Link off-days with existing schedule and issue data
Pattern: Foreign key relationships via user IDs and dates

interface ScheduleIntegration {
  userID: string;               // Links to user management system
  date: string;                 // Links to off-days date
  scheduleCount: number;        // Computed from schedules collection
  issueCount: number;          // Computed from issues collection
  scheduleData: ScheduleDataI[]; // Populated via joins
}

Query Pattern Example:

// Complex join operation for dashboard table
const dashboardData = await db.collection('userOffDays').aggregate([
  { $match: { organizationID: orgId } },
  { $unwind: "$dates" },
  { $lookup: {
    from: "schedules",
    let: { userId: "$userID", date: "$dates" },
    pipeline: [
      { $match: { 
        $expr: { 
          $and: [
            { $eq: ["$assignedUser", "$$userId"] },
            { $eq: ["$scheduledDate", "$$date"] }
          ]
        }
      }}
    ],
    as: "schedules"
  }},
  { $lookup: {
    from: "issues",
    let: { userId: "$userID", date: "$dates" },
    pipeline: [
      { $match: { 
        $expr: { 
          $and: [
            { $eq: ["$assignedTo", "$$userId"] },
            { $eq: ["$dueDate", "$$date"] }
          ]
        }
      }}
    ],
    as: "issues"
  }},
  { $group: {
    _id: { userID: "$userID", date: "$dates" },
    scheduleCount: { $size: "$schedules" },
    issueCount: { $size: "$issues" },
    scheduleData: { $first: "$schedules" }
  }}
]);

Data Hierarchy & Inheritance

Organizational Hierarchy

Organization (Firestore)
├── Site Off-Days (MongoDB)
│   ├── Override: disabled = false
│   └── Inherit: disabled = true
└── User Off-Days (MongoDB)
    ├── Individual assignments
    └── Respect site/org rules

Priority Resolution Logic

const getEffectiveOffDays = (date: string, userID: string, siteID: string) => {
  // 1. Check user-specific assignment
  const userOffDay = await getUserOffDay(userID, date);
  if (userOffDay) return true;
  
  // 2. Check site-specific configuration
  const siteConfig = await getSiteOffDay(siteID);
  if (siteConfig && !siteConfig.disabled && siteConfig.dates.includes(date)) {
    return true;
  }
  
  // 3. Check organization-wide setting
  const orgOffDay = await getOrganizationOffDay(organizationID);
  if (orgOffDay && orgOffDay.dates[date]) {
    return true;
  }
  
  return false;
};

Data Consistency & Integrity

Transaction Patterns

// Site off-days update with rollback
const updateSiteOffDays = async (siteID: string, newData: Partial<SiteOffDay>) => {
  const session = await mongoose.startSession();
  session.startTransaction();
  
  try {
    // Update site configuration
    await SiteOffDay.findOneAndUpdate(
      { siteID, organizationID },
      { ...newData, updatedAt: new Date() },
      { upsert: true, session }
    );
    
    // Log audit trail
    await AuditLog.create({
      action: 'SITE_OFFDAYS_UPDATE',
      targetType: 'SITE',
      targetId: siteID,
      changes: newData,
      userId: currentUser.id
    }, { session });
    
    await session.commitTransaction();
    return { success: true };
  } catch (error) {
    await session.abortTransaction();
    throw error;
  } finally {
    session.endSession();
  }
};

Validation Rules

// MongoDB Schema Validation
const userOffDaySchema = {
  $jsonSchema: {
    bsonType: "object",
    required: ["organizationID", "userID", "dates"],
    properties: {
      organizationID: {
        bsonType: "string",
        pattern: "^org_[a-zA-Z0-9_]+$"
      },
      userID: {
        bsonType: "string",
        pattern: "^user_[a-zA-Z0-9_]+$"
      },
      dates: {
        bsonType: "array",
        items: {
          bsonType: "string",
          pattern: "^\\d{4}-\\d{2}-\\d{2}$"
        }
      },
      createdAt: { bsonType: "date" },
      updatedAt: { bsonType: "date" }
    }
  }
};

Performance Optimization

Caching Strategy

// Redis caching for frequently accessed data
const cacheKeys = {
  userOffDays: (userID: string) => `user_offdays:${userID}`,
  siteOffDays: (siteID: string) => `site_offdays:${siteID}`,
  orgOffDays: (orgID: string) => `org_offdays:${orgID}`,
  userMetrics: (orgID: string) => `metrics:${orgID}:${moment().format('YYYY-MM-DD')}`
};
 
// Cache with TTL
const cacheUserOffDays = async (userID: string, data: UserOffDay) => {
  await redis.setex(
    cacheKeys.userOffDays(userID),
    3600, // 1 hour TTL
    JSON.stringify(data)
  );
};

Query Optimization

// Optimized dashboard query with pagination
const getDashboardData = async (filters: DashboardFilters) => {
  const pipeline = [
    // Stage 1: Match filters
    { $match: buildMatchStage(filters) },
    
    // Stage 2: Lookup user information
    { $lookup: {
      from: 'users',
      localField: 'userID',
      foreignField: '_id',
      as: 'user',
      pipeline: [
        { $project: { name: 1, department: 1, site: 1 } }
      ]
    }},
    
    // Stage 3: Apply search filter
    { $match: buildSearchStage(filters.search) },
    
    // Stage 4: Sort
    { $sort: { [filters.sortBy]: filters.order === 'desc' ? -1 : 1 } },
    
    // Stage 5: Pagination
    { $facet: {
      data: [
        { $skip: (filters.page - 1) * filters.limit },
        { $limit: filters.limit }
      ],
      totalCount: [{ $count: "count" }]
    }}
  ];
  
  return await UserOffDay.aggregate(pipeline);
};

User Interface

The Non-Operational Day Management System features a sophisticated user interface designed for efficiency, usability, and real-time collaboration across multiple organizational levels.

Route Structure

RouteComponentPurposeAccess Level
/admin/offdaysOrganization OffDaysManagerOrganization-wide off-days managementAdmin
/admin/auditors/useroffdaysAuditor OffDaysManagerIndividual user assignmentsAdmin
/admin/auditors/offdays-dashboardOffDaysDashboardAnalytics and reportingAdmin
/sites/{siteID}/settingsSiteOffDays (embedded)Site-specific configurationSite Admin

Route Configuration:

// Lazy-loaded route definitions
const AdminRoutes = [
  {
    path: "/admin/offdays",
    component: lazy(() => import("pages/offdays")),
    exact: true,
    permissions: ['non-operational-days.all']
  },
  {
    path: "/admin/auditors/useroffdays", 
    component: lazy(() => import("pages/auditorsOffdays")),
    exact: true,
    permissions: ['non-operational-days.users']
  },
  {
    path: "/admin/auditors/offdays-dashboard",
    component: lazy(() => import("pages/auditorsOffDaysDashboard")),
    exact: true,
    permissions: ['non-operational-days.view']
  }
];

File: src/components/global/Sidebar/constants/SubMenuList.constants.ts

const nonOperationalMenuItems = {
  key: 'non-operational-days',
  icon: CalendarIcon,
  label: 'nav.nonOperationalDays',
  children: [
    {
      key: 'organization-offdays',
      path: '/admin/offdays',
      label: 'nav.organizationOffDays',
      permissions: ['non-operational-days.all']
    },
    {
      key: 'user-offdays',
      path: '/admin/auditors/useroffdays',
      label: 'nav.userOffDays', 
      permissions: ['non-operational-days.users']
    },
    {
      key: 'offdays-dashboard',
      path: '/admin/auditors/offdays-dashboard',
      label: 'nav.offDaysDashboard',
      permissions: ['non-operational-days.view']
    }
  ]
};

Organization Level Interface

Organization Off-Days Management Page

Route: /admin/offdays
Component: src/components/offdays/OffDaysManager.tsx

UI Layout:

┌─────────────────────────────────────────────────────────────┐
│ Page Header                                                 │
├─────────────────────────────────────────────────────────────┤
│ Title: "Non-Operational Days"          [Save Button]       │
│ Subtitle: "Manage organization-wide..."                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ Calendar Component (75%)    │ Selected Dates List (25%)    │
│                             │                               │
│ [Interactive Calendar]      │ January                       │
│ • Month navigation          │ ├─ 15 January                │
│ • Year selector             │ ├─ 16 January                │
│ • Date highlighting         │                               │
│                             │ February                      │
│                             │ ├─ 14 February               │
│                             │                               │
└─────────────────────────────────────────────────────────────┘

Key Features:

  • Real-time Updates: Firestore live synchronization
  • Responsive Design: Desktop 2-month, mobile 1-month view
  • Visual Feedback: Loading states, success/error toasts
  • Accessibility: Keyboard navigation, screen reader support

Component Breakdown:

<Layout>
  <AdminPage>
    <AdaptiveWrapper>
      <OffDaysHeader>
        <HeaderSection>
          <Title>{t('message.offDaysPage.title')}</Title>
          <Subtitle>{t('message.offDaysPage.subtitle')}</Subtitle>
        </HeaderSection>
        <SaveSection>
          {isLoading && <LoadingSpinner />}
          <SaveButton onClick={handleSave} disabled={isLoading}>
            {t('button.save')}
          </SaveButton>
        </SaveSection>
      </OffDaysHeader>
      
      <OffDaysDatePicker
        type="organization"
        organizationOffDay={tempOrganizationOffDay}
        handleUpdateOffDay={handleUpdateOffDay}
      />
    </AdaptiveWrapper>
  </AdminPage>
</Layout>

Site Level Interface

Site Off-Days Configuration

Location: Embedded in Site Settings page
Component: src/components/sites/SiteOffDays/SiteOffDays.tsx

UI Layout:

┌─────────────────────────────────────────────────────────────┐
│ Site Off-Days Configuration                                 │
├─────────────────────────────────────────────────────────────┤
│ ⚠️ Site-specific off-days override organization settings    │
├─────────────────────────────────────────────────────────────┤
│ Enable Site Off-Days               [Toggle Switch]  [Save] │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ Calendar Component (75%)    │ Selected Dates List (25%)    │
│                             │                               │
│ [Interactive Calendar]      │ Organization Days (•)        │
│ • Organization days as dots │ Site Days (highlighted)      │
│ • Site days highlighted     │                               │
│ • Visual inheritance        │                               │
│                             │                               │
└─────────────────────────────────────────────────────────────┘

Toggle Switch Component:

const Slider = ({ disabled, onClick }: SliderProps) => (
  <SliderContainer disabled={disabled} onClick={onClick}>
    <div className="circle" />
  </SliderContainer>
);
 
// CSS-in-JS styling for visual toggle
const SliderContainer = styled.div<SliderProps>`
  background: ${({ disabled }) => (!disabled ? '#574FCF' : '#C4C4C4')};
  
  .circle {
    left: ${({ disabled }) => (!disabled ? 'calc(100% - 8px)' : '0%')};
  }
`;

Visual Inheritance Pattern:

  • Organization Days: Small dots below calendar dates
  • Site Days: Highlighted background with border
  • Tooltip System: Hover information for inherited days

User Level Interface

Auditor Off-Days Management

Route: /admin/auditors/useroffdays
Component: src/components/auditors/offDaysManager/OffDaysManager.tsx

UI Layout:

┌─────────────────────────────────────────────────────────────┐
│ Manage Non-Operational Days    [Back] [Save]               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ Enhanced Calendar (60%)         │ User Assignment (40%)    │
│                                 │                           │
│ [Interactive Calendar]          │ Selected Date: Jan 15    │
│ • User count indicators         │                           │
│ • Multi-user assignments        │ Assigned Users:          │
│ • Visual user counts            │ ☑️ John Doe              │
│                                 │ ☑️ Jane Smith            │
│                                 │ ☐ Mike Johnson           │
│                                 │ ☐ Sarah Wilson           │
│                                 │                           │
│                                 │ [Add User] [Remove]      │
└─────────────────────────────────────────────────────────────┘

User Assignment Interface:

const UserAssignmentPanel = ({ selectedDate, users, onUserToggle }) => (
  <AssignmentPanel>
    <DateHeader>
      Selected Date: {moment(selectedDate).format('MMMM DD, YYYY')}
    </DateHeader>
    
    <UserList>
      {users.map(user => (
        <UserItem key={user.id}>
          <Checkbox 
            checked={user.assigned}
            onChange={() => onUserToggle(user.id)}
          />
          <UserName>{user.name}</UserName>
          <UserRole>{user.role}</UserRole>
        </UserItem>
      ))}
    </UserList>
    
    <ActionButtons>
      <Button variant="outline" onClick={handleAddUser}>
        Add User
      </Button>
      <Button variant="danger" onClick={handleRemoveSelected}>
        Remove Selected
      </Button>
    </ActionButtons>
  </AssignmentPanel>
);

Dashboard Interface

Analytics Dashboard

Route: /admin/auditors/offdays-dashboard
Component: src/components/auditors/offDaysDashboard/OffDaysDashboard.tsx

Dashboard Layout:

┌─────────────────────────────────────────────────────────────┐
│ Non-Operational Days Dashboard                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ Main Content Area (75%)        │ Sidebar (25%)             │
│                                │                            │
│ ┌─ User Metrics ─────────────┐ │ ┌─ Monthly Chart ───────┐ │
│ │Today │Week │Month │Year  │ │ │                        │ │
│ │  5   │ 12  │ 45   │ 150  │ │ │ [Line Chart]          │ │
│ └─────────────────────────────┘ │ │ • Month selector      │ │
│                                │ │ • Gradient styling    │ │
│ ┌─ Data Table ───────────────┐ │ └────────────────────────┘ │
│ │ [Manage] Search: [____]   │ │                            │
│ │ 👤 📅 [Filter] [👁️] [📅] │ │ ┌─ Upcoming Schedule ──┐ │
│ │                           │ │ │Today:                 │ │
│ │ Name    │Date    │Sched  │ │ │👤 John Doe           │ │
│ │John Doe │Jan 15  │3     │ │ │👤 Jane Smith         │ │
│ │Jane S.  │Jan 16  │1     │ │ │                       │ │
│ │         │        │      │ │ │This Week:             │ │
│ │ [Pagination 1 2 3]      │ │ │👤 Mike Johnson       │ │
│ └─────────────────────────────┘ │ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

User Metrics Widget

Component: src/components/auditors/offDaysDashboard/UserMetrics.tsx

const UserMetrics = () => (
  <MetricsContainer>
    <Header>
      <AnalyticsIcon />
      <Title>User Metrics</Title>
    </Header>
    
    <MetricsGrid>
      <MetricCard>
        <CardHeader>Today</CardHeader>
        <CardValue>{userCount?.today || 0}</CardValue>
      </MetricCard>
      
      <MetricCard>
        <CardHeader>This Week</CardHeader>
        <CardValue>{userCount?.week || 0}</CardValue>
      </MetricCard>
      
      <MetricCard>
        <CardHeader>This Month</CardHeader>
        <CardValue>{userCount?.month || 0}</CardValue>
      </MetricCard>
      
      <MetricCard>
        <CardHeader>This Year</CardHeader>
        <CardValue>{userCount?.year || 0}</CardValue>
      </MetricCard>
    </MetricsGrid>
  </MetricsContainer>
);

Advanced Data Table

Component: src/components/auditors/offDaysDashboard/OffDaysTable.tsx

Table Features:

  • Dual View Modes: User-wise and Date-wise perspectives
  • Advanced Filtering: Multi-dimensional filter system
  • Real-time Search: Debounced search with highlighting
  • Interactive Calendar: Date selection for date-wise view
  • Drill-down Navigation: Links to detailed schedule and issue views

Filter System:

const FilterConfiguration = [
  {
    name: 'user',
    label: 'User',
    type: FilterFieldType.MULTI_SELECT,
    options: userOptions,
    placeholder: 'Select Users'
  },
  {
    name: 'date', 
    label: 'Date Range',
    type: FilterFieldType.DATE_RANGE_PRESET,
    placeholder: 'Date Range'
  },
  {
    name: 'sites',
    label: 'Sites', 
    type: FilterFieldType.MULTI_SELECT,
    options: siteOptions,
    placeholder: 'Select Sites'
  },
  {
    name: 'departments',
    label: 'Department',
    type: FilterFieldType.MULTI_SELECT, 
    options: departmentOptions,
    placeholder: 'Select Department'
  }
];

View Toggle Component:

const ViewToggle = () => (
  <SegmentedButton
    items={[
      {
        value: 'userWise',
        children: <ViewListIcon />
      },
      {
        value: 'dateWise', 
        children: <CalendarIcon />
      }
    ]}
    value={viewType}
    onItemClick={({ value }) => setViewType(value)}
  />
);

Responsive Design System

Breakpoint Strategy

// Responsive breakpoints
$breakpoints: (
  mobile: 320px,
  tablet: 768px,
  desktop: 992px,
  large: 1275px,
  xlarge: 1440px
);
 
// Calendar responsiveness
.calendar-container {
  .DayPicker {
    // Mobile: 1 month
    @media (max-width: 682px) {
      .CalendarMonthGrid {
        grid-template-columns: 1fr;
      }
    }
    
    // Tablet: 2 months if space allows
    @media (min-width: 683px) and (max-width: 991px) {
      .CalendarMonthGrid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    
    // Desktop: 1 month (992-1275px)
    @media (min-width: 992px) and (max-width: 1274px) {
      .CalendarMonthGrid {
        grid-template-columns: 1fr;
      }
    }
    
    // Large desktop: 2 months
    @media (min-width: 1275px) {
      .CalendarMonthGrid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
  }
}

Mobile Optimization

// Dynamic month count based on screen size
const useResponsiveCalendar = () => {
  const [monthCount, setMonthCount] = useState(() => 
    window.innerWidth > 1275 ? 2 : 1
  );
  
  useLayoutEffect(() => {
    const handleResize = () => {
      const width = window.innerWidth;
      if (width > 1275) setMonthCount(2);
      else if (width < 1275 && width > 991) setMonthCount(1);
      else if (width < 992 && width > 682) setMonthCount(2);
      else setMonthCount(1);
    };
    
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  
  return monthCount;
};

Accessibility Features

WCAG 2.1 Compliance

  • Keyboard Navigation: Full keyboard accessibility for calendar and tables
  • Screen Reader Support: ARIA labels and semantic HTML structure
  • Color Contrast: 4.5:1 ratio for all text elements
  • Focus Management: Visible focus indicators and logical tab order
// Accessible calendar navigation
const AccessibleCalendarDay = ({ date, isSelected, isOffDay, onClick }) => (
  <CalendarDay
    role="button"
    tabIndex={0}
    aria-label={`${date.format('MMMM DD, YYYY')}${isOffDay ? ', Off Day' : ''}`}
    aria-pressed={isSelected}
    onKeyDown={(e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        onClick(date);
      }
    }}
    onClick={() => onClick(date)}
  >
    {date.format('DD')}
    {isOffDay && <OffDayIndicator aria-hidden="true" />}
  </CalendarDay>
);

Internationalization (i18n)

Translation Files: Multiple language support across all components

// Language files structure
const translations = {
  'en': {
    'nav.nonOperationalDays': 'Non-Operational Days',
    'message.offDaysPage.title': 'Manage Non-Operational Days',
    'message.offDaysPage.subtitle': 'Configure organization-wide off-days...',
    'button.save': 'Save',
    'addOn.offDays.success': 'Off-days updated successfully',
    'addOn.offDays.fail': 'Failed to update off-days'
  },
  'es': {
    'nav.nonOperationalDays': 'Días No Operacionales',
    'message.offDaysPage.title': 'Gestionar Días No Operacionales',
    // ... additional translations
  }
};

Performance Optimizations

Code Splitting & Lazy Loading

// Route-level code splitting
const OffDaysPage = lazy(() => import('components/offdays/OffDaysManager'));
const AuditorsOffDaysPage = lazy(() => import('components/auditors/offDaysManager/OffDaysManager'));
const DashboardPage = lazy(() => import('components/auditors/offDaysDashboard/OffDaysDashboard'));
 
// Component-level lazy loading
const ScheduleListModal = lazy(() => import('./ScheduleListModal'));
const ScheduleDetailModal = lazy(() => import('./ScheduleDetailModal'));

Memoization Strategy

// Expensive calculations memoized
const memoizedTableData = useMemo(() => {
  return nonOpsList?.docs?.map((nonOps, index) => ({
    key: `${viewType}-${index}`,
    value: {
      name: viewType === 'userWise' 
        ? nonOps?.name || ''
        : nonOps?.data?.map(d => d?.name).join(', '),
      // ... complex data transformation
    }
  })) || [];
}, [nonOpsList, viewType]);
 
// Debounced search to reduce API calls
const debouncedSearch = useMemo(
  () => debounce((text: string) => fetchNonOps(text), 500),
  []
);

Business Logic

The Non-Operational Day Management System implements sophisticated business logic that handles complex organizational hierarchies, data transformations, and real-time synchronization patterns.

Organizational Hierarchy Logic

Priority Resolution System

The system implements a three-tier priority system where higher-level settings can be overridden by more specific configurations:

/**
 * Priority Resolution Order:
 * 1. User-specific assignments (highest priority)
 * 2. Site-specific configurations  
 * 3. Organization-wide settings (lowest priority)
 */
const resolveEffectiveOffDay = async (
  date: string, 
  userID: string, 
  siteID: string, 
  organizationID: string
): Promise<boolean> => {
  // Level 1: Check user-specific assignment
  const userAssignment = await getUserOffDayAssignment(userID, date);
  if (userAssignment !== null) {
    return userAssignment; // Explicit user assignment takes precedence
  }
  
  // Level 2: Check site-specific configuration
  const siteConfig = await getSiteOffDayConfiguration(siteID);
  if (siteConfig && !siteConfig.disabled) {
    return siteConfig.dates.includes(date);
  }
  
  // Level 3: Fall back to organization-wide setting
  const orgConfig = await getOrganizationOffDay(organizationID);
  return orgConfig?.dates?.[date] || false;
};

Site Override Logic

Component: src/components/sites/SiteOffDays/hook/useSiteOffDays.ts:56

const handleOffDayToggle = () => {
  setSiteOffDays({ 
    ...siteOffDays, 
    disabled: !siteOffDays.disabled 
  });
};
 
/**
 * When disabled = false: Site off-days are active and override organization
 * When disabled = true: Site inherits organization settings
 */
const getEffectiveSiteOffDays = (date: string) => {
  if (siteOffDays.disabled) {
    // Inherit from organization
    return organizationOffDay?.dates?.[date] || false;
  } else {
    // Use site-specific configuration
    return siteOffDays.dates[date] || false;
  }
};

Data Transformation Logic

User Assignment Data Mapping

Component: src/components/auditors/offDaysManager/OffDaysManager.tsx:79

The system performs complex bidirectional data transformations between frontend and API formats:

/**
 * API Response Format: Array of user objects with date arrays
 * Frontend Format: Date objects with user arrays
 */
 
// API to Frontend Transformation
const transformApiToFrontend = (apiData: Array<{ [userID: string]: string[] }>) => {
  const frontendFormat: { [date: string]: string[] } = {};
  
  apiData.forEach(userObject => {
    Object.entries(userObject).forEach(([userID, dates]) => {
      dates.forEach(date => {
        if (!frontendFormat[date]) {
          frontendFormat[date] = [];
        }
        frontendFormat[date].push(userID);
      });
    });
  });
  
  return frontendFormat;
};
 
// Frontend to API Transformation
const transformFrontendToApi = (
  frontendData: { [date: string]: string[] },
  initialUserIDs: string[]
) => {
  // Convert date-user mapping to user-date mapping
  const convertedData: { [userID: string]: string[] } = {};
  
  Object.entries(frontendData).forEach(([date, userIDs]) => {
    userIDs.forEach(userID => {
      if (!convertedData[userID]) {
        convertedData[userID] = [];
      }
      convertedData[userID].push(date);
    });
  });
  
  // Handle removals: users not in final data get empty arrays
  const finalUserIDs = Object.keys(convertedData);
  const removedUserIDs = initialUserIDs.filter(
    userID => !finalUserIDs.includes(userID)
  );
  
  // Create API format with removal logic
  const apiFormat = Object.entries(convertedData).map(([userID, dates]) => ({
    [userID]: dates
  }));
  
  // Add removed users with empty arrays
  removedUserIDs.forEach(userID => {
    apiFormat.push({ [userID]: [] });
  });
  
  return apiFormat;
};

Site Data Processing

Component: src/components/sites/SiteOffDays/hook/useSiteOffDays.ts:97

/**
 * Site off-days data transformation from API array to frontend boolean mapping
 */
const processedSiteOffDays = useMemo(() => {
  return {
    ...siteOffDaysResponse,
    dates: siteOffDaysResponse.dates.reduce<{ [date: string]: boolean }>(
      (siteOffDaysMap, dateString) => {
        siteOffDaysMap[dateString] = true;
        return siteOffDaysMap;
      }, 
      {}
    )
  };
}, [siteOffDaysResponse]);
 
/**
 * Reverse transformation for API submission
 */
const handleSubmitOffDay = () => {
  const apiPayload = {
    ...siteOffDays,
    dates: Object.keys(siteOffDays.dates || {}) // Convert boolean map back to array
  };
  
  dispatch(upsertSiteOffDays.request({
    siteID,
    updatedSiteOffDays: apiPayload
  }));
};

Calendar Business Logic

Dynamic Month Count Calculation

Component: src/components/global/OffDaysDatePicker/OffDaysDatePicker.tsx:89

/**
 * Responsive calendar logic based on screen dimensions
 */
const handleResize = () => {
  const width = window.innerWidth;
  
  if (width > 1275) {
    setMonthCount(2);        // Large desktop: 2 months
  } else if (width < 1275 && width > 991) {
    setMonthCount(1);        // Desktop: 1 month  
  } else if (width < 992 && width > 682) {
    setMonthCount(2);        // Tablet: 2 months (side-by-side)
  } else if (width < 682) {
    setMonthCount(1);        // Mobile: 1 month
  }
};
 
/**
 * Calendar date rendering with inheritance visualization
 */
const renderDayContents = (day: moment.Moment) => {
  const dateString = day.format('YYYY-MM-DD');
  const isOrganizationOffDay = organizationOffDay?.dates?.[dateString];
  const isSiteOffDay = siteOffDay?.dates?.[dateString];
  
  return (
    <CalendarDates>
      {removeZero(day.format('DD'))}
      {type === 'site' && isOrganizationOffDay && (
        <InheritanceDot>
          <span className="tooltip-text">{t('label.offDaysPage.non-op')}</span>
        </InheritanceDot>
      )}
    </CalendarDates>
  );
};

Date Selection Logic

/**
 * Calendar date toggle with state management
 */
const handleToggleDate = (date: moment.Moment) => {
  const dateString = date.format('YYYY-MM-DD');
  const isCurrentlySelected = offDayState?.dates?.[dateString];
  
  const clonedDates = cloneDeep(offDayState);
  
  if (isCurrentlySelected) {
    // Remove date
    delete clonedDates!.dates[dateString];
  } else {
    // Add date  
    clonedDates!.dates = { 
      ...clonedDates!.dates, 
      [dateString]: true 
    };
  }
  
  setOffDayState(clonedDates);
  handleUpdateOffDay(clonedDates!);
};

Dashboard Analytics Logic

User Metrics Calculation

Component: src/components/auditors/offDaysDashboard/UserMetrics.tsx:22

The dashboard calculates real-time metrics across different time periods:

/**
 * Server-side aggregation pipeline for user metrics
 */
const calculateUserMetrics = async (organizationID: string) => {
  const now = new Date();
  const startOfDay = moment().startOf('day').toDate();
  const startOfWeek = moment().startOf('week').toDate();
  const startOfMonth = moment().startOf('month').toDate();
  const startOfYear = moment().startOf('year').toDate();
  
  const pipeline = [
    { $match: { organizationID } },
    { $unwind: "$dates" },
    { 
      $addFields: {
        dateObj: { $dateFromString: { dateString: "$dates" } }
      }
    },
    {
      $group: {
        _id: null,
        today: {
          $sum: {
            $cond: [
              {
                $and: [
                  { $gte: ["$dateObj", startOfDay] },
                  { $lt: ["$dateObj", moment(startOfDay).add(1, 'day').toDate()] }
                ]
              },
              1, 0
            ]
          }
        },
        week: {
          $sum: {
            $cond: [{ $gte: ["$dateObj", startOfWeek] }, 1, 0]
          }
        },
        month: {
          $sum: {
            $cond: [{ $gte: ["$dateObj", startOfMonth] }, 1, 0]
          }
        },
        year: {
          $sum: {
            $cond: [{ $gte: ["$dateObj", startOfYear] }, 1, 0]
          }
        }
      }
    }
  ];
  
  return await UserOffDay.aggregate(pipeline);
};

Monthly Chart Data Processing

Component: src/components/auditors/offDaysDashboard/TotalNonOffDays.tsx:46

/**
 * Chart data transformation with chronological sorting
 */
const processChartData = (monthlyNonOps: MonthlyNonOpsI) => {
  let monthLabels: string[] = [];
  let monthValues: number[] = [];
  
  if (monthlyNonOps) {
    // Sort dates chronologically
    Object.keys(monthlyNonOps)
      .sort((a: string, b: string) => moment(a).diff(moment(b), 'days'))
      .forEach((date: string) => {
        if (date) {
          monthLabels.push(moment(date).format("D MMM 'YY"));
          monthValues.push(monthlyNonOps[date] || 0);
        }
      });
  }
  
  return {
    labels: monthLabels,
    datasets: [{
      fill: true,
      label: 'Non Operational Days',
      data: monthValues,
      borderColor: '#574FCF',
      backgroundColor: (context: any) => {
        const ctx = context.chart.ctx;
        const gradient = ctx.createLinearGradient(0, 0, 0, context.chart.height);
        gradient.addColorStop(0, 'rgba(87, 79, 207, 0.30)');
        gradient.addColorStop(0.7, 'rgba(87, 79, 207, 0.00)');
        return gradient;
      }
    }]
  };
};

Table View Logic

Dual View Mode Processing

Component: src/components/auditors/offDaysDashboard/OffDaysTable.tsx:115

/**
 * Complex table data mapping for dual view modes
 */
const mappedTableData: TableRow[] = useMemo(() => {
  return nonOpsList?.docs?.map((nonOps, index) => ({
    key: `${viewType}-${index}`,
    value: {
      // Dynamic name field based on view type
      name: viewType === 'userWise'
        ? nonOps?.name || ''
        : nonOps?.data?.map((nonOpsDetails) => nonOpsDetails?.name).join(', ') || '',
      
      // Dynamic date field based on view type  
      date: viewType === 'userWise'
        ? nonOps?.data?.map((nonOpsDetails) => nonOpsDetails?.date).join(', ') || ''
        : nonOps?.date || '',
      
      // Aggregated schedule and issue counts
      scheduleCount: nonOps?.data?.map((nonOpsDetails) => 
        nonOpsDetails?.scheduleCount).join(', '),
      issueCount: nonOps?.data?.map((nonOpsDetails) => 
        nonOpsDetails?.issueCount).join(', '),
      
      // Raw data for drill-down operations
      scheduleData: nonOps?.data || [],
      userID: nonOps?.userID || ''
    }
  })) || [];
}, [nonOpsList, viewType]);
 
/**
 * Column configuration based on view mode
 */
const columnConfigs: ColumnConfigs = useMemo(() => {
  if (viewType === 'userWise') {
    return [
      { name: 'name', title: 'Name', width: '30%', onSort: handleSort },
      { name: 'date', title: 'Date', width: '20%', customCellRender: customDateCell },
      { name: 'scheduleCount', title: 'Schedules on this date', width: '25%' },
      { name: 'issueCount', title: 'Issues due on this date', width: '25%' }
    ];
  } else {
    return [
      { name: 'date', title: 'Date', width: '20%', onSort: handleSort },
      { name: 'name', title: 'Name', width: '30%', customCellRender: customNameCell },
      { name: 'scheduleCount', title: 'Schedules on this date', width: '25%' },
      { name: 'issueCount', title: 'Issues due on this date', width: '25%' }
    ];
  }
}, [viewType]);

Advanced Filtering Logic

/**
 * Multi-dimensional filter processing
 */
const buildFilterQuery = (filters: DashboardFilters) => {
  let queryParams: any = {
    type: filters.viewType,
    sortBy: filters.sortBy,
    order: filters.order,
    limit: filters.limit,
    page: filters.page
  };
  
  if (filters.viewType === 'userWise') {
    // User-wise view filters
    if (filters.departments?.length) {
      queryParams.department = filters.departments;
    }
    if (filters.sites?.length) {
      queryParams.site = filters.sites;
    }
    if (filters.users?.length) {
      queryParams.users = filters.users;
    }
    if (filters.dateRange?.startDate) {
      queryParams.startDate = formatDate(filters.dateRange.startDate);
    }
    if (filters.dateRange?.endDate) {
      queryParams.endDate = formatDate(filters.dateRange.endDate);
    }
    if (filters.search) {
      queryParams.search = filters.search;
    }
  } else {
    // Date-wise view filters
    if (filters.selectedDates?.length) {
      queryParams.dates = filters.selectedDates;
    }
  }
  
  return queryParams;
};

Search and Pagination Logic

Debounced Search Implementation

/**
 * Optimized search with debouncing to reduce API calls
 */
const handleSearch = debounce(async (searchText: string) => {
  const params = buildFilterQuery({
    ...currentFilters,
    search: searchText,
    page: 1 // Reset to first page on new search
  });
  
  const results = await fetchNonOpsList(params);
  setNonOpsList(results);
}, 500);
 
const handleSearchInput = useCallback((text: string) => {
  setSearchText(text);
  handleSearch(text);
}, [handleSearch]);

Calendar Date Selection for Date-wise View

/**
 * Multi-date selection logic for date-wise table view
 */
const handleSelectedDates = (date: Moment | null) => {
  if (date) {
    const dateString = date.format('YYYY-MM-DD');
    
    if (selectedDates?.includes(dateString)) {
      // Remove date if already selected
      setSelectedDates(
        selectedDates.filter(selectedDate => selectedDate !== dateString)
      );
    } else {
      // Add date to selection
      setSelectedDates([...selectedDates, dateString]);
    }
  }
};
 
/**
 * Calendar day rendering with selection indicators
 */
const renderDayContent = (day: moment.Moment) => {
  const dateString = day.format('YYYY-MM-DD');
  const isSelected = selectedDates?.includes(dateString);
  const hasData = nonOpsList?.docs?.some(doc => doc?.date === dateString);
  
  return (
    <CalendarDates isActive={isSelected}>
      {hasData && <DataIndicatorDot />}
      {removeZero(day.format('DD'))}
    </CalendarDates>
  );
};

Integration Navigation Logic

Cross-module Navigation

/**
 * Navigation to related modules with context preservation
 */
const handleIssueNavigation = (rowData: TableRow, index: number) => {
  let selectedUser = '';
  let selectedDate = '';
  
  if (viewType === 'userWise') {
    selectedUser = rowData?.value?.userID || '';
    selectedDate = rowData.value?.scheduleData?.[index]?.date || '';
  } else {
    selectedUser = rowData.value?.scheduleData?.[index]?.userId || '';
    selectedDate = rowData.value?.date || '';
  }
  
  // Navigate with query parameters for filtered view
  history.push(
    `/issues?qUser=${selectedUser}&qStartDate=${selectedDate}&qEndDate=${selectedDate}`
  );
};
 
/**
 * Schedule detail modal navigation
 */
const handleScheduleDetailNavigation = (scheduleData: TableRow, index: number) => {
  setSelectedSchedule(scheduleData.value?.scheduleData?.[index]?.scheduleData || []);
  setScheduleUser(
    viewType === 'userWise' 
      ? scheduleData.value?.name 
      : scheduleData.value?.scheduleData?.[index]?.name
  );
  setScheduleDate(
    viewType === 'userWise' 
      ? scheduleData.value?.scheduleData?.[index]?.date 
      : scheduleData.value?.date
  );
  setShowScheduleList(true);
};

Error Handling and Recovery Logic

Hierarchical Error Handling

/**
 * Component-level error boundaries with fallback strategies
 */
const handleApiError = (error: any, operation: string) => {
  // Log error for monitoring
  Monitoring.logEvent(`OffDays_${operation}_Error`, {
    error: error.message,
    stack: error.stack,
    timestamp: new Date().toISOString(),
    userAgent: navigator.userAgent
  });
  
  // User feedback based on error type
  if (error.code === 'NETWORK_ERROR') {
    toast.error(t('error.network.message'));
    // Attempt retry with exponential backoff
    scheduleRetry(operation);
  } else if (error.code === 'PERMISSION_DENIED') {
    toast.error(t('error.permission.message'));
    // Redirect to unauthorized page
    history.push('/unauthorized');
  } else {
    toast.error(t('addOn.offDays.fail'));
  }
};
 
/**
 * Optimistic updates with rollback capability
 */
const optimisticUpdate = async (newState: any, apiCall: () => Promise<any>) => {
  const previousState = cloneDeep(currentState);
  
  // Apply optimistic update
  setState(newState);
  
  try {
    await apiCall();
    // Success - state is already updated
  } catch (error) {
    // Rollback on failure
    setState(previousState);
    handleApiError(error, 'optimistic_update');
  }
};

Permission and Access Control Logic

Dynamic Permission Checking

/**
 * Granular permission validation
 */
const checkOffDaysPermissions = (level: 'organization' | 'site' | 'user') => {
  const userPermissions = userAccess.admin['non-operational-days'];
  
  switch (level) {
    case 'organization':
      return userPermissions.all.permissions?.includes('write') || 
             userPermissions.organization?.includes('write');
    
    case 'site':
      return userPermissions.all.permissions?.includes('write') || 
             userPermissions.site?.includes('write');
    
    case 'user':
      return userPermissions.all.permissions?.includes('write') || 
             userPermissions.users?.includes('write');
    
    default:
      return false;
  }
};
 
/**
 * Component-level permission enforcement
 */
const PermissionGuard = ({ level, children }: PermissionGuardProps) => {
  const hasPermission = checkOffDaysPermissions(level);
  
  if (!hasPermission) {
    return <UnauthorizedView />;
  }
  
  return <>{children}</>;
};

Performance and Optimization Logic

Intelligent Data Loading

/**
 * Progressive data loading with priority
 */
const loadDashboardData = async () => {
  // Priority 1: Load critical metrics first
  const metricsPromise = fetchUserCount();
  
  // Priority 2: Load table data (can be shown with loading state)
  const tablePromise = fetchNonOpsList(currentFilters);
  
  // Priority 3: Load chart data (less critical)
  const chartPromise = fetchMonthNonOps(selectedMonth.value);
  
  // Priority 4: Load upcoming schedule (sidebar widget)
  const schedulePromise = fetchUpcomingLeaves();
  
  try {
    // Load high-priority data first
    const [metrics] = await Promise.all([metricsPromise]);
    setUserCount(metrics);
    
    // Load remaining data in background
    const [tableData, chartData, scheduleData] = await Promise.all([
      tablePromise,
      chartPromise, 
      schedulePromise
    ]);
    
    setNonOpsList(tableData);
    setMonthlyNonOps(chartData);
    setUpcomingSchedule(scheduleData);
    
  } catch (error) {
    handleApiError(error, 'dashboard_load');
  }
};

This comprehensive business logic documentation covers all the critical computational patterns, data transformations, and decision-making algorithms that power the Non-Operational Day Management System.

Integration Points

The Non-Operational Day Management System integrates deeply with multiple modules within the audit administration platform, creating a comprehensive ecosystem for workforce management and scheduling.

Core System Integration

User Management System Integration

Integration Point: User data, roles, and permissions
Files: src/hooks/useUserDataOptions.ts

/**
 * User data integration for off-days assignment
 */
const useUserDataOptions = () => {
  const { userMap, userOptions } = useSelector(state => state.users);
  
  // Filter users by organization and active status
  const availableUsers = useMemo(() => {
    return userOptions.filter(user => 
      user.organizationID === currentOrganization &&
      user.status === 'active' &&
      user.role.includes('auditor')
    );
  }, [userOptions, currentOrganization]);
  
  return { userMap, availableUsers };
};

Integration Features:

  • User Selection: Multi-select dropdowns populated from user management
  • Role-based Filtering: Only auditors shown in assignment interfaces
  • Permission Validation: User access controls for off-days management
  • Profile Information: User names, departments, and site assignments

Site Management Integration

Integration Point: Site configurations and hierarchies
Files: src/hooks/useSiteOptions.ts

/**
 * Site data integration for filtering and assignment
 */
const useSiteOptions = () => {
  const { siteMap, siteOptions } = useSelector(state => state.sites);
  
  const activeSites = useMemo(() => {
    return siteOptions.filter(site => 
      site.status === 'active' &&
      site.organizationID === currentOrganization
    );
  }, [siteOptions, currentOrganization]);
  
  return { siteMap, activeSites };
};

Integration Features:

  • Site-specific Off-days: Override organization settings per site
  • Filtering by Site: Dashboard filters include site selection
  • Site Hierarchy: Respects organizational site structure
  • Site Settings: Embedded in site configuration pages

Department Management Integration

Integration Point: Departmental structure and assignments
Files: src/hooks/useDepartmentOptions.ts

/**
 * Department data integration for organizational filtering
 */
const useDepartmentOptions = () => {
  const { departmentMap, departmentOptions } = useSelector(state => state.departments);
  
  return {
    departmentMap,
    departmentOptions: departmentOptions.filter(dept => dept.active)
  };
};

Schedule Management Integration

Schedule System Integration

Purpose: Link off-days with existing schedules and assignments
Data Flow: Off-days impact schedule availability and conflict detection

/**
 * Schedule conflict detection
 */
const checkScheduleConflicts = async (userID: string, date: string) => {
  // Check if user has off-day assignment
  const hasOffDay = await checkUserOffDay(userID, date);
  if (hasOffDay) {
    return {
      conflict: true,
      type: 'OFF_DAY',
      message: 'User is assigned off-day on this date'
    };
  }
  
  // Check site-level restrictions
  const userSite = await getUserSite(userID);
  const siteOffDay = await checkSiteOffDay(userSite, date);
  if (siteOffDay) {
    return {
      conflict: true,
      type: 'SITE_OFF_DAY',
      message: 'Site is non-operational on this date'
    };
  }
  
  return { conflict: false };
};

Integration Points:

  • Schedule Creation: Validate availability during schedule assignment
  • Schedule Modification: Check conflicts when updating existing schedules
  • Schedule Dashboard: Display schedule counts for off-day dates
  • Bulk Scheduling: Mass schedule operations respect off-day settings

Issue Management Integration

Purpose: Display issue due dates that conflict with off-days
Navigation: Direct links from off-days dashboard to issues page

/**
 * Issue dashboard integration
 */
const handleIssueNavigation = (userID: string, date: string) => {
  const issueFilterParams = {
    qUser: userID,
    qStartDate: date,
    qEndDate: date,
    status: 'open'
  };
  
  history.push(`/issues?${queryString.stringify(issueFilterParams)}`);
};

Integration Features:

  • Issue Count Display: Show number of issues due on off-days
  • Contextual Navigation: Filter issues by user and date
  • Conflict Alerts: Highlight issues due on non-operational days
  • Workflow Integration: Issue resolution considers off-day status

Permission System Integration

Role-based Access Control

Integration Point: Admin permission system
Permission Structure: userAccess.admin['non-operational-days']

/**
 * Permission hierarchy validation
 */
const permissionLevels = {
  'non-operational-days.all': {
    organization: true,
    site: true,
    user: true,
    dashboard: true
  },
  'non-operational-days.organization': {
    organization: true,
    site: false,
    user: false,
    dashboard: true
  },
  'non-operational-days.site': {
    organization: false,
    site: true,
    user: false,
    dashboard: true
  },
  'non-operational-days.users': {
    organization: false,
    site: false,
    user: true,
    dashboard: true
  },
  'non-operational-days.view': {
    organization: false,
    site: false,
    user: false,
    dashboard: true
  }
};

Audit and Compliance Integration

Audit Trail Integration

Purpose: Track all off-days changes for compliance
Integration Point: System-wide audit logging

/**
 * Audit trail for off-days changes
 */
const logOffDayChange = async (action: string, data: any) => {
  await AuditLog.create({
    module: 'NON_OPERATIONAL_DAYS',
    action: action,
    entityType: data.type, // 'ORGANIZATION', 'SITE', 'USER'
    entityId: data.id,
    changes: {
      before: data.previousState,
      after: data.newState,
      changedFields: data.changedFields
    },
    userId: currentUser.id,
    timestamp: new Date(),
    metadata: {
      userAgent: navigator.userAgent,
      ipAddress: clientIP,
      organizationId: currentUser.organizationId
    }
  });
};

Analytics and Reporting Integration

Executive Dashboard Integration

Purpose: Provide high-level metrics for executive dashboards
Data Export: Off-days metrics available for executive reporting

/**
 * Executive dashboard metrics
 */
const getExecutiveMetrics = async (organizationID: string, timeframe: string) => {
  return {
    nonOperationalDaysCount: await getTotalOffDays(organizationID, timeframe),
    affectedUsersCount: await getAffectedUsersCount(organizationID, timeframe),
    productivityImpact: await calculateProductivityImpact(organizationID, timeframe),
    scheduleConflicts: await getScheduleConflicts(organizationID, timeframe),
    trends: await getOffDaysTrends(organizationID, timeframe)
  };
};

Notification System Integration

Email Notification Integration

Purpose: Notify stakeholders of off-days changes
Integration Point: System notification service

/**
 * Notification triggers for off-days changes
 */
const triggerNotifications = async (changeType: string, data: any) => {
  const notifications = [];
  
  if (changeType === 'ORGANIZATION_OFF_DAY_CHANGE') {
    // Notify all site managers
    notifications.push({
      type: 'EMAIL',
      recipients: await getSiteManagers(data.organizationID),
      template: 'organization_offday_change',
      data: data
    });
  }
  
  if (changeType === 'USER_OFF_DAY_ASSIGNMENT') {
    // Notify assigned user and manager
    notifications.push({
      type: 'EMAIL',
      recipients: [data.userEmail, data.managerEmail],
      template: 'user_offday_assignment',
      data: data
    });
  }
  
  await NotificationService.sendBatch(notifications);
};

Bulk Operations Integration

Bulk Management Integration

Purpose: Mass operations for off-days management
Files: src/pages/bulkOpsRevamp/bulkOpsUtils.ts

/**
 * Bulk off-days operations
 */
const bulkOffDaysOperations = {
  assignMultipleUsers: async (userIDs: string[], dates: string[]) => {
    const operations = userIDs.map(userID => ({
      userID,
      dates,
      action: 'ASSIGN'
    }));
    
    return await executeBulkOffDaysUpdate(operations);
  },
  
  copyFromTemplate: async (templateID: string, targetUserIDs: string[]) => {
    const template = await getOffDaysTemplate(templateID);
    const operations = targetUserIDs.map(userID => ({
      userID,
      dates: template.dates,
      action: 'REPLACE'
    }));
    
    return await executeBulkOffDaysUpdate(operations);
  }
};

Testing

The Non-Operational Day Management System includes comprehensive testing strategies covering unit tests, integration tests, and end-to-end user scenarios.

Unit Testing

Component Testing Strategy

Testing Framework: Jest + React Testing Library
Test Files: Component-specific .test.tsx files
Example: src/components/sites/SiteOffDays/SiteOffDays.test.tsx

/**
 * Site Off-Days Component Tests
 */
describe('SiteOffDays Component', () => {
  const mockProps = {
    organizationOffDay: {
      organization: 'test-org',
      dates: { '2024-01-15': true }
    },
    siteKey: 'test-site'
  };
  
  beforeEach(() => {
    jest.clearAllMocks();
    // Mock Redux hooks
    (useSelector as jest.Mock).mockReturnValue({
      isFetchLoading: false,
      isUpsertLoading: false,
      siteOffDays: { disabled: false, dates: {} }
    });
  });
  
  test('renders loading state correctly', () => {
    (useSelector as jest.Mock).mockReturnValueOnce({
      isFetchLoading: true
    });
    
    render(<SiteOffDays {...mockProps} />);
    expect(screen.getByTestId('loading-container')).toBeInTheDocument();
  });
  
  test('renders toggle switch correctly', () => {
    render(<SiteOffDays {...mockProps} />);
    const toggle = screen.getByTestId('offday-toggle');
    expect(toggle).toBeInTheDocument();
  });
  
  test('handles toggle switch interaction', () => {
    const mockDispatch = jest.fn();
    (useDispatch as jest.Mock).mockReturnValue(mockDispatch);
    
    render(<SiteOffDays {...mockProps} />);
    const toggle = screen.getByTestId('offday-toggle');
    
    fireEvent.click(toggle);
    // Verify state change logic
    expect(mockDispatch).toHaveBeenCalled();
  });
  
  test('handles save button interaction', () => {
    render(<SiteOffDays {...mockProps} />);
    const saveButton = screen.getByTestId('submit-button');
    
    fireEvent.click(saveButton);
    // Verify API call is triggered
    expect(mockAPICall).toHaveBeenCalledWith(expectedPayload);
  });
});

Hook Testing

/**
 * Custom Hook Tests
 */
describe('useSiteOffDays Hook', () => {
  const mockSiteID = 'test-site-123';
  const mockCallbacks = {
    onFetchError: jest.fn(),
    onUpsertError: jest.fn(),
    onUpsertSuccess: jest.fn()
  };
  
  test('fetches site off-days on mount', () => {
    const { result } = renderHook(() => 
      useSiteOffDays({ siteID: mockSiteID, ...mockCallbacks })
    );
    
    expect(mockDispatch).toHaveBeenCalledWith(
      fetchSiteOffDays.request({ siteID: mockSiteID })
    );
  });
  
  test('handles toggle functionality', () => {
    const { result } = renderHook(() => 
      useSiteOffDays({ siteID: mockSiteID, ...mockCallbacks })
    );
    
    act(() => {
      result.current[1].handleOffDayToggle();
    });
    
    // Verify state change
    expect(result.current[0].siteOffDays.disabled).toBe(true);
  });
});

Integration Testing

API Integration Tests

/**
 * API Service Integration Tests
 */
describe('Auditor Off-Days API Integration', () => {
  beforeEach(() => {
    fetchMock.resetMocks();
  });
  
  test('fetchUserCount returns formatted data', async () => {
    const mockResponse = {
      data: { today: 5, week: 12, month: 45, year: 150 }
    };
    
    fetchMock.mockResponseOnce(JSON.stringify(mockResponse));
    
    const result = await fetchUserCount();
    
    expect(fetch).toHaveBeenCalledWith(
      expect.stringContaining('/users/off-days/count'),
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          Authorization: expect.any(String)
        })
      })
    );
    
    expect(result).toEqual(mockResponse.data);
  });
  
  test('handles API error responses', async () => {
    fetchMock.mockRejectOnce(new Error('Network error'));
    
    await expect(fetchUserCount()).rejects.toThrow('Network error');
  });
  
  test('fetchNonOpsList handles complex query parameters', async () => {
    const params = {
      type: 'user',
      search: 'john',
      sortBy: 'name',
      order: 'asc',
      limit: 10,
      page: 1
    };
    
    fetchMock.mockResponseOnce(JSON.stringify({ data: { docs: [] } }));
    
    await fetchNonOpsList(params);
    
    expect(fetch).toHaveBeenCalledWith(
      expect.stringContaining('type=user&search=john&sortBy=name'),
      expect.any(Object)
    );
  });
});

Redux Integration Tests

/**
 * Redux Saga Integration Tests
 */
describe('Site Off-Days Saga Integration', () => {
  test('handles successful fetch request', () => {
    const generator = runSaga(
      {
        dispatch: (action) => dispatched.push(action),
        getState: () => ({}),
      },
      fetchSiteOffDaysSaga,
      fetchSiteOffDays.request({ siteID: 'test-site' })
    );
    
    expect(generator.next().value).toEqual(
      call(siteOffDaysService.fetchSiteOffDays, 'test-site')
    );
    
    const mockData = { siteID: 'test-site', dates: ['2024-01-15'] };
    expect(generator.next(mockData).value).toEqual(
      put(fetchSiteOffDays.success(mockData))
    );
  });
  
  test('handles fetch error', () => {
    const generator = runSaga(
      mockStore,
      fetchSiteOffDaysSaga,
      fetchSiteOffDays.request({ siteID: 'test-site' })
    );
    
    generator.next();
    const error = new Error('API Error');
    
    expect(generator.throw(error).value).toEqual(
      put(fetchSiteOffDays.failure(error.message))
    );
  });
});

End-to-End Testing

User Workflow Tests

/**
 * E2E Test Scenarios
 */
describe('Off-Days Management E2E', () => {
  beforeEach(async () => {
    await page.goto('/admin/offdays');
    await page.waitForSelector('[data-testid="calendar"]');
  });
  
  test('organization admin can set off-days', async () => {
    // Select date on calendar
    await page.click('[data-date="2024-01-15"]');
    
    // Verify date is highlighted
    const selectedDate = await page.$('[data-date="2024-01-15"].selected');
    expect(selectedDate).toBeTruthy();
    
    // Save changes
    await page.click('[data-testid="submit-button"]');
    
    // Verify success message
    await page.waitForSelector('.toast-success');
    const successMessage = await page.textContent('.toast-success');
    expect(successMessage).toContain('Off-days updated successfully');
  });
  
  test('site admin can override organization settings', async () => {
    await page.goto('/sites/test-site/settings');
    
    // Enable site off-days
    await page.click('[data-testid="offday-toggle"]');
    
    // Add site-specific date
    await page.click('[data-date="2024-02-20"]');
    
    // Save configuration
    await page.click('[data-testid="submit-button"]');
    
    // Verify override is active
    const toggle = await page.$('[data-testid="offday-toggle"][data-enabled="true"]');
    expect(toggle).toBeTruthy();
  });
  
  test('dashboard shows correct metrics', async () => {
    await page.goto('/admin/auditors/offdays-dashboard');
    
    // Wait for metrics to load
    await page.waitForSelector('[data-testid="user-metrics"]');
    
    // Verify metric cards display numbers
    const todayCount = await page.textContent('[data-metric="today"]');
    expect(parseInt(todayCount)).toBeGreaterThanOrEqual(0);
    
    // Test table filtering
    await page.click('[data-testid="filter-toggle"]');
    await page.selectOption('[data-testid="site-filter"]', 'site-123');
    await page.click('[data-testid="apply-filters"]');
    
    // Verify filtered results
    await page.waitForSelector('[data-testid="table-row"]');
    const tableRows = await page.$$('[data-testid="table-row"]');
    expect(tableRows.length).toBeGreaterThan(0);
  });
});

Performance Testing

Load Testing

/**
 * Performance Test Suite
 */
describe('Off-Days Performance', () => {
  test('calendar renders within performance budget', async () => {
    const startTime = performance.now();
    
    render(<OffDaysDatePicker {...mockProps} />);
    
    const endTime = performance.now();
    const renderTime = endTime - startTime;
    
    // Calendar should render within 100ms
    expect(renderTime).toBeLessThan(100);
  });
  
  test('dashboard data loads within acceptable time', async () => {
    const startTime = performance.now();
    
    const { findByTestId } = render(<OffDaysDashboard />);
    await findByTestId('user-metrics');
    
    const endTime = performance.now();
    const loadTime = endTime - startTime;
    
    // Dashboard should load within 2 seconds
    expect(loadTime).toBeLessThan(2000);
  });
  
  test('table pagination performs efficiently', async () => {
    const mockLargeDataset = Array.from({ length: 1000 }, (_, i) => ({
      id: i,
      name: `User ${i}`,
      dates: ['2024-01-15']
    }));
    
    jest.spyOn(api, 'fetchNonOpsList').mockResolvedValue({
      docs: mockLargeDataset.slice(0, 10),
      totalDocs: 1000,
      totalPages: 100
    });
    
    const startTime = performance.now();
    
    render(<OffDaysTable />);
    
    const endTime = performance.now();
    const renderTime = endTime - startTime;
    
    // Table with 10 rows should render quickly
    expect(renderTime).toBeLessThan(50);
  });
});

Accessibility Testing

A11y Compliance Tests

/**
 * Accessibility Test Suite
 */
describe('Off-Days Accessibility', () => {
  test('calendar has proper ARIA labels', async () => {
    render(<OffDaysDatePicker {...mockProps} />);
    
    const calendarDays = screen.getAllByRole('button');
    
    calendarDays.forEach(day => {
      expect(day).toHaveAttribute('aria-label');
      expect(day).toHaveAttribute('tabIndex');
    });
  });
  
  test('supports keyboard navigation', async () => {
    render(<OffDaysDatePicker {...mockProps} />);
    
    const firstDay = screen.getAllByRole('button')[0];
    firstDay.focus();
    
    fireEvent.keyDown(firstDay, { key: 'ArrowRight' });
    
    // Verify focus moves to next day
    const nextDay = screen.getAllByRole('button')[1];
    expect(nextDay).toHaveFocus();
  });
  
  test('screen reader announces changes', async () => {
    const { container } = render(<OffDaysDatePicker {...mockProps} />);
    
    const liveRegion = container.querySelector('[aria-live]');
    expect(liveRegion).toBeInTheDocument();
    
    // Simulate date selection
    const dayButton = screen.getAllByRole('button')[5];
    fireEvent.click(dayButton);
    
    // Verify announcement
    await waitFor(() => {
      expect(liveRegion).toHaveTextContent(/selected/i);
    });
  });
});

Dependencies

The Non-Operational Day Management System relies on a carefully curated set of dependencies that provide functionality for UI components, data management, and development tooling.

Core Framework Dependencies

PackageVersionPurposeUsage in Off-Days Module
react^17.0.2Core React frameworkAll component rendering and state management
react-dom^17.0.2React DOM renderingComponent mounting and DOM manipulation
typescript^4.5.4Type safety and development toolingType definitions for all components and APIs

State Management Dependencies

PackageVersionPurposeUsage in Off-Days Module
react-redux^7.2.6React bindings for ReduxSite off-days state management
redux^4.1.2Predictable state containerSite off-days reducer and actions
redux-saga^1.1.3Side effect managementAsync API calls for site off-days
react-redux-firebase^3.11.0Firebase-Redux integrationOrganization off-days real-time sync

State Management Usage:

// Redux usage in site off-days
const siteOffDaysReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_SITE_OFF_DAYS_SUCCESS:
      return { ...state, data: action.payload };
    // ... other cases
  }
};
 
// Firebase integration for organization off-days
const firestoreConnect = [
  {
    collection: 'organizationOffDay',
    doc: organizationID,
    storeAs: 'organizationOffDay'
  }
];

UI Component Dependencies

PackageVersionPurposeUsage in Off-Days Module
react-dates^21.8.0Advanced calendar componentsMain calendar picker for all off-days interfaces
styled-components^5.3.3CSS-in-JS stylingComponent styling and theming
react-select^5.2.1Advanced select componentsYear selector and filter dropdowns
@nimbly-technologies/audit-component^1.2.3Internal component librarySegmented buttons and form controls

UI Component Usage Examples:

// React-dates calendar integration
<DayPickerSingleDateController
  numberOfMonths={monthCount}
  onDateChange={handleToggleDate}
  isDayHighlighted={(date) => offDayState.dates[date.format('YYYY-MM-DD')]}
  renderDayContents={renderDayContents}
/>
 
// Styled-components theming
const CalendarContainer = styled.div`
  .CalendarDay {
    border: 1px solid #eae9f9;
    border-radius: 5px;
    color: #867ff8;
  }
`;

Data Visualization Dependencies

PackageVersionPurposeUsage in Off-Days Module
chart.js^3.7.0Chart rendering engineMonthly non-operational days trend chart
react-chartjs-2^4.0.1React wrapper for Chart.jsChart component integration

Chart Usage Example:

<Line
  options={{
    responsive: true,
    scales: {
      y: { min: 0, max: 100 }
    }
  }}
  data={{
    labels: monthLabels,
    datasets: [{
      label: 'Non Operational Days',
      data: monthValues,
      borderColor: '#574FCF',
      backgroundColor: gradientFill
    }]
  }}
/>

Date and Time Dependencies

PackageVersionPurposeUsage in Off-Days Module
moment^2.29.1Date manipulation and formattingDate calculations, formatting, and calendar logic

Moment.js Usage:

// Date formatting for display
const formattedDate = moment(date).format('DD MMMM YYYY');
 
// Date range calculations
const startOfWeek = moment().startOf('week').toDate();
const isToday = moment(date).isSame(moment(), 'day');
 
// Year filtering
const isCurrentYear = moment(date).isSame(selectedYear, 'year');

API and HTTP Dependencies

PackageVersionPurposeUsage in Off-Days Module
query-string^7.1.0URL query parameter handlingAPI request parameter serialization

Query String Usage:

// API parameter building
const queryParams = queryString.stringify({
  type: 'user',
  search: searchText,
  sortBy: 'name',
  order: 'asc',
  limit: 10,
  page: currentPage
});
 
const url = `${apiURL}/users/off-days/userOffDaysData?${queryParams}`;

Utility Dependencies

PackageVersionPurposeUsage in Off-Days Module
lodash^4.17.21Utility functionsDeep cloning, debouncing, and data manipulation
clonedeep^2.1.0Deep object cloningState immutability in calendar updates

Utility Usage Examples:

// Deep cloning for immutable updates
const clonedDates = cloneDeep(offDayState);
clonedDates.dates[dateString] = true;
 
// Debounced search
const debouncedSearch = debounce((text: string) => fetchData(text), 500);

Firebase Dependencies

PackageVersionPurposeUsage in Off-Days Module
firebase^9.6.1Firebase SDKAuthentication and Firestore integration

Firebase Usage:

// Firestore operations
const ref = firestore.collection('organizationOffDay').doc(organizationID);
await ref.set({ 
  dates: newDates, 
  updatedBy: auth.uid, 
  updatedAt: firestore.Timestamp.now() 
});

Internationalization Dependencies

PackageVersionPurposeUsage in Off-Days Module
react-i18next^11.15.3Internationalization frameworkMulti-language support for all UI text
i18next^21.6.10i18n core libraryTranslation key management

i18n Usage:

const { t } = useTranslation();
 
// Translation usage in components
<Title>{t('message.offDaysPage.title')}</Title>
<Button>{t('button.save')}</Button>
toast.success(t('addOn.offDays.success'));

Development Dependencies

PackageVersionPurposeUsage in Off-Days Module
@testing-library/react^12.1.2React component testingUnit tests for all off-days components
@testing-library/jest-dom^5.16.1Custom Jest matchersEnhanced assertions for component testing
jest^27.4.7Testing frameworkTest runner and assertion library

Type Definition Dependencies

PackageVersionPurposeUsage in Off-Days Module
@types/react^17.0.38React type definitionsComponent prop types and hooks
@types/styled-components^5.1.21Styled-components typesCSS-in-JS type safety
@types/moment^2.13.0Moment.js type definitionsDate manipulation type safety
@nimbly-technologies/nimbly-common^2.1.0Shared type definitionsCommon types across Nimbly systems

Type Usage Examples:

import { SiteOffdayMongo } from '@nimbly-technologies/nimbly-common';
 
interface OffDayProps {
  type: 'site' | 'organization';
  organizationOffDay: OffDays;
  siteOffDay?: SiteOffdayMongo;
  handleUpdateOffDay: (offDays: OffDays) => void;
}

Notification Dependencies

PackageVersionPurposeUsage in Off-Days Module
react-toastify^8.1.0Toast notification systemSuccess/error feedback for all operations

Toast Usage:

// Success notifications
toast.success(t('addOn.offDays.success'));
 
// Error notifications  
toast.error(t('addOn.offDays.fail'));
 
// Custom toast configuration
toast.configure({
  position: 'top-right',
  autoClose: 3000,
  hideProgressBar: false
});

Performance Monitoring Dependencies

PackageVersionPurposeUsage in Off-Days Module
Custom MonitoringInternalError tracking and performance monitoringError logging and performance metrics

Monitoring Usage:

// Error logging
Monitoring.logEvent('OffDaysManager -> handleSave', error);
 
// Performance tracking
Monitoring.trackTiming('calendar_render_time', renderDuration);

Bundle Analysis

Bundle Size Impact

  • react-dates: ~150KB (largest single dependency)
  • chart.js: ~120KB (dashboard charts)
  • moment: ~70KB (date operations)
  • styled-components: ~45KB (styling)
  • Total Off-Days Module: ~800KB (minified + gzipped: ~200KB)

Code Splitting Strategy

// Route-level splitting
const OffDaysPage = lazy(() => import('pages/offdays'));
const DashboardPage = lazy(() => import('pages/auditorsOffDaysDashboard'));
 
// Component-level splitting for heavy features
const ChartComponent = lazy(() => import('./TotalNonOffDays'));
const DataTable = lazy(() => import('./OffDaysTable'));

This comprehensive dependency analysis ensures proper version management, security updates, and optimal bundle sizing for the Non-Operational Day Management System.