1- import { useState , useEffect } from "react" ;
1+ import { useState , useEffect , ChangeEvent } from "react" ;
22import { useRouter } from "next/router" ;
33import Input from "../input/Input" ;
44import Image from "next/image" ;
@@ -18,8 +18,10 @@ const ChangeBebridge = ({ onUpdate }: ChangeBebridgeProps) => {
1818 { }
1919 ) ;
2020 const [ title , setTitle ] = useState ( "" ) ;
21+ const [ titleLength , setTitleLength ] = useState < number > ( 0 ) ;
2122 const [ selected , setSelected ] = useState < number | null > ( null ) ;
2223 const colors = [ "#7ac555" , "#760DDE" , "#FF9800" , "#76A5EA" , "#E876EA" ] ;
24+ const maxTitleLength = 30 ;
2325
2426 /* 대시보드 이름 데이터 */
2527 useEffect ( ( ) => {
@@ -40,18 +42,26 @@ const ChangeBebridge = ({ onUpdate }: ChangeBebridgeProps) => {
4042 }
4143 } catch ( error ) {
4244 console . error ( "대시보드 상세내용 불러오는데 오류 발생:" , error ) ;
45+ toast . error ( "대시보드를 불러오는 데 실패했습니다." ) ;
4346 }
4447 } ;
4548 if ( dashboardId ) {
4649 fetchDashboardTitle ( ) ;
4750 }
4851 } , [ dashboardId ] ) ;
4952
50- /* 대시보드 이름 변경 버튼 */
51- const handleUpdate = async ( ) => {
52- const dashboardIdNumber = Number ( dashboardId ) ;
53+ /* 대시보드 이름 글자수 제한 */
54+ const handleTitleChange = async ( value : string ) => {
55+ if ( value . length <= maxTitleLength ) {
56+ setTitle ( value ) ;
57+ setTitleLength ( value . length ) ;
58+ }
59+ } ;
60+
61+ const handleSubmit = async ( ) => {
5362 if ( ! dashboardId || selected === null ) return ;
5463
64+ const dashboardIdNumber = Number ( dashboardId ) ;
5565 const payload = {
5666 title,
5767 color : colors [ selected ] ,
@@ -68,7 +78,7 @@ const ChangeBebridge = ({ onUpdate }: ChangeBebridgeProps) => {
6878 color : colors [ selected ] ,
6979 } ) ) ;
7080
71- toast . success ( "대시보드가 변경되었습니다! " ) ;
81+ toast . success ( "대시보드가 변경되었습니다. " ) ;
7282 if ( onUpdate ) onUpdate ( ) ;
7383 } catch ( error ) {
7484 console . error ( "대시보드 변경 실패:" , error ) ;
@@ -77,48 +87,68 @@ const ChangeBebridge = ({ onUpdate }: ChangeBebridgeProps) => {
7787 } ;
7888
7989 return (
80- < div className = "lg:w-[620px] lg:h-[344px] sm:w-[544px] sm:h-[344px] w-[284px] h-[312px] bg-white rounded-[12px] p-[24px] flex flex-col" >
81- < h2 className = "text-black3 text-[20px] sm:text-[24px] font-bold" >
82- { dashboardDetail . title }
83- </ h2 >
84- < Input
85- type = "text"
86- onChange = { setTitle }
87- label = "대시보드 이름"
88- labelClassName = "text-black3 text-[16px] sm:text-[18px] font-medium mt-6"
89- placeholder = "뉴프로젝트"
90- className = "max-w-[620px] mb-1"
91- />
90+ < div className = "min-h-[312px] lg:w-[620px] sm:w-[544px] w-[284px] bg-white rounded-[12px] p-[24px] flex flex-col" >
91+ < div className = "w-full flex justify-center" >
92+ { /* 내부 아이템 컨테이너 */ }
93+ < div className = "flex flex-col lg:w-[564px] md:w-[488px] w-[252px]" >
94+ { /* 헤더 */ }
95+ < h2 className = "text-left text-black3 font-bold sm:text-[24px] text-[20px]" >
96+ { dashboardDetail . title }
97+ </ h2 >
9298
93- < div className = "flex mt-3" >
94- { colors . map ( ( color , index ) => (
95- < div key = { index } className = "relative" >
96- < button
97- className = "cursor-pointer w-[30px] h-[30px] rounded-[15px] mr-2 transition-all duration-200
98- hover:opacity-70 hover:scale-110"
99- style = { { backgroundColor : color } }
100- onClick = { ( ) => setSelected ( index ) } // 색상 선택 시 selected 업데이트
99+ { /* 변경할 제목 입력창 */ }
100+ < div className = "relative w-full mt-6" >
101+ < Input
102+ type = "text"
103+ onChange = { handleTitleChange }
104+ value = { title }
105+ label = "대시보드 이름"
106+ labelClassName = "text-left text-black3 font-medium sm:text-[18px] text-[16px] mb-1"
107+ placeholder = "변경할 이름을 입력해 주세요"
108+ className = "max-w-none mb-1 pr-[52px] placeholder:text-[14px] placeholder:sm:text-[16px]"
101109 />
102- { selected === index && (
103- < Image
104- src = "/svgs/check.svg"
105- alt = "선택됨"
106- width = { 23 }
107- height = { 23 }
108- className = "cursor-pointer absolute top-4 left-3.5 transform -translate-x-1/2 -translate-y-1/2"
109- />
110- ) }
110+ < span className = "absolute right-3 bottom-1 top-4/6 -translate-y-2/6 font-light text-[12px] sm:text-[14px] text-[var(--color-gray1)] sm:pr-1.5" >
111+ { titleLength } / { maxTitleLength }
112+ </ span >
111113 </ div >
112- ) ) }
113- </ div >
114- < div className = "mt-8 flex" >
115- < button
116- onClick = { handleUpdate }
117- disabled = { selected === null } // color가 없으면 버튼 비활성화
118- className = { `cursor-pointer sm:w-[572px] sm:h-[54px] w-[252px] h-[54px] rounded-[8px] border border-[var(--color-gray3)] bg-[var(--primary)] text-[var(--color-white)] ${ selected === null ? "bg-gray-300 cursor-not-allowed" : "bg-[var(--primary)]" } ` }
119- >
120- 변경
121- </ button >
114+
115+ { /* 컬러칩 선택 */ }
116+ < div className = "flex mt-3" >
117+ { colors . map ( ( color , index ) => (
118+ < div key = { index } className = "relative" >
119+ < button
120+ className = "cursor-pointer w-[30px] h-[30px] rounded-[15px] mr-2 transition-all duration-200
121+ hover:opacity-70 hover:scale-110"
122+ style = { { backgroundColor : color } }
123+ onClick = { ( ) => setSelected ( index ) } // 색상 선택 시 selected 업데이트
124+ />
125+ { selected === index && (
126+ < Image
127+ src = "/svgs/check.svg"
128+ alt = "선택됨"
129+ width = { 23 }
130+ height = { 23 }
131+ className = "cursor-pointer absolute top-4 left-3.5 transform -translate-x-1/2 -translate-y-1/2"
132+ />
133+ ) }
134+ </ div >
135+ ) ) }
136+ </ div >
137+
138+ { /* 변경 버튼 */ }
139+ < div className = "flex mt-6" >
140+ < button
141+ onClick = { handleSubmit }
142+ disabled = { selected === null } // color가 없으면 버튼 비활성화
143+ className = { `cursor-pointer w-full sm:h-[54px] h-[54px]
144+ rounded-[8px] border border-[var(--color-gray3)] bg-[var(--primary)]
145+ text-[var(--color-white)] font-semibold text-[14px] sm:text-[16px]
146+ ${ selected === null ? "bg-gray-300 cursor-not-allowed" : "bg-[var(--primary)]" } ` }
147+ >
148+ 변경
149+ </ button >
150+ </ div >
151+ </ div >
122152 </ div >
123153 </ div >
124154 ) ;
0 commit comments