@php $tabMeta = array_filter([ 'overview' => ['label' => __('Overview'), 'icon' => 'squares-2x2'], 'employment' => ['label' => __('Employment'), 'icon' => 'identification'], 'attendance' => ['label' => __('Attendance'), 'icon' => 'clock'], 'leave' => ['label' => __('Leave'), 'icon' => 'calendar-days'], 'pay' => $canSeePay ? ['label' => $employee->is_consultant ? __('Fees & advices') : __('Pay & payslips'), 'icon' => 'banknotes'] : null, 'documents' => $canSeeFile ? ['label' => __('Documents'), 'icon' => 'folder'] : null, 'conduct' => $canSeeFile ? ['label' => __('Conduct'), 'icon' => 'flag'] : null, ]); $badgeMeta = [ 'active' => ['color' => 'emerald', 'label' => __('Active')], 'probation' => ['color' => 'amber', 'label' => __('On probation')], 'contract_ending' => ['color' => 'amber', 'label' => __('Contract ending')], 'contract_expired' => ['color' => 'rose', 'label' => __('Contract lapsed')], 'inactive' => ['color' => 'slate', 'label' => __('Suspended')], 'exited' => ['color' => 'slate', 'label' => __('Left the company')], ]; $badge = $badgeMeta[$status] ?? $badgeMeta['active']; $initials = \Illuminate\Support\Str::of($employee->user?->name ?? '?') ->explode(' ')->take(2)->map(fn ($w) => mb_substr($w, 0, 1))->implode(''); $kindColors = [ 'allowance' => 'emerald', 'benefit' => 'sky', 'deduction' => 'rose', 'employer_cost' => 'violet', ]; $leaveStatusColors = [ 'pending' => 'amber', 'approved' => 'emerald', 'rejected' => 'rose', 'cancelled' => 'slate', ]; @endphp
@if ($canViewDirectory) {{ __('All employees') }} @elseif ($isSelf) {{ __('My details') }} @endif {{-- ------------------------------------------------------- Identity --}}
{{-- Their photo where there is one, initials where there is not. Looking at your own record with no photo, the placeholder is the prompt to go and add one. --}} @if ($employee->user?->hasProfilePhoto()) {{ $employee->user->name }} @elseif ($isSelf) {{ $initials }} @else {{ $initials }} @endif

{{ $employee->user?->name ?? __('Unknown') }}

{{ $badge['label'] }} @if ($isSelf) {{ __('You') }} @endif

{{ $employee->job_title ?: __('No job title set') }} @if ($employee->department) · {{ $employee->department }} @endif

@if ($employee->employee_number) {{ $employee->employee_number }} @endif @if ($employee->user?->email) {{ $employee->user->email }} @endif {{-- Only worth showing when it differs from the login: this is the address their payslip actually goes to. --}} @if ($employee->usesPersonalEmail()) {{ $employee->personal_email }} ({{ __('personal') }}) @endif @if ($employee->phone) {{ $employee->phone }} @endif @if ($tenure !== null) {{ __(':n yrs service', ['n' => rtrim(rtrim(number_format($tenure, 1), '0'), '.')]) }} @endif
{{-- Your own record is read-only here by design: the personal half of it belongs to you, and lives on My Details. --}} @if ($isSelf) {{ __('My details & photo') }} @endif @if ($canManageRecords) {{ __('Edit record') }} @endif @if ($canManagePay) {{ __('Pay details') }} @endif @if ($canManageRecords) @if ($employee->exited_on) {{ __('Reinstate') }} @else {{ __('Record exit') }} @endif @endif
@if ($employee->exited_on)
{{ __('Left on :date', ['date' => $employee->exited_on->format('j M Y')]) }} @if ($employee->exit_reason), {{ $employee->exit_reason }} @endif
@elseif ($todayRow)
@php $todayLabels = [ 'in' => __('On the clock now'), 'out' => __('Clocked out for the day'), 'leave' => __('On approved leave'), 'absent' => __('Not clocked in today'), 'off' => __('Non-working day'), ]; @endphp {{ $todayLabels[$todayRow['status']] ?? '' }} @if ($todayRow['clock_in']) · {{ $todayRow['clock_in'] }}@if ($todayRow['clock_out']) – {{ $todayRow['clock_out'] }}@endif · {{ __(':h worked', ['h' => round($todayRow['worked_minutes'] / 60, 1).'h']) }} @endif
@endif
{{-- ----------------------------------------------------------- Tabs --}}
@foreach ($tabMeta as $key => $meta) @endforeach
{{-- ======================================================= OVERVIEW --}} @if ($tab === 'overview')
@php $overviewCards = [ ['label' => __('Attendance'), 'value' => $monthStats['attendancePct'].'%', 'icon' => 'check-circle', 'accent' => '#10b981', 'sub' => $monthStats['label']], ['label' => __('Hours worked'), 'value' => $monthStats['workedHours'].'h', 'icon' => 'clock', 'accent' => '#124a61', 'sub' => trans_choice('{1}:count day present|[2,*]:count days present', $monthStats['daysPresent'], ['count' => $monthStats['daysPresent']])], ['label' => __('Overtime'), 'value' => $monthStats['overtimeHours'].'h', 'icon' => 'play', 'accent' => '#f59e0b', 'sub' => __('This month')], ['label' => __('Leave left'), 'value' => rtrim(rtrim(number_format($leave['remaining'], 1), '0'), '.'), 'icon' => 'calendar-days', 'accent' => '#6366f1', 'sub' => __(':taken of :ent days taken', ['taken' => rtrim(rtrim(number_format($leave['taken'], 1), '0'), '.'), 'ent' => rtrim(rtrim(number_format($leave['entitlement'], 1), '0'), '.')])], ]; @endphp @foreach ($overviewCards as $m)

