components([ Tabs::make('Employee Details') ->tabs([ Tab::make('Overview') ->schema([ Section::make('Profile') ->schema([ ImageEntry::make('profile_photo_path') ->label('Photo') ->disk(config('hr.file_uploads.disk')) ->visibility('private') ->circular() ->height(120) ->placeholder('—') ->columnSpanFull(), TextEntry::make('employee_number') ->label('Employee #'), TextEntry::make('full_name'), TextEntry::make('national_id') ->label('National ID') ->placeholder('—'), TextEntry::make('gender') ->badge() ->color(fn (Gender $state): string => $state->color()) ->formatStateUsing(fn (Gender $state): string => $state->label()), TextEntry::make('birth_date') ->date(), TextEntry::make('phone'), TextEntry::make('address') ->placeholder('—') ->columnSpanFull(), ]) ->columns(2), Section::make('Organization') ->schema([ TextEntry::make('department.name') ->label('Department') ->badge() ->color('info'), TextEntry::make('position.name') ->label('Position') ->badge() ->color('primary'), TextEntry::make('shift.name') ->label('Shift') ->badge() ->color('gray'), TextEntry::make('employment_status') ->badge() ->color(fn (EmploymentStatus $state): string => $state->color()) ->formatStateUsing(fn (EmploymentStatus $state): string => $state->label()) ->icon(fn (EmploymentStatus $state): string => $state->icon()), ]) ->columns(2), Section::make('Employment Timeline') ->schema([ TextEntry::make('hire_date') ->label('Hire Date') ->date() ->icon('heroicon-o-calendar'), TextEntry::make('termination_date') ->label('Termination Date') ->date() ->placeholder('—') ->icon('heroicon-o-calendar-days'), TextEntry::make('tenure') ->label('Tenure') ->state(fn (Employee $record): string => $record->hire_date ? $record->hire_date->diffForHumans(now(), true) : '—'), TextEntry::make('notes') ->placeholder('—') ->columnSpanFull(), ]) ->columns(2), ]), Tab::make('Statistics') ->schema([ Section::make('Leave & Attendance') ->schema([ TextEntry::make('stats_vacation_taken') ->label('Vacation Taken (days)') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationTaken) ->numeric() ->icon('heroicon-o-sun'), TextEntry::make('stats_vacation_remaining') ->label('Vacation Remaining (days)') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationRemaining) ->numeric() ->color('success') ->icon('heroicon-o-calendar'), TextEntry::make('stats_sick_leave_count') ->label('Sick Leave Records') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->sickLeaveCount) ->numeric() ->icon('heroicon-o-heart'), ]) ->columns(3), Section::make('HR Records') ->schema([ TextEntry::make('stats_reports_count') ->label('Disciplinary Reports') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->reportsCount) ->numeric() ->icon('heroicon-o-exclamation-triangle'), TextEntry::make('stats_bonuses_total') ->label('Total Bonuses') ->state(fn (Employee $record): float => app(EmployeeStatisticsService::class)->summary($record)->bonusesTotal) ->money('TMT') ->icon('heroicon-o-banknotes'), TextEntry::make('stats_gifts_count') ->label('Gifts Received') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->giftsCount) ->numeric() ->icon('heroicon-o-gift'), ]) ->columns(3), ]), Tab::make('Leave Summary') ->schema([ Section::make('Annual Leave Balance') ->schema([ TextEntry::make('leave_balance_taken') ->label('Days Taken') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationTaken) ->suffix(' days'), TextEntry::make('leave_balance_remaining') ->label('Days Remaining') ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationRemaining) ->suffix(' days') ->color('success'), TextEntry::make('leave_balance_total') ->label('Annual Allowance') ->state(fn (): int => (int) config('hr.annual_leave_days')) ->suffix(' days'), ]) ->columns(3), Section::make('Upcoming Approved Leave') ->schema([ TextEntry::make('upcoming_leave') ->label('Scheduled Vacations') ->state(function (Employee $record): string { $upcoming = app(EmployeeStatisticsService::class) ->summary($record) ->upcomingLeave; if ($upcoming->isEmpty()) { return 'No upcoming approved leave'; } return $upcoming ->map(fn (Vacation $vacation): string => sprintf( '%s: %s – %s (%d days)', $vacation->type->label(), $vacation->start_date->format('M j, Y'), $vacation->end_date->format('M j, Y'), $vacation->days, )) ->implode("\n"); }) ->listWithLineBreaks() ->columnSpanFull(), ]), Section::make('Other Leave Types') ->schema([ TextEntry::make('unpaid_leaves_count') ->label('Unpaid Leave Records') ->state(fn (Employee $record): int => $record->unpaidLeaves()->count()) ->numeric(), TextEntry::make('explanations_count') ->label('Explanations') ->state(fn (Employee $record): int => $record->explanations()->count()) ->numeric(), ]) ->columns(2), ]), ]) ->columnSpanFull(), ]); } }