Skip to main content

Deactivating Staff

This guide covers the staff deactivation process, including soft deletion, impact on scheduling, data retention, and reactivation procedures.


Understanding Deactivation​

Soft Delete Approach​

Shyfts uses soft deletion for staff members rather than permanent deletion. This means:

  1. Data Preserved - All staff records remain in the database
  2. Historical Integrity - Past shifts and reports stay accurate
  3. Audit Trail - Employment history is maintained
  4. Reversible - Staff can be reactivated if needed

Deactivation vs Deletion​

ActionEffectReversible
DeactivateSets is_active = false✅ Yes
DeleteRemoves record entirely❌ No

Shyfts only supports deactivation to maintain data integrity.


Deactivation Process​

From Staff List​

  1. Navigate to Dashboard → Staff Management
  2. Find the staff member to deactivate
  3. Click the Delete/Deactivate button (trash icon)
  4. Confirm the action in the dialog
// Source: src/components/staff/StaffList.tsx:58-82
const handleDelete = async (staffId: string) => {
if (!confirm('Are you sure you want to deactivate this staff member?')) {
return;
}

try {
setDeletingId(staffId);
const response = await fetch(`/api/staff/${staffId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ is_active: false }),
});

if (!response.ok) {
throw new Error('Failed to deactivate staff member');
}

await loadStaff();
} catch (err) {
console.error('Error deactivating staff:', err);
alert('Failed to deactivate staff member');
} finally {
setDeletingId(null);
}
};

Confirmation Dialog​

The system displays a confirmation dialog before deactivation:

// Source: src/components/staff/StaffList.tsx:59
if (!confirm('Are you sure you want to deactivate this staff member?')) {
return;
}
Confirmation Required

Deactivation requires explicit confirmation. This prevents accidental removal of staff members from the active roster.


API Endpoint​

Deactivate Staff​

Endpoint: PATCH /api/staff/[id]

Request Body:

{
"is_active": false
}

Response:

{
"success": true,
"data": {
"id": "staff-uuid",
"first_name": "John",
"last_name": "Smith",
"is_active": false,
"updated_at": "2025-01-13T10:30:00Z"
}
}

Database Update​

The deactivation updates the staff table:

UPDATE staff
SET is_active = false,
updated_at = NOW()
WHERE id = 'staff-uuid';

Impact of Deactivation​

Immediate Effects​

AreaImpact
Staff ListStaff member hidden from active list
SchedulingCannot be assigned to new shifts
DropdownsRemoved from staff selection options
LoginAccount access may be revoked

Preserved Data​

Data TypeStatus
Historical ShiftsPreserved and visible
Leave RecordsMaintained for reporting
DocumentsRetained in storage
Time RecordsKept for payroll/audit
Profile DataUnchanged

Calendar Impact​

Deactivated staff:

  • Future shifts - Should be reassigned or cancelled
  • Past shifts - Remain visible in historical views
  • Reports - Continue to appear in historical reports

Staff List Filtering​

Active/Inactive Filter​

The staff list can filter by status:

// Source: src/components/staff/CompanyStaffManagement.tsx:202-203
(filterStatus === 'active' && member.isActive) ||
(filterStatus === 'inactive' && !member.isActive)

Status Display​

// Source: src/components/staff/CompanyStaffManagement.tsx:413
{staff.filter(s => s.isActive).length}

Filter Options​

FilterShows
AllActive and inactive staff
ActiveOnly is_active = true
InactiveOnly is_active = false

Before Deactivation​

Pre-Deactivation Checklist​

Before deactivating a staff member, ensure:

  1. Future Shifts Reassigned

    • Check for upcoming shifts
    • Reassign or cancel as needed
  2. Leave Requests Resolved

    • Approve or reject pending requests
    • Cancel approved future leave
  3. Outstanding Time Records

    • Review any pending timesheet submissions
    • Approve completed time records
  4. Documents Collected

    • Ensure all company property returned
    • Collect any required exit documentation
  5. Access Revoked

    • Deactivation will prevent login
    • Consider timing of access removal

Finding Future Shifts​

SELECT s.*, r.name as room_name
FROM shifts s
JOIN rooms r ON s.room_id = r.id
WHERE s.staff_id = 'staff-uuid'
AND s.start_time > NOW()
AND s.status = 'SCHEDULED'
ORDER BY s.start_time;

Offboarding Workflow​

  1. Notify HR/Management

    • Document reason for departure
    • Set last working day
  2. Review Scheduled Work

    • Check calendar for future shifts
    • Arrange coverage or reassignment
  3. Process Final Pay

    • Review outstanding timesheets
    • Calculate final payment
  4. Collect Company Property

    • Keys, badges, equipment
    • Company documents
  5. Document Return

    • Obtain signed acknowledgments
    • File exit documentation
  6. Deactivate Account

    • Set is_active = false
    • Timing: after last working day
  7. Communicate Departure

    • Inform relevant team members
    • Update schedules as needed

Reactivating Staff​

When to Reactivate​

Staff can be reactivated when:

  • Employee returns from extended leave
  • Rehiring a former employee
  • Accidental deactivation
  • Seasonal staff returning

Reactivation Process​

  1. Navigate to Staff Management
  2. Filter to show Inactive staff
  3. Find the staff member
  4. Click Edit Profile
  5. Change status to Active
  6. Save changes

Reactivation API​

Endpoint: PATCH /api/staff/[id]

Request Body:

{
"is_active": true
}

Post-Reactivation​

After reactivating:

  1. Update Role - Verify role assignment is current
  2. Check Credentials - Ensure login access is restored
  3. Review Availability - Update availability schedule
  4. Assign Shifts - Begin scheduling as needed

Bulk Deactivation​

Multiple Staff Deactivation​

For bulk operations (e.g., seasonal staff):

const deactivateMultiple = async (staffIds: string[]) => {
const promises = staffIds.map(id =>
fetch(`/api/staff/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ is_active: false })
})
);