{{ $m['label'] }}

{{ $m['value'] }}

{{ $m['sub'] }}
@endforeach

{{ __('Personal & emergency details') }}

@php $details = [ __('Engagement') => $employee->employmentTypeLabel(), __('Reports to') => $employee->manager?->name, __('Date joined') => $employee->hired_on?->format('j M Y'), __('Probation ends') => $employee->probation_ends_on?->format('j M Y'), __('Contract ends') => $employee->contract_ends_on?->format('j M Y'), __('Full name') => $employee->full_name, __('Date of birth') => $employee->date_of_birth?->format('j M Y'), __('National ID') => $employee->national_id, __('Gender') => $employee->gender, __('Phone') => $employee->phone, ]; @endphp @foreach ($details as $label => $value)
{{ $label }}
{{ $value ?: '—' }}
@endforeach
@if ($employee->address)
{{ __('Address') }}
{{ $employee->address }}
@endif

{{ __('Emergency contact') }}

@if ($employee->emergency_contact_name)

{{ $employee->emergency_contact_name }} @if ($employee->emergency_contact_relation) ({{ $employee->emergency_contact_relation }}) @endif

{{ $employee->emergency_contact_phone ?: '—' }}

@else

{{ __('No emergency contact on file, worth chasing.') }}

@endif
{{-- HR notes are written ABOUT this person, by HR. The subject of a note is the last person who should read it off their own profile page. --}} @if ($employee->notes && $canManageRecords)
{{ __('HR notes') }}
{{ $employee->notes }}
@endif
@if ($documentAlerts->isNotEmpty())

{{ __('Paperwork expiring') }}

    @foreach ($documentAlerts as $doc)
  • {{ $doc->title }} {{ $doc->expires_on->format('j M Y') }}
  • @endforeach
@endif @if ($openLoans->isNotEmpty())

{{ __('Active staff loans') }}

    @foreach ($openLoans as $loan)
  • {{ $loan->reference ?? __('Loan') }} {{ $baseCode }} {{ number_format((float) $loan->outstanding(), 2) }}
  • @endforeach

{{ __('Recovered automatically from payroll.') }}

@endif @if ($canSeePay && $openLiabilities->isNotEmpty())

{{ __('Loss recovery') }}

    @foreach ($openLiabilities as $liability)
  • {{ $liability->reason }} {{ $baseCode }} {{ number_format((float) $liability->outstanding, 2) }}
  • @endforeach
@endif
@endif {{-- ===================================================== EMPLOYMENT --}} @if ($tab === 'employment')

{{ __('Employment record') }}

{{ __('The contractual facts of this engagement.') }}

