fix: show access state in reports
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user