Skip to content

Commit 76bcc9f

Browse files
committed
refactor: create calendar component
1 parent 042ca78 commit 76bcc9f

8 files changed

Lines changed: 148 additions & 71 deletions

File tree

packages/react-use-calendar-component/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ This project is aimed to provide an easy-to-use API interface for those people w
1010
- [ ] Select multiple dates
1111
- [ ] Support disabled date
1212
- [ ] Support displaying two calendar
13+
- [ ] Support week, month, year selection
Lines changed: 15 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,24 @@
1-
import { useEffect } from 'react';
1+
import { useState } from 'react';
22

3-
import useCalendarComponent from '../lib';
4-
import { getWeekDayList, getMonthList } from '../lib/utils/locale';
5-
import LeftArrow from './components/LeftArrow';
6-
import RightArrow from './components/RightArrow';
3+
import Single from './components/Examples/Single';
74

8-
const weekDayList = getWeekDayList();
9-
const monthList = getMonthList();
5+
type ExampleType = 'single';
106

11-
function App() {
12-
const {
13-
displayedYear,
14-
displayedMonth,
15-
selectedDate,
16-
changeDisplayedMonth,
17-
changeDisplayedYear,
18-
getDateCellInfos,
19-
} = useCalendarComponent();
7+
const exampleMap = {
8+
single: <Single />,
9+
};
2010

21-
useEffect(() => {
22-
const { year, month, dayOfMonth } = selectedDate;
23-
console.log(new Date(year, month, dayOfMonth).toLocaleString());
24-
}, [selectedDate]);
25-
26-
const dateCells = getDateCellInfos().map(
27-
({ key, monthStatus, dayOfMonth, isToday, isSelected, selectThisDate }) => {
28-
let className = 'rounded-full';
29-
if (monthStatus !== 'current') className = `${className} text-slate-300`;
30-
if (isSelected) className = `${className} bg-green-200`;
31-
if (isToday && !isSelected) className = `${className} bg-amber-200`;
32-
33-
return (
34-
<button
35-
key={key}
36-
className={className}
37-
onClick={() => {
38-
selectThisDate({ changeDisplayedValues: true });
39-
}}>
40-
<div className='flex items-center justify-center'>
41-
<span>{dayOfMonth}</span>
42-
</div>
43-
</button>
44-
);
45-
}
46-
);
11+
export default function App() {
12+
const [value, setValue] = useState<ExampleType>('single');
4713

4814
return (
49-
<div className='bg-white shadow-2xl rounded-3xl p-8 w-[500px]'>
50-
<div className='flex justify-between items-center'>
51-
<LeftArrow arrowAmount={2} onClick={() => changeDisplayedYear(-1)} />
52-
<LeftArrow onClick={() => changeDisplayedMonth(-1)} />
53-
<div className='flex flex-col justify-center items-center'>
54-
<span className='text-lg'>{displayedYear}</span>
55-
<span className='text-sm'>{monthList[displayedMonth]}</span>
56-
</div>
57-
<RightArrow onClick={() => changeDisplayedMonth(1)} />
58-
<RightArrow arrowAmount={2} onClick={() => changeDisplayedYear(1)} />
59-
</div>
60-
<div className='mt-5'>
61-
<div className='grid grid-cols-7 mb-4'>
62-
{weekDayList.map((d, i) => (
63-
<div key={i} className='flex items-center justify-center'>
64-
{d}
65-
</div>
66-
))}
67-
</div>
68-
<div className='grid grid-cols-7 gap-y-4'>{dateCells}</div>
69-
</div>
15+
<div className='flex flex-col items-center gap-10 pt-10 min-h-screen bg-slate-500'>
16+
<select
17+
value={value}
18+
onChange={e => setValue(e.currentTarget.value as ExampleType)}>
19+
<option value='single'>single</option>
20+
</select>
21+
{exampleMap[value]}
7022
</div>
7123
);
7224
}
73-
74-
export default App;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useEffect } from 'react';
2+
3+
import useCalendarComponent from '../../lib';
4+
import CalendarBody from './CalendarBody';
5+
import CalendarHeader from './CalendarHeader';
6+
7+
interface Props {
8+
calendarControl: ReturnType<typeof useCalendarComponent>;
9+
}
10+
11+
export default function Calendar({ calendarControl }: Props) {
12+
const {
13+
displayedYear,
14+
displayedMonth,
15+
selectedDate,
16+
changeDisplayedMonth,
17+
changeDisplayedYear,
18+
getDateCellInfos,
19+
} = calendarControl;
20+
21+
useEffect(() => {
22+
const { year, month, dayOfMonth } = selectedDate;
23+
console.log(new Date(year, month, dayOfMonth).toLocaleString());
24+
}, [selectedDate]);
25+
26+
return (
27+
<div className='bg-white shadow-2xl rounded-3xl p-8 w-[500px]'>
28+
<CalendarHeader
29+
onYearClick={changeDisplayedYear}
30+
onMonthClick={changeDisplayedMonth}
31+
year={displayedYear}
32+
month={displayedMonth}
33+
/>
34+
<CalendarBody dateCellInfos={getDateCellInfos()} />
35+
</div>
36+
);
37+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { DateCellInfo } from '../../lib/types';
2+
import { getWeekDayList } from '../../lib/utils/locale';
3+
import CalendarCell from './CalendarCell';
4+
5+
const weekDayList = getWeekDayList();
6+
7+
interface Props {
8+
dateCellInfos: DateCellInfo[];
9+
}
10+
11+
export default function CalendarBody({ dateCellInfos }: Props) {
12+
return (
13+
<div className='mt-5'>
14+
<div className='grid grid-cols-7 mb-4'>
15+
{weekDayList.map((d, i) => (
16+
<div key={i} className='flex items-center justify-center'>
17+
{d}
18+
</div>
19+
))}
20+
</div>
21+
<div className='grid grid-cols-7 gap-y-4'>
22+
{dateCellInfos.map(info => (
23+
<CalendarCell key={info.key} dateCellInfo={info} />
24+
))}
25+
</div>
26+
</div>
27+
);
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { DateCellInfo } from '../../lib/types';
2+
3+
interface Props {
4+
dateCellInfo: DateCellInfo;
5+
}
6+
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+
15+
return (
16+
<button
17+
key={key}
18+
className={className}
19+
onClick={() => {
20+
selectThisDate({ changeDisplayedValues: true });
21+
}}>
22+
<div className='flex items-center justify-center'>
23+
<span>{dayOfMonth}</span>
24+
</div>
25+
</button>
26+
);
27+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { getMonthList } from '../../lib/utils/locale';
2+
import LeftArrow from './LeftArrow';
3+
import RightArrow from './RightArrow';
4+
5+
const monthList = getMonthList();
6+
7+
interface Props {
8+
year: number;
9+
month: number;
10+
onYearClick: (value: number) => void;
11+
onMonthClick: (value: number) => void;
12+
}
13+
14+
export default function CalendarHeader({
15+
year,
16+
month,
17+
onYearClick,
18+
onMonthClick,
19+
}: Props) {
20+
return (
21+
<div className='flex justify-between items-center'>
22+
<LeftArrow arrowAmount={2} onClick={() => onYearClick(-1)} />
23+
<LeftArrow onClick={() => onMonthClick(-1)} />
24+
<div className='flex flex-col justify-center items-center'>
25+
<span className='text-lg'>{year}</span>
26+
<span className='text-sm'>{monthList[month]}</span>
27+
</div>
28+
<RightArrow onClick={() => onMonthClick(1)} />
29+
<RightArrow arrowAmount={2} onClick={() => onYearClick(1)} />
30+
</div>
31+
);
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import useCalendarComponent from '../../../lib';
2+
import Calendar from '../Calendar';
3+
4+
export default function Single() {
5+
const calendarControl = useCalendarComponent();
6+
7+
return <Calendar calendarControl={calendarControl} />;
8+
}

packages/react-use-calendar-component/src/app/index.css

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,3 @@
22
@tailwind components;
33
@tailwind utilities;
44

5-
#root {
6-
padding-top: 10rem;
7-
display: flex;
8-
flex-direction: column;
9-
align-items: center;
10-
}

0 commit comments

Comments
 (0)