components([ Tabs::make(__('hr.sections.employee_details')) ->tabs([ Tab::make(__('hr.sections.overview')) ->schema([ Section::make(__('hr.sections.profile')) ->schema([ ImageEntry::make('profile_photo_path') ->label(__('hr.fields.photo')) ->disk(config('hr.file_uploads.disk')) ->visibility('private') ->circular() ->height(120) ->placeholder('—') ->columnSpanFull(), TextEntry::make('employee_number') ->label(__('hr.fields.employee_number')), TextEntry::make('full_name'), TextEntry::make('national_id') ->label(__('hr.fields.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(__('hr.navigation.organization')) ->schema([ TextEntry::make('department.name') ->label(__('hr.fields.department')) ->badge() ->color('info'), TextEntry::make('position.name') ->label(__('hr.fields.position')) ->badge() ->color('primary'), TextEntry::make('shift.name') ->label(__('hr.fields.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(__('hr.sections.employment_timeline')) ->schema([ TextEntry::make('hire_date') ->label(__('hr.fields.hire_date')) ->date() ->icon('heroicon-o-calendar'), TextEntry::make('termination_date') ->label(__('hr.fields.termination_date')) ->date() ->placeholder('—') ->icon('heroicon-o-calendar-days'), TextEntry::make('tenure') ->label(__('hr.fields.tenure')) ->state(fn (Employee $record): string => $record->hire_date ? $record->hire_date->diffForHumans(now(), true) : '—'), TextEntry::make('notes') ->placeholder('—') ->columnSpanFull(), ]) ->columns(2), ]), Tab::make(__('hr.sections.statistics')) ->schema([ Section::make(__('hr.sections.leave_attendance')) ->schema([ TextEntry::make('stats_vacation_taken') ->label(__('hr.fields.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(__('hr.fields.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(__('hr.fields.sick_leave_records')) ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->sickLeaveCount) ->numeric() ->icon('heroicon-o-heart'), ]) ->columns(3), Section::make(__('hr.sections.hr_records')) ->schema([ TextEntry::make('stats_reports_count') ->label(__('hr.fields.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(__('hr.fields.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(__('hr.fields.gifts_received')) ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->giftsCount) ->numeric() ->icon('heroicon-o-gift'), ]) ->columns(3), ]), Tab::make(__('hr.sections.leave_summary')) ->schema([ Section::make(__('hr.sections.annual_leave_balance')) ->schema([ TextEntry::make('leave_balance_taken') ->label(__('hr.fields.days_taken')) ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationTaken) ->suffix(' ' . __('hr.messages.days_suffix')), TextEntry::make('leave_balance_remaining') ->label(__('hr.fields.days_remaining')) ->state(fn (Employee $record): int => app(EmployeeStatisticsService::class)->summary($record)->vacationRemaining) ->suffix(' ' . __('hr.messages.days_suffix')) ->color('success'), TextEntry::make('leave_balance_total') ->label(__('hr.fields.annual_allowance')) ->state(fn (): int => (int) config('hr.annual_leave_days')) ->suffix(' ' . __('hr.messages.days_suffix')), ]) ->columns(3), Section::make(__('hr.sections.upcoming_approved_leave')) ->schema([ TextEntry::make('upcoming_leave') ->label(__('hr.fields.scheduled_vacations')) ->state(function (Employee $record): string { $upcoming = app(EmployeeStatisticsService::class) ->summary($record) ->upcomingLeave; if ($upcoming->isEmpty()) { return __('hr.messages.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(__('hr.sections.other_leave_types')) ->schema([ TextEntry::make('unpaid_leaves_count') ->label(__('hr.fields.unpaid_leave_records')) ->state(fn (Employee $record): int => $record->unpaidLeaves()->count()) ->numeric(), TextEntry::make('explanations_count') ->label(__('hr.fields.explanations')) ->state(fn (Employee $record): int => $record->explanations()->count()) ->numeric(), ]) ->columns(2), ]), ]) ->columnSpanFull(), ]); } }