33import React , { useState , useEffect } from "react" ;
44import { ArrowLeft , Save , XCircle } from "lucide-react" ;
55import Link from "next/link" ;
6+ import { auth } from "@/lib/firebase/config" ; // Import auth
67
7- interface CategoryOption { // Define interfaces for fetched data
8+ interface CategoryOption {
89 optionId : number ;
910 optionName : string ;
1011}
@@ -23,19 +24,18 @@ const AddProjectPage = () => {
2324 useEffect ( ( ) => {
2425 const fetchCategories = async ( ) => {
2526 try {
26- const res = await fetch ( '/api/categories' ) ;
27- if ( ! res . ok ) {
28- throw new Error ( `HTTP error! status: ${ res . status } ` ) ;
29- }
27+ const res = await fetch ( "/api/categories" ) ;
28+ if ( ! res . ok ) throw new Error ( `HTTP error! status: ${ res . status } ` ) ;
3029 const data : Category [ ] = await res . json ( ) ;
3130 setCategories ( data ) ;
3231 } catch ( e : any ) {
3332 setErrorCategories ( e . message ) ;
34- console . error ( "Failed to fetch categories for form :" , e ) ;
33+ console . error ( "Failed to fetch categories:" , e ) ;
3534 } finally {
3635 setLoadingCategories ( false ) ;
3736 }
3837 } ;
38+
3939 fetchCategories ( ) ;
4040 } , [ ] ) ;
4141
@@ -45,35 +45,31 @@ const AddProjectPage = () => {
4545 projectLink : "" ,
4646 createdAt : "" ,
4747 members : [ { name : "" , linkedin : "" } ] ,
48- selectedCategoryOptions : { } as Record < string , string > , // Map category name to selected option name
49- customDomain : "" , // Keep customDomain separate if 'Domain' is 'Other'
48+ selectedCategoryOptions : { } as Record < string , string > ,
49+ customDomain : "" ,
5050 } ;
5151
5252 const [ formData , setFormData ] = useState ( initialFormState ) ;
5353 const [ showPopup , setShowPopup ] = useState ( false ) ;
5454 const [ loading , setLoading ] = useState ( false ) ;
5555
5656 useEffect ( ( ) => {
57- // Set initial default values for dropdowns after categories are fetched
5857 if ( ! loadingCategories && categories . length > 0 ) {
59- setFormData ( prev => {
58+ setFormData ( ( prev ) => {
6059 const newSelectedOptions : Record < string , string > = { } ;
61- categories . forEach ( cat => {
60+ categories . forEach ( ( cat ) => {
6261 if ( cat . options . length > 0 ) {
6362 newSelectedOptions [ cat . categoryName ] = cat . options [ 0 ] . optionName ;
6463 }
6564 } ) ;
66- return {
67- ...prev ,
68- selectedCategoryOptions : newSelectedOptions ,
69- } ;
65+ return { ...prev , selectedCategoryOptions : newSelectedOptions } ;
7066 } ) ;
7167 }
7268 } , [ loadingCategories , categories ] ) ;
7369
7470 const handleSubmit = async ( e : React . FormEvent ) => {
7571 e . preventDefault ( ) ;
76- if ( loading ) return ;
72+ if ( loading ) return ;
7773
7874 const hasValidMember = formData . members . some (
7975 ( member ) => member . name . trim ( ) !== ""
@@ -89,10 +85,14 @@ const AddProjectPage = () => {
8985 ( member ) => member . name . trim ( ) !== ""
9086 ) ;
9187
92- // Prepare category options for backend
93- const projectCategoryOptions : { categoryName : string ; optionName : string } [ ] = Object . entries ( formData . selectedCategoryOptions ) . map ( ( [ categoryName , optionName ] ) => ( {
88+ const projectCategoryOptions :{ categoryName : string ; optionName :string } [ ] = Object . entries (
89+ formData . selectedCategoryOptions
90+ ) . map ( ( [ categoryName , optionName ] ) => ( {
9491 categoryName,
95- optionName : categoryName === 'Domain' && optionName === 'Other' ? formData . customDomain : optionName // Use customDomain if 'Other' domain is selected
92+ optionName :
93+ categoryName === "Domain" && optionName === "Other"
94+ ? formData . customDomain
95+ : optionName ,
9696 } ) ) ;
9797
9898 const projectData = {
@@ -101,20 +101,35 @@ const AddProjectPage = () => {
101101 projectLink : formData . projectLink ,
102102 createdAt : new Date ( ) . toISOString ( ) ,
103103 members : filteredMembers ,
104- projectCategoryOptions, // Send as a generic array of category options
105- customDomain : formData . selectedCategoryOptions [ 'Domain' ] === 'Other' ? formData . customDomain : undefined , // Send customDomain separately
104+ projectCategoryOptions,
105+ customDomain :
106+ formData . selectedCategoryOptions [ "Domain" ] === "Other"
107+ ? formData . customDomain
108+ : undefined ,
106109 } ;
107110
108111 try {
112+ const user = auth . currentUser ;
113+ if ( ! user ) {
114+ alert ( "You must be logged in to submit a project." ) ;
115+ setLoading ( false ) ;
116+ return ;
117+ }
118+
119+ const idToken = await user . getIdToken ( ) ;
120+ document . cookie = `__session=${ idToken } ; path=/;` ;
121+
109122 const response = await fetch ( "/api/projects" , {
110123 method : "POST" ,
111- headers : { "Content-Type" : "application/json" } ,
112- body : JSON . stringify ( projectData )
124+ headers : {
125+ "Content-Type" : "application/json" ,
126+ } ,
127+ body : JSON . stringify ( projectData ) ,
113128 } ) ;
114129
115130 if ( response . ok ) {
116- localStorage . removeItem ( ' cachedProjects' ) ; // Invalidate projects cache
117- setFormData ( initialFormState ) ; // Reset form
131+ localStorage . removeItem ( " cachedProjects" ) ;
132+ setFormData ( initialFormState ) ;
118133 setShowPopup ( true ) ;
119134 setTimeout ( ( ) => setShowPopup ( false ) , 3000 ) ;
120135 } else {
@@ -156,7 +171,7 @@ const AddProjectPage = () => {
156171 const addMember = ( ) => {
157172 setFormData ( {
158173 ...formData ,
159- members : [ ...formData . members , { name : "" , linkedin : "" } ]
174+ members : [ ...formData . members , { name : "" , linkedin : "" } ] ,
160175 } ) ;
161176 } ;
162177
@@ -174,7 +189,11 @@ const AddProjectPage = () => {
174189 }
175190
176191 if ( errorCategories ) {
177- return < div className = "text-center py-8 text-red-500" > Error loading form data: { errorCategories } </ div > ;
192+ return (
193+ < div className = "text-center py-8 text-red-500" >
194+ Error loading form data: { errorCategories }
195+ </ div >
196+ ) ;
178197 }
179198
180199 return (
@@ -188,24 +207,9 @@ const AddProjectPage = () => {
188207 </ div >
189208 </ div >
190209
191- { /* Pop-up Message */ }
192210 { showPopup && (
193- < div
194- style = { {
195- position : "fixed" ,
196- top : "20%" ,
197- left : "50%" ,
198- transform : "translateX(-50%)" ,
199- backgroundColor : "#4CAF50" ,
200- color : "white" ,
201- padding : "20px" ,
202- borderRadius : "10px" ,
203- fontSize : "20px" ,
204- fontWeight : "bold" ,
205- animation : "popIn 0.6s ease-in-out"
206- } }
207- >
208- 🎉 Congratulations! Your project was saved successfully! 🎉
211+ < div className = "fixed top-20 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-4 rounded-lg shadow-lg z-50" >
212+ 🎉 Congratulations! Your project was saved successfully!
209213 </ div >
210214 ) }
211215
@@ -232,37 +236,39 @@ const AddProjectPage = () => {
232236 onChange = { handleChange }
233237 value = { formData . projectDescription }
234238 />
235-
236- { /* Dynamic Category Selects */ }
237- { categories . length > 0 && categories . map ( category => (
239+
240+ { categories . length > 0 && categories . map ( ( category ) => (
238241 < div key = { category . categoryId } className = "mb-4" >
239- < label htmlFor = { `category- ${ category . categoryName } ` } className = "block text-sm font-medium text-gray-700 " >
242+ < label className = "block mb-1 text-sm font-medium" >
240243 { category . categoryName }
241244 </ label >
242245 < select
243- id = { `category-${ category . categoryName } ` }
246+ id = { `category-${ category . categoryName } ` }
244247 name = { `category-${ category . categoryName } ` }
245248 required
246249 className = "w-full px-4 py-2 border rounded-lg"
247250 onChange = { handleChange }
248- value = { formData . selectedCategoryOptions [ category . categoryName ] || '' }
251+ value = {
252+ formData . selectedCategoryOptions [ category . categoryName ] || ""
253+ }
249254 >
250255 { category . options . map ( ( option ) => (
251256 < option key = { option . optionId } value = { option . optionName } >
252257 { option . optionName }
253258 </ option >
254259 ) ) }
255260 </ select >
256- { category . categoryName === "Domain" && formData . selectedCategoryOptions [ "Domain" ] === "Other" && (
257- < input
258- type = "text"
259- name = "customDomain"
260- className = "mt-2 w-full px-4 py-2 border rounded-lg"
261- placeholder = "Enter custom domain"
262- onChange = { handleChange }
263- value = { formData . customDomain }
264- />
265- ) }
261+ { category . categoryName === "Domain" &&
262+ formData . selectedCategoryOptions [ "Domain" ] === "Other" && (
263+ < input
264+ type = "text"
265+ name = "customDomain"
266+ className = "mt-2 w-full px-4 py-2 border rounded-lg"
267+ placeholder = "Enter custom domain"
268+ onChange = { handleChange }
269+ value = { formData . customDomain }
270+ />
271+ ) }
266272 </ div >
267273 ) ) }
268274
@@ -271,12 +277,11 @@ const AddProjectPage = () => {
271277 name = "projectLink"
272278 required
273279 className = "w-full px-4 py-2 border rounded-lg"
274- placeholder = "Github link or google drive link of project contents "
280+ placeholder = "Project Link (e.g. GitHub) "
275281 onChange = { handleChange }
276282 value = { formData . projectLink }
277283 />
278284
279- { /* Members Section */ }
280285 { formData . members . map ( ( member , index ) => (
281286 < div key = { index } className = "flex items-center gap-2" >
282287 < input
0 commit comments