Last Updated: November 2, 2025
Version: 1.5.0
This document provides a comprehensive technical overview of the ShiftIQ system architecture, codebase organization, and key implementation details. Use this as a reference when resuming development or onboarding new team members.
Latest Updates (v1.5.0):
- ✅ Added complete database schema documentation for AuditLogs, EmailQueue, and SystemSettings tables
- ✅ Documented all database constraints (CHECK, CASCADE behaviors, UNIQUE)
- ✅ Added comprehensive performance index documentation
- ✅ Complete enumeration value mappings for all enums
- ✅ Enhanced database file information with data type specifications
C:\ROTA\
├── src/ # Backend .NET solution
│ ├── StaffRota.Core/ # Domain layer
│ │ ├── Entities/ # Database entities
│ │ ├── Enums/ # Enumerations (UserRole, ShiftStatus, etc.)
│ │ └── Interfaces/ # Service and repository interfaces
│ ├── StaffRota.Business/ # Business logic layer
│ │ ├── Services/ # Business services
│ │ │ ├── ApprovalWorkflowService.cs # Approval workflow engine
│ │ │ └── EmailService.cs # Email notification system
│ │ └── Models/ # Business models
│ ├── StaffRota.Data/ # Data access layer
│ │ └── Repositories/ # Repository implementations
│ ├── StaffRota.Web/ # Web API layer
│ │ ├── Controllers/ # API controllers
│ │ ├── Models/ # DTOs and view models
│ │ ├── Services/ # Web-specific services
│ │ ├── Middleware/ # Custom middleware
│ │ ├── appsettings.json # Configuration
│ │ └── StaffRotaDb.sqlite # SQLite database file
│ └── StaffRota.Tests/ # Unit tests
├── frontend/staff-rota-ui/ # React frontend
│ ├── src/
│ │ ├── components/
│ │ │ ├── layout/ # Layout components (Header, Sidebar)
│ │ │ ├── pages/ # Page components
│ │ │ └── settings/ # Settings components
│ │ ├── theme/ # Theme configuration
│ │ │ ├── createTheme.ts # MUI theme factory
│ │ │ ├── ThemeProvider.tsx # Theme context provider
│ │ │ └── types.ts # Theme type definitions & defaults
│ │ ├── api/ # API client functions
│ │ ├── services/ # Frontend services
│ │ ├── contexts/ # React contexts
│ │ ├── types/ # TypeScript type definitions
│ │ └── App.tsx # Main app component
│ └── package.json # npm dependencies
├── reset_and_populate_db.sql # Test data population script
└── README.md # Project documentation
- Configuration:
frontend/staff-rota-ui/src/theme/types.ts - Factory:
frontend/staff-rota-ui/src/theme/createTheme.ts - Provider:
frontend/staff-rota-ui/src/theme/ThemeProvider.tsx
// Default theme configuration (types.ts)
brandColors: {
primary: '#1D1F48', // Primary - Navy
secondary: '#B21A53', // Secondary - Raspberry
accent: '#9bcd4e', // Accent - Core Green
success: '#9bcd4e', // Success - Core Green
warning: '#ed6c02', // Warning - Orange (standard)
error: '#B21A53', // Error - Raspberry
info: '#43C5B8', // Info - Eggplant (Teal)
titleColor: '#1D1F48', // Page title color - Navy
}- Primary - Eggplant: #43C5B8 (R 67, G 197, B 184) - Used for info
- Primary - Navy: #1D1F48 (R 29, G 31, B 72) - Main primary color
- Secondary - Raspberry: #B21A53 (R 178, G 26, B 83) - Secondary color
- Secondary - Charcoal: #303040 (R 48, G 48, B 64) - Available
- Secondary - Gray: #E6E7E8 (R 230, G 231, B 232) - Available
- Tertiary - Black: #000000 - Available
- Tertiary - White: #FFFFFF - Available
- Accent - Core Green: #9bcd4e (R 155, G 205, B 78) - Success/accent
- Dynamic theme switching: Light/dark mode support
- Persistent storage: Theme saved to localStorage
- CSS custom properties: Theme values available as CSS variables
- Admin configurable: Colors can be changed via Settings → Color Schemes
- Component overrides: Custom styling for MUI components (Button, Card, Paper, TextField, TableHead)
import { useTheme } from '@mui/material';
const MyComponent = () => {
const theme = useTheme();
// Access theme colors
const primaryColor = theme.palette.primary.main;
const secondaryColor = theme.palette.secondary.main;
// Convert hex to rgba for opacity
const hexToRgba = (hex: string, alpha: number) => {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
return (
<Box sx={{
background: `linear-gradient(135deg,
${hexToRgba(theme.palette.primary.main, 0.15)} 0%,
${hexToRgba(theme.palette.secondary.main, 0.15)} 100%)`
}}>
Content
</Box>
);
};- Location:
src/StaffRota.Web/Controllers/AuthController.cs - Token Generation: JWT tokens with user ID, email, and role claims
- Configuration:
appsettings.json→ JwtSettings section - Middleware: JWT Bearer authentication in
Program.cs
- Service:
frontend/staff-rota-ui/src/services/authService.ts - Storage: JWT token stored in
localStorageasshiftiq_token - API Headers: Token sent as
Authorization: Bearer <token>
// src/StaffRota.Core/Enums/UserRole.cs
public enum UserRole {
TeamMember = 1, // Standard staff member
TeamLead = 2, // Team manager/lead
TeamAdmin = 3 // System administrator
}- Admin:
test@admin.com/Test123!- Password Hash:
$2a$12$YLtHMLFGSH9sFQqPBsd/AO992UD8KXmLcoNaqK/Mex.NNzxdDYskG - Role: 3 (TeamAdmin)
- Password Hash:
- All Test Users: Password is
Password123!
- Primary Key:
Id(INTEGER) - Important Fields:
Email(UNIQUE),Username(UNIQUE)PasswordHash- Hashed passwordRole- UserRole enum (1=TeamMember, 2=TeamLead, 3=TeamAdmin)TeamId- Foreign key to TeamsFirstName,LastName,JobTitlePhoneNumber,HourlyRateIsActive- Soft delete flagPreferredTimezone- User timezone (default 'UTC')
- Primary Key:
Id(INTEGER) - Important Fields:
Name(UNIQUE)ManagerId- Foreign key to Users (team lead)LocationId- Foreign key to LocationsIsActive- Soft delete flag
- Primary Key:
Id(INTEGER) - Important Fields:
Name(UNIQUE)Address,CapacityIsActive- Soft delete flag
- Primary Key:
Id(INTEGER) - Important Fields:
Title,DescriptionStartDateTime,EndDateTime(TEXT in ISO format)LocationId,TeamId- Foreign keysStatus- ShiftStatus enumPriority- Integer priority levelRequiredStaff- Number of staff neededRecurrencePatternId- NULL for one-time shiftsPayRate- Decimal hourly rate
- Primary Key:
Id(INTEGER) - Important Fields:
Type- RecurrenceType enum (0=Daily, 1=Weekly, 2=Monthly)Interval- Repeat every N days/weeks/monthsDaysOfWeek- Comma-separated (e.g., "1,3,5" for Mon/Wed/Fri)StartDate,EndDate(datetime2)MaxOccurrences- Optional limit on repetitions
- Primary Key:
Id(INTEGER) - Unique Constraint:
(ShiftId, UserId)- One assignment per user per shift - Important Fields:
ShiftId,UserId- Foreign keysAssignedByUserId- Who made the assignmentIsConfirmed- Boolean confirmation statusStatus- Assignment status enum
- Primary Key:
Id(INTEGER) - Important Fields:
Type- ApprovalRequestType enumStatus- ApprovalStatus enum (Pending, Approved, Rejected)RequesterId,ApproverId- Foreign keys to UsersShiftId,SwapRequestId- Foreign keys to related entitiesRequestData- JSON serialized request detailsPriority- Request priority (1=Low to 5=Critical)
- Primary Key:
Id(INTEGER) - Purpose: Complete audit trail for all system actions
- Important Fields:
UserId- Foreign key to Users (who performed the action)Action- Action performed (e.g., "Create", "Update", "Delete")EntityType- Type of entity affected (e.g., "Shift", "User")EntityId- ID of the affected entityChanges- Summary of changes madeOldValues- JSON of previous valuesNewValues- JSON of new valuesTimestamp- When the action occurredIpAddress- Client IP addressUserAgent- Browser/client informationNotes- Additional context
- Indexes: Action, EntityType, EntityId, Timestamp, UserId
- Use Cases: Security auditing, compliance, debugging, change history
- Primary Key:
Id(INTEGER) - Purpose: Email queuing system with retry logic and priority support
- Important Fields:
ToAddress,FromAddress- Email addressesSubject,Body- Email content (HTML)PlainTextBody- Plain text version (optional)Status- EmailStatus enum (1=Queued, 2=Processing, 3=Sent, 4=Failed, 5=FailedPermanently)CreatedAt- When email was queuedSentAt- When email was successfully sentRetryCount- Number of send attempts (default: 0)MaxRetries- Maximum retry attempts (default: 3)LastError- Error message from last failed attemptPriority- Email priority (1=Critical to 5=Low, default: 3)ScheduledAt- When to send (for scheduled emails)TemplateName- Email template identifierTemplateData- JSON data for template rendering
- Constraints:
CK_EmailQueue_MaxRetries- MaxRetries >= 0CK_EmailQueue_Priority- Priority BETWEEN 1 AND 5CK_EmailQueue_RetryCount- RetryCount >= 0
- Indexes: Status, Priority, CreatedAt, ScheduledAt, ToAddress
- Composite Index:
IX_EmailQueue_Processing(Status, Priority, CreatedAt) for efficient queue processing
- Primary Key:
Key(TEXT) - Purpose: Dynamic system configuration with type validation and encryption support
- Important Fields:
Key- Unique setting identifier (e.g., "EmailProvider.SmtpHost")Value- Current setting valueDescription- Human-readable descriptionCategory- Grouping category (default: "General")DataType- Expected data type (default: "string")ModifiedAt- Last modification timestampModifiedByUserId- Foreign key to Users (who last changed it)IsEncrypted- Whether value is encrypted (for sensitive data)IsReadOnly- Prevents UI modification of system-critical settingsDefaultValue- Factory default for reset functionalityValidationRules- JSON schema for value validation
- Indexes: Category, ModifiedAt, ModifiedByUserId
- Use Cases: Application configuration, feature flags, email settings, theme customization
- Shifts:
CK_Shifts_EndAfterStart- Ensures EndDateTime > StartDateTimeCK_Shifts_PayRate- Ensures PayRate >= 0
- SwapRequests:
CK_SwapRequests_DifferentUsers- Prevents RequestingUserId = TargetUserId (no self-swaps)
- EmailQueue:
CK_EmailQueue_MaxRetries- Ensures MaxRetries >= 0CK_EmailQueue_Priority- Ensures Priority BETWEEN 1 AND 5CK_EmailQueue_RetryCount- Ensures RetryCount >= 0
- ON DELETE CASCADE: RecurrencePatterns → Shifts (deleting pattern removes all occurrences)
- ON DELETE RESTRICT: Prevents deletion of Users who created shifts/requests (preserves audit trail)
- ON DELETE SET NULL: Most foreign keys (allows entity deletion while preserving records)
- Users: Email (IX_Users_Email), Username (IX_Users_Username)
- Teams: Name
- Locations: Name
- Shifts:
IX_Shifts_DateRange(StartDateTime, EndDateTime) - Range queries - ApprovalRequests:
IX_ApprovalRequests_Status_ApproverId- Manager approval dashboardsIX_ApprovalRequests_Status_Priority- Priority-sorted pending queuesIX_ApprovalRequests_Status_RequesterId- User request tracking
- EmailQueue:
IX_EmailQueue_Processing(Status, Priority, CreatedAt) - Queue processing
- High-traffic query fields: UserId, TeamId, LocationId, Status, StartDateTime, EndDateTime
- Foreign keys: All foreign key columns for JOIN performance
- Filter fields: IsActive, Role, Status enums
TeamMember = 1 - Standard staff member
TeamLead = 2 - Team manager/lead
TeamAdmin = 3 - System administrator
Draft = 1 - Created but not published
Published = 2 - Visible to team members
Active = 3 - Ready for assignment
Assigned = 4 - Assigned to team member
SwapRequested = 5 - Swap request pending
Completed = 6 - Shift completed
Cancelled = 7 - Shift cancelled
Assigned = 0 - Assigned but not confirmed
Confirmed = 1 - User confirmed attendance
Declined = 2 - User declined assignment
Cancelled = 3 - Manager cancelled assignment
NoShow = 4 - User didn't show up
Completed = 5 - Shift completed successfully
Pending = 1 - Awaiting review
Approved = 2 - Approved by manager
Rejected = 3 - Rejected by manager
Cancelled = 4 - Cancelled by requester
Expired = 5 - Expired (time limit exceeded)
ShiftCreation = 1 - Request to create shift
ShiftModification = 2 - Request to modify shift
ShiftCancellation = 3 - Request to cancel shift
ShiftSwap = 4 - Request to swap shifts
OvertimeRequest = 5 - Request for overtime
TimeOffRequest = 6 - Request for time off
Pending = 1 - Awaiting target user response
Accepted = 2 - Target accepted, awaiting approval
Declined = 3 - Target declined request
Approved = 4 - Team Lead approved swap
Rejected = 5 - Team Lead rejected swap
Cancelled = 6 - Requester cancelled
Queued = 1 - Queued for sending
Processing = 2 - Currently being sent
Sent = 3 - Successfully sent
Failed = 4 - Failed, will retry
FailedPermanently = 5 - Failed after max retries
Low = 1 - Can be processed when convenient
Medium = 2 - Standard processing time
High = 3 - Should be processed quickly
Urgent = 4 - Requires immediate attention
Low = 0 - Low priority shift
Normal = 1 - Normal priority (default)
High = 2 - High priority shift
Critical = 3 - Critical priority shift
Daily = 0 - Repeat daily
Weekly = 1 - Repeat weekly (use DaysOfWeek)
Monthly = 2 - Repeat monthly
# Shift Management Notifications
ShiftAssigned = 1 - User assigned to shift
ShiftUnassigned = 2 - User removed from shift
ShiftCancelled = 3 - Shift cancelled
ShiftModified = 4 - Shift details changed
ShiftReminder = 5 - Upcoming shift reminder
# Swap Request Notifications
SwapRequested = 10 - Swap request received
SwapApproved = 11 - Swap approved by manager
SwapRejected = 12 - Swap rejected by manager
SwapCancelled = 13 - Swap cancelled by requester
# Schedule Notifications
SchedulePublished = 20 - Schedule published
ScheduleModified = 21 - Schedule changed
WeeklyScheduleReminder = 22 - Weekly schedule reminder
# Administrative Notifications
AccountCreated = 30 - New account created
PasswordReset = 31 - Password reset link
AccountDeactivated = 32 - Account deactivated
RoleChanged = 33 - User role changed
# Approval Workflow Notifications
ShiftApprovalRequired = 40 - Shift needs approval
ShiftApproved = 41 - Shift approved
ShiftRejected = 42 - Shift rejected
OvertimeApprovalRequired = 43 - Overtime needs approval
# System Notifications
SystemMaintenance = 50 - Scheduled maintenance
SystemUpdate = 51 - System update notice
TestNotification = 52 - Test notification
- Location:
src/StaffRota.Web/StaffRotaDb.sqlite - Type: SQLite database
- Data Types:
- DateTime fields: Stored as TEXT in ISO 8601 format
- Decimal fields:
decimal(8,2)for currency/rates - Boolean fields: INTEGER (0=false, 1=true)
- Migrations: Entity Framework Core migrations in
StaffRota.Data - Note: SQLite limitations - concurrent writes may cause locking (not suitable for high-traffic production)
- File:
database-scripts/reset_and_populate_db.sql - Documentation: See
database-scripts/README.mdfor details - What it does:
- Preserves
test@admin.comaccount - Deletes all other data (users, teams, locations, shifts)
- Creates 6 locations, 13 teams, 44 users
- Creates 47 shifts (41 one-time + 6 recurring)
- Assigns some staff to shifts
- Preserves
Run script:
cd C:\ROTA\src\StaffRota.Web
Get-Content ..\..\database-scripts\reset_and_populate_db.sql | sqlite3 StaffRotaDb.sqlite- Route:
/dashboard - Purpose: Main landing page after login
- Layout: 3-column Box flexbox layout
- Left Column: Recent Shifts (placeholder)
- Middle Column: Upcoming Shifts
- Grouped by week (startOfWeek/endOfWeek)
- Shows first week only
- Day/date display:
format(parseISO(shift.startTime), 'EEE').toUpperCase()+ date number - Alternating row backgrounds with theme gradient (15% opacity)
- Right Column: Stat cards (YTD, This Month, Unassigned, Pending Approval, TBC x2)
- Features:
- Auto-updating timestamp (updates every 60 seconds)
- Shift details dialog (two-column layout)
- Fetches from
/api/shifts/my-shifts - Filters for upcoming shifts only
- Route:
/dashboard-mock - Status: Mock version, not actively used
- Note: LiveDashboard.tsx is the actual dashboard
- Route:
/my-shifts - Purpose: User's personal shift schedule
- Views:
- All Shifts - 2-column card grid layout
- Weekly View - Calendar-style week view
- Monthly Views - This/Next/Last month tabs
- Features:
- Shift details dialog
- Swap shift functionality
- Filter by time period
- Route:
/monthly-timeline - Purpose: Monthly shift overview
- Layout: Weekly list view grouped by weeks
- Shows all weeks in the month (including cross-month weeks)
- Day/date display (MON 21, TUE 22, etc.)
- Alternating row backgrounds
- Route:
/approvals - Purpose: Shift swap approval workflow
- Tabs:
- Pending Approvals (for managers)
- My Requests (user's submitted requests)
- History (processed requests)
- Layout: Two-column (65%/35% split)
- Left: Request list
- Right: Shift details panel
- Features:
- Self-approval prevention
- Coverage impact warnings
- Decision comments
- Badge notifications
- Route:
/team-management - Access: TeamLead and TeamAdmin roles
- Features:
- TeamLeads: Manage only their team members
- Admins: Accordion view of all teams
- Expand/collapse all functionality
- Create users with team/role assignment
- Location:
frontend/staff-rota-ui/src/components/layout/Header.tsx - Features:
- ShiftIQ logo and branding
- "Team Member" badge (Core Green background)
- User profile menu
- Notifications icon
- Sign out functionality
- Navigation menu
- Role-based menu items
POST /api/auth/login- User login, returns JWT tokenPOST /api/auth/register- User registrationPOST /api/auth/refresh- Refresh JWT token
GET /api/users- Get all users (Admin only)GET /api/users/{id}- Get user by IDGET /api/users/my-team-members- Get team members (role-based filtering)POST /api/users- Create new userPUT /api/users/{id}- Update userDELETE /api/users/{id}- Delete user (soft delete)GET /api/users/by-role/{role}- Get users by role
GET /api/shifts- Get all shiftsGET /api/shifts/{id}- Get shift by IDGET /api/shifts/my-shifts- Get current user's shiftsPOST /api/shifts- Create new shiftPUT /api/shifts/{id}- Update shiftDELETE /api/shifts/{id}- Delete shiftPOST /api/shifts/recurring- Create recurring shift pattern
GET /api/teams- Get all teamsGET /api/teams/{id}- Get team by IDPOST /api/teams- Create teamPUT /api/teams/{id}- Update teamDELETE /api/teams/{id}- Delete team
GET /api/locations- Get all locationsGET /api/locations/{id}- Get location by IDPOST /api/locations- Create locationPUT /api/locations/{id}- Update locationDELETE /api/locations/{id}- Delete location
GET /api/approvals/pending- Get pending approval requestsGET /api/approvals/my-requests- Get user's submitted requestsGET /api/approvals/history- Get processed requestsPOST /api/approvals/approve/{id}- Approve requestPOST /api/approvals/reject/{id}- Reject request
GET /api/swap-requests- Get all swap requestsPOST /api/swap-requests- Create swap requestPUT /api/swap-requests/{id}/approve- Approve swapPUT /api/swap-requests/{id}/reject- Reject swap
cd C:\ROTA\src\StaffRota.Web
dotnet restore # First time only
dotnet run- Backend runs on
https://localhost:5001 - Swagger UI available at
https://localhost:5001/swagger
cd C:\ROTA\frontend\staff-rota-ui
npm install # First time only
npm start- Frontend runs on
http://localhost:3000 - Auto-opens in browser
# Run migrations
dotnet ef database update
# Create new migration
dotnet ef migrations add MigrationName
# Build solution
dotnet build
# Run tests
cd src\StaffRota.Tests
dotnet test# Install dependencies
npm install
# Start dev server
npm start
# Build for production
npm run build
# Run linter
npm run lintcd C:\ROTA\src\StaffRota.Web
sqlite3 StaffRotaDb.sqlite
# Inside sqlite3:
.tables # List all tables
.schema Users # Show table schema
SELECT * FROM Users; # Query data
.exit # Exit sqlite3cd C:\ROTA\src\StaffRota.Web
Get-Content ..\..\reset_and_populate_db.sql | sqlite3 StaffRotaDb.sqliteAll pages should follow this pattern:
<Box sx={{ p: 3 }}>
<Box sx={{ mb: 4 }}>
<Typography
variant="h4"
sx={{
fontWeight: 700,
color: 'primary.main' // Uses theme titleColor
}}
>
Page Title
</Typography>
<Typography variant="body1" color="text.secondary">
Page subtitle or description
</Typography>
</Box>
{/* Page content */}
</Box>Right-aligned buttons with consistent spacing:
<Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, mb: 3 }}>
<Button variant="outlined">Cancel</Button>
<Button variant="contained">Save</Button>
</Box>For list views with subtle color distinction:
const theme = useTheme();
const hexToRgba = (hex: string, alpha: number) => {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
};
// In map:
<Box sx={{
background: index % 2 === 0
? `linear-gradient(135deg,
${hexToRgba(theme.palette.primary.main, 0.15)} 0%,
${hexToRgba(theme.palette.secondary.main, 0.15)} 100%)`
: 'transparent'
}}>
{/* Row content */}
</Box>- Version: MUI v7
- Note: Grid2 API not compatible - use Box/Stack with flexbox instead
- Example:
// Don't use Grid2:
// <Grid2 container spacing={2}>
// Use Box with flexbox:
<Box sx={{ display: 'flex', gap: 2 }}>
<Box sx={{ flex: 1 }}>Column 1</Box>
<Box sx={{ flex: 1 }}>Column 2</Box>
</Box>- Cause: Role enum values incorrect (using 0 instead of 1)
- Fix: Run
UPDATE Users SET Role = 1 WHERE Role = 0;in SQLite
- Cause: Need to restart frontend after theme changes
- Fix: Stop npm (Ctrl+C) and run
npm startagain
- Location:
src/StaffRota.Web/Program.cs - Check: CORS policy allows
http://localhost:3000
- Fix: Log out and log in again
- Location: Token stored in
localStorage.shiftiq_token
- Cause: Multiple connections to SQLite
- Fix: Close all sqlite3 sessions and restart backend
- Backend config:
src/StaffRota.Web/appsettings.json - Frontend config:
frontend/staff-rota-ui/package.json - Theme defaults:
frontend/staff-rota-ui/src/theme/types.ts
- Main DB:
src/StaffRota.Web/StaffRotaDb.sqlite - Write-ahead log:
src/StaffRota.Web/StaffRotaDb.sqlite-wal - Shared memory:
src/StaffRota.Web/StaffRotaDb.sqlite-shm
Microsoft.AspNetCore.Authentication.JwtBearer- JWT authenticationMicrosoft.EntityFrameworkCore.Sqlite- SQLite providerMicrosoft.EntityFrameworkCore.Tools- EF migrationsSwashbuckle.AspNetCore- Swagger/OpenAPI
react^18.0.0 - UI library@mui/material^7.x - Material-UI components@mui/icons-material- Material iconsdate-fns- Date manipulationreact-router-dom- Routingtypescript- Type safety
- ✅ Complete database schema documentation
- Added AuditLogs table (audit trail system)
- Added EmailQueue table (email queuing with retry logic)
- Added SystemSettings table (dynamic configuration)
- Documented all database constraints (CHECK, CASCADE, UNIQUE)
- Comprehensive performance index documentation
- ✅ Complete enumeration reference
- All enum values mapped with descriptions
- ShiftStatus, AssignmentStatus, ApprovalStatus/Type
- SwapRequestStatus, EmailStatus, Priority levels
- RecurrenceType documentation
- ✅ Enhanced technical details
- SQLite data type specifications
- Foreign key cascade behavior documentation
- Composite and single-column index strategies
- Corporate color scheme implementation
- Theme-based dynamic gradients
- Comprehensive test data script
- Fixed user role enum values
- Team Management interface for TeamLeads/Admins
- Configurable title color system
- UI consistency across all pages
- Complete approval workflow system
- Self-approval prevention
- Email notification system
- All Shifts 2-column layout
- Monthly calendar views
- Space optimization
- Use functional components with hooks
- Props interfaces named
{Component}Props - Use
constfor component definitions - Theme access via
useTheme()hook
- Async/await for all async operations
- Repository pattern for data access
- Service layer for business logic
- DTOs for API responses
- React components: PascalCase (e.g.,
MyComponent.tsx) - Services: camelCase (e.g.,
authService.ts) - C# files: PascalCase matching class name
- Recent Shifts section population in LiveDashboard
- Actual data for YTD, Unassigned, Pending Approval stats
- TBC placeholder card functionality
- Weekly view optimization (2-week display)
- Enhanced mobile responsiveness
- Real-time push notifications
- Advanced reporting and analytics
- SQLite not suitable for high-concurrency production
- Email service requires SMTP configuration
- No real-time updates (polling only)
- Limited offline support
README.md- Project overview and quick startTECHNICAL_REFERENCE.md- This fileProject.md- Detailed project specificationsTEST_PLAN.md- Testing documentationAPPROVAL_WORKFLOW_TEST_PLAN.md- Approval system tests
- URL: https://github.com/Kariko762/ShiftIQ
- Branch: master
- Database: SQLite at
src/StaffRota.Web/StaffRotaDb.sqlite - Admin Account:
test@admin.com/Test123!- Password Hash:
$2a$12$YLtHMLFGSH9sFQqPBsd/AO992UD8KXmLcoNaqK/Mex.NNzxdDYskG
- Password Hash:
- API Base URL:
https://localhost:5001 - Frontend URL:
http://localhost:3000
Document Version: 1.0
Last Updated: November 2, 2025
Maintainer: Development Team