Skip to content

Commit

Permalink
(#0) InputDatePicker Modal형식으로 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
baegofda committed Dec 7, 2023
1 parent 2334526 commit a93de0f
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 109 deletions.
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,23 @@
"storybook:build": "storybook build"
},
"peerDependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"@types/react": "18.2.0",
"@types/react-dom": "18.2.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.5"
},
"dependencies": {
"@phosphor-icons/react": "2.0.15",
"@toss/use-overlay": "1.3.8",
"autoprefixer": "10.4.16",
"clsx": "2.0.0",
"dayjs": "1.11.10",
"postcss": "8.4.31",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-tooltip": "5.24.0",
"react-quill": "2.0.0",
"react-tooltip": "5.24.0",
"tailwindcss": "3.3.5"
},
"devDependencies": {
Expand Down
88 changes: 88 additions & 0 deletions src/core/components/Input/InputDatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useId, useState } from "react";

import Button from "../../Button";
import DatePickerCalendar from "../../Calendar/DatePickerCalendar";
import { PeriodDates } from "../../Calendar/DatePickerCalendar/types/CalendarComponentProps";
import Divider from "../../Divider";
import ModalPopUp from "../../Modal/ModalPopUp";
import GeneralTab from "../../Tab/GeneralTab/GeneralTab";
import Typography from "../../Typography";
import { DatePickerProps } from "./types";

const DatePicker = ({
isOpen,
close,
currentMonth,
disabled,
disabledDates,
useTab = false,
}: DatePickerProps) => {
const id = useId();
const [ selectedDate, setSelectedDate ] = useState<string>("");
const [ periodDates, setPeriodDates ] = useState<PeriodDates>({
startDate: "",
endDate: "",
});
const [ tabSelected, setTabSelected ] = useState("selectedDate");
const tabData = [
{ key: "selectedDate", label: "선택한 기간만 적용" },
{ key: "afterAllDate", label: "시작일부터 모든 날짜 적용" },
];

const handleClose = () => {
close(periodDates);
};

const tabItems = tabData.map(item => (
<GeneralTab.Item
key = {item.key}
label = {item.label}
name = {id}
theme = "body-01-bold"
checked = {item.key === tabSelected}
value = {item.key}
onChange = {(e: React.ChangeEvent<HTMLInputElement>) => {
setTabSelected(e.target.value);
}}
/>
));

const onDateClick = (date: string, periodDates: PeriodDates) => {
setSelectedDate(date);
setPeriodDates(periodDates!);
};

return (
<ModalPopUp isOpen = {isOpen}>
<div className = {"w-[30rem] pt-6 rounded-xl border bg-white"}>
<div className = "px-4">
<Typography element = "h6" text = "날짜 선택" theme = "subhead-01-bold" />
{useTab && <GeneralTab items = {tabItems} className = "mt-4 mb-11" />}
<DatePickerCalendar
selectedDate = {selectedDate}
periodDates = {periodDates}
currentMonth = {currentMonth}
disabledDates = {disabledDates}
onDateClick = {onDateClick}
disabled = {disabled}
afterAllDate = {tabSelected === "afterAllDate"}
/>
</div>
<Divider />
<div className = "flex gap-3 py-5 px-6">
<Button
backgroundColor = "white"
color = "gray-06"
content = "닫기"
size = "h-60"
rounded = "rounded-12"
className = "w-full border"
onClick = {handleClose}
/>
</div>
</div>
</ModalPopUp>
);
};

export default DatePicker;
Original file line number Diff line number Diff line change
@@ -1,50 +1,57 @@
import { useState } from "react";
import { Meta } from "@storybook/react";

import { PeriodDates } from "@/core/components/Calendar/DatePickerCalendar/types/CalendarComponentProps";
import { OverlayProvider, useOverlay } from "@toss/use-overlay";
import ModalPopUp from "../../Modal/ModalPopUp";
import InputDatePicker from "./index";

const meta = {
title: "core/Input/InputDatePicker",
parameters: {
layout: "fullscreen",
},
component: InputDatePicker,
} satisfies Meta<typeof InputDatePicker>;

export default meta;

export const Default = () => {
const [ isOpen, setIsOpen ] = useState<boolean>(false);
const [ selectedDate, setSelectedDate ] = useState<string>("");
const [ periodDates, setPeriodDates ] = useState<PeriodDates>({
startDate: "",
endDate: "",
});

const onDateClick = (date: string, periodDates: PeriodDates) => {
setSelectedDate(date);
setPeriodDates(periodDates!);
};

const onCalendarToggle = () => {
setIsOpen(prev => !prev);
};
return (
<OverlayProvider>
<div id = "modal"/>
<div className = "flex gap-2">
<div className = "w-[500px]">
<InputDatePicker
useTab
/>
</div>
</div>
</OverlayProvider>
);
};

const onCalendarClose = () => {
setIsOpen(false);
const Layout = () => {
const overlay = useOverlay();
const onOverlay = () => {
overlay.open(({ isOpen }) => {
return (
<ModalPopUp isOpen = {isOpen}>
<InputDatePicker useTab = {false} />
</ModalPopUp>
);
});
};

return (
<div className = "flex gap-2">
<div className = "w-[500px]">
<InputDatePicker
isOpen = {isOpen}
periodDates = {periodDates}
selectedDate = {selectedDate}
onToggle = {onCalendarToggle}
onDateClick = {onDateClick}
onClose = {onCalendarClose}
useTab = {true}
/>
</div>
</div>
<button onClick = {onOverlay}>클릭</button>
);
};

export const ModalDatePicker = () => {
return (
<OverlayProvider>
<div id = "modal"/>
<Layout />
</OverlayProvider>
);
};
103 changes: 34 additions & 69 deletions src/core/components/Input/InputDatePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,56 @@
import { useState, useId, useEffect } from "react";
import dayjs from "dayjs";
import clsx from "clsx";
import { CalendarBlank } from "@phosphor-icons/react";

import DatePickerCalendar from "../../Calendar/DatePickerCalendar";
import { useOverlay } from "@toss/use-overlay";
import dayjs from "dayjs";
import { useState } from "react";
import { PeriodDates } from "../../Calendar/DatePickerCalendar/types/CalendarComponentProps";
import Typography from "../../Typography";
import Divider from "../../Divider";
import Button from "../../Button";
import GeneralTab from "../../Tab/GeneralTab/GeneralTab";
import DatePicker from "./DatePicker";
import { InputDatePickerProps } from "./types";
import useClickOutside from "@/hooks/useClickOutSide";

const InputDatePicker = ({
isOpen,
periodDates,
selectedDate,
currentMonth,
disabledDates,
currentMonth,
useTab = false,
disabled = false,
onToggle,
onClose,
onDateClick,
}: InputDatePickerProps) => {
const id = useId();
const overlay = useOverlay();
const [ periodDates, setPeriodDates ] = useState<PeriodDates>({
startDate: "",
endDate: "",
});
const startDate = dayjs(periodDates.startDate).format("YYYY. MM. DD");
const endDate = dayjs(periodDates.endDate).format("YYYY. MM. DD");
const { contentRef } = useClickOutside<HTMLDivElement>(onClose);
const [ tabSelected, setTabSelected ] = useState("selectedDate");
const tabData = [
{ key: "selectedDate", label: "선택한 기간만 적용" },
{ key: "afterAllDate", label: "시작일부터 모든 날짜 적용" },
];

const tabItems = tabData.map(item => (
<GeneralTab.Item
key = {item.key}
label = {item.label}
name = {id}
theme = "body-01-bold"
checked = {item.key === tabSelected}
value = {item.key}
onChange = {(e: React.ChangeEvent<HTMLInputElement>) => {
setTabSelected(e.target.value);
}}
/>
));
const onDatePickerClick = (): Promise<PeriodDates> => {
return new Promise(resolve => {
overlay.open(({ isOpen, close }) => (
<DatePicker
disabled = {disabled}
isOpen = {isOpen}
currentMonth = {currentMonth}
close = {(periodDates: PeriodDates) => {
resolve(periodDates);
close();
}}
useTab = {useTab}
disabledDates = {disabledDates}/>
));
});
};

const handleDatePicker = async () => {
const periodDates = await onDatePickerClick();

useEffect(() => {
if (disabled) {
onClose();
}
}, [disabled]);
setPeriodDates(periodDates);
};

return (
<div className = "relative" ref = {contentRef}>
<div>
<button
type = "button"
className = "w-full flex items-center justify-between px-3 py-4 text-subhead-02-regular bg-transparent rounded-xl overflow-hidden border border-gray-03"
onClick = {onToggle}
onClick = {handleDatePicker}
disabled = {disabled}
>
{
Expand All @@ -71,33 +63,6 @@ const InputDatePicker = ({
}
<CalendarBlank size = {24} className = "text-gray-05" />
</button>
<div className = {clsx("absolute end-0 w-full pt-6 z-10 rounded-xl border mt-2 bg-white", { "hidden": !isOpen })}>
<div className = "px-4">
<Typography element = "h6" text = "날짜 선택" theme = "subhead-01-bold" />
{useTab && <GeneralTab items = {tabItems} className = "mt-4 mb-11" />}
<DatePickerCalendar
selectedDate = {selectedDate}
periodDates = {periodDates}
currentMonth = {currentMonth}
disabledDates = {disabledDates}
onDateClick = {onDateClick}
disabled = {disabled}
afterAllDate = {tabSelected === "afterAllDate"}
/>
</div>
<Divider />
<div className = "flex gap-3 py-5 px-6">
<Button
backgroundColor = "white"
color = "gray-06"
content = "닫기"
size = "h-60"
rounded = "rounded-12"
className = "w-full border"
onClick = {onToggle}
/>
</div>
</div>
</div>
);
};
Expand Down
10 changes: 4 additions & 6 deletions src/core/components/Input/InputDatePicker/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { CalendarComponentProps } from "@/core/components/Calendar/DatePickerCalendar/types/CalendarComponentProps";
import { PeriodDates } from "@/core/components/Calendar/DatePickerCalendar/types/CalendarComponentProps";
import { CalendarComponentProps, PeriodDates } from "@/core/components/Calendar/DatePickerCalendar/types/CalendarComponentProps";

export interface InputDatePickerProps extends Omit<CalendarComponentProps, "afterAllDate"> {
export interface DatePickerProps extends Pick<CalendarComponentProps, "currentMonth" | "disabled" | "disabledDates"> {
isOpen: boolean;
periodDates: PeriodDates;
close: (periodDates: PeriodDates) => void;
useTab?: boolean;
onToggle: () => void;
onClose: () => void;
}
export interface InputDatePickerProps extends Omit<DatePickerProps, "isOpen"| "close"> {}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2765,6 +2765,11 @@
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.1.tgz#27337d72046d5236b32fd977edee3f74c71d332f"
integrity sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==

"@toss/[email protected]":
version "1.3.8"
resolved "https://registry.yarnpkg.com/@toss/use-overlay/-/use-overlay-1.3.8.tgz#5a5dd2d042e9d6f1208d1898c46a754ee7397045"
integrity sha512-VdyAOaZsiDN5I+eo3oNZVOTqDU+S+WL+xg7Qln/ea073JO7l+UVnv4GWkRTCsmF1GB0OI4WBDDi0U7XEkLt0nQ==

"@types/aria-query@^5.0.1":
version "5.0.4"
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
Expand Down

0 comments on commit a93de0f

Please sign in to comment.