-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from depromeet/SCRUM-26-사용자로서-할-일을-등록할-수-있는-서비…
…스가-필요합니다 SCRUM-26 사용자로서 할 일을 등록할 수 있는 서비스가 필요합니다.
- Loading branch information
Showing
20 changed files
with
1,129 additions
and
62 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 104 additions & 0 deletions
104
src/app/create/_components/DateSelectedComponent/DateSelectedComponent.tsx
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,104 @@ | ||
'use client'; | ||
|
||
import { useState } from 'react'; | ||
import { ChevronDown } from 'lucide-react'; | ||
import { format } from 'date-fns'; | ||
import { ko } from 'date-fns/locale'; | ||
import DatePicker from '../../../../components/datePicker/DatePicker'; | ||
import { | ||
Drawer, | ||
DrawerClose, | ||
DrawerContent, | ||
DrawerFooter, | ||
DrawerHeader, | ||
DrawerTitle, | ||
DrawerTrigger, | ||
} from '../../../../components/ui/drawer'; | ||
import { Button } from '@/components/ui/button'; | ||
|
||
interface DateSelectedComponentProps { | ||
selectedDate: Date | undefined; | ||
handleDateChange: (date: Date) => void; | ||
} | ||
|
||
const DateSelectedComponent = ({ | ||
selectedDate, | ||
handleDateChange, | ||
}: DateSelectedComponentProps) => { | ||
const [isOpen, setIsOpen] = useState(false); | ||
const [temporaryDate, setTemporaryDate] = useState<Date | undefined>( | ||
selectedDate, | ||
); | ||
|
||
const handleToggle = () => { | ||
setIsOpen((prev) => !prev); | ||
}; | ||
|
||
const handleTemporaryDate = (date: Date) => { | ||
setTemporaryDate(date); | ||
}; | ||
|
||
return ( | ||
<Drawer open={isOpen} onDrag={() => setIsOpen(false)}> | ||
<DrawerTrigger> | ||
<div className="relative mt-2 w-full"> | ||
<button | ||
className="relative flex w-full flex-col items-start border-b border-gray-300 pb-2" | ||
onClick={handleToggle} | ||
> | ||
<span | ||
className={`absolute left-0 text-gray-500 transition-all duration-200 ${ | ||
selectedDate !== undefined | ||
? 'text-neutral b3 top-[-8px]' | ||
: 't3 top-1' | ||
}`} | ||
> | ||
마감일 선택 | ||
</span> | ||
<div className="flex w-full items-center justify-between pt-4"> | ||
<span className="t3 text-base font-semibold"> | ||
{selectedDate | ||
? format(selectedDate, 'M월 d일 (E)', { locale: ko }) | ||
: ''} | ||
</span> | ||
<ChevronDown | ||
className={`h-4 w-4 text-gray-500 transition-transform duration-200 ${ | ||
isOpen ? 'rotate-180' : '' | ||
}`} | ||
/> | ||
</div> | ||
</button> | ||
<DrawerContent className="w-auto border-0 bg-component-gray-secondary px-5 pb-[33px] pt-2"> | ||
<DrawerHeader className="px-0 pb-10 pt-6"> | ||
<DrawerTitle className="t3 text-left"> | ||
마감일을 선택해주세요 | ||
</DrawerTitle> | ||
</DrawerHeader> | ||
<DatePicker | ||
selectedDate={temporaryDate} | ||
handleDateChange={handleTemporaryDate} | ||
/> | ||
<DrawerFooter className="px-0"> | ||
<DrawerClose> | ||
<Button | ||
variant="primary" | ||
className="mt-4 flex w-full items-center justify-center" | ||
onClick={() => { | ||
if (temporaryDate) { | ||
handleDateChange(temporaryDate); | ||
setIsOpen(false); | ||
} | ||
}} | ||
> | ||
확인 | ||
</Button> | ||
</DrawerClose> | ||
</DrawerFooter> | ||
</DrawerContent> | ||
</div> | ||
</DrawerTrigger> | ||
</Drawer> | ||
); | ||
}; | ||
|
||
export default DateSelectedComponent; |
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,74 @@ | ||
import ClearableInput from '@/components/clearableInput/ClearableInput'; | ||
import DateSelectedComponent from '@/app/create/_components/DateSelectedComponent/DateSelectedComponent'; | ||
import { useEffect, useRef, useState } from 'react'; | ||
import { Button } from '@/components/ui/button'; | ||
|
||
const WAITING_TIME = 300; | ||
const MAX_TASK_LENGTH = 15; | ||
|
||
interface TaskInputProps { | ||
onClick: (task: string) => void; | ||
} | ||
|
||
const TaskInput = ({ onClick }: TaskInputProps) => { | ||
const [task, setTask] = useState<string>(''); | ||
const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined); | ||
|
||
const inputRef = useRef<HTMLInputElement>(null); | ||
|
||
const isInvalid = task.length > MAX_TASK_LENGTH || task.length === 0; | ||
|
||
const handleTaskChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
setTask(event.target.value); | ||
}; | ||
|
||
const handleDateChange = (date: Date) => { | ||
setSelectedDate(date); | ||
}; | ||
|
||
useEffect(() => { | ||
if (inputRef.current) { | ||
setTimeout(() => { | ||
inputRef.current?.focus(); | ||
}, WAITING_TIME); | ||
} | ||
}, []); | ||
|
||
return ( | ||
<div className="w-full"> | ||
<div className="pb-10 pt-4"> | ||
<span className="t2">어떤 일의 마감이 급하신가요?</span> | ||
</div> | ||
<div className="flex flex-col gap-6"> | ||
<div> | ||
<ClearableInput | ||
ref={inputRef} | ||
value={task} | ||
onChange={handleTaskChange} | ||
/> | ||
{task.length > MAX_TASK_LENGTH && ( | ||
<p className="mt-2 text-sm text-red-500"> | ||
최대 16자 이내로 입력할 수 있어요. | ||
</p> | ||
)} | ||
</div> | ||
|
||
<DateSelectedComponent | ||
selectedDate={selectedDate} | ||
handleDateChange={handleDateChange} | ||
/> | ||
</div> | ||
|
||
<Button | ||
variant="primary" | ||
className="mt-6" | ||
onClick={() => onClick(task)} | ||
disabled={isInvalid} | ||
> | ||
다음 | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TaskInput; |
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,54 @@ | ||
export type TaskInputType = { | ||
task?: string; | ||
deadlineDate?: Date; | ||
deadlineTime?: string; | ||
smallAction?: string; | ||
estimatedHour?: string; | ||
estimatedMinute?: string; | ||
taskType?: string; | ||
moodType?: string; | ||
}; | ||
|
||
export type SmallActionInputType = { | ||
task: string; | ||
deadlineDate: Date; | ||
deadlineTime: string; | ||
smallAction?: string; | ||
estimatedHour?: string; | ||
estimatedMinute?: string; | ||
taskType?: string; | ||
moodType?: string; | ||
}; | ||
|
||
export type EstimatedTimeInputType = { | ||
task: string; | ||
deadlineDate: Date; | ||
deadlineTime: string; | ||
smallAction: string; | ||
estimatedHour?: string; | ||
estimatedMinute?: string; | ||
taskType?: string; | ||
moodType?: string; | ||
}; | ||
|
||
export type BufferTimeType = { | ||
task: string; | ||
deadlineDate: Date; | ||
deadlineTime: string; | ||
smallAction: string; | ||
estimatedHour: string; | ||
estimatedMinute: string; | ||
taskType?: string; | ||
moodType?: string; | ||
}; | ||
|
||
export type TaskTypeInputType = { | ||
task: string; | ||
deadlineDate: Date; | ||
deadlineTime: string; | ||
smallAction: string; | ||
estimatedHour: string; | ||
estimatedMinute: string; | ||
taskType: string; | ||
moodType: string; | ||
}; |
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,80 @@ | ||
'use client'; | ||
|
||
import { createFunnelSteps, useFunnel } from '@use-funnel/browser'; | ||
import { | ||
BufferTimeType, | ||
EstimatedTimeInputType, | ||
SmallActionInputType, | ||
TaskInputType, | ||
TaskTypeInputType, | ||
} from './context'; | ||
import useMount from '@/hooks/useMount'; | ||
import TaskInput from './_components/taskInput/TaskInput'; | ||
import BackHeader from '@/components/backHeader/BackHeader'; | ||
|
||
type FormState = { | ||
task?: string; | ||
deadlineDate?: Date; | ||
deadlineTime?: string; | ||
smallAction?: string; | ||
estimatedHour?: string; | ||
estimatedMinute?: string; | ||
taskType?: string; | ||
moodType?: string; | ||
}; | ||
|
||
const steps = createFunnelSteps<FormState>() | ||
.extends('taskForm') | ||
.extends('smallActionInput', { | ||
requiredKeys: ['task', 'deadlineDate', 'deadlineTime'], | ||
}) | ||
.extends('estimatedTimeInput', { requiredKeys: 'smallAction' }) | ||
.extends('bufferTime', { requiredKeys: ['estimatedHour', 'estimatedMinute'] }) | ||
.extends('taskTypeInput', { requiredKeys: ['taskType', 'moodType'] }) | ||
.build(); | ||
|
||
const TaskCreate = () => { | ||
const funnel = useFunnel<{ | ||
taskForm: TaskInputType; | ||
smallActionInput: SmallActionInputType; | ||
estimatedTimeInput: EstimatedTimeInputType; | ||
bufferTime: BufferTimeType; | ||
taskTypeInput: TaskTypeInputType; | ||
}>({ | ||
id: 'task-create-main', | ||
steps: steps, | ||
initial: { | ||
step: 'taskForm', | ||
context: {}, | ||
}, | ||
}); | ||
|
||
const { isMounted } = useMount(); | ||
|
||
if (!isMounted) return null; | ||
|
||
return ( | ||
<div className="background-primary flex min-h-screen w-full flex-col items-center justify-start overflow-y-auto px-5"> | ||
<BackHeader onClick={() => funnel.history.back()} /> | ||
<funnel.Render | ||
taskForm={({ history }) => ( | ||
<TaskInput | ||
onClick={(task: string) => | ||
history.push('smallActionInput', { | ||
task: task, | ||
deadlineDate: new Date(), | ||
deadlineTime: '', | ||
}) | ||
} | ||
/> | ||
)} | ||
smallActionInput={() => <div>작은행동 입력</div>} | ||
estimatedTimeInput={() => <div>예상시간 입력</div>} | ||
bufferTime={() => <div>버퍼시간 입력</div>} | ||
taskTypeInput={() => <div>할 일 종류 입력</div>} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TaskCreate; |
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
Oops, something went wrong.