캘린더 수정정

This commit is contained in:
2025-10-15 12:17:36 +00:00
parent 0ab4b037eb
commit 9c0aeb73e8
3 changed files with 157 additions and 38 deletions

View File

@@ -4,11 +4,18 @@ import Arrow from "./svgs/arrow";
import { DateRangeEnum } from "@/app/constants/dateRange";
import { useState,useEffect } from "react";
export default function CalenderSelector( {dateString, is_small, onRangeChange}: {dateString: string, is_ri: boolean, is_small: boolean, onRangeChange?: (start: Date, end: Date) => void} ) {
const [isOpen, setIsOpen] = useState(false);
export default function CalenderSelector({ dateString, is_small, onRangeChange, isOpen: controlledOpen, onOpenChange }: { dateString: string, is_ri: boolean, is_small: boolean, onRangeChange?: (start: Date, end: Date) => void, isOpen?: boolean, onOpenChange?: (open: boolean) => void }) {
const CUSTOM = -1; // 커스텀(년/월) 선택 표기용
const [internalOpen, setInternalOpen] = useState(false);
const isOpen = typeof controlledOpen === 'boolean' ? controlledOpen : internalOpen;
const setOpen = (next: boolean) => { if (onOpenChange) onOpenChange(next); else setInternalOpen(next); };
const [selected, setSelected] = useState<number>(DateRangeEnum.ONE_MONTH);
const [rangeStart, setRangeStart] = useState<Date>(new Date());
const [rangeEnd, setRangeEnd] = useState<Date>(new Date());
const [yearInput, setYearInput] = useState<string>('');
const [monthInput, setMonthInput] = useState<string>('');
const [customLabel, setCustomLabel] = useState<string>('');
const [isCustomActive, setIsCustomActive] = useState<boolean>(false);
useEffect(() => {
const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
@@ -16,6 +23,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(startDate);
setRangeEnd(endDate);
onRangeChange?.(startDate, endDate);
const now = new Date();
setYearInput(String(now.getFullYear()));
setMonthInput(String(now.getMonth() + 1).padStart(2,'0'));
}, []);
return (
@@ -27,7 +37,7 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
border-1 rounded-lg flex flex-row items-center justify-between gap-2 px-2 cursor-pointer`}
onClick={() => {
console.log('click');
setIsOpen(!isOpen);
setOpen(!isOpen);
}}
>
<div className="flex-shrink-0">
@@ -38,13 +48,15 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
)}
</div>
<div className={`flex-1 min-w-0 font-semibold ${is_small ? 'text-xs':'text-sm'}`}>
{selected === DateRangeEnum.ONE_MONTH&& '최근 1개월'}
{selected === DateRangeEnum.ONE_WEEK&& '최근 1주일'}
{selected === DateRangeEnum.TWO_MONTHS&& '최근 2개월'}
{selected === DateRangeEnum.THREE_MONTHS&& '최근 3개월'}
{selected === DateRangeEnum.SIX_MONTHS&& '최근 6개월'}
{selected === DateRangeEnum.ONE_YEAR&& '최근 1년'}
{selected === DateRangeEnum.ALL&& '전체'}
{customLabel || (
selected === DateRangeEnum.ONE_MONTH ? '최근 1개월' :
selected === DateRangeEnum.ONE_WEEK ? '최근 1주일' :
selected === DateRangeEnum.TWO_MONTHS ? '최근 2개월' :
selected === DateRangeEnum.THREE_MONTHS ? '최근 3개월' :
selected === DateRangeEnum.SIX_MONTHS ? '최근 6개월' :
selected === DateRangeEnum.ONE_YEAR ? '최근 1년' :
selected === DateRangeEnum.ALL ? '전체' : ''
)}
</div>
<div className={`pt-[3px] transition-transform ${isOpen ? 'rotate-180' : ''} flex-shrink-0`}>
<Arrow color="#A4A0A0" width={is_small ? 12 : 18} height={is_small ? 8 : 12} />
@@ -59,11 +71,13 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
onClick={() => {
setSelected(DateRangeEnum.ALL);
const end = new Date();
const start = new Date(0);
const start = new Date(Date.UTC(2025, 0, 1));
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<Realtime color={selected === DateRangeEnum.ALL ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -79,7 +93,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.ONE_WEEK ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -95,7 +111,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.ONE_MONTH ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -111,7 +129,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.TWO_MONTHS ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -127,7 +147,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.THREE_MONTHS ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -143,7 +165,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.SIX_MONTHS ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -159,7 +183,9 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
setIsOpen(false);
setCustomLabel('');
setIsCustomActive(false);
setOpen(false);
}}
>
<OneMonth color={selected === DateRangeEnum.ONE_YEAR ? '#F94B37' : '#848484'} width={16} height={16} />
@@ -167,6 +193,52 @@ export default function CalenderSelector( {dateString, is_small, onRangeChange}:
</button>
</div>
<div className="mt-2 pt-2 border-t-1 border-border-pale">
<div className={`flex items-center gap-2 px-1 ${isCustomActive ? 'bg-[#FFF3F2] font-semibold rounded-md py-2' : ''}`}>
<input
type="number"
className="w-[88px] h-[32px] border-1 border-border-pale rounded px-2 pr-1 text-sm"
placeholder="YYYY"
min={2000}
max={2100}
value={yearInput}
onChange={(e)=> setYearInput(e.target.value.replace(/[^0-9]/g,''))}
/>
<span className="text-sm"></span>
<input
type="number"
className="w-[50px] h-[32px] border-1 border-border-pale rounded px-2 pr-1 text-sm"
placeholder="MM"
min={1}
max={12}
value={monthInput}
onChange={(e)=> {
const v = e.target.value.replace(/[^0-9]/g,'');
setMonthInput(v);
}}
/>
<span className="text-sm"></span>
<button
className="ml-auto h-[32px] min-w-[80px] px-4 shrink-0 whitespace-nowrap rounded-md bg-[#F94B37] border-1 border-[#D73B29] text-white text-sm font-semibold hover:bg-[#D73B29]"
onClick={() => {
const y = parseInt(yearInput, 10);
const m = parseInt(monthInput, 10);
if (!Number.isFinite(y) || y < 2000 || y > 2100) return;
if (!Number.isFinite(m) || m < 1 || m > 12) return;
const start = new Date(y, m - 1, 1);
const end = new Date(y, m, 0, 23, 59, 59, 999);
setRangeStart(start);
setRangeEnd(end);
onRangeChange?.(start, end);
const mm = String(m).padStart(2, '0');
setCustomLabel(`${y}.${mm}`);
setIsCustomActive(true);
setSelected(CUSTOM);
setOpen(false);
}}
></button>
</div>
</div>
</div>
)}
</div>