d && onChange(toISODate(d))}
+ dateFormat="yyyy.MM.dd"
+ dateFormatCalendar="yyyy.M월"
+ locale="ko"
+ placeholderText={placeholder ?? '날짜를 선택하세요'}
+ className="dt-input"
+ popperClassName="acs-datepicker"
+ />
+ );
+};
diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx
index 6720d75..68933a3 100644
--- a/frontend/src/components/Layout.tsx
+++ b/frontend/src/components/Layout.tsx
@@ -32,14 +32,13 @@ export const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) =>
출입신청
{hasRole('ADMIN') && 승인대기}
{hasRole('HOST', 'SECURITY', 'ADMIN') && 출입콘솔}
- {hasRole('SECURITY', 'ADMIN') && 리포트}
+ {hasRole('SECURITY', 'ADMIN') && 보고서}
{hasRole('ADMIN') && 블랙리스트}
{hasRole('ADMIN') && 발송내역}
{hasRole('ADMIN') && 감사로그}
- {user?.fullName}
{user?.roles.map((r) => (
{ROLE_LABEL[r] ?? r}
diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx
index d4f1a67..aa56754 100644
--- a/frontend/src/pages/DashboardPage.tsx
+++ b/frontend/src/pages/DashboardPage.tsx
@@ -1,17 +1,22 @@
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
-import { getStatsSummary, listVisitRequests } from '../api';
+import { getStatsSummary, listInside, listVisitRequests } from '../api';
import { StatsSummary, VisitRequestView } from '../types';
import { STATUS_CLASS, STATUS_LABEL, formatDateTime } from '../status';
export const DashboardPage: React.FC = () => {
const [items, setItems] = useState([]);
const [stats, setStats] = useState(null);
+ const [insideIds, setInsideIds] = useState>(new Set());
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
getStatsSummary().then(setStats).catch(() => setStats(null));
+ // currently-inside visits → show "재실중" instead of the plain approved status
+ listInside()
+ .then((rows) => setInsideIds(new Set(rows.map((r) => r.visitRequestId))))
+ .catch(() => setInsideIds(new Set()));
listVisitRequests()
.then(setItems)
.catch((e) => setError(e instanceof Error ? e.message : '조회 실패'))
@@ -56,7 +61,13 @@ export const DashboardPage: React.FC = () => {
| {r.company || '-'} |
{r.zoneName || '-'} |
{formatDateTime(r.visitFrom)} |
- {STATUS_LABEL[r.status]} |
+
+ {insideIds.has(r.id) ? (
+ 재실중
+ ) : (
+ {STATUS_LABEL[r.status]}
+ )}
+ |
))}
diff --git a/frontend/src/pages/DeliveryOutboxPage.tsx b/frontend/src/pages/DeliveryOutboxPage.tsx
index 71eedf0..9549e46 100644
--- a/frontend/src/pages/DeliveryOutboxPage.tsx
+++ b/frontend/src/pages/DeliveryOutboxPage.tsx
@@ -45,7 +45,7 @@ export const DeliveryOutboxPage: React.FC = () => {
-
+
{error && {error}
}
diff --git a/frontend/src/pages/ReportPage.tsx b/frontend/src/pages/ReportPage.tsx
index 344e209..246f4fb 100644
--- a/frontend/src/pages/ReportPage.tsx
+++ b/frontend/src/pages/ReportPage.tsx
@@ -1,17 +1,22 @@
import React, { useState } from 'react';
import { reportDownloadUrl } from '../api';
+import { DatePickerField } from '../components/DatePickerField';
+const pad = (n: number) => String(n).padStart(2, '0');
+
+/** Today in YYYY-MM-DD (local). */
function todayISO(): string {
- return new Date().toISOString().slice(0, 10);
-}
-function monthAgoISO(): string {
const d = new Date();
- d.setMonth(d.getMonth() - 1);
- return d.toISOString().slice(0, 10);
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
+}
+/** First day of the current month in YYYY-MM-DD (local). */
+function firstOfMonthISO(): string {
+ const d = new Date();
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-01`;
}
export const ReportPage: React.FC = () => {
- const [from, setFrom] = useState(monthAgoISO());
+ const [from, setFrom] = useState(firstOfMonthISO());
const [to, setTo] = useState(todayISO());
const onDownload = () => {
@@ -29,18 +34,18 @@ export const ReportPage: React.FC = () => {
return (
-
방문 리포트
+
출입관리 보고서
-
기간을 선택하고 엑셀(.xlsx) 파일로 내려받습니다. (방문 시작일 기준)
+
기간을 선택하고 [엑셀 다운로드] 버튼을 클릭하면, 엑셀(.xlsx) 파일로 내려받습니다. (방문 시작일 기준)
diff --git a/frontend/src/styles/common.css b/frontend/src/styles/common.css
index 136a7f5..92e2c79 100644
--- a/frontend/src/styles/common.css
+++ b/frontend/src/styles/common.css
@@ -288,7 +288,7 @@ button:disabled { opacity: .55; cursor: not-allowed; }
.badge-qr { width: 200px; height: 200px; image-rendering: pixelated; }
.badge-meta { text-align: center; margin: 16px 0; font-size: 13px; }
.badge-meta > div { padding: 4px 0; border-bottom: 1px dashed var(--border); }
-.badge-foot { font-size: 12px; color: var(--muted); margin-top: 8px; }
+.badge-foot { font-size: 11px; color: var(--muted); margin-top: 8px; white-space: nowrap; }
@media print {
.topbar, .no-print { display: none !important; }