refactor: simplify state management and enhance styling for SingleDatePicker component

This commit is contained in:
Astrian Zheng 2025-02-19 14:57:21 +11:00
parent 4aa4c8f4e7
commit 1a9cb24e6e
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
2 changed files with 31 additions and 6 deletions

View File

@ -8,16 +8,15 @@ export default () => {
const [currentYear, setCurrentYear] = useState(new Date().getFullYear()) const [currentYear, setCurrentYear] = useState(new Date().getFullYear())
const [selectedDate, setSelectedDate] = useState(new Date()) const [selectedDate, setSelectedDate] = useState(new Date())
const [dates, setDates] = useState<Date[]>([]) const [dates, setDates] = useState<Date[]>([])
const [l10nDays, setL10nDays] = useState<string[]>(getL10Weekday()) const l10nDays = getL10Weekday()
useEffect(() => { useEffect(() => {
setDates(getCalendarDates(currentMonth, currentYear)) setDates(getCalendarDates(currentMonth, currentYear))
}, [currentMonth, currentYear]) }, [currentMonth, currentYear])
useEffect(() => { function selectDate(date: Date) {
setCurrentMonth(selectedDate.getMonth()) setSelectedDate(date)
setCurrentYear(selectedDate.getFullYear()) }
}, [selectedDate])
return (<div className='datenel-component'> return (<div className='datenel-component'>
<div className='header'> <div className='header'>
@ -29,8 +28,10 @@ export default () => {
{l10nDays.map(day => <div className='item day-indicator' key={day}>{day}</div>)} {l10nDays.map(day => <div className='item day-indicator' key={day}>{day}</div>)}
{dates.map(date => <button className={`item date ${selectedDate.getMonth() !== date.getMonth() ? 'extra-month' : ''}`} key={date.toString()}> {dates.map(date => <button className={`item date ${currentMonth !== date.getMonth() && 'extra-month'} ${selectedDate.toDateString() === date.toDateString() && 'active'}`} key={date.toString()} onClick={() => selectDate(date)}>
{date.getDate()} {date.getDate()}
{/* 是今天 */}
{date.toDateString() === new Date().toDateString() && <svg xmlns="http://www.w3.org/2000/svg" className='today-indicator' viewBox="0 0 24 24" fill="currentColor"><path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"></path></svg>}
</button>)} </button>)}
</div> </div>
</div>) </div>)

View File

@ -1,5 +1,11 @@
.datenel-component { .datenel-component {
--main-color: #000000;
--accent-color: #000000;
--reversed-color: #ffffff;
--hover-color: #0000002a;
user-select: none; user-select: none;
color: var(--main-color);
.header { .header {
padding: 0.75rem; padding: 0.75rem;
@ -22,6 +28,7 @@
display: grid; display: grid;
grid-template-columns: repeat(7, 1fr); grid-template-columns: repeat(7, 1fr);
padding: 0.75rem; padding: 0.75rem;
gap: 0.125rem;
.item { .item {
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
@ -37,11 +44,28 @@
border: none; border: none;
background: none; background: none;
cursor: pointer; cursor: pointer;
color: var(--main-color);
} }
button.item.date{ button.item.date{
border-radius: 50%;
position: relative;
&.extra-month { &.extra-month {
opacity: 0.3; opacity: 0.3;
} }
&:hover {
background: var(--hover-color);
}
.today-indicator{
position: absolute;
bottom: 0.25rem;
width: 0.25rem;
height: 0.25rem;
}
&.active {
background: var(--accent-color);
color: var(--reversed-color);
}
} }
} }