diff --git a/app/Http/Controllers/DailyLogController.php b/app/Http/Controllers/DailyLogController.php index 3a69e567..df909ff0 100644 --- a/app/Http/Controllers/DailyLogController.php +++ b/app/Http/Controllers/DailyLogController.php @@ -3,6 +3,8 @@ namespace App\Http\Controllers; use App\Models\Admin\AdminPmDailyLogEntry; +use App\Models\Admin\AdminPmIssue; +use App\Models\Admin\AdminPmTask; use App\Services\ProjectManagement\DailyLogService; use App\Services\ProjectManagement\ProjectService; use Illuminate\View\View; @@ -29,6 +31,12 @@ public function index(): View $entryStatuses = AdminPmDailyLogEntry::getStatuses(); $assignees = $this->dailyLogService->getAssigneeList($tenantId); + // 주의 필요 이슈 조회 (마감초과, 마감임박, 긴급) + $attentionIssues = $this->getAttentionIssues(); + + // 주의 필요 태스크 조회 (마감초과, 마감임박, 긴급) + $attentionTasks = $this->getAttentionTasks(); + return view('daily-logs.index', compact( 'projects', 'stats', @@ -36,10 +44,92 @@ public function index(): View 'pendingEntries', 'assigneeTypes', 'entryStatuses', - 'assignees' + 'assignees', + 'attentionIssues', + 'attentionTasks' )); } + /** + * 주의 필요 이슈 조회 + * - 마감일 지난 것 (overdue) + * - 이번 주 마감 예정 (이번 주 월~일) + * - 긴급 표시된 것 + */ + private function getAttentionIssues(): array + { + $today = now()->startOfDay(); + $weekEnd = now()->endOfWeek(); // 이번 주 일요일 + + $issues = AdminPmIssue::with(['project', 'assignee', 'department']) + ->whereIn('status', [AdminPmIssue::STATUS_OPEN, AdminPmIssue::STATUS_IN_PROGRESS]) + ->where(function ($q) use ($today, $weekEnd) { + // 마감일 지난 것 (overdue) + $q->where(function ($q2) use ($today) { + $q2->whereNotNull('due_date') + ->where('due_date', '<', $today); + }) + // 이번 주 마감 예정 + ->orWhere(function ($q2) use ($today, $weekEnd) { + $q2->whereNotNull('due_date') + ->whereBetween('due_date', [$today, $weekEnd]); + }) + // 긴급 표시 + ->orWhere('is_urgent', true); + }) + ->orderByRaw("CASE WHEN due_date < CURDATE() THEN 0 ELSE 1 END") // 마감초과 우선 + ->orderBy('is_urgent', 'desc') + ->orderBy('due_date') + ->get(); + + return [ + 'items' => $issues, + 'overdue_count' => $issues->filter(fn ($i) => $i->due_status === 'overdue')->count(), + 'due_soon_count' => $issues->filter(fn ($i) => $i->due_status === 'due_soon' || ($i->due_date && $i->due_date->lte($weekEnd) && $i->due_date->gte($today)))->count(), + 'urgent_count' => $issues->filter(fn ($i) => $i->is_urgent)->count(), + ]; + } + + /** + * 주의 필요 태스크 조회 + * - 마감일 지난 것 (overdue) + * - 이번 주 마감 예정 (이번 주 월~일) + * - 긴급 표시된 것 + */ + private function getAttentionTasks(): array + { + $today = now()->startOfDay(); + $weekEnd = now()->endOfWeek(); // 이번 주 일요일 + + $tasks = AdminPmTask::with(['project', 'assignee']) + ->where('status', '!=', AdminPmTask::STATUS_DONE) + ->where(function ($q) use ($today, $weekEnd) { + // 마감일 지난 것 (overdue) + $q->where(function ($q2) use ($today) { + $q2->whereNotNull('due_date') + ->where('due_date', '<', $today); + }) + // 이번 주 마감 예정 + ->orWhere(function ($q2) use ($today, $weekEnd) { + $q2->whereNotNull('due_date') + ->whereBetween('due_date', [$today, $weekEnd]); + }) + // 긴급 표시 + ->orWhere('is_urgent', true); + }) + ->orderByRaw("CASE WHEN due_date < CURDATE() THEN 0 ELSE 1 END") + ->orderBy('is_urgent', 'desc') + ->orderBy('due_date') + ->get(); + + return [ + 'items' => $tasks, + 'overdue_count' => $tasks->filter(fn ($t) => $t->due_status === 'overdue')->count(), + 'due_soon_count' => $tasks->filter(fn ($t) => $t->due_date && $t->due_date->lte($weekEnd) && $t->due_date->gte($today))->count(), + 'urgent_count' => $tasks->filter(fn ($t) => $t->is_urgent)->count(), + ]; + } + /** * 일일 로그 상세 화면 */ diff --git a/resources/views/daily-logs/index.blade.php b/resources/views/daily-logs/index.blade.php index 30b61fc4..c445d4d3 100644 --- a/resources/views/daily-logs/index.blade.php +++ b/resources/views/daily-logs/index.blade.php @@ -110,6 +110,252 @@ class="day-card w-full text-left p-3 rounded-lg border-2 transition-all hover:sh + +@if($attentionIssues['items']->count() > 0 || $attentionTasks['items']->count() > 0) +
+
+

