Skip to content

Commit 044afb7

Browse files
authored
Merge pull request #157 from codeit-2team/fix/156
Fix/156 일정 검증로직 추가
2 parents 4c1d2e1 + e25bad5 commit 044afb7

File tree

4 files changed

+83
-19
lines changed

4 files changed

+83
-19
lines changed

src/app/(with-header)/myactivity/[id]/hooks/useEditActivityForm.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ActivityDetailEdit, Schedule } from '@/types/activityDetailType';
99
import { AxiosError } from 'axios';
1010
import { toast } from 'sonner';
1111
import { notFound } from 'next/navigation';
12+
import { validateSchedules } from '../../utils/dateValidatoin';
1213

1314
interface SubImageType {
1415
id?: number;
@@ -208,6 +209,11 @@ export const useEditActivityForm = () => {
208209

209210
const handleSubmit = async (e: React.FormEvent) => {
210211
e.preventDefault();
212+
const validationMessage = validateSchedules(dates);
213+
if (validationMessage) {
214+
toast.error(validationMessage);
215+
return;
216+
}
211217
try {
212218
await mutation.mutateAsync();
213219
} catch (error) {

src/app/(with-header)/myactivity/components/ScheduleSelect.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ interface ScheduleSelectProps {
1919
export function ScheduleSelect({
2020
index,
2121
isRemovable,
22-
2322
onRemove,
2423
onDateChange,
2524
onStartTimeChange,
@@ -29,9 +28,9 @@ export function ScheduleSelect({
2928
endTime,
3029
}: ScheduleSelectProps) {
3130
return (
32-
<div className='pt-5 w-full'>
33-
<div className='flex flex-wrap items-end gap-4 w-full'>
34-
<div className='flex flex-col gap-10 flex-1 min-w-0'>
31+
<div className='w-full pt-5'>
32+
<div className='flex w-full flex-wrap items-end gap-4'>
33+
<div className='flex min-w-0 flex-1 flex-col gap-10'>
3534
<Input
3635
className='w-full'
3736
type='date'
@@ -40,7 +39,7 @@ export function ScheduleSelect({
4039
variant='compact'
4140
/>
4241
</div>
43-
<div className='flex flex-col gap-10 flex-1 min-w-0'>
42+
<div className='flex min-w-0 flex-1 flex-col gap-10'>
4443
<Input
4544
className='w-full'
4645
type='time'
@@ -49,7 +48,7 @@ export function ScheduleSelect({
4948
variant='compact'
5049
/>
5150
</div>
52-
<div className='flex flex-col gap-10 flex-1 min-w-0'>
51+
<div className='flex min-w-0 flex-1 flex-col gap-10'>
5352
<Input
5453
className='w-full'
5554
type='time'
@@ -61,11 +60,11 @@ export function ScheduleSelect({
6160

6261
<div className='flex-shrink-0'>
6362
{isRemovable && (
64-
<div className="flex-shrink-0 w-44">
63+
<div className='w-44 flex-shrink-0'>
6564
<button
66-
type="button"
65+
type='button'
6766
onClick={() => onRemove(index)}
68-
className="w-full h-46 border border-gray-300 rounded-[10px] flex items-center justify-center hover:bg-gray-100"
67+
className='flex h-46 w-full items-center justify-center rounded-[10px] border border-gray-300 hover:bg-gray-100'
6968
>
7069
<IconClose />
7170
</button>
Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { toast } from 'sonner';
34
import { ScheduleSelect } from './ScheduleSelect';
45
import { Schedule } from '@/types/activityDetailType';
56

@@ -14,6 +15,17 @@ interface ScheduleSelectFormProps {
1415
) => void;
1516
}
1617

18+
function isPastDate(dateStr: string) {
19+
const selected = new Date(dateStr);
20+
const today = new Date();
21+
today.setHours(0, 0, 0, 0);
22+
return selected < today;
23+
}
24+
25+
function isInvalidTimeRange(start: string, end: string) {
26+
return start >= end;
27+
}
28+
1729
export function ScheduleSelectForm({
1830
dates,
1931
onAddDate,
@@ -23,38 +35,54 @@ export function ScheduleSelectForm({
2335
return (
2436
<div className='space-y-4 pt-24'>
2537
<div className='flex flex-row items-center justify-between gap-5'>
26-
<p className='text-xl text-black font-bold'>예약 가능한 시간대</p>
38+
<p className='text-xl font-bold text-black'>예약 가능한 시간대</p>
2739
<div>
2840
<button
2941
type='button'
3042
onClick={onAddDate}
31-
className='w-44 h-44 rounded-[10px] bg-green-300 px-10 py-5 hover:bg-green-600'
43+
className='h-44 w-44 rounded-[10px] bg-green-300 px-10 py-5 hover:bg-green-600'
3244
>
3345
<p className='text-2xl font-bold text-white'>+</p>
3446
</button>
3547
</div>
3648
</div>
49+
3750
{dates.map((dateSlot, idx) => (
3851
<div key={dateSlot.id ?? idx} className='flex'>
3952
<ScheduleSelect
4053
index={idx}
4154
isRemovable={dates.length > 1}
4255
onAddDate={onAddDate}
4356
onRemove={onRemoveDate}
44-
onDateChange={(index, value) => onDateChange(index, 'date', value)}
45-
onStartTimeChange={(index, value) =>
46-
onDateChange(index, 'startTime', value)
47-
}
48-
onEndTimeChange={(index, value) =>
49-
onDateChange(index, 'endTime', value)
50-
}
57+
onDateChange={(index, value) => {
58+
if (isPastDate(value)) {
59+
toast.error('오늘 이전 날짜는 선택할 수 없습니다.');
60+
return;
61+
}
62+
onDateChange(index, 'date', value);
63+
}}
64+
onStartTimeChange={(index, value) => {
65+
const end = dates[index].endTime;
66+
if (end && isInvalidTimeRange(value, end)) {
67+
toast.error('시작 시간은 종료 시간보다 빨라야 합니다.');
68+
return;
69+
}
70+
onDateChange(index, 'startTime', value);
71+
}}
72+
onEndTimeChange={(index, value) => {
73+
const start = dates[index].startTime;
74+
if (start && isInvalidTimeRange(start, value)) {
75+
toast.error('종료 시간은 시작 시간보다 늦어야 합니다.');
76+
return;
77+
}
78+
onDateChange(index, 'endTime', value);
79+
}}
5180
date={dateSlot.date}
5281
startTime={dateSlot.startTime}
5382
endTime={dateSlot.endTime}
5483
/>
5584
</div>
5685
))}
57-
5886
</div>
5987
);
6088
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Schedule } from '@/types/activityDetailType';
2+
3+
export function validateSchedules(schedules: Schedule[]) {
4+
const today = new Date();
5+
today.setHours(0, 0, 0, 0);
6+
7+
for (let i = 0; i < schedules.length; i++) {
8+
const { date, startTime, endTime } = schedules[i];
9+
10+
if (!date || !startTime || !endTime) {
11+
return `날짜와 시간이 모두 입력되어야 합니다!`;
12+
}
13+
14+
const selectedDate = new Date(date);
15+
if (selectedDate < today) {
16+
return `오늘보다 이전 날짜는 선택할 수 없습니다!`;
17+
}
18+
19+
const [startHour, startMinute] = startTime.split(':').map(Number);
20+
const [endHour, endMinute] = endTime.split(':').map(Number);
21+
22+
const startMinutes = startHour * 60 + startMinute;
23+
const endMinutes = endHour * 60 + endMinute;
24+
25+
if (startMinutes >= endMinutes) {
26+
return `종료 시간은 시작 시간보다 늦어야 합니다!`;
27+
}
28+
}
29+
30+
return null;
31+
}

0 commit comments

Comments
 (0)