feat: [daily-logs] 일일 스크럼 기능 구현
주요 기능:
- 일일 로그 CRUD (생성, 조회, 수정, 삭제, 복원, 영구삭제)
- 로그 항목(Entry) 관리 (추가, 상태변경, 삭제, 순서변경)
- 주간 타임라인 (최근 7일 진행률 표시)
- 테이블 리스트 아코디언 상세보기
- 담당자 자동완성 (일반 사용자는 슈퍼관리자 목록 제외)
- HTMX 기반 동적 테이블 로딩 및 필터링
- Soft Delete 지원
파일 추가:
- Models: AdminPmDailyLog, AdminPmDailyLogEntry
- Controllers: DailyLogController (Web, API)
- Service: DailyLogService
- Requests: StoreDailyLogRequest, UpdateDailyLogRequest
- Views: index, show, table partial, modal-form partial
라우트 추가:
- Web: /daily-logs, /daily-logs/today, /daily-logs/{id}
- API: /api/admin/daily-logs/* (CRUD + 항목관리)
This commit is contained in:
129
resources/views/daily-logs/partials/table.blade.php
Normal file
129
resources/views/daily-logs/partials/table.blade.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<!-- 일일 로그 테이블 -->
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">날짜</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">프로젝트</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">요약</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">항목</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">작성자</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">상태</th>
|
||||
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">액션</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
@forelse($logs as $log)
|
||||
<!-- 메인 행 (클릭 가능) -->
|
||||
<tr class="log-row cursor-pointer hover:bg-gray-50 {{ $log->trashed() ? 'bg-red-50' : '' }}"
|
||||
data-log-id="{{ $log->id }}"
|
||||
onclick="toggleTableAccordion({{ $log->id }}, event)">
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<svg class="accordion-chevron w-4 h-4 mr-2 text-gray-400 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{{ $log->log_date->format('Y-m-d') }}
|
||||
</div>
|
||||
<div class="text-xs text-gray-500">
|
||||
{{ $log->log_date->format('l') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
@if($log->project)
|
||||
<span class="px-2 py-1 text-xs font-medium rounded-full bg-blue-100 text-blue-800">
|
||||
{{ $log->project->name }}
|
||||
</span>
|
||||
@else
|
||||
<span class="text-gray-400">전체</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
@if($log->summary)
|
||||
<div class="text-sm text-gray-900 truncate max-w-xs" title="{{ $log->summary }}">
|
||||
{{ Str::limit($log->summary, 50) }}
|
||||
</div>
|
||||
@else
|
||||
<span class="text-gray-400">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="text-sm text-gray-900">{{ $log->entries_count }}개</span>
|
||||
@if($log->entries->count() > 0)
|
||||
<div class="flex space-x-1">
|
||||
@php
|
||||
$stats = $log->entry_stats;
|
||||
@endphp
|
||||
@if($stats['todo'] > 0)
|
||||
<span class="w-2 h-2 rounded-full bg-gray-400" title="예정: {{ $stats['todo'] }}"></span>
|
||||
@endif
|
||||
@if($stats['in_progress'] > 0)
|
||||
<span class="w-2 h-2 rounded-full bg-yellow-400" title="진행중: {{ $stats['in_progress'] }}"></span>
|
||||
@endif
|
||||
@if($stats['done'] > 0)
|
||||
<span class="w-2 h-2 rounded-full bg-green-400" title="완료: {{ $stats['done'] }}"></span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $log->creator?->name ?? '-' }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
@if($log->trashed())
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">
|
||||
삭제됨
|
||||
</span>
|
||||
@else
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
|
||||
활성
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2" onclick="event.stopPropagation()">
|
||||
@if($log->trashed())
|
||||
<!-- 삭제된 항목 -->
|
||||
<button onclick="confirmRestore({{ $log->id }}, '{{ $log->log_date->format('Y-m-d') }}')"
|
||||
class="text-green-600 hover:text-green-900">복원</button>
|
||||
@if(auth()->user()?->is_super_admin)
|
||||
<button onclick="confirmForceDelete({{ $log->id }}, '{{ $log->log_date->format('Y-m-d') }}')"
|
||||
class="text-red-600 hover:text-red-900">영구삭제</button>
|
||||
@endif
|
||||
@else
|
||||
<!-- 일반 항목 액션 -->
|
||||
<button onclick="editLog({{ $log->id }})"
|
||||
class="text-indigo-600 hover:text-indigo-900">수정</button>
|
||||
<button onclick="confirmDelete({{ $log->id }}, '{{ $log->log_date->format('Y-m-d') }}')"
|
||||
class="text-red-600 hover:text-red-900">삭제</button>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 아코디언 상세 행 (숨겨진 상태) -->
|
||||
<tr class="accordion-row hidden" data-accordion-for="{{ $log->id }}">
|
||||
<td colspan="7" class="px-6 py-4 bg-gray-50">
|
||||
<div class="accordion-content" id="accordion-content-{{ $log->id }}">
|
||||
<div class="text-center py-4 text-gray-500">로딩 중...</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="px-6 py-12 text-center text-gray-500">
|
||||
일일 로그가 없습니다.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 페이지네이션 -->
|
||||
@if($logs->hasPages())
|
||||
<div class="px-6 py-4 border-t border-gray-200">
|
||||
{{ $logs->withQueryString()->links() }}
|
||||
</div>
|
||||
@endif
|
||||
Reference in New Issue
Block a user