{{-- The clock itself lives on /attendance now; this is the desk that decides things, so keep the way back one click away. --}} {{ __('Attendance') }} {{-- KPIs ----------------------------------------------------------- --}}
@foreach ($kpis as $m)

{{ $m['label'] }}

{{ $m['value'] }}

{{ $m['sub'] }}
@endforeach
{{-- Tabs ----------------------------------------------------------- --}} @php // Labels + icons for every tab; the component decides WHICH of them this // person may open ($visibleTabs), so a tab that would 403 is never drawn. $tabMeta = [ 'requests' => ['label' => __('Requests'), 'icon' => 'inbox'], 'leave' => ['label' => __('Leave'), 'icon' => 'calendar-days'], 'overtime' => ['label' => __('Overtime'), 'icon' => 'play'], 'leave_cash' => ['label' => __('Leave cash-out'), 'icon' => 'banknotes'], 'settings' => ['label' => __('Settings'), 'icon' => 'cog-6-tooth'], ]; $tabs = array_intersect_key($tabMeta, array_flip($visibleTabs)); @endphp
count($tabs) < 2, ])> @foreach ($tabs as $key => $meta) @endforeach
{{-- THE INBOX: everything waiting on a decision --}} @if ($tab === 'requests')
@if ($inboxLeave->isEmpty() && $inboxLoans->isEmpty() && collect($inboxLinks)->sum('count') === 0)
@endif {{-- Leave: the one queue that is settled in a click, so it is answered here rather than linked to. --}} @if ($inboxLeave->isNotEmpty())

{{ __('Leave requests') }} {{ $inboxLeave->count() }}

{{ __('Whole days and part-days, oldest first.') }}

    @foreach ($inboxLeave as $leave)
  • {{ $leave->user?->name }} · {{ $leave->leaveType?->name }} @if ($leave->isPartial()) {{ $leave->lengthLabel() }} @endif

    {{ $leave->isPartial() ? $leave->start_date->format('D d M Y') : $leave->start_date->format('D d M') . ' – ' . $leave->end_date->format('D d M Y') }} · {{ trans_choice('{1} :count day|[2,*] :count days', (float) $leave->requested_days, ['count' => (float) $leave->requested_days]) }} {{ __('off the balance') }} @if ($leave->reason) {{ $leave->reason }} @endif

    @if ($canDecideLeave)
    {{ __('Approve') }} {{ __('Reject') }}
    @endif
  • @endforeach
@endif {{-- Staff loans --}} @if ($inboxLoans->isNotEmpty())

{{ __('Loan requests') }} {{ $inboxLoans->count() }}

{{ __('Approving one pays the money out of a treasury account there and then.') }}

    @foreach ($inboxLoans as $loan)
  • {{ $loan->borrower_label }} {{ $loan->currency_code }} {{ number_format((float) $loan->principal, 2) }}

    {{ trans_choice('{1} :count month|[2,*] :count months', (int) $loan->term_months, ['count' => (int) $loan->term_months]) }} · {{ __(':cur :amount a month', [ 'cur' => $loan->currency_code, 'amount' => number_format((float) $loan->monthly_instalment, 2), ]) }} @if ($loan->notes) {{ $loan->notes }} @endif

    @if ($canDecideLoans)
    {{ __('Approve & pay out') }} {{ __('Decline') }}
    @endif
  • @endforeach
@endif {{-- The queues that are decided on their own page, where the reason box and the backdating rules already live. --}} @if (collect($inboxLinks)->sum('count') > 0)
@foreach ($inboxLinks as $link) @continue($link['count'] === 0)

{{ $link['label'] }} {{ $link['count'] }}

{{ $link['hint'] }}

@endforeach
@endif {{-- Managing the team is more than a queue: the roster and the hours gap are one click away. --}}
@elseif ($tab === 'leave')

{{ __('Pending approvals') }}

@if ($pending->isEmpty())
@else
    @foreach ($pending as $leave)
  • {{ $leave->user?->name }} · {{ $leave->leaveType?->name }}

    {{ $leave->start_date->format('d M') }} – {{ $leave->end_date->format('d M Y') }} · {{ (float) $leave->requested_days }} {{ __('day(s)') }} @if ($leave->reason)— {{ $leave->reason }}@endif

    {{ __('Approve') }} {{ __('Reject') }}
  • @endforeach
