input('step', 1); $icons = config('sales_scenario.icons'); // 체크리스트 진행 상태 조회 $progress = $this->getChecklistProgress($tenantId, 'sales'); // HTMX 요청이면 단계 콘텐츠만 반환 if ($request->header('HX-Request') && $request->has('step')) { return view('sales.modals.scenario-step', [ 'tenant' => $tenant, 'steps' => $steps, 'currentStep' => $currentStep, 'step' => collect($steps)->firstWhere('id', $currentStep), 'progress' => $progress, 'scenarioType' => 'sales', 'icons' => $icons, ]); } return view('sales.modals.scenario-modal', [ 'tenant' => $tenant, 'steps' => $steps, 'currentStep' => $currentStep, 'progress' => $progress, 'scenarioType' => 'sales', 'icons' => $icons, ]); } /** * 매니저 시나리오 모달 뷰 */ public function managerScenario(int $tenantId, Request $request): View|Response { $tenant = Tenant::findOrFail($tenantId); $steps = config('sales_scenario.manager_steps'); $currentStep = (int) $request->input('step', 1); $icons = config('sales_scenario.icons'); // 체크리스트 진행 상태 조회 $progress = $this->getChecklistProgress($tenantId, 'manager'); // HTMX 요청이면 단계 콘텐츠만 반환 if ($request->header('HX-Request') && $request->has('step')) { return view('sales.modals.scenario-step', [ 'tenant' => $tenant, 'steps' => $steps, 'currentStep' => $currentStep, 'step' => collect($steps)->firstWhere('id', $currentStep), 'progress' => $progress, 'scenarioType' => 'manager', 'icons' => $icons, ]); } return view('sales.modals.scenario-modal', [ 'tenant' => $tenant, 'steps' => $steps, 'currentStep' => $currentStep, 'progress' => $progress, 'scenarioType' => 'manager', 'icons' => $icons, ]); } /** * 체크리스트 항목 토글 (HTMX) */ public function toggleChecklist(Request $request): Response { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', 'step_id' => 'required|integer', 'checkpoint_id' => 'required|string', 'checked' => 'required|boolean', ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); $stepId = $request->input('step_id'); $checkpointId = $request->input('checkpoint_id'); $checked = $request->boolean('checked'); // 캐시 키 생성 $cacheKey = "scenario_checklist:{$tenantId}:{$scenarioType}"; // 현재 체크리스트 상태 조회 $checklist = cache()->get($cacheKey, []); // 체크리스트 상태 업데이트 $key = "{$stepId}_{$checkpointId}"; if ($checked) { $checklist[$key] = [ 'checked_at' => now()->toDateTimeString(), 'checked_by' => auth()->id(), ]; } else { unset($checklist[$key]); } // 캐시에 저장 (30일 유지) cache()->put($cacheKey, $checklist, now()->addDays(30)); // 진행률 계산 $progress = $this->calculateProgress($tenantId, $scenarioType); return response()->json([ 'success' => true, 'progress' => $progress, 'checked' => $checked, ]); } /** * 진행률 조회 */ public function getProgress(int $tenantId, string $type): Response { $progress = $this->calculateProgress($tenantId, $type); return response()->json([ 'success' => true, 'progress' => $progress, ]); } /** * 체크리스트 진행 상태 조회 */ private function getChecklistProgress(int $tenantId, string $scenarioType): array { $cacheKey = "scenario_checklist:{$tenantId}:{$scenarioType}"; return cache()->get($cacheKey, []); } /** * 진행률 계산 */ private function calculateProgress(int $tenantId, string $scenarioType): array { $steps = config("sales_scenario.{$scenarioType}_steps"); $checklist = $this->getChecklistProgress($tenantId, $scenarioType); $totalCheckpoints = 0; $completedCheckpoints = 0; $stepProgress = []; foreach ($steps as $step) { $stepCompleted = 0; $stepTotal = count($step['checkpoints']); $totalCheckpoints += $stepTotal; foreach ($step['checkpoints'] as $checkpoint) { $key = "{$step['id']}_{$checkpoint['id']}"; if (isset($checklist[$key])) { $completedCheckpoints++; $stepCompleted++; } } $stepProgress[$step['id']] = [ 'total' => $stepTotal, 'completed' => $stepCompleted, 'percentage' => $stepTotal > 0 ? round(($stepCompleted / $stepTotal) * 100) : 0, ]; } return [ 'total' => $totalCheckpoints, 'completed' => $completedCheckpoints, 'percentage' => $totalCheckpoints > 0 ? round(($completedCheckpoints / $totalCheckpoints) * 100) : 0, 'steps' => $stepProgress, ]; } /** * 특정 단계의 체크포인트 체크 여부 확인 */ public function isCheckpointChecked(int $tenantId, string $scenarioType, int $stepId, string $checkpointId): bool { $checklist = $this->getChecklistProgress($tenantId, $scenarioType); $key = "{$stepId}_{$checkpointId}"; return isset($checklist[$key]); } }