await Promise.all(promises);
};

Bulk Reactivation​

Similarly for reactivation:

const reactivateMultiple = async (staffIds: string[]) => {
const promises = staffIds.map(id =>
fetch(`/api/staff/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ is_active: true })
})
);

await Promise.all(promises);
};

Data Retention​

Retention Policy​

Deactivated staff data is retained according to legal requirements:

Data TypeRetention Period
Employment records6 years after departure
Payroll/tax records6 years
Disciplinary recordsDuration of warning + 12 months
Training records3 years
Medical records40 years (occupational health)

Permanent Deletion​

If permanent deletion is required (e.g., GDPR request):

  1. Verify eligibility - Check legal retention requirements
  2. Document request - Record the deletion request
  3. Remove from database - Delete staff record
  4. Clear storage - Remove associated documents
  5. Audit log - Record deletion in audit trail
GDPR Compliance

Permanent deletion should only be performed when legally required and after verification that retention periods have been met.


Access Control​

Login Status​

When a staff member is deactivated:

ScenarioAccess
Active sessionMay continue until logout
New login attemptShould be prevented
Password resetShould be blocked

Immediate Lockout​

For immediate access revocation, consider:

  1. Force logout - Invalidate active sessions
  2. Password reset - Change password to random value
  3. Account lock - Set account lock flag

Reporting​

Including Inactive Staff​

Reports can include or exclude inactive staff:

// Include all staff
const allStaff = await supabase
.from('staff')
.select('*')
.eq('company_id', companyId);

// Active only (default)
const activeStaff = await supabase
.from('staff')
.select('*')
.eq('company_id', companyId)
.eq('is_active', true);

// Inactive only
const inactiveStaff = await supabase
.from('staff')
.select('*')
.eq('company_id', companyId)
.eq('is_active', false);

Historical Reports​

For historical accuracy, reports typically include all staff who were active during the reporting period, regardless of current status.


Best Practices​

Deactivation Timing​

ScenarioRecommended Timing
ResignationLast working day
TerminationEffective immediately
RetirementLast working day
Leave of absenceStart of leave (if extended)
Seasonal endEnd of season

Communication​

  1. Internal - Inform relevant team members
  2. Scheduling - Update future rotas promptly
  3. Handover - Ensure knowledge transfer
  4. Documentation - Record departure details

Compliance​

  1. Follow company policy - Adhere to HR procedures
  2. Document reasons - Maintain departure records
  3. Exit interviews - Conduct when appropriate
  4. Reference requests - Prepare for future references

Troubleshooting​

Common Issues​

IssueSolution
Cannot find inactive staffChange filter to "All" or "Inactive"
Deactivation failedCheck network connection, verify permissions
Staff still showing in dropdownsRefresh page, clear cache
Future shifts not cancelledManually cancel or reassign shifts

Error Messages​

ErrorCauseSolution
"Failed to deactivate"API errorCheck console for details
"Permission denied"Insufficient rightsContact administrator
"Staff not found"Invalid IDRefresh staff list


Source Files:

  • src/components/staff/StaffList.tsx - Deactivation handler
  • src/components/staff/CompanyStaffManagement.tsx - Status filtering
  • src/app/api/staff/[id]/route.ts - Staff update API
  • src/types/database.types.ts - Staff type definitions