@endif

{{ __('Recently decided') }}

@if ($recentLeave->isEmpty())
{{ __('No decisions yet.') }}
@else
    @foreach ($recentLeave as $leave)
  • {{ $leave->user?->name }} · {{ $leave->start_date->format('d M') }}–{{ $leave->end_date->format('d M') }} {{ ucfirst($leave->status) }}
  • @endforeach
@endif
{{-- Leave types --}}

{{ __('Leave types') }}

    @foreach ($leaveTypes as $type)
  • {{ $type->name }}
    @if ($type->counts_against_entitlement){{ __('counts') }}@endif @if ($type->cashable){{ __('cashable') }}@endif @unless ($type->is_paid){{ __('unpaid') }}@endunless
  • @endforeach
{{ __('Add type') }}
@elseif ($tab === 'overtime' || $tab === 'leave_cash') @php $isOt = $tab === 'overtime'; @endphp

{{ $isOt ? __('Overtime earnings') : __('Leave cash-outs') }}

{{ __('Generate from the period, then approve. Approved items are paid in the next payroll run.') }}

@if ($isOt) {{ __('Add overtime') }} @endif {{ __('Generate') }}
@if (! $isOt && ! ($leaveCashable ?? false))
{{ __('Leave cash-out is currently disabled. Enable it in Settings to generate.') }}
@endif @if ($earnings->isEmpty())
@else
@foreach ($earnings as $e) @endforeach
{{ __('Employee') }} {{ __('Period') }} {{ $isOt ? __('Hours') : __('Days') }} {{ __('Rate') }} {{ __('Amount') }} {{ __('Status') }}
{{ $e->user?->name }} @if ($e->source === 'manual'){{ __('manual') }}@endif {{ $e->period->format('M Y') }} {{ (float) $e->quantity }} {{ $e->currency_code }} {{ number_format((float) $e->rate, 2) }} {{ $e->currency_code }} {{ number_format((float) $e->amount, 2) }} @php $tone = match ($e->status) { 'approved' => 'sky', 'paid' => 'emerald', 'cancelled' => 'slate', default => 'amber' }; @endphp {{ ucfirst($e->status) }} @if ($e->status === 'pending') {{ __('Approve') }} @endif @if (in_array($e->status, ['pending', 'approved'], true)) @endif
{{ $earnings->links() }}
@endif
{{-- Manual overtime modal --}} @if ($isOt) {{ __('Add overtime') }}

{{ __('Priced at the staff member\'s hourly rate (from their salary) × the overtime multiplier (:x×). Lands as pending, approve it to include it in the next payroll run.', ['x' => rtrim(rtrim(number_format($otMultiplier, 2), '0'), '.')]) }}

@if ($staffMembers->isEmpty())

{{ __('No active staff profiles. Add salaries under Payroll → Staff first.') }}

@endif
@if ($otPreview)
{{ __('Hourly rate') }} {{ $baseCode }} {{ number_format($otPreview['hourly'], 2) }}
{{ __('Overtime rate') }} (× {{ rtrim(rtrim(number_format($otMultiplier, 2), '0'), '.') }}) {{ $baseCode }} {{ number_format($otPreview['rate'], 2) }}
{{ (float) $otPreview['hours'] }} {{ __('hrs') }} → {{ __('Total') }} {{ $baseCode }} {{ number_format($otPreview['amount'], 2) }}
@endif
{{ __('Cancel') }} {{ __('Add overtime') }}
@endif {{-- SETTINGS --}} @elseif ($tab === 'settings')

{{ __('Working calendar') }}

{{ __('Set each day Off, Half day or Full. Half-days earn half the standard hours and count as 0.5 of a leave day.') }}

