Skip to content

Commit 1b59df8

Browse files
committed
refactor: use array to store selected date
1 parent 76bcc9f commit 1b59df8

10 files changed

Lines changed: 108 additions & 53 deletions

File tree

packages/react-use-calendar-component/src/app/components/Calendar.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { useEffect } from 'react';
2-
31
import useCalendarComponent from '../../lib';
42
import CalendarBody from './CalendarBody';
53
import CalendarHeader from './CalendarHeader';
@@ -12,17 +10,11 @@ export default function Calendar({ calendarControl }: Props) {
1210
const {
1311
displayedYear,
1412
displayedMonth,
15-
selectedDate,
1613
changeDisplayedMonth,
1714
changeDisplayedYear,
1815
getDateCellInfos,
1916
} = calendarControl;
2017

21-
useEffect(() => {
22-
const { year, month, dayOfMonth } = selectedDate;
23-
console.log(new Date(year, month, dayOfMonth).toLocaleString());
24-
}, [selectedDate]);
25-
2618
return (
2719
<div className='bg-white shadow-2xl rounded-3xl p-8 w-[500px]'>
2820
<CalendarHeader

packages/react-use-calendar-component/src/app/components/CalendarBody.tsx

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,33 @@ export default function CalendarBody({ dateCellInfos }: Props) {
1919
))}
2020
</div>
2121
<div className='grid grid-cols-7 gap-y-4'>
22-
{dateCellInfos.map(info => (
23-
<CalendarCell key={info.key} dateCellInfo={info} />
24-
))}
22+
{dateCellInfos.map(
23+
({
24+
key,
25+
monthStatus,
26+
isSelected,
27+
isToday,
28+
dayOfMonth,
29+
selectThisDate,
30+
}) => {
31+
let className = 'rounded-full';
32+
if (monthStatus !== 'current')
33+
className = `${className} text-slate-300`;
34+
if (isSelected) className = `${className} bg-green-200`;
35+
if (isToday && !isSelected) className = `${className} bg-amber-200`;
36+
if (!isToday && !isSelected)
37+
className = `${className} hover:bg-stone-100`;
38+
39+
return (
40+
<CalendarCell
41+
key={key}
42+
onClick={selectThisDate}
43+
className={className}
44+
dayOfMonth={dayOfMonth}
45+
/>
46+
);
47+
}
48+
)}
2549
</div>
2650
</div>
2751
);

packages/react-use-calendar-component/src/app/components/CalendarCell.tsx

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1-
import type { DateCellInfo } from '../../lib/types';
2-
31
interface Props {
4-
dateCellInfo: DateCellInfo;
2+
className: string;
3+
onClick: () => void;
4+
dayOfMonth: number;
55
}
66

