Employee Portal · Business GuideReference sections by EMP-XXX
EMP-001

System Overview & Role

The Employee portal is a personal workspace for staff members assigned to engineering projects. Employees cannot see other users's data — every endpoint filters by auth()->id(). The typical employee is a site engineer, supervisor, or technical officer linked to a StaffProfile record.

CapabilityHow it works
View tasksEmployeeTask WHERE assigned_user_id = auth()->id()
Clock in/outTimeClockEntry per user; only one open entry at a time
Log site visitsSiteVisit linked to project_id and user_id
View calendarCalendarEvent WHERE assigned_user_id = auth()->id()
Upload to galleryGalleryItem with uploaded_by = auth()->id()
Receive notificationsAppNotification WHERE user_id = auth()->id()
EMP-002

Authentication

Employees authenticate via POST /api/login with user_type: employee. The rejectUnlessPortalUserType("employee") guard on every employee endpoint checks this field and returns 403 if the user is not an employee.

⚠ Employee users have NO permission system — all employee endpoints are accessible to any valid employee. Employees cannot see admin, contractor, or client data.
EMP-003

Task Lifecycle

Tasks are created by admin/staff users and assigned to an employee via assigned_user_id. The employee portal is read-only for task data — employees can view their tasks but status updates must be done by admin.

Task statusMeaning
pendingNot yet started; visible on employee home screen
in_progressWork started
completedDone
cancelledNo longer needed
Task priorityUsage
highUrgent; should surface at top of task list
normalStandard priority
lowBackground task
EMP-004

Time Clock Rules

The time clock system tracks employee hours per project. The rules are enforced server-side:

1POST /api/employee/clock/in → server checks for existing open entry (clock_out_at IS NULL)
2If open entry exists → returns 422 "Already clocked in"
3If no open entry → creates new TimeClockEntry with clock_in_at = now()
4POST /api/employee/clock/out → finds open entry, sets clock_out_at = now()
5If no open entry → returns 422 "Not clocked in"
// Duration formula (client-side)
duration_hours = (clock_out_at - clock_in_at) / 3600
// Weekly total
weekly_hours = SUM(duration_hours) WHERE user_id=N AND clock_in_at BETWEEN week_start AND week_end
⚠ project_id on clock entries is optional. If the employee is not assigned to a specific project they can clock in with project_id: null.
EMP-005

Site Visits

Site visits are structured log entries for field observations. Unlike daily logs (which are contractor-submitted), site visits are submitted by employees.

FieldNotes
titleRequired; brief description of the visit purpose
notesFull observations, issues found, actions taken
project_idOptional; links the visit to a specific project
visited_atDefaults to now() if not provided; use for backdating
statusAuto-set to completed on creation
EMP-006

Error Reference

CodeCause
401Token missing or expired
403user_type is not employee
422Validation failed (e.g. already clocked in, missing required field)