-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
169 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/Component/Common/DateRangePicker/DateRangePicker.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import DateRangePicker from '@/Component/Common/DateRangePicker/DateRangePicker'; | ||
|
||
const meta: Meta<typeof DateRangePicker> = { | ||
title: '날짜 구간 선택 컴포넌트', | ||
component: DateRangePicker, | ||
tags: ['autodocs'], | ||
parameters: { | ||
layout: 'fullscreen', | ||
}, | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof DateRangePicker>; | ||
|
||
export const BaseDateRangePickerCalendar: Story = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { useEffect } from 'react'; | ||
|
||
import Calendar from '@/Component/Common/Calendar/Calendar'; | ||
import Flex from '@/Component/Common/Flex/Flex'; | ||
import { ToastContainer, ToastManager } from '@/Component/Common/Toast'; | ||
import useDateRangeCalendar from '@/hooks/useDateRangeCalendar'; | ||
interface DateRangePickerProps { | ||
readonly isFutureDaysRestricted?: boolean; | ||
} | ||
|
||
const DateRangePicker = ({ | ||
isFutureDaysRestricted = true, | ||
}: DateRangePickerProps) => { | ||
const { selectCurrentDate, selectEndDate, hasError, isDateWithRange } = | ||
useDateRangeCalendar({ isFutureDaysRestricted }); | ||
|
||
useEffect(() => { | ||
if (hasError) { | ||
ToastManager.error('올바른 날짜를 선택해주세요!'); | ||
} | ||
}, [hasError]); | ||
|
||
return ( | ||
<Flex flexWrap="wrap"> | ||
<Calendar | ||
onSelectDate={(newDate) => selectCurrentDate(newDate)} | ||
isDateInRange={isDateWithRange} | ||
/> | ||
<Calendar | ||
onSelectDate={(newDate) => selectEndDate(newDate)} | ||
isDateInRange={isDateWithRange} | ||
/> | ||
<ToastContainer enterTimeout={500} leaveTimeout={1000} /> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default DateRangePicker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { useState } from 'react'; | ||
|
||
import { compareAsc, isWithinInterval } from 'date-fns'; | ||
|
||
interface UseDateRangeCalenDarProps { | ||
onStartDateSelect?: () => void; | ||
onEndDateSelect?: () => void; | ||
isFutureDaysRestricted?: boolean; | ||
} | ||
|
||
export default function useDateRangeCalendar({ | ||
onStartDateSelect, | ||
onEndDateSelect, | ||
isFutureDaysRestricted, | ||
}: UseDateRangeCalenDarProps) { | ||
const currentDate = new Date(); | ||
const [hasError, setError] = useState(false); | ||
const [startDate, setStartDate] = useState<null | Date>(null); | ||
const [endDate, setEndDate] = useState<null | Date>(null); | ||
|
||
const clearBothStartDateEndDate = () => { | ||
setStartDate(null); | ||
setEndDate(null); | ||
}; | ||
|
||
const selectCurrentDate = (_newDate: Date) => { | ||
if (startDate) { | ||
clearBothStartDateEndDate(); | ||
return; | ||
} | ||
if (onStartDateSelect) { | ||
onStartDateSelect(); | ||
} | ||
setStartDate(_newDate); | ||
setError(false); | ||
}; | ||
|
||
const selectEndDate = (_newEndDate: Date) => { | ||
if (endDate) { | ||
setEndDate(null); | ||
return; | ||
} | ||
if (compareAsc(_newEndDate, currentDate) !== -1) { | ||
clearBothStartDateEndDate(); | ||
setError(true); | ||
|
||
return; | ||
} | ||
|
||
if (onEndDateSelect) { | ||
onEndDateSelect(); | ||
} | ||
|
||
if (startDate) { | ||
setEndDate(_newEndDate); | ||
setError(false); | ||
} | ||
}; | ||
|
||
const isDateWithRange = (date: Date) => { | ||
if (startDate && endDate && compareAsc(startDate, endDate) === -1) | ||
return isWithinInterval(date, { | ||
start: startDate, | ||
end: endDate, | ||
}); | ||
|
||
return false; | ||
}; | ||
|
||
return { | ||
isDateWithRange, | ||
selectCurrentDate, | ||
selectEndDate, | ||
endDate, | ||
hasError, | ||
startDate, | ||
}; | ||
} |