123 lines
3.6 KiB
Vue
123 lines
3.6 KiB
Vue
<template>
|
|
<div>
|
|
<AppHeader />
|
|
|
|
<div class="container py-4">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h4 class="mb-0">
|
|
<i class="bi bi-journal-text me-2"></i>내 주간보고
|
|
</h4>
|
|
<NuxtLink to="/report/weekly/write" class="btn btn-primary">
|
|
<i class="bi bi-plus me-1"></i>작성하기
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th style="width: 150px">주차</th>
|
|
<th style="width: 200px">기간</th>
|
|
<th>프로젝트</th>
|
|
<th style="width: 100px">상태</th>
|
|
<th style="width: 150px">작성일</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-if="isLoading">
|
|
<td colspan="5" class="text-center py-4">
|
|
<span class="spinner-border spinner-border-sm me-2"></span>로딩 중...
|
|
</td>
|
|
</tr>
|
|
<tr v-else-if="reports.length === 0">
|
|
<td colspan="5" class="text-center py-5 text-muted">
|
|
<i class="bi bi-inbox display-4"></i>
|
|
<p class="mt-2 mb-0">작성한 주간보고가 없습니다.</p>
|
|
</td>
|
|
</tr>
|
|
<tr v-else v-for="r in reports" :key="r.reportId"
|
|
@click="router.push(`/report/weekly/${r.reportId}`)"
|
|
style="cursor: pointer;">
|
|
<td>
|
|
<strong>{{ r.reportYear }}년 {{ r.reportWeek }}주차</strong>
|
|
</td>
|
|
<td>{{ formatDate(r.weekStartDate) }} ~ {{ formatDate(r.weekEndDate) }}</td>
|
|
<td>
|
|
<span class="badge bg-primary">{{ r.projectCount }}개 프로젝트</span>
|
|
</td>
|
|
<td>
|
|
<span :class="getStatusBadgeClass(r.reportStatus)">
|
|
{{ getStatusText(r.reportStatus) }}
|
|
</span>
|
|
</td>
|
|
<td>{{ formatDateTime(r.createdAt) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const { fetchCurrentUser } = useAuth()
|
|
const router = useRouter()
|
|
|
|
const reports = ref<any[]>([])
|
|
const isLoading = ref(true)
|
|
|
|
onMounted(async () => {
|
|
const user = await fetchCurrentUser()
|
|
if (!user) {
|
|
router.push('/login')
|
|
return
|
|
}
|
|
loadReports()
|
|
})
|
|
|
|
async function loadReports() {
|
|
isLoading.value = true
|
|
try {
|
|
const res = await $fetch<any>('/api/report/weekly/list')
|
|
reports.value = res.reports || []
|
|
} catch (e) {
|
|
console.error(e)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
function formatDate(dateStr: string) {
|
|
if (!dateStr) return ''
|
|
return dateStr.split('T')[0]
|
|
}
|
|
|
|
function formatDateTime(dateStr: string) {
|
|
if (!dateStr) return ''
|
|
const d = new Date(dateStr)
|
|
return d.toLocaleDateString('ko-KR')
|
|
}
|
|
|
|
function getStatusBadgeClass(status: string) {
|
|
const classes: Record<string, string> = {
|
|
'DRAFT': 'badge bg-secondary',
|
|
'SUBMITTED': 'badge bg-success',
|
|
'AGGREGATED': 'badge bg-info'
|
|
}
|
|
return classes[status] || 'badge bg-secondary'
|
|
}
|
|
|
|
function getStatusText(status: string) {
|
|
const texts: Record<string, string> = {
|
|
'DRAFT': '작성중',
|
|
'SUBMITTED': '제출완료',
|
|
'AGGREGATED': '취합완료'
|
|
}
|
|
return texts[status] || status
|
|
}
|
|
</script>
|