fix: confirm visit datetime picker selection

This commit is contained in:
unknown
2026-07-16 14:02:24 +09:00
parent b094241408
commit cc79abde44
2 changed files with 39 additions and 16 deletions

View File

@@ -769,3 +769,14 @@
- `/api/admin/teams` 200 OK. - `/api/admin/teams` 200 OK.
- `/api/visit-requests/upload` 테스트 엑셀 업로드 성공: `totalRows=1`, `successCount=1`, `errors=[]`. - `/api/visit-requests/upload` 테스트 엑셀 업로드 성공: `totalRows=1`, `successCount=1`, `errors=[]`.
- 업로드로 생성된 테스트 신청은 즉시 취소 처리. - 업로드로 생성된 테스트 신청은 즉시 취소 처리.
- 2026-07-16 출입신청 일시 선택 UI 수정:
- 운영 서버 출입신청 화면에서 출입일시 캘린더의 `[입력]` 버튼 클릭 시 선택값이 확정되지 않는 문제 확인.
- `DateTimePicker`를 확정형 동작으로 변경:
- 달력 내부 선택값은 `draft`로 보관.
- `[입력]` 버튼 클릭 시 `visitFrom`/`visitTo` 값으로 반영 후 팝업 닫기.
- 팝업 open 상태를 컴포넌트 state로 제어해 브라우저별 동작 차이를 줄임.
- 검증:
- `npm.cmd run typecheck` 성공.
- `npm.cmd run build` 성공.
- `npm.cmd test` 성공.

View File

@@ -1,4 +1,4 @@
import React, { useRef } from 'react'; import React, { useEffect, useState } from 'react';
import DatePicker, { registerLocale } from 'react-datepicker'; import DatePicker, { registerLocale } from 'react-datepicker';
import { ko } from 'date-fns/locale'; import { ko } from 'date-fns/locale';
import 'react-datepicker/dist/react-datepicker.css'; import 'react-datepicker/dist/react-datepicker.css';
@@ -14,31 +14,43 @@ interface Props {
const pad = (n: number) => String(n).padStart(2, '0'); const pad = (n: number) => String(n).padStart(2, '0');
/** Date → "YYYY-MM-DDTHH:mm" (local), the format the form/back-end expect. */
function toLocalString(d: Date): string { function toLocalString(d: Date): string {
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
} }
/** function fromLocalString(value: string): Date | null {
* Korean-localized date+time picker that replaces the browser-native return value ? new Date(value) : null;
* <input type="datetime-local"> (whose popup labels/border/buttons cannot be }
* styled). Keeps the calendar open until the user presses [입력] so the choice
* is explicit.
*/
export const DateTimePicker: React.FC<Props> = ({ value, onChange, placeholder }) => { export const DateTimePicker: React.FC<Props> = ({ value, onChange, placeholder }) => {
const ref = useRef<DatePicker>(null); const [open, setOpen] = useState(false);
const [draft, setDraft] = useState<Date | null>(fromLocalString(value));
useEffect(() => {
setDraft(fromLocalString(value));
}, [value]);
const confirm = () => {
if (draft) {
onChange(toLocalString(draft));
}
setOpen(false);
};
return ( return (
<DatePicker <DatePicker
ref={ref} selected={draft}
selected={value ? new Date(value) : null} onChange={(d: Date | null) => setDraft(d)}
onChange={(d: Date | null) => d && onChange(toLocalString(d))} open={open}
onInputClick={() => setOpen(true)}
onCalendarOpen={() => setOpen(true)}
onClickOutside={() => setOpen(false)}
showTimeSelect showTimeSelect
timeIntervals={5} timeIntervals={5}
timeCaption="시간" timeCaption="시간"
timeFormat="a K:mm" timeFormat="a h:mm"
dateFormat="yyyy.MM.dd (eee) a K:mm" dateFormat="yyyy.MM.dd (eee) a h:mm"
dateFormatCalendar="yyyy.M" dateFormatCalendar="yyyy.MM"
locale="ko" locale="ko"
shouldCloseOnSelect={false} shouldCloseOnSelect={false}
placeholderText={placeholder ?? '날짜와 시간을 선택하세요'} placeholderText={placeholder ?? '날짜와 시간을 선택하세요'}
@@ -46,7 +58,7 @@ export const DateTimePicker: React.FC<Props> = ({ value, onChange, placeholder }
popperClassName="acs-datepicker" popperClassName="acs-datepicker"
> >
<div className="dt-actions"> <div className="dt-actions">
<button type="button" className="btn-primary dt-confirm" onClick={() => ref.current?.setOpen(false)}> <button type="button" className="btn-primary dt-confirm" onClick={confirm}>
</button> </button>
</div> </div>