7-
export default function CalendarCell({ dateCellInfo }: Props) {
8-
const { key, monthStatus, dayOfMonth, isToday, isSelected, selectThisDate } =
9-
dateCellInfo;
10-
let className = 'rounded-full hover:bg-stone-100';
11-
if (monthStatus !== 'current') className = `${className} text-slate-300`;
12-
if (isSelected) className = `${className} bg-green-200`;
13-
if (isToday && !isSelected) className = `${className} bg-amber-200`;
14-
7+
export default function CalendarCell({
8+
className,
9+
onClick,
10+
dayOfMonth,
11+
}: Props) {
1512
return (
16-
<button
17-
key={key}
18-
className={className}
19-
onClick={() => {
20-
selectThisDate({ changeDisplayedValues: true });
21-
}}>
13+
<button className={className} onClick={onClick}>
2214
<div className='flex items-center justify-center'>
2315
<span>{dayOfMonth}</span>
2416
</div>

packages/react-use-calendar-component/src/app/components/Examples/Single.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@ import useCalendarComponent from '../../../lib';
22
import Calendar from '../Calendar';
33

44
export default function Single() {
5-
const calendarControl = useCalendarComponent();
5+
const calendarControl = useCalendarComponent({});
6+
// const { selectedDate } = calendarControl;
7+
// const { year, month, dayOfMonth } = selectedDate;
68

7-
return <Calendar calendarControl={calendarControl} />;
9+
return (
10+
<div>
11+
<Calendar calendarControl={calendarControl} />
12+
{/* <p className='text-center mt-10 text-white'>
13+
{new Date(year, month, dayOfMonth).toLocaleString(navigator.language, {
14+
dateStyle: 'long',
15+
})}
16+
</p> */}
17+
</div>
18+
);
819
}

packages/react-use-calendar-component/src/lib/hooks/useCalendarComponent.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import { useState } from 'react';
22

33
import type {
4+
UseCalendarOptions,
45
DateCellInfo,
56
SelectDate,
67
ChangeDisplayedValue,
78
SelectDateOptions,
9+
ControlOptions,
810
} from '../types';
9-
import getNumberOfDays from '../utils/getNumberOfDays';
10-
import isToday from '../utils/isToday';
11-
12-
const dateInstance = new Date();
11+
import { getNumberOfDays, isToday } from '../utils';
1312

1413
const CELLS_OF_PICKER = 42;
1514

16-
export default function useCalendarComponent(initialDate: Date = new Date()) {
17-
const [displayedYear, setDisplayedYear] = useState(initialDate.getFullYear());
18-
const [displayedMonth, setDisplayedMonth] = useState(initialDate.getMonth());
19-
const [selectedDate, internalSetSelectedDate] = useState({
20-
year: displayedYear,
21-
month: displayedMonth,
22-
dayOfMonth: dateInstance.getDate(),
23-
});
15+
export default function useCalendarComponent<C extends ControlOptions>({
16+
displayedDate = new Date(),
17+
}: UseCalendarOptions<C> = {}) {
18+
const [displayedYear, setDisplayedYear] = useState(
19+
displayedDate.getFullYear()
20+
);
21+
const [displayedMonth, setDisplayedMonth] = useState(
22+
displayedDate.getMonth()
23+
);
24+
25+
const [selectedDate, setSelectedDate] = useState<Date[]>([]);
2426

2527
const getDateCellInfo = (cellIndex: number): DateCellInfo => {
2628
const prevMonth = displayedMonth === 0 ? 11 : displayedMonth - 1;
@@ -65,9 +67,9 @@ export default function useCalendarComponent(initialDate: Date = new Date()) {
6567
dayOfWeek: weekDay,
6668
isToday: isToday(year, month, dayOfMonth),
6769
isSelected:
68-
year === selectedDate.year &&
69-
month === selectedDate.month &&
70-
dayOfMonth === selectedDate.dayOfMonth,
70+
year === selectedDate[0]?.getFullYear() &&
71+
month === selectedDate[0]?.getMonth() &&
72+
dayOfMonth === selectedDate[0]?.getDate(),
7173
monthStatus:
7274
monthOffset < 0 ? 'previous' : monthOffset > 0 ? 'next' : 'current',
7375
selectThisDate,
@@ -111,19 +113,21 @@ export default function useCalendarComponent(initialDate: Date = new Date()) {
111113
} else setDisplayedMonth(nextMonth);
112114
};
113115

114-
const selectDate: SelectDate = (dateUnit, options = {}) => {
116+
const selectDate: SelectDate = (
117+
{ year, month, dayOfMonth },
118+
options = {}
119+
) => {
115120
const { changeDisplayedValues = false } = options;
116-
internalSetSelectedDate(dateUnit);
121+
setSelectedDate([new Date(year, month, dayOfMonth)]);
117122
if (changeDisplayedValues) {
118-
setDisplayedYear(dateUnit.year);
119-
setDisplayedMonth(dateUnit.month);
123+
setDisplayedYear(year);
124+
setDisplayedMonth(month);
120125
}
121126
};
122127

123128
return {
124129
displayedYear,
125130
displayedMonth,
126-
selectedDate,
127131
changeDisplayedYear,
128132
changeDisplayedMonth,
129133
getDateCellInfos,

packages/react-use-calendar-component/src/lib/types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
// useCalendarComponent
2+
export interface SingleOptions {
3+
defaultSelectedDate?: Date;
4+
type: 'single';
5+
}
6+
7+
export interface MultipleOptions {
8+
defaultSelectedDate?: Date[];
9+
type: 'multiple';
10+
}
11+
12+
export interface RangeOptions {
13+
defaultRange?: [Date, Date];
14+
type: 'range';
15+
}
16+
17+
export type ControlOptions = SingleOptions | MultipleOptions;
18+
export type SelectedDate<C extends ControlOptions> = C extends SingleOptions
19+
? SingleOptions['defaultSelectedDate']
20+
: C extends MultipleOptions
21+
? MultipleOptions['defaultSelectedDate']
22+
: never;
23+
24+
export type UseCalendarOptions<C extends ControlOptions> = {
25+
displayedDate?: Date;
26+
controlOptions?: C;
27+
};
28+
129
export interface DateCellInfo {
230
key: string;
331
year: number;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const MAGIC_NUMBER = 40;
22

3-
export default function getNumberOfDays(year: number, month: number) {
3+
export function getNumberOfDays(year: number, month: number) {
44
return MAGIC_NUMBER - new Date(year, month, MAGIC_NUMBER).getDate();
55
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './getNumberOfDays';
2+
export * from './isToday';
3+
export * from './locale';

packages/react-use-calendar-component/src/lib/utils/isToday.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export default function isToday(year: number, month: number, date: number) {
1+
export function isToday(year: number, month: number, date: number) {
22
const todayDate = new Date();
33

44
return (

packages/react-use-calendar-component/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"resolveJsonModule": true,
1515
"isolatedModules": true,
1616
"noEmit": true,
17-
"jsx": "react-jsx"
17+
"jsx": "react-jsx",
18+
"noUncheckedIndexedAccess": true
1819
},
1920
"include": ["src/"],
2021
"references": [{ "path": "./tsconfig.node.json" }]

0 commit comments

Comments
 (0)