@if ($canManageRecords) {{ __('Edit') }} @endif
@php $employmentRows = [ __('Employee number') => $employee->employee_number, __('Job title') => $employee->job_title, __('Department') => $employee->department, __('Engagement') => $employee->employmentTypeLabel(), __('Works') => $employee->workModeLabel().($employee->work_mode === 'hybrid' && $employee->remote_days ? ' ('.collect($employee->remote_days)->map(fn ($d) => ucfirst($d))->implode(', ').' '.__('remote').')' : ''), __('Reports to') => $employee->manager?->name, __('Date joined') => $employee->hired_on?->format('j M Y'), __('Probation ends') => $employee->probation_ends_on?->format('j M Y'), __('Contract ends') => $employee->contract_ends_on?->format('j M Y'), __('Years of service') => $tenure !== null ? rtrim(rtrim(number_format($tenure, 1), '0'), '.') : null, ]; @endphp @foreach ($employmentRows as $label => $value)
{{ $label }}
{{ $value ?: '—' }}
@endforeach
@endif {{-- ===================================================== ATTENDANCE --}} @if ($tab === 'attendance')

{{ __('Clock history') }}

{{ $attendanceMonthLabel }} · {{ trans_choice('{0}no days worked|{1}:count day|[2,*]:count days', $attendanceTotals['days'], ['count' => $attendanceTotals['days']]) }} · {{ $attendanceTotals['workedHours'] }}h · {{ __(':h overtime', ['h' => $attendanceTotals['overtimeHours'].'h']) }} @if ($attendanceTotals['offNetwork'] > 0) · {{ trans_choice('{1}:count off-site|[2,*]:count off-site', $attendanceTotals['offNetwork'], ['count' => $attendanceTotals['offNetwork']]) }} @endif

@forelse ($attendanceRecords as $r) @empty @endforelse
{{ __('Date') }} {{ __('In') }} {{ __('Out') }} {{ __('Worked') }} {{ __('Overtime') }} {{ __('Source') }}
{{ $r->business_date->format('D j M') }} {{ $r->clock_in_at?->timezone($tz)?->format('H:i') ?? '—' }} {{ $r->clock_out_at?->timezone($tz)?->format('H:i') ?? '—' }} {{ round($r->worked_minutes / 60, 1) }}h {{ $r->overtime_minutes > 0 ? round($r->overtime_minutes / 60, 1).'h' : '—' }} @if ($r->is_remote) {{ __('Remote') }} @else {{ $r->source === 'manual' ? __('Keyed in') : ($r->gatePassed() ? __('On site') : __('Off-site')) }} @endif
@endif {{-- ========================================================== LEAVE --}} @if ($tab === 'leave')
@foreach ([ ['label' => __('Entitlement'), 'value' => $leave['entitlement'], 'accent' => '#124a61', 'icon' => 'calendar-days'], ['label' => __('Taken'), 'value' => $leave['taken'], 'accent' => '#f59e0b', 'icon' => 'minus-circle'], ['label' => __('Remaining'), 'value' => $leave['remaining'], 'accent' => '#10b981', 'icon' => 'check-circle'], ] as $m)

{{ $m['label'] }}

{{ rtrim(rtrim(number_format($m['value'], 1), '0'), '.') }} {{ __('days') }}

@endforeach

{{ __('Leave history') }}

{{ __('Every request, approved or not.') }}

@forelse ($leaveHistory as $l) @empty @endforelse
{{ __('Dates') }} {{ __('Type') }} {{ __('Days') }} {{ __('Status') }} {{ __('Reason') }}
{{ $l->start_date->format('j M') }} – {{ $l->end_date->format('j M Y') }} {{ $l->leaveType?->name ?? '—' }} {{ rtrim(rtrim(number_format((float) $l->requested_days, 1), '0'), '.') }} {{ ucfirst($l->status) }} {{ $l->reason ?: $l->blocked_reason ?: '—' }}
@endif {{-- ============================================================ PAY --}} @if ($tab === 'pay' && $canSeePay)

{{ __('Basic salary') }}

{{ $employee->salary_currency_code ?: $baseCode }} {{ number_format((float) $employee->monthly_salary, 2) }}

{{ __('per month') }}

{{ __('Daily rate') }}
{{ $baseCode }} {{ number_format($rates['daily_rate'], 2) }}
{{ __('Hourly rate') }}
{{ $baseCode }} {{ number_format($rates['hourly_rate'], 2) }}
{{ __('Overtime rate') }}
{{ $baseCode }} {{ number_format($rates['hourly_rate'] * $rates['overtime_multiplier'], 2) }}

{{ __('How they get paid') }}

{{ $employee->payMethodLabel() }}

{{ $employee->payFundAccount?->name ?? __('Uses the account chosen at finalize') }}

@if ($employee->pay_method === 'bank')
{{ __('Bank') }}
{{ $employee->bank_name ?: '—' }}
{{ __('Account') }}
{{ $employee->bank_account_number ?: '—' }}
@elseif ($employee->pay_method === 'ecocash')
{{ __('Mobile number') }}
{{ $employee->mobile_money_number ?: '—' }}
@endif
{{ __('Tax number') }}
{{ $employee->tax_number ?: '—' }}
{{ __('Social security') }}
{{ $employee->social_security_number ?: '—' }}

{{ __('Awaiting the next run') }}

{{ $baseCode }} {{ number_format($pendingCommission + $pendingEarnings->sum('amount'), 2) }}

{{ __('Commission + overtime not yet paid') }}

@if ($pendingEarnings->isNotEmpty())
    @foreach ($pendingEarnings->take(4) as $earning)
  • {{ $earning->type === 'overtime' ? __('Overtime') : __('Leave cash-out') }} · {{ $earning->period?->format('M Y') }} {{ number_format((float) $earning->amount, 2) }}
  • @endforeach
@endif @if (($owedSalary ?? collect())->isNotEmpty())

{{ __('Salary owed') }}

    @foreach ($owedSalary as $owed)
  • {{ $owed->periodLabel() }}@if ($owed->deferred) · {{ __('deferred') }}@endif {{ number_format($owed->outstanding(), 2) }}
  • @endforeach
@endif
{{-- Commission pauses (CRM_PLAN.md section 17, owned by CRM S8) --}} {{-- Benefits & deductions ------------------------------------- --}}

{{ __('Benefits & deductions') }}

{{ __('What payroll adds to and takes off this person automatically.') }} @if ($employee->is_consultant) {{ __('They are engaged as a consultant, so the team-wide items below do not reach them, only what is assigned here by name.') }} @endif

@if ($canManagePay) @endif
@if ($canManagePay) @endif @foreach ($blanketComponents as $c) @if ($canManagePay) @endif @endforeach @forelse ($assignedComponents as $c) @if ($canManagePay) @endif @empty @if ($blanketComponents->isEmpty()) @endif @endforelse
{{ __('Item') }} {{ __('Kind') }} {{ __('How it is worked out') }} {{ __('Applies') }}{{ __('Actions') }}
{{ $c->name }} {{ $c->kindLabel() }} {{ $c->ruleLabel($baseCode) }} {{ $employee->is_consultant ? __('Employees only') : __('Everyone') }} {{ __('Team-wide') }}
{{ $c->name }} @if ($c->pivot->notes) {{ $c->pivot->notes }} @endif {{ $c->kindLabel() }} @if ($c->pivot->value !== null) {{ rtrim(rtrim(number_format((float) $c->pivot->value, 4), '0'), '.') }} ({{ __('override') }}) @else {{ $c->ruleLabel($baseCode) }} @endif @if ($c->pivot->starts_on || $c->pivot->ends_on) {{ $c->pivot->starts_on ? \Illuminate\Support\Carbon::parse($c->pivot->starts_on)->format('M Y') : __('always') }} – {{ $c->pivot->ends_on ? \Illuminate\Support\Carbon::parse($c->pivot->ends_on)->format('M Y') : __('ongoing') }} @else {{ __('Ongoing') }} @endif
{{-- Payslips --------------------------------------------------- --}}

{{ $employee->is_consultant ? __('Payment advices') : __('Payslips') }}

{{ __('Finalized runs only, a draft is not a statement of what was paid.') }}

@forelse ($payslips as $slip) @empty @endforelse
{{ __('Period') }} {{ __('Document') }} {{ $employee->is_consultant ? __('Fee') : __('Gross') }} {{ __('Deductions') }} {{ __('Net paid') }} {{ __('Paid via') }} {{ __('Actions') }}
{{ $slip->run?->period?->format('F Y') }} {{ $slip->payslip_number ?: '—' }} {{ number_format((float) $slip->gross_pay, 2) }} {{ (float) $slip->deduction_total > 0 ? '−'.number_format((float) $slip->deduction_total, 2) : '—' }} {{ $baseCode }} {{ number_format((float) $slip->net_pay, 2) }} @if ($slip->isPartlyPaid()) {{ __('paid now :a · owed :b', ['a' => number_format($slip->amountPaidNow(), 2), 'b' => number_format($slip->amountOwed(), 2)]) }} @endif {{ $slip->payMethodLabel() }} @if ($slip->fundAccount) {{ $slip->fundAccount->name }} @endif
@endif {{-- ====================================================== DOCUMENTS --}} @if ($tab === 'documents')

{{ __('Employee file') }}

@if ($canManageRecords) {{ __('CV, interview notes, offer, job description, contract, ID and conduct records. Files are private; you choose what the employee can open.') }} @else {{ __('The documents HR has shared with you.') }} @endif

@if ($canManageRecords)
@if ($driveEnabled) @if ($employee->drive_folder_url) {{ __('Open in Drive') }} @endif {{ __('Check Drive for new files') }} {{ __('Checking…') }} @endif {{ __('Add document') }}
@endif
@if ($canManageRecords) @endif @forelse ($documents as $doc) @if ($canManageRecords) @endif @empty @endforelse
{{ __('Document') }} {{ __('Type') }} {{ __('Issued') }} {{ __('Expires') }} {{ __('Added by') }}{{ __('Employee sees it') }}{{ __('Actions') }}
{{ $doc->title }} @if ($doc->body) {{ \Illuminate\Support\Str::limit($doc->body, 180) }} @endif @if ($doc->hasFile()) {{ $doc->original_name }} · {{ $doc->humanSize() }} @if ($doc->drive_file_id) · {{ __('in Drive') }} @endif @endif {{ $doc->typeLabel() }} {{ $doc->issued_on?->format('j M Y') ?? '—' }} @if ($doc->expires_on) {{ $doc->expires_on->format('j M Y') }} @else — @endif {{ $doc->uploader?->name ?? '—' }}
@if ($doc->hasFile()) @endif @if ($canManageRecords) @endif
@endif {{-- ======================================================= CONDUCT --}} @if ($tab === 'conduct' && $canSeeFile) @endif {{-- ========================================================= MODALS --}} {{-- Employment record --}} {{ __('Employment record') }}

{{ __('Issued automatically. The prefix is set in Settings → Numbering.') }}

{{ __('Remote staff clock in from anywhere; the shop geofence does not apply.') }}

@if ($e_work_mode === 'hybrid')
@foreach (['mon' => __('Mon'), 'tue' => __('Tue'), 'wed' => __('Wed'), 'thu' => __('Thu'), 'fri' => __('Fri'), 'sat' => __('Sat'), 'sun' => __('Sun')] as $dayKey => $dayLabel) @endforeach
@endif

{{ __('Leave blank for permanent staff.') }}

{{ __('Personal') }}

{{ __('As it appears on their ID. Payslips and statutory returns use this name.') }}

{{ __('Where payslips are sent. Blank means the login address.') }}

{{ __('Emergency contact') }}

{{ __('Cancel') }} {{ __('Save record') }} {{ __('Saving…') }}
{{-- Pay details --}} @if ($canManagePay) {{ __('Pay details') }}

{{ __('Salary changes only reach a payslip when the draft run for that month is rebuilt. Finalized runs never change.') }}

{{ __('Their net pay is deducted from this account when the run is finalized.') }}

@if ($p_pay_method === 'bank')
@elseif ($p_pay_method === 'ecocash')
@endif
{{ __('Cancel') }} {{ __('Save pay details') }} {{ __('Saving…') }}
{{-- Assign a benefit / deduction --}} {{ __('Assign a benefit or deduction') }}
@if ($availableComponents->isEmpty())

{{ __('Nothing left to assign, add more under Payroll → Benefits & Deductions.') }}

@endif
{{ __('Cancel') }} {{ __('Assign') }}
@endif {{-- Exit --}} {{ __('Record exit') }}

{{ __('This takes them off payroll and the daily roster from now on. Past payslips and attendance are kept.') }}

{{ __('Cancel') }} {{ __('Record exit') }}
{{-- Document --}} {{ __('Add to employee file') }}

{{ __('Set this and the directory will warn you before it lapses.') }}

{{ __('Cancel') }} {{ __('Add to file') }} {{ __('Saving…') }}