fix(ui): 테스트 피드백 반영 (출입증/보고서/상단바/대시보드/엑셀)
1. 출입증 카드 하단 안내문을 한 줄로(.badge-foot font-size 11px + nowrap). 2. 보고서 화면: 명칭 '리포트→보고서'·'방문 리포트→출입관리 보고서', 안내문 보강, 날짜 입력을 YYYY.MM.DD 표시 커스텀 피커(DatePickerField)로 교체, 기본값 시작일=이번 달 1일·종료일=오늘. 3. 보고서 엑셀 열 너비를 내용 기준(한글 2폭)으로 계산해 설정 → 셀 잘림 해소 (POI autoSizeColumn의 CJK 과소측정 문제 회피). 4. 상단바에서 사용자 이름 표시 제거(역할 태그만 유지) → '발송내역' 메뉴 잘림 해소, 발송내역 화면 [새로고침]→[조회]. 5. 대시보드 '최근 출입 신청'에서 현재 재실 중인 방문자는 상태를 '재실중'으로 표시 (기존 listInside API 재활용, 백엔드 무변경). 검증: 프론트 tsc+vite 빌드 통과, 백엔드 build+test(9건) 통과, 생성 xlsx의 열 너비가 내용에 맞게 설정됨(연락처15·출입일시18·상태10 등) 확인. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
43
frontend/src/components/DatePickerField.tsx
Normal file
43
frontend/src/components/DatePickerField.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React, { useRef } from 'react';
|
||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||
import { ko } from 'date-fns/locale';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
|
||||
registerLocale('ko', ko);
|
||||
|
||||
interface Props {
|
||||
/** date string in "YYYY-MM-DD" (the format the back-end expects). */
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const pad = (n: number) => String(n).padStart(2, '0');
|
||||
|
||||
/** Date → "YYYY-MM-DD" (local). */
|
||||
function toISODate(d: Date): string {
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Korean-localized date-only picker. Displays the value as YYYY.MM.DD (which the
|
||||
* native <input type="date"> cannot force — it follows the OS locale) while the
|
||||
* bound value stays "YYYY-MM-DD" for the API.
|
||||
*/
|
||||
export const DatePickerField: React.FC<Props> = ({ value, onChange, placeholder }) => {
|
||||
const ref = useRef<DatePicker>(null);
|
||||
|
||||
return (
|
||||
<DatePicker
|
||||
ref={ref}
|
||||
selected={value ? new Date(`${value}T00:00:00`) : null}
|
||||
onChange={(d: Date | null) => d && onChange(toISODate(d))}
|
||||
dateFormat="yyyy.MM.dd"
|
||||
dateFormatCalendar="yyyy.M월"
|
||||
locale="ko"
|
||||
placeholderText={placeholder ?? '날짜를 선택하세요'}
|
||||
className="dt-input"
|
||||
popperClassName="acs-datepicker"
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -32,14 +32,13 @@ export const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) =>
|
||||
<NavLink to="/visit-requests">출입신청</NavLink>
|
||||
{hasRole('ADMIN') && <NavLink to="/approvals">승인대기</NavLink>}
|
||||
{hasRole('HOST', 'SECURITY', 'ADMIN') && <NavLink to="/access">출입콘솔</NavLink>}
|
||||
{hasRole('SECURITY', 'ADMIN') && <NavLink to="/reports">리포트</NavLink>}
|
||||
{hasRole('SECURITY', 'ADMIN') && <NavLink to="/reports">보고서</NavLink>}
|
||||
{hasRole('ADMIN') && <NavLink to="/blacklist">블랙리스트</NavLink>}
|
||||
{hasRole('ADMIN') && <NavLink to="/deliveries">발송내역</NavLink>}
|
||||
{hasRole('ADMIN') && <NavLink to="/audit">감사로그</NavLink>}
|
||||
</nav>
|
||||
<div className="user-box">
|
||||
<span className="user-name">
|
||||
{user?.fullName}
|
||||
<span className="role-tags">
|
||||
{user?.roles.map((r) => (
|
||||
<span key={r} className="role-tag">{ROLE_LABEL[r] ?? r}</span>
|
||||
|
||||
Reference in New Issue
Block a user