@@ -8,6 +8,7 @@ import { createTodoSchema } from '../schemas';
88import { toast } from 'sonner' ;
99import { useEventBus } from '@/hooks/use-event-bus' ;
1010import { useRouter } from 'next/navigation' ;
11+ import { Plus , X , Sparkles , ArrowDown , Minus , AlertTriangle , Flame } from 'lucide-react' ;
1112
1213export default function CreateTodoForm ( props : { userId : string } ) {
1314 const [ isFormOpen , setIsFormOpen ] = useState ( false ) ;
@@ -22,88 +23,170 @@ export default function CreateTodoForm(props: { userId: string }) {
2223 } ) ;
2324
2425 const {
25- form : { register, formState, reset } ,
26+ form : { register, formState, reset, setValue , watch } ,
2627 action,
2728 handleSubmitWithAction,
2829 } = useHookFormAction ( createTodo , zodResolver ( createTodoSchema ) , {
2930 actionProps : {
3031 onSuccess : ( ) => {
31- toast . success ( 'Todo created successfully' ) ;
32+ toast . success ( 'Task created successfully' ) ;
3233 reset ( ) ;
3334 setIsFormOpen ( false ) ;
3435 } ,
3536 onError : ( { error } ) => {
36- toast . error ( typeof error === 'string' ? error : 'Failed to create todo ' ) ;
37+ toast . error ( typeof error === 'string' ? error : 'Failed to create task ' ) ;
3738 } ,
3839 } ,
3940 formProps : {
4041 defaultValues : {
4142 title : '' ,
4243 description : '' ,
44+ priority : 'MEDIUM' ,
45+ dueDate : '' ,
46+ category : '' ,
4347 } ,
4448 } ,
4549 } ) ;
4650
51+ const selectedPriority = watch ( 'priority' ) ;
52+
53+ const priorities = [
54+ { value : 'LOW' , label : 'Low' , icon : ArrowDown , color : 'text-emerald-400' , bg : 'bg-emerald-500/10' , border : 'border-emerald-500/30' , activeBg : 'bg-emerald-500/20' } ,
55+ { value : 'MEDIUM' , label : 'Med' , icon : Minus , color : 'text-amber-400' , bg : 'bg-amber-500/10' , border : 'border-amber-500/30' , activeBg : 'bg-amber-500/20' } ,
56+ { value : 'HIGH' , label : 'High' , icon : AlertTriangle , color : 'text-orange-400' , bg : 'bg-orange-500/10' , border : 'border-orange-500/30' , activeBg : 'bg-orange-500/20' } ,
57+ { value : 'URGENT' , label : 'Urgent' , icon : Flame , color : 'text-red-400' , bg : 'bg-red-500/10' , border : 'border-red-500/30' , activeBg : 'bg-red-500/20' } ,
58+ ] ;
59+
4760 if ( ! isFormOpen ) {
4861 return (
4962 < div className = "mb-6" >
5063 < button
5164 onClick = { ( ) => setIsFormOpen ( true ) }
52- className = "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 "
65+ className = "group inline-flex items-center gap-2.5 btn-primary py-2.5 px-5 text-sm "
5366 >
54- + Add New Todo
67+ < div className = "w-5 h-5 rounded-md bg-white/20 flex items-center justify-center group-hover:bg-white/30 transition-colors" >
68+ < Plus className = "w-3.5 h-3.5 text-white" />
69+ </ div >
70+ Add New Task
5571 </ button >
5672 </ div >
5773 ) ;
5874 }
5975
6076 return (
61- < div className = "bg-white shadow-md rounded-lg p-6 mb-6" >
62- < h2 className = "text-lg font-medium text-gray-900 mb-4" > Create New Todo</ h2 >
77+ < div className = "glass-card rounded-xl p-6 mb-6 animate-scale-in" >
78+ < div className = "flex items-center gap-2 mb-5" >
79+ < Sparkles className = "w-5 h-5 text-violet-400" />
80+ < h2 className = "text-lg font-semibold text-zinc-200" > Create New Task</ h2 >
81+ </ div >
82+
6383 < form onSubmit = { handleSubmitWithAction } className = "space-y-4" >
84+ { /* Title */ }
6485 < div >
65- < label htmlFor = "title" className = "block text-sm font-medium text-gray-700 " >
86+ < label htmlFor = "title" className = "form-label " >
6687 Title
6788 </ label >
6889 < input
6990 id = "title"
7091 { ...register ( 'title' ) }
71- placeholder = "Your TODO item title. "
72- className = "mt-1 p-2 block w-full rounded-md border-gray-300 shadow -sm focus:border-indigo-500 focus:ring-indigo-500 "
92+ placeholder = "What needs to be done? "
93+ className = "w-full px-3.5 py-2.5 rounded-xl glass-input text -sm text-zinc-200 placeholder-zinc-600 "
7394 />
74- { formState . errors . title && < p className = "mt-1 text-sm text-red-600" > { formState . errors . title . message } </ p > }
95+ { formState . errors . title && (
96+ < p className = "mt-1 text-xs text-red-400" > { formState . errors . title . message } </ p >
97+ ) }
7598 </ div >
7699
100+ { /* Description */ }
77101 < div >
78- < label htmlFor = "description" className = "block text-sm font-medium text-gray-700 " >
102+ < label htmlFor = "description" className = "form-label " >
79103 Description
80104 </ label >
81105 < textarea
82106 id = "description"
83107 { ...register ( 'description' ) }
84108 rows = { 3 }
85- placeholder = "Describe your TODO item ."
86- className = "mt-1 p-2 block w-full rounded-md border-gray-300 shadow -sm focus:border-indigo-500 focus:ring-indigo-500 "
109+ placeholder = "Add some details.. ."
110+ className = "w-full px-3.5 py-2.5 rounded-xl glass-input text -sm text-zinc-200 placeholder-zinc-600 resize-none "
87111 />
88112 { formState . errors . description && (
89- < p className = "mt-1 text-sm text-red-600 " > { formState . errors . description . message } </ p >
113+ < p className = "mt-1 text-xs text-red-400 " > { formState . errors . description . message } </ p >
90114 ) }
91115 </ div >
92116
93- < div className = "flex justify-end space-x-2" >
117+ { /* Priority Selector */ }
118+ < div >
119+ < label className = "form-label" > Priority</ label >
120+ < div className = "flex gap-2" >
121+ { priorities . map ( ( p ) => {
122+ const Icon = p . icon ;
123+ const isActive = selectedPriority === p . value ;
124+ return (
125+ < button
126+ key = { p . value }
127+ type = "button"
128+ onClick = { ( ) => setValue ( 'priority' , p . value as 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT' ) }
129+ className = { `flex items-center gap-1.5 px-3 py-2 rounded-lg text-xs font-medium border transition-all duration-200 ${
130+ isActive
131+ ? `${ p . activeBg } ${ p . color } ${ p . border } `
132+ : 'bg-transparent text-zinc-500 border-white/[0.06] hover:border-white/[0.12]'
133+ } `}
134+ >
135+ < Icon className = "w-3.5 h-3.5" />
136+ { p . label }
137+ </ button >
138+ ) ;
139+ } ) }
140+ </ div >
141+ </ div >
142+
143+ { /* Due Date & Category Row */ }
144+ < div className = "grid grid-cols-1 sm:grid-cols-2 gap-3" >
145+ < div >
146+ < label htmlFor = "dueDate" className = "form-label" >
147+ Due Date
148+ </ label >
149+ < input
150+ id = "dueDate"
151+ type = "date"
152+ { ...register ( 'dueDate' ) }
153+ className = "w-full px-3.5 py-2.5 rounded-xl glass-input text-sm text-zinc-200 [color-scheme:dark]"
154+ />
155+ </ div >
156+ < div >
157+ < label htmlFor = "category" className = "form-label" >
158+ Category
159+ </ label >
160+ < input
161+ id = "category"
162+ type = "text"
163+ { ...register ( 'category' ) }
164+ placeholder = "e.g. Work, Personal"
165+ className = "w-full px-3.5 py-2.5 rounded-xl glass-input text-sm text-zinc-200 placeholder-zinc-600"
166+ />
167+ </ div >
168+ </ div >
169+
170+ { /* Actions */ }
171+ < div className = "flex justify-end gap-2 pt-2" >
94172 < button
95173 type = "button"
96- onClick = { ( ) => setIsFormOpen ( false ) }
97- className = "inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-gray-700 bg-gray-200 hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
174+ onClick = { ( ) => {
175+ setIsFormOpen ( false ) ;
176+ reset ( ) ;
177+ } }
178+ className = "btn-ghost inline-flex items-center gap-1.5"
98179 >
180+ < X className = "w-3.5 h-3.5" />
99181 Cancel
100182 </ button >
101183 < button
102184 type = "submit"
103185 disabled = { action . isExecuting }
104- className = "inline-flex justify -center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 "
186+ className = "btn-primary inline-flex items -center gap-1.5 "
105187 >
106- { action . isExecuting ? 'Creating...' : 'Create Todo' }
188+ < Plus className = "w-3.5 h-3.5" />
189+ { action . isExecuting ? 'Creating...' : 'Create Task' }
107190 </ button >
108191 </ div >
109192 </ form >
0 commit comments