+ + + + 주의 필요 항목 +

+
+ @if($attentionIssues['overdue_count'] + $attentionTasks['overdue_count'] > 0) + + 마감초과 {{ $attentionIssues['overdue_count'] + $attentionTasks['overdue_count'] }} + + @endif + @if($attentionIssues['due_soon_count'] + $attentionTasks['due_soon_count'] > 0) + + 이번주 {{ $attentionIssues['due_soon_count'] + $attentionTasks['due_soon_count'] }} + + @endif + @if($attentionIssues['urgent_count'] + $attentionTasks['urgent_count'] > 0) + + 긴급 {{ $attentionIssues['urgent_count'] + $attentionTasks['urgent_count'] }} + + @endif + + {{ $attentionIssues['items']->count() + $attentionTasks['items']->count() }}건 + +
+
+
+ @php + // 이슈를 팀별로 그룹핑 (team_display 사용) + $issuesByTeam = $attentionIssues['items']->groupBy(fn($issue) => $issue->team_display ?? '팀 미지정'); + // 태스크를 담당자 기준 그룹핑 (프로젝트 팀 정보가 없으므로 담당자로) + $tasksByAssignee = $attentionTasks['items']->groupBy(fn($task) => $task->assignee?->name ?? '담당자 미지정'); + + // 팀 키 수집 + $allTeams = $issuesByTeam->keys(); + @endphp + + {{-- 이슈: 팀별 카드 --}} + @foreach($allTeams as $teamName) + @php + $teamIssues = $issuesByTeam->get($teamName, collect()); + @endphp +
+ +
+
+ + + + {{ Str::limit($teamName, 12) }} + ({{ $teamIssues->count() }}) +
+ 이슈 +
+ + +
+ @foreach($teamIssues as $issue) +
+
+ +
+ @if($issue->is_urgent) + + @endif + @if($issue->due_status === 'overdue') + D+{{ abs($issue->dday) }} + @elseif($issue->due_status === 'due_soon') + D{{ $issue->dday == 0 ? '-day' : $issue->dday }} + @endif +
+ + + @if($issue->type === 'bug') + + @elseif($issue->type === 'feature') + + @else + + @endif + + + {{ $issue->title }} + +
+ @if($issue->status === 'open') + + @endif + +
+
+ + +
+ @endforeach +
+
+ @endforeach + + {{-- 태스크: 담당자별 카드 --}} + @foreach($tasksByAssignee as $assigneeName => $assigneeTasks) +
+ +
+
+ + + + {{ Str::limit($assigneeName, 12) }} + ({{ $assigneeTasks->count() }}) +
+ 태스크 +
+ + +
+ @foreach($assigneeTasks as $task) +
+
+ +
+ @if($task->is_urgent) + + @endif + @if($task->due_status === 'overdue') + D+{{ abs($task->dday) }} + @elseif($task->due_status === 'due_soon') + D{{ $task->dday == 0 ? '-day' : $task->dday }} + @endif +
+ + + @if($task->priority === 'high') + + @elseif($task->priority === 'medium') + + @else + + @endif + + + {{ $task->title }} + +
+ @if($task->status === 'todo') + + @endif + +
+
+ + +
+ @endforeach +
+
+ @endforeach +
+
+@endif + @if(count($pendingEntries) > 0)
@@ -342,7 +588,6 @@ class="flex-1 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 @endsection @push('scripts') -