|
1 | 1 | 'use client' |
2 | 2 |
|
3 | | -import api from '@lib/axios' |
4 | | -import { useQueryClient } from '@tanstack/react-query' |
5 | | -import axios from 'axios' |
6 | | -import Image from 'next/image' |
7 | | -import { useRouter } from 'next/navigation' |
8 | | -import React, { useEffect, useState } from 'react' |
9 | | - |
10 | | -import { DASHBOARD_COLORS } from '@/app/shared/constants/colors' |
11 | | -import { useSelectedDashboardStore } from '@/app/shared/store/useSelectedDashboardStore' |
12 | | -import { CreateDashboardRequest } from '@/app/shared/types/dashboard' |
| 3 | +import DashboardForm from '@components/dashboard/DashboardForm' |
| 4 | +import { useDashboardForm } from '@hooks/useDashboardForm' |
| 5 | +import React from 'react' |
13 | 6 |
|
14 | 7 | export default function EditInfo() { |
15 | | - const router = useRouter() |
16 | | - const { selectedDashboard, setSelectedDashboard } = |
17 | | - useSelectedDashboardStore() |
18 | | - const queryClient = useQueryClient() |
19 | | - |
20 | | - const [formData, setFormData] = useState<CreateDashboardRequest>({ |
21 | | - title: '', |
22 | | - color: DASHBOARD_COLORS[0], |
23 | | - }) |
24 | | - const [isSubmitting, setIsSubmitting] = useState(false) |
25 | | - |
26 | | - // selectedDashboard가 있을 때 formData 초기화 |
27 | | - useEffect(() => { |
28 | | - if (selectedDashboard) { |
29 | | - setFormData({ |
30 | | - title: selectedDashboard.title, |
31 | | - color: selectedDashboard.color, |
32 | | - }) |
33 | | - } |
34 | | - }, [selectedDashboard]) |
35 | | - |
36 | | - // 입력값 변경 핸들러 |
37 | | - const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
38 | | - const { name, value } = e.target |
39 | | - setFormData((prev) => ({ |
40 | | - ...prev, |
41 | | - [name]: value, |
42 | | - })) |
43 | | - } |
44 | | - |
45 | | - // 색상 선택 핸들러 |
46 | | - const handleColorSelect = (color: string) => { |
47 | | - setFormData((prev) => ({ ...prev, color })) |
48 | | - } |
49 | | - |
50 | | - // 제출 핸들러 |
51 | | - const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { |
52 | | - e.preventDefault() |
53 | | - |
54 | | - if (!formData.title || !formData.color) return |
55 | | - |
56 | | - try { |
57 | | - setIsSubmitting(true) |
58 | | - |
59 | | - if (!process.env.NEXT_PUBLIC_TEAM_ID || !selectedDashboard?.id) { |
60 | | - throw new Error('필수 정보가 누락되었습니다.') |
61 | | - } |
62 | | - |
63 | | - const response = await api.put( |
64 | | - `/${process.env.NEXT_PUBLIC_TEAM_ID}/dashboards/${selectedDashboard.id}`, |
65 | | - formData, |
66 | | - ) |
67 | | - |
68 | | - const data = response.data |
69 | | - |
70 | | - // 1. 상태 업데이트 (헤더, 수정정보 실시간 반영) |
71 | | - setSelectedDashboard(data) |
72 | | - |
73 | | - // 2. react-query 캐시 무효화 → Sidebar 목록 재요청 유도 |
74 | | - await queryClient.invalidateQueries({ queryKey: ['dashboards'] }) |
75 | | - |
76 | | - // 성공 시 상세 페이지 이동 |
77 | | - router.push(`/dashboard/${data.id}/edit`) |
78 | | - } catch (error: unknown) { |
79 | | - if (axios.isAxiosError(error)) { |
80 | | - const message = |
81 | | - error.response?.data?.message || |
82 | | - '대시보드 수정 중 오류가 발생했습니다.' |
83 | | - console.error('대시보드 수정 오류:', message) |
84 | | - alert(message) |
85 | | - } else { |
86 | | - console.error('대시보드 수정 오류:', error) |
87 | | - alert('알 수 없는 오류가 발생했습니다.') |
88 | | - } |
89 | | - } finally { |
90 | | - setIsSubmitting(false) |
91 | | - } |
92 | | - } |
| 8 | + const { |
| 9 | + formData, |
| 10 | + isSubmitting, |
| 11 | + handleChange, |
| 12 | + handleColorSelect, |
| 13 | + handleSubmit, |
| 14 | + selectedDashboard, |
| 15 | + } = useDashboardForm('edit') |
93 | 16 |
|
94 | 17 | return ( |
95 | 18 | <div> |
96 | | - {/* 컨테이너 */} |
97 | 19 | <div className="BG-white h-300 w-584 rounded-16 px-32 py-24"> |
98 | 20 | <h2 className="Text-black mb-24 text-18 font-bold"> |
99 | 21 | {selectedDashboard?.title || '대시보드 편집'} |
100 | 22 | </h2> |
101 | 23 |
|
102 | | - <form onSubmit={handleSubmit}> |
103 | | - {/* 제목 입력 */} |
104 | | - <div className="mb-16"> |
105 | | - <label htmlFor="title" className="Text-black mb-8 block text-16"> |
106 | | - 대시보드 이름 |
107 | | - </label> |
108 | | - <input |
109 | | - type="text" |
110 | | - id="title" |
111 | | - name="title" |
112 | | - value={formData.title} |
113 | | - onChange={handleChange} |
114 | | - placeholder="대시보드 이름을 입력해주세요." |
115 | | - className="Border-section w-512 rounded-8 px-12 py-10 text-16 outline-none" |
116 | | - required |
117 | | - /> |
118 | | - </div> |
119 | | - |
120 | | - {/* 색상 선택 */} |
121 | | - <div className="mb-30"> |
122 | | - <div className="flex gap-8"> |
123 | | - {DASHBOARD_COLORS.map((color) => ( |
124 | | - <button |
125 | | - key={color} |
126 | | - type="button" |
127 | | - onClick={() => handleColorSelect(color)} |
128 | | - className="relative flex size-30 items-center justify-center rounded-full" |
129 | | - style={{ backgroundColor: color }} |
130 | | - aria-label={`색상 ${color}`} |
131 | | - > |
132 | | - {/* 선택된 색상에 체크 표시 */} |
133 | | - {formData.color === color && ( |
134 | | - <div className="relative size-24 items-center justify-center"> |
135 | | - <Image |
136 | | - src="/images/check.svg" |
137 | | - alt="check" |
138 | | - fill |
139 | | - className="object-contain" |
140 | | - /> |
141 | | - </div> |
142 | | - )} |
143 | | - </button> |
144 | | - ))} |
145 | | - </div> |
146 | | - </div> |
147 | | - |
148 | | - {/* 하단 버튼 */} |
149 | | - <div> |
150 | | - <button |
151 | | - type="submit" |
152 | | - disabled={!formData.title || !formData.color || isSubmitting} |
153 | | - className={`BG-violet h-48 w-512 rounded-8 px-16 py-10 text-16 font-semibold text-white transition-opacity ${ |
154 | | - !formData.title || !formData.color || isSubmitting |
155 | | - ? 'cursor-not-allowed opacity-50' |
156 | | - : 'hover:opacity-90' |
157 | | - }`} |
158 | | - > |
159 | | - 변경 |
160 | | - </button> |
161 | | - </div> |
162 | | - </form> |
| 24 | + <DashboardForm |
| 25 | + formData={formData} |
| 26 | + onChange={handleChange} |
| 27 | + onColorSelect={handleColorSelect} |
| 28 | + onSubmit={handleSubmit} |
| 29 | + isSubmitting={isSubmitting} |
| 30 | + submitText="변경" |
| 31 | + submitButtonWidth="w-516" |
| 32 | + /> |
163 | 33 | </div> |
164 | 34 | </div> |
165 | 35 | ) |
|
0 commit comments