@foreach (['mon' => 'Monday', 'tue' => 'Tuesday', 'wed' => 'Wednesday', 'thu' => 'Thursday', 'fri' => 'Friday', 'sat' => 'Saturday', 'sun' => 'Sunday'] as $code => $lbl)
{{ $lbl }}
@foreach (['off' => __('Off'), 'half' => __('Half day'), 'full' => __('Full')] as $mode => $modeLabel) @endforeach
@endforeach
{{-- Clock reminders & the absence rule --}}
@if ($s_clock_reminders)
@php // The field is live, so it can be mid-edit or blank; never let a // half-typed time blow up the settings page. $cutoffLabel = rescue(fn () => \Illuminate\Support\Carbon::createFromFormat('H:i', $s_work_start) ->addMinutes(max(0, (int) $s_grace_minutes))->format('H:i'), null, false); @endphp @if ($cutoffLabel)

{{ __('Clock in by :cutoff and the day is on time. After that it is recorded late, and anyone who never clocks in is marked absent and told how to appeal.', ['cutoff' => $cutoffLabel]) }}

@endif
@endif

{{ __('Also the daily overtime threshold.') }}

{{ __('Blank = half of a full day.') }}

{{-- Derived rate basis --}}

{{ __('Salary rate basis (auto-derived from the calendar)') }}

{{ __('Days / week') }}
{{ rtrim(rtrim(number_format($rateBasis['days_per_week'], 2), '0'), '.') }}
{{ __('Avg working days / month') }}
{{ number_format($rateBasis['avg_days_per_month'], 2) }}
{{ __('Hours / week') }}
{{ rtrim(rtrim(number_format($rateBasis['weekly_hours'], 2), '0'), '.') }}
{{ __('Avg working hours / month') }}
{{ number_format($rateBasis['avg_monthly_hours'], 2) }}
{{ __('Daily rate') }} = {{ __('Salary') }} ÷ {{ number_format($rateBasis['avg_days_per_month'], 2) }}
{{ __('Hourly rate') }} = {{ __('Salary') }} ÷ {{ number_format($rateBasis['avg_monthly_hours'], 2) }}
{{ __('Overtime') }} = {{ __('OT hours') }} × {{ __('Hourly rate') }} × {{ rtrim(rtrim(number_format((float) $s_overtime_multiplier, 2), '0'), '.') ?: '1' }}

{{ __('Clock-in and clock-out times are shown in this timezone. Times are stored in UTC, so changing this never rewrites history.') }}

{{ __('Right now it is :time here.', ['time' => $localNowLabel]) }}

{{ __('Overtime & leave policy') }}

{{-- Where staff may clock in from. Two independent passes, either of which lets someone in: standing at the shop, or arriving from a known office IP. There is no WiFi-name option because browsers do not expose the network name. --}}

{{ __('Where staff can clock in') }}

{{ __('Shop location') }}

{{ __('Filled in from this device, accurate to about') }} m. {{ __('Save to apply.') }}

{{ __('200 m suits a single premises. Raise it if staff on laptops get blocked — a desktop with no GPS is positioned off nearby WiFi and can be a few hundred metres out.') }}

{{ __('Leave the coordinates empty to switch the location check off entirely.') }}

{{ __('Work update reminders') }}

{{ __('Someone clocked in this long with no recorded work today (no work update, job time, job change, quote, invoice or note) is politely asked for a quick update, and directors get a note. Once a day per person. It never changes pay or attendance.') }}

{{ __('Your current IP:') }} {{ request()->ip() }}

{{ __('A matching IP lets someone clock in without a location check — useful on a fixed line. Starlink and most mobile data rotate the address through the day, so an entry here goes stale; the shop location above is the reliable check. Leave this empty unless your line has a static IP.') }}

{{ __('End-of-day cash-up') }}

{{ __('This person can\'t clock out until they\'ve declared the day\'s cash. Leave unassigned to disable the block.') }}

{{ __('Save settings') }}
@endif
{{-- Declining a loan. A reason is required: it is shown to the employee with the decision, and "no" without one is how morale goes. --}} {{ __('Decline loan request') }} {{ __('Cancel') }} {{ __('Decline') }} {{-- Reject modal --}} {{ __('Reject leave request') }} {{ __('Cancel') }} {{ __('Reject') }}