|
| 1 | +import { ChangeEvent, FormEvent, useMemo, useState } from "react"; |
1 | 2 | import Check from "../../assets/icons/check.svg?react";
|
2 | 3 | import Closed from "../../assets/icons/closed.svg?react";
|
3 | 4 | import CategoryChip from "./CategoryChip";
|
| 5 | +import { StoryForm } from "../../types/common/backlog"; |
| 6 | +import useStoryEmitEvent from "../../hooks/pages/backlog/useStoryEmitEvent"; |
| 7 | +import { Socket } from "socket.io-client"; |
| 8 | +import { useOutletContext } from "react-router-dom"; |
| 9 | +// import useShowDetail from "../../hooks/pages/backlog/useShowDetail"; |
| 10 | +import EpicDropdown from "./EpicDropdown"; |
| 11 | +import { EpicCategoryDTO } from "../../types/DTO/backlogDTO"; |
| 12 | +import useDropdownState from "../../hooks/common/dropdown/useDropdownState"; |
4 | 13 |
|
5 |
| -const StoryCreateForm = () => ( |
6 |
| - <div className="flex items-center gap-5 py-1 border-t border-b"> |
7 |
| - <div className="w-[5rem]"> |
8 |
| - <CategoryChip content="프로젝트" bgColor="green" /> |
9 |
| - </div> |
10 |
| - <input className="w-[38.75rem]" type="text" /> |
11 |
| - <div className="flex items-center "> |
12 |
| - <input className="w-14" type="number" id="point-number" /> |
13 |
| - <label htmlFor="point-number" className=""> |
14 |
| - POINT |
15 |
| - </label> |
16 |
| - </div> |
17 |
| - <div className="flex items-center gap-2"> |
18 |
| - <button |
19 |
| - className="flex items-center justify-center w-6 h-6 rounded-md bg-confirm-green" |
20 |
| - type="button" |
21 |
| - > |
22 |
| - <Check width={20} height={20} stroke="white" /> |
23 |
| - </button> |
24 |
| - <button |
25 |
| - className="flex items-center justify-center w-6 h-6 rounded-md bg-error-red" |
26 |
| - type="button" |
| 14 | +interface StoryCreateFormProps { |
| 15 | + onCloseClick: () => void; |
| 16 | + epicList: EpicCategoryDTO[]; |
| 17 | +} |
| 18 | + |
| 19 | +const StoryCreateForm = ({ onCloseClick, epicList }: StoryCreateFormProps) => { |
| 20 | + const { socket }: { socket: Socket } = useOutletContext(); |
| 21 | + const [{ title, point, epicId, status }, setStoryFormData] = |
| 22 | + useState<StoryForm>({ |
| 23 | + title: "", |
| 24 | + point: undefined, |
| 25 | + status: "시작전", |
| 26 | + epicId: undefined, |
| 27 | + }); |
| 28 | + const { open, handleClose, handleOpen, dropdownRef } = useDropdownState(); |
| 29 | + const { emitStoryCreateEvent } = useStoryEmitEvent(socket); |
| 30 | + |
| 31 | + const handleTitleChange = ({ target }: ChangeEvent<HTMLInputElement>) => { |
| 32 | + const { value } = target; |
| 33 | + setStoryFormData({ title: value, point, epicId, status }); |
| 34 | + }; |
| 35 | + |
| 36 | + const handlePointChange = ({ target }: ChangeEvent<HTMLInputElement>) => { |
| 37 | + const { value } = target; |
| 38 | + setStoryFormData({ title, point: Number(value), epicId, status }); |
| 39 | + }; |
| 40 | + |
| 41 | + const handleSubmit = (event: FormEvent) => { |
| 42 | + event.preventDefault(); |
| 43 | + if (epicId === undefined) { |
| 44 | + alert("에픽을 지정해주세요."); |
| 45 | + return; |
| 46 | + } |
| 47 | + |
| 48 | + if (!title) { |
| 49 | + alert("제목을 입력해주세요."); |
| 50 | + return; |
| 51 | + } |
| 52 | + |
| 53 | + if (point === undefined) { |
| 54 | + alert("포인트를 입력해주세요."); |
| 55 | + return; |
| 56 | + } |
| 57 | + |
| 58 | + emitStoryCreateEvent({ title, status, epicId, point }); |
| 59 | + onCloseClick(); |
| 60 | + }; |
| 61 | + |
| 62 | + const handleEpicChange = (selectedEpicId: number) => { |
| 63 | + setStoryFormData({ title, status, point, epicId: selectedEpicId }); |
| 64 | + handleClose(); |
| 65 | + }; |
| 66 | + |
| 67 | + const handleEpicColumnClick = () => { |
| 68 | + if (!open) { |
| 69 | + handleOpen(); |
| 70 | + } |
| 71 | + }; |
| 72 | + |
| 73 | + const selectedEpic = useMemo( |
| 74 | + () => epicList.filter(({ id }) => id === epicId)[0], |
| 75 | + [epicId] |
| 76 | + ); |
| 77 | + return ( |
| 78 | + <form |
| 79 | + className="flex items-center w-full py-1 border-t border-b" |
| 80 | + onSubmit={handleSubmit} |
| 81 | + > |
| 82 | + <div |
| 83 | + className="w-[5rem] min-h-[1.75rem] bg-light-gray rounded-md mr-7 hover:cursor-pointer relative" |
| 84 | + onClick={handleEpicColumnClick} |
| 85 | + ref={dropdownRef} |
27 | 86 | >
|
28 |
| - <Closed stroke="white" /> |
29 |
| - </button> |
30 |
| - </div> |
31 |
| - </div> |
32 |
| -); |
| 87 | + {epicId && ( |
| 88 | + <CategoryChip |
| 89 | + content={selectedEpic.name} |
| 90 | + bgColor={selectedEpic.color} |
| 91 | + /> |
| 92 | + )} |
| 93 | + {open && ( |
| 94 | + <EpicDropdown |
| 95 | + selectedEpic={selectedEpic} |
| 96 | + epicList={epicList} |
| 97 | + onEpicSelect={handleEpicChange} |
| 98 | + /> |
| 99 | + )} |
| 100 | + </div> |
| 101 | + <input |
| 102 | + className="w-[34.7rem] h-[1.75rem] mr-[1.5rem] bg-light-gray rounded-md focus:outline-none" |
| 103 | + type="text" |
| 104 | + value={title} |
| 105 | + onChange={handleTitleChange} |
| 106 | + /> |
| 107 | + <div className="flex items-center mr-[2.8rem] "> |
| 108 | + <input |
| 109 | + className="w-24 h-[1.75rem] mr-1 text-right rounded-md bg-light-gray no-arrows focus:outline-none" |
| 110 | + type="number" |
| 111 | + id="point-number" |
| 112 | + value={point} |
| 113 | + onChange={handlePointChange} |
| 114 | + /> |
| 115 | + <label htmlFor="point-number" className=""> |
| 116 | + POINT |
| 117 | + </label> |
| 118 | + </div> |
| 119 | + <div className="w-[4rem] mr-[2.76rem] text-right"> |
| 120 | + <span>0%</span> |
| 121 | + </div> |
| 122 | + <div className="flex items-center gap-2"> |
| 123 | + <button |
| 124 | + className="flex items-center justify-center w-6 h-6 rounded-md bg-confirm-green" |
| 125 | + type="button" |
| 126 | + onClick={handleSubmit} |
| 127 | + > |
| 128 | + <Check width={20} height={20} stroke="white" /> |
| 129 | + </button> |
| 130 | + <button |
| 131 | + className="flex items-center justify-center w-6 h-6 rounded-md bg-error-red" |
| 132 | + type="button" |
| 133 | + onClick={onCloseClick} |
| 134 | + > |
| 135 | + <Closed stroke="white" /> |
| 136 | + </button> |
| 137 | + </div> |
| 138 | + </form> |
| 139 | + ); |
| 140 | +}; |
33 | 141 |
|
34 | 142 | export default StoryCreateForm;
|
0 commit comments