Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"axios": "^1.7.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"dayjs": "^1.11.13",
"es-toolkit": "^1.32.0",
"lenis": "^1.1.20",
Expand Down
2 changes: 1 addition & 1 deletion src/app/(after-login)/form/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function FormPage() {

return (
<div className='p-10'>
<div className='rounded-md bg-white p-10'>
<div className='max-w-screen-md rounded-md bg-white p-10'>
<div className='mb-10 grid gap-3'>
{/* input sample : controlled */}
<Input
Expand Down
185 changes: 185 additions & 0 deletions src/assets/css/datepicker.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
.react-datepicker {
border-color: #e5e7eb;
display: flex;
font-family: inherit;
box-shadow:0 0 12px rgba(0,0,0,0.08)
}

.react-datepicker__month-container {
float: none;
flex: 1;
padding: 4px;
}

.react-datepicker-popper .react-datepicker__triangle,
.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle {
stroke: #e5e7eb;
fill: #fff;
color: #fff;
}

.react-datepicker__header {
border: none;
background: transparent;
padding: 0;
}

.react-datepicker__header--time,
.react-datepicker__time-list-item {
display: flex;
align-items: center;
justify-content: center;
}

.react-datepicker__header.react-datepicker__header--time {
display:none;
}

.react-datepicker__time{
height:100%;
position:relative;
}

.react-datepicker__time-list{
width:100%;
height:100% !important;
position:absolute;
top:0;
left:0;

}

.react-datepicker__time-list-item {
border: 1px solid #e5e7eb;
border-radius: 5px;
}
.react-datepicker__time-list-item:hover{
border-color:#ccc;
transition:border 0.2s
}

.react-datepicker__time-list-item + .react-datepicker__time-list-item {
margin-top: 4px;
}

.react-datepicker__day--outside-month {
opacity: 0.2;
}

.react-datepicker .saturday:not([aria-selected="true"]) {
color: blue;
}

.react-datepicker .sunday:not([aria-selected="true"]) {
color: red;
}


.react-datepicker__day-name,
.react-datepicker__day,
.react-datepicker__time-name {
width: 28px;
height: 28px;
line-height: 28px;
font-size: 12px;
}

.react-datepicker__time-container {
padding: 4px;
float: none;
width: 80px;
background: #f8f9fa;
border-left: 1px solid #eee;
}

.react-datepicker__time-container * {
box-sizing: border-box !important;
}

.react-datepicker__time-container .react-datepicker__time {
background: transparent;
}

.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box {
width: 100%;
padding: 0;
}

.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list {
padding-right: 2px;
}

.react-datepicker__time-list::-webkit-scrollbar {
width: 2px;
}

.react-datepicker__time-list::-webkit-scrollbar-thumb {
background: #333;
}

.react-datepicker__time-list::-webkit-scrollbar-track {
background: #eee;
}

.react-datepicker__day--selected,
.react-datepicker__day--in-selecting-range,
.react-datepicker__day--in-range,
.react-datepicker__month-text--selected,
.react-datepicker__month-text--in-selecting-range,
.react-datepicker__month-text--in-range,
.react-datepicker__quarter-text--selected,
.react-datepicker__quarter-text--in-selecting-range,
.react-datepicker__quarter-text--in-range,
.react-datepicker__year-text--selected,
.react-datepicker__year-text--in-selecting-range,
.react-datepicker__year-text--in-range,
.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected {
color:#fff;
background: #5534da;
}

.react-datepicker__day--selected:not([aria-disabled=true]):hover,
.react-datepicker__day--in-selecting-range:not([aria-disabled=true]):hover,
.react-datepicker__day--in-range:not([aria-disabled=true]):hover,
.react-datepicker__month-text--selected:not([aria-disabled=true]):hover,
.react-datepicker__month-text--in-selecting-range:not([aria-disabled=true]):hover,
.react-datepicker__month-text--in-range:not([aria-disabled=true]):hover,
.react-datepicker__quarter-text--selected:not([aria-disabled=true]):hover,
.react-datepicker__quarter-text--in-selecting-range:not([aria-disabled=true]):hover,
.react-datepicker__quarter-text--in-range:not([aria-disabled=true]):hover,
.react-datepicker__year-text--selected:not([aria-disabled=true]):hover,
.react-datepicker__year-text--in-selecting-range:not([aria-disabled=true]):hover,
.react-datepicker__year-text--in-range:not([aria-disabled=true]):hover{
background: #2C0CAC;
}

.react-datepicker__day--keyboard-selected,
.react-datepicker__month-text--keyboard-selected,
.react-datepicker__quarter-text--keyboard-selected,
.react-datepicker__year-text--keyboard-selected{
background: #5534da10;
}

.react-datepicker__day--keyboard-selected:not([aria-disabled=true]):hover{
color:#fff;
background: #5534da;
}

.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:not([aria-selected="true"]) {
height: 34px;
background: #fff;
}

.react-datepicker__day-names {
margin: 0;
}

.react-datepicker__day-name {
opacity: 0.5;
font-weight: 500;
}

.react-datepicker__month {
margin-top: 0;
}

1 change: 1 addition & 0 deletions src/assets/icons/circle_arrow_left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/icons/circle_arrow_right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 35 additions & 2 deletions src/components/ui/Field/DateInput.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { InputHTMLAttributes, useId } from 'react';
import Image from 'next/image';
import DatePicker from 'react-datepicker';
import dayjs from 'dayjs';
import DatePicker, { ReactDatePickerCustomHeaderProps, registerLocale } from 'react-datepicker';
import { ko } from 'date-fns/locale/ko';
import { getMonth, getYear } from 'date-fns';
import { cn } from '@/utils/helper';
import { BaseError, baseErrorClassName, baseFieldClassName, BaseItem, BaseLabel } from './Base';
import calendarIcon from '@/assets/icons/calendar.svg';
import { BaseField } from './types';
import arrowLeft from '@/assets/icons/circle_arrow_left.svg';
import arrowRight from '@/assets/icons/circle_arrow_right.svg';
import 'react-datepicker/dist/react-datepicker.css';
import '@/assets/css/datepicker.css';

registerLocale('ko', ko);

type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';

type DateInputProps = BaseField &
Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> & {
value: Date;
onChange: (value: Date | null) => void;
};

const getDayClassName = (date: Date) => {
return dayjs(date).format('dddd').toLowerCase() as DayOfWeek;
};

export function DateInput({ label, error, value, onChange, onBlur, placeholder, required, className, disabled, readOnly }: DateInputProps) {
const id = useId();

Expand All @@ -25,7 +39,6 @@ export function DateInput({ label, error, value, onChange, onBlur, placeholder,
)}
<div className='relative grid'>
<Image src={calendarIcon} alt='날짜선택' className={cn('pointer-events-none absolute left-4 top-1/2 z-20 h-auto w-4 -translate-y-1/2 opacity-50', value && 'opacity-100')} />
{/* TODO: DatePicker 스타일링 및 locale 설정 예정 */}
<DatePicker //
id={id}
selected={value}
Expand All @@ -40,9 +53,29 @@ export function DateInput({ label, error, value, onChange, onBlur, placeholder,
placeholderText={placeholder}
disabled={disabled}
readOnly={readOnly}
locale='ko'
timeCaption='시간'
dayClassName={getDayClassName}
renderCustomHeader={(props) => <CustomHeader {...props} />}
/>
</div>
{error && <BaseError>{error}</BaseError>}
</BaseItem>
);
}

function CustomHeader({ date, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }: ReactDatePickerCustomHeaderProps) {
return (
<div className='mb-2 flex h-10 items-center justify-between rounded-md border border-gray-20 px-4 py-2 shadow-[0_6px_12px_rgba(0,0,0,0.04)]'>
<button type='button' className='text-xs disabled:opacity-30' onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
<Image src={arrowLeft} alt='이전달' className='h-5 w-5' />
</button>
<div className='text-md font-medium'>
{getYear(date)}년 {getMonth(date) + 1}월
</div>
<button type='button' className='text-xs disabled:opacity-30' onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
<Image src={arrowRight} alt='다음달' className='h-5 w-5' />
</button>
</div>
);
}