NhanSu); $this->departments = $user->is_admin ? DonVi::pluck('name', 'id')->toArray() : DonVi::whereIn('id', $nhansu->NhanSuDonVis->pluck('DonVi.id'))->pluck('name', 'id')->toArray(); $this->departmentId = array_key_first($this->departments); $this->resetToDefault(); } protected function resetToDefault(): void { $this->data = [ 'department_id' => $this->departmentId, 'month' => now()->month, 'year' => now()->year, 'reports' => [], ]; $this->loaded = false; $this->schemaKey = 'init'; } /** 🔧 Định nghĩa schema */ public function schema(Schema $schema): Schema { return $schema ->statePath('data') ->key($this->schemaKey) ->components($this->getFormSchema()); } protected function getFormSchema(): array { $components = [ Section::make('Chọn thời gian nhập báo cáo') ->schema([ Grid::make(3)->schema([ Select::make('department_id') ->label('Bộ phận') ->options(fn() => $this->departments) ->default(fn() => $this->departmentId) ->required() ->disabled(fn() => $this->loaded), Select::make('month') ->label('Tháng') ->options(collect(range(1, 12))->mapWithKeys(fn($m) => [$m => "Tháng $m"])) ->default(now()->month) ->required() ->disabled(fn() => $this->loaded), Select::make('year') ->label('Năm') ->options(collect(range(now()->year - 2, now()->year + 1))->mapWithKeys(fn($y) => [$y => $y])) ->default(now()->year) ->required() ->disabled(fn() => $this->loaded), ]), ]) ->footerActions([ Action::make('load') ->label('📂 Tải dữ liệu') ->button() ->color('info') ->visible(fn() => !$this->loaded) ->action(fn() => $this->loadDataForSelectedTime()), Action::make('reset') ->label('🔄 Chọn lại tháng khác') ->button() ->color('gray') ->visible(fn() => $this->loaded) // ->requiresConfirmation() // ->modalHeading('Xác nhận chọn lại tháng') // ->modalDescription('Bạn có chắc muốn chọn lại tháng? Dữ liệu chưa lưu sẽ bị mất.') // ->modalSubmitActionLabel('Đồng ý') // ->modalCancelActionLabel('Hủy') ->action(fn() => $this->doReset()), ]), ]; // ✅ Khi dữ liệu đã tải, render thêm phần báo cáo if ($this->loaded) { $components[] = Section::make('Báo cáo công việc theo nhóm báo cáo') ->schema($this->buildTreeSections()) ->collapsed(false); } return $components; } /** ✅ Fix thật sự: rebuild schema ngay sau khi load dữ liệu */ public function loadDataForSelectedTime(): void { $month = $this->data['month'] ?? now()->month; $year = $this->data['year'] ?? now()->year; $deptId = $this->data['department_id'] ?? $this->departmentId; if (!$deptId) { Notification::make()->title('Vui lòng chọn đơn vị trước khi tải dữ liệu')->danger()->send(); return; } $existing = ReportsMonthly::where('department_id', $deptId) ->where('month', $month) ->where('year', $year) ->get(); $reports = []; foreach ($existing as $r) { $reports[$r->report_group_id][] = [ 'id' => $r->id, 'work_content' => $r->work_content, 'current_result' => $r->current_result, 'next_plan' => $r->next_plan, ]; } $this->data['reports'] = $reports; $this->loaded = true; $this->schemaKey = 'loaded_' . now()->timestamp; Notification::make() ->title('📂 Dữ liệu báo cáo tháng đã được tải. Vui lòng nhập thông tin và lưu lại.') ->success() ->send(); } public function doReset(): void { $this->resetToDefault(); // $this->dispatch('$refresh'); Notification::make() ->title('🔄 Đã reset. Vui lòng chọn tháng/năm và tải dữ liệu mới.') ->info() ->send(); } protected function buildTreeSections(?int $parentId = null): array { $groups = ReportGroup::orderBy('_lft')->get(); return $this->makeNestedSections($groups, $parentId); } protected function makeNestedSections(Collection $groups, ?int $parentId): array { $sections = []; foreach ($groups->where('parent_id', $parentId) as $group) { $children = $this->makeNestedSections($groups, $group->id); if ($group->is_leaf) { $sections[] = Section::make($group->name) ->schema([ Repeater::make("reports.{$group->id}") ->label('Danh sách công việc') ->addActionLabel('➕ Thêm công việc') ->schema([ Hidden::make('id'), Grid::make(3)->schema([ Textarea::make('work_content')->label('Công việc')->rows(2)->required(), Textarea::make('current_result')->label('Kết quả tháng này')->rows(2), Textarea::make('next_plan')->label('Kế hoạch tháng sau')->rows(2), ]), ]) ->itemLabel(fn(array $state): string => $state['work_content'] ?? '(Chưa nhập công việc)') ->collapsed(false) ->reorderable(false) ->defaultItems(0), ]) ->collapsible() ->collapsed(); } else { $sections[] = Section::make($group->name) ->schema($children) ->collapsible() ->collapsed(); } } return $sections; } public function save(): void { if (!$this->loaded) { Notification::make()->title('⚠️ Vui lòng tải dữ liệu trước khi lưu.')->warning()->send(); return; } $state = $this->data; $deptId = $state['department_id'] ?? $this->departmentId; $savedIds = []; foreach ($state['reports'] ?? [] as $groupId => $items) { foreach ($items as $item) { if (empty($item['work_content']) && empty($item['current_result']) && empty($item['next_plan'])) { continue; } $report = ReportsMonthly::updateOrCreate( ['id' => $item['id'] ?? null], [ 'department_id' => $deptId, 'report_group_id' => $groupId, 'user_id' => Auth::id(), 'month' => $state['month'], 'year' => $state['year'], 'work_content' => $item['work_content'] ?? '', 'current_result' => $item['current_result'] ?? '', 'next_plan' => $item['next_plan'] ?? '', ] ); $savedIds[] = $report->id; } } // dọn dữ liệu thừa ReportsMonthly::where('department_id', $deptId) ->where('month', $state['month']) ->where('year', $state['year']) ->when(!empty($savedIds), fn($q) => $q->whereNotIn('id', $savedIds)) ->delete(); Notification::make() ->title('💾 Báo cáo tháng đã được lưu thành công!') ->success() ->send(); } protected function getHeaderActions(): array { return [ Action::make('save') ->label('💾 Lưu báo cáo') ->color('success') ->visible(fn() => $this->loaded) ->action(fn() => $this->save()), ]; } }