fix: show access state in reports

This commit is contained in:
unknown
2026-07-22 19:51:35 +09:00
parent dee612fc5c
commit eec18e7179

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { listReportVisits, reportDownloadUrl } from '../api'; import { listReportVisits, listTodayAccess, reportDownloadUrl } from '../api';
import { DatePickerField } from '../components/DatePickerField'; import { DatePickerField } from '../components/DatePickerField';
import { VisitRequestView } from '../types'; import { AccessRecord, VisitRequestView } from '../types';
import { STATUS_CLASS, STATUS_LABEL, formatDateTime } from '../status'; import { STATUS_CLASS, STATUS_LABEL, formatDateTime } from '../status';
const pad = (n: number) => String(n).padStart(2, '0'); const pad = (n: number) => String(n).padStart(2, '0');
@@ -21,21 +21,41 @@ export const ReportPage: React.FC = () => {
const [from, setFrom] = useState(firstOfMonthISO()); const [from, setFrom] = useState(firstOfMonthISO());
const [to, setTo] = useState(todayISO()); const [to, setTo] = useState(todayISO());
const [items, setItems] = useState<VisitRequestView[]>([]); const [items, setItems] = useState<VisitRequestView[]>([]);
const [accessRecords, setAccessRecords] = useState<AccessRecord[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const load = () => { const load = () => {
setLoading(true); setLoading(true);
setError(null); setError(null);
listReportVisits(from, to) Promise.all([
.then(setItems) listReportVisits(from, to),
listTodayAccess().catch(() => [] as AccessRecord[]),
])
.then(([visits, records]) => {
setItems(visits);
setAccessRecords(records);
})
.catch((e) => { .catch((e) => {
setItems([]); setItems([]);
setAccessRecords([]);
setError(e instanceof Error ? e.message : '보고서 조회에 실패했습니다.'); setError(e instanceof Error ? e.message : '보고서 조회에 실패했습니다.');
}) })
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}; };
const accessById = new Map(accessRecords.map((r) => [r.visitRequestId, r]));
const statusBadge = (r: VisitRequestView) => {
const access = accessById.get(r.id);
if (access?.inside) {
return { className: 'green', label: '재실중' };
}
if (access?.checkOutAt) {
return { className: 'gray', label: '퇴장' };
}
return { className: STATUS_CLASS[r.status], label: STATUS_LABEL[r.status] };
};
useEffect(() => { useEffect(() => {
load(); load();
// Load the default month range once; explicit 조회 handles later date changes. // Load the default month range once; explicit 조회 handles later date changes.
@@ -113,7 +133,12 @@ export const ReportPage: React.FC = () => {
<td>{r.workName || '-'}</td> <td>{r.workName || '-'}</td>
<td>{formatDateTime(r.visitFrom)}</td> <td>{formatDateTime(r.visitFrom)}</td>
<td>{formatDateTime(r.visitTo)}</td> <td>{formatDateTime(r.visitTo)}</td>
<td><span className={`badge badge-${STATUS_CLASS[r.status]}`}>{STATUS_LABEL[r.status]}</span></td> <td>
{(() => {
const badge = statusBadge(r);
return <span className={`badge badge-${badge.className}`}>{badge.label}</span>;
})()}
</td>
</tr> </tr>
))} ))}
</tbody> </tbody>