33 IRoadmapCategory ,
44} from "@changes-page/supabase/types/page" ;
55import { Dialog , Transition } from "@headlessui/react" ;
6+ import { XIcon } from "@heroicons/react/outline" ;
67import { Fragment , useCallback } from "react" ;
78import MarkdownEditor from "../core/editor.component" ;
89import { FormErrors , ItemForm , RoadmapItemWithRelations } from "./types" ;
@@ -45,7 +46,7 @@ export default function RoadmapItemModal({
4546 return (
4647 // @ts -ignore
4748 < Transition appear show = { isOpen } as = { Fragment } >
48- < Dialog as = "div" className = "relative z-10 " onClose = { onClose } >
49+ < Dialog as = "div" className = "relative z-50 " onClose = { onClose } >
4950 < Transition . Child
5051 // @ts -ignore
5152 as = { Fragment }
@@ -71,127 +72,138 @@ export default function RoadmapItemModal({
7172 leaveFrom = "opacity-100 translate-y-0 sm:scale-100"
7273 leaveTo = "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
7374 >
74- < div className = "relative" >
75+ < div className = "relative w-full sm:w-auto" >
76+ { /* Desktop Close Button */ }
7577 < button
7678 type = "button"
77- className = "absolute -top-4 -right-4 z-10 rounded-full bg-white dark:bg-gray-700 p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 shadow-lg border border-gray-200 dark:border-gray-600"
79+ className = "hidden sm:block absolute -top-4 -right-4 z-30 rounded-full bg-white dark:bg-gray-700 p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 shadow-lg border border-gray-200 dark:border-gray-600"
7880 onClick = { onClose }
7981 >
80- < svg
81- className = "h-5 w-5"
82- fill = "none"
83- viewBox = "0 0 24 24"
84- strokeWidth = { 2 }
85- stroke = "currentColor"
86- >
87- < path
88- strokeLinecap = "round"
89- strokeLinejoin = "round"
90- d = "M6 18L18 6M6 6l12 12"
91- />
92- </ svg >
82+ < XIcon className = "h-5 w-5" aria-hidden = "true" />
9383 </ button >
94- < Dialog . Panel className = "w-full max-w-5xl transform overflow-hidden rounded-t-2xl sm:rounded-2xl bg-white dark:bg-gray-800 p-8 text-left align-middle shadow-xl transition-all min-h-[50vh] sm:min-h-0" >
95- < form onSubmit = { onSubmit } >
96- { formErrors . general && (
97- < div className = "rounded-md bg-red-50 dark:bg-red-900/20 p-4 mb-6" >
98- < div className = "text-sm text-red-700 dark:text-red-400" >
99- { formErrors . general }
100- </ div >
101- </ div >
102- ) }
10384
104- { formErrors . title && (
105- < div className = "rounded-md bg-red-50 dark:bg-red-900/20 p-3 mb-4" >
106- < div className = "text-sm text-red-700 dark:text-red-400" >
107- { formErrors . title }
85+ < Dialog . Panel className = "w-full h-full sm:h-auto sm:max-w-5xl sm:min-w-[880px] transform overflow-hidden rounded-none sm:rounded-2xl bg-white dark:bg-gray-900 text-left align-middle shadow-xl transition-all flex flex-col sm:block" >
86+ { /* Mobile Header with Close Button */ }
87+ < div className = "flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700 sm:hidden" >
88+ < h3 className = "text-lg font-semibold text-gray-900 dark:text-white truncate" >
89+ { editingItem ? "Edit Item" : "Create Item" }
90+ </ h3 >
91+ < button
92+ type = "button"
93+ className = "rounded-full p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-indigo-500"
94+ onClick = { onClose }
95+ >
96+ < XIcon className = "h-6 w-6" aria-hidden = "true" />
97+ </ button >
98+ </ div >
99+ < div className = "p-4 sm:p-8 overflow-y-auto flex-1 sm:h-auto" >
100+ < form onSubmit = { onSubmit } className = "h-full" >
101+ { formErrors . general && (
102+ < div className = "rounded-md bg-red-50 dark:bg-red-900/20 p-4 mb-6" >
103+ < div className = "text-sm text-red-700 dark:text-red-400" >
104+ { formErrors . general }
105+ </ div >
108106 </ div >
109- </ div >
110- ) }
111-
112- < div className = "grid grid-cols-1 lg:grid-cols-3 gap-8 relative" >
113- < div className = "hidden lg:block absolute left-2/3 top-0 bottom-0 w-px bg-gray-200 dark:bg-gray-700 transform -translate-x-1/2 z-10" > </ div >
107+ ) }
114108
115- < div className = "lg:col-span-2 space-y-6" >
116- < div >
117- < input
118- type = "text"
119- value = { itemForm . title }
120- onChange = { ( e ) =>
121- setItemForm ( ( prev ) => ( {
122- ...prev ,
123- title : e . target . value ,
124- } ) )
125- }
126- className = "w-full text-xl font-semibold leading-6 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 focus:outline-none mb-6"
127- placeholder = "Enter item title..."
128- />
129- < MarkdownEditor
130- value = { itemForm . description }
131- onChange = { handleDescriptionChange }
132- imagesFolderPrefix = { null }
133- />
109+ { formErrors . title && (
110+ < div className = "rounded-md bg-red-50 dark:bg-red-900/20 p-3 mb-4" >
111+ < div className = "text-sm text-red-700 dark:text-red-400" >
112+ { formErrors . title }
113+ </ div >
134114 </ div >
135- </ div >
115+ ) }
136116
137- < div className = "lg:col-span-1 space-y-6" >
138- { categories . length > 0 && (
139- < div className = "flex items-center justify-between" >
140- < span className = "text-sm font-medium text-gray-500 dark:text-gray-400" >
141- Category
142- </ span >
143- < select
144- value = { itemForm . category_id }
117+ < div className = "grid grid-cols-1 lg:grid-cols-3 gap-8 relative h-full" >
118+ { /* Column Divider */ }
119+ < div className = "hidden lg:block absolute left-2/3 top-0 bottom-0 w-px bg-gray-200 dark:bg-gray-800 transform -translate-x-1/2 z-10" > </ div >
120+
121+ { /* Left side - Content */ }
122+ < div className = "lg:col-span-2 space-y-6" >
123+ < h3 className = "hidden sm:block text-xl font-semibold leading-6 text-gray-900 dark:text-white" >
124+ { editingItem ? "Edit Item" : "Create Item" }
125+ </ h3 >
126+ < div >
127+ < input
128+ type = "text"
129+ value = { itemForm . title }
145130 onChange = { ( e ) =>
146131 setItemForm ( ( prev ) => ( {
147132 ...prev ,
148- category_id : e . target . value ,
133+ title : e . target . value ,
149134 } ) )
150135 }
151- className = "text-sm rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-700 dark:text-gray-300"
152- >
153- < option value = "" > No category</ option >
154- { categories . map ( ( category ) => (
155- < option key = { category . id } value = { category . id } >
156- { category . name }
157- </ option >
158- ) ) }
159- </ select >
136+ className = "w-full text-xl font-semibold leading-6 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 focus:outline-none mb-6"
137+ placeholder = "Enter item title..."
138+ />
139+ < MarkdownEditor
140+ value = { itemForm . description }
141+ onChange = { handleDescriptionChange }
142+ imagesFolderPrefix = { null }
143+ />
160144 </ div >
161- ) }
162-
163- < div className = "flex items-center justify-between" >
164- < span className = "text-sm font-medium text-gray-500 dark:text-gray-400" >
165- Board
166- </ span >
167- < span className = "text-sm text-gray-900 dark:text-gray-100 font-medium" >
168- { board . title }
169- </ span >
170145 </ div >
171146
172- < div className = "space-y-3 pt-4" >
173- < button
174- type = "submit"
175- disabled = { isSubmitting }
176- className = "w-full inline-flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
177- >
178- { isSubmitting
179- ? "Saving..."
180- : editingItem
181- ? "Update Item"
182- : "Create Item" }
183- </ button >
184- < button
185- type = "button"
186- onClick = { onClose }
187- className = "w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 shadow-sm hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
188- >
189- Cancel
190- </ button >
147+ { /* Right side - Metadata */ }
148+ < div className = "lg:col-span-1 space-y-6" >
149+ { categories . length > 0 && (
150+ < div className = "flex items-center justify-between" >
151+ < span className = "text-sm font-medium text-gray-500 dark:text-gray-400" >
152+ Category
153+ </ span >
154+ < select
155+ value = { itemForm . category_id }
156+ onChange = { ( e ) =>
157+ setItemForm ( ( prev ) => ( {
158+ ...prev ,
159+ category_id : e . target . value ,
160+ } ) )
161+ }
162+ className = "text-sm rounded-md border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-700 dark:text-gray-300"
163+ >
164+ < option value = "" > No category</ option >
165+ { categories . map ( ( category ) => (
166+ < option key = { category . id } value = { category . id } >
167+ { category . name }
168+ </ option >
169+ ) ) }
170+ </ select >
171+ </ div >
172+ ) }
173+
174+ < div className = "flex items-center justify-between" >
175+ < span className = "text-sm font-medium text-gray-500 dark:text-gray-400" >
176+ Board
177+ </ span >
178+ < span className = "text-sm text-gray-900 dark:text-gray-100 font-medium" >
179+ { board . title }
180+ </ span >
181+ </ div >
182+
183+ < div className = "space-y-3 pt-4" >
184+ < button
185+ type = "submit"
186+ disabled = { isSubmitting }
187+ className = "w-full inline-flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
188+ >
189+ { isSubmitting
190+ ? "Saving..."
191+ : editingItem
192+ ? "Update Item"
193+ : "Create Item" }
194+ </ button >
195+ < button
196+ type = "button"
197+ onClick = { onClose }
198+ className = "w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 shadow-sm hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
199+ >
200+ Cancel
201+ </ button >
202+ </ div >
191203 </ div >
192204 </ div >
193- </ div >
194- </ form >
205+ </ form >
206+ </ div >
195207 </ Dialog . Panel >
196208 </ div >
197209 </ Transition . Child >
0 commit comments