Skip to content

Commit ff581e8

Browse files
committed
fix(edit-project): correct members type and resolve Netlify build error
1 parent 6aea1cf commit ff581e8

File tree

2 files changed

+144
-161
lines changed

2 files changed

+144
-161
lines changed

app/edit/[projectId]/page.tsx

Lines changed: 133 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,33 @@ import { ArrowLeft } from "lucide-react";
1010
export default function EditProjectPage() {
1111
const router = useRouter();
1212
const params = useParams();
13-
const projectId = params?.projectId;
13+
14+
const projectId =
15+
typeof params?.projectId === "string" ? params.projectId : undefined;
1416

1517
const [userToken, setUserToken] = useState<string | null>(null);
1618
const [categories, setCategories] = useState<Category[]>([]);
1719
const [project, setProject] = useState<Project | null>(null);
1820
const [loading, setLoading] = useState(true);
1921
const [error, setError] = useState<string | null>(null);
2022

23+
/* ------------------ AUTH ------------------ */
2124
useEffect(() => {
2225
const unsubscribe = onAuthStateChanged(auth, async (user) => {
23-
if (user) {
24-
const token = await user.getIdToken();
25-
setUserToken(token);
26-
} else {
26+
if (!user) {
2727
setError("You must be logged in to edit projects.");
2828
setLoading(false);
29+
return;
2930
}
31+
32+
const token = await user.getIdToken();
33+
setUserToken(token);
3034
});
35+
3136
return () => unsubscribe();
3237
}, []);
3338

39+
/* ------------------ FETCH DATA ------------------ */
3440
useEffect(() => {
3541
if (!userToken || !projectId) return;
3642

@@ -43,30 +49,36 @@ export default function EditProjectPage() {
4349
}),
4450
]);
4551

46-
if (!catRes.ok || !projRes.ok) throw new Error("Failed to fetch data");
52+
if (!catRes.ok || !projRes.ok) {
53+
throw new Error("Failed to fetch data");
54+
}
4755

48-
const categoriesData = await catRes.json();
56+
const categoriesData: Category[] = await catRes.json();
4957
const projectData = await projRes.json();
5058

5159
const selectedCategoryOptions: Record<string, string> = {};
52-
categoriesData.forEach((category: Category) => {
53-
const normalizedCategoryName = category.categoryName
54-
.trim()
55-
.toLowerCase();
60+
61+
categoriesData.forEach((category) => {
5662
const matched = projectData.categories?.find(
5763
(c: any) =>
58-
c.categoryName.trim().toLowerCase() === normalizedCategoryName
64+
c.categoryName.trim().toLowerCase() ===
65+
category.categoryName.trim().toLowerCase()
5966
);
67+
6068
selectedCategoryOptions[category.categoryName] =
6169
matched?.optionName || "";
6270
});
6371

6472
setCategories(categoriesData);
73+
6574
setProject({
6675
...projectData,
6776
createdAt: projectData.createdAt.split("T")[0],
6877
selectedCategoryOptions,
69-
members: projectData.members?.slice(0, 1) || [{ name: "" , linkedin: ""}],
78+
members:
79+
projectData.members?.slice(0, 1) || [
80+
{ name: "", linkedin: "" },
81+
],
7082
});
7183
} catch (err: any) {
7284
setError(err.message);
@@ -78,12 +90,14 @@ export default function EditProjectPage() {
7890
fetchData();
7991
}, [userToken, projectId]);
8092

93+
/* ------------------ HANDLE CHANGE ------------------ */
8194
const handleChange = (
8295
e: React.ChangeEvent<
8396
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
8497
>
8598
) => {
8699
if (!project) return;
100+
87101
const { name, value } = e.target;
88102

89103
if (name.startsWith("category-")) {
@@ -100,11 +114,20 @@ export default function EditProjectPage() {
100114
...project,
101115
members: [{ ...project.members[0], name: value }],
102116
});
117+
} else if (name === "contactLinkedIn") {
118+
setProject({
119+
...project,
120+
members: [{ ...project.members[0], linkedin: value }],
121+
});
103122
} else {
104-
setProject({ ...project, [name]: value });
123+
setProject({
124+
...project,
125+
[name]: value,
126+
});
105127
}
106128
};
107129

130+
/* ------------------ SUBMIT ------------------ */
108131
const handleSubmit = async (e: React.FormEvent) => {
109132
e.preventDefault();
110133
if (!project || !userToken) return;
@@ -128,181 +151,134 @@ export default function EditProjectPage() {
128151
},
129152
body: JSON.stringify(payload),
130153
});
154+
131155
if (!res.ok) throw new Error("Failed to update project");
156+
132157
router.push("/profile");
133158
} catch (err: any) {
134159
setError(err.message);
135160
}
136161
};
137162

138-
if (loading)
163+
/* ------------------ UI STATES ------------------ */
164+
if (loading) {
139165
return (
140166
<div className="min-h-screen flex items-center justify-center bg-white">
141167
<div className="text-center">
142-
<div className="w-12 h-12 border-4 border-blue-300 border-t-blue-600 rounded-full animate-spin mx-auto"></div>
168+
<div className="w-12 h-12 border-4 border-blue-300 border-t-blue-600 rounded-full animate-spin mx-auto" />
143169
<p className="mt-4 text-blue-700 font-medium">
144170
Loading your project...
145171
</p>
146172
</div>
147173
</div>
148174
);
175+
}
176+
177+
if (error) {
178+
return <div className="p-8 text-red-600 text-center">{error}</div>;
179+
}
149180

150-
if (error) return <div className="p-8 text-red-600 text-center">{error}</div>;
151-
if (!project) return <div className="p-8 text-center">Project not found</div>;
181+
if (!project) {
182+
return <div className="p-8 text-center">Project not found</div>;
183+
}
152184

185+
/* ------------------ FORM ------------------ */
153186
return (
154187
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-white flex items-center justify-center p-4">
155188
<div className="bg-white p-6 rounded-2xl shadow-xl max-w-3xl w-full max-h-[90vh] overflow-y-auto">
156-
{/* Back Button */}
157189
<button
158190
onClick={() => router.push("/profile")}
159-
className="flex items-center text-blue-600 hover:text-blue-800 transition-colors duration-200 mb-4"
191+
className="flex items-center text-blue-600 hover:text-blue-800 mb-4"
160192
>
161193
<ArrowLeft className="w-5 h-5 mr-2" />
162-
<span className="font-medium">Back to Profile</span>
194+
Back to Profile
163195
</button>
164196

165-
<h2 className="text-2xl font-bold mb-4 text-center text-blue-700">Edit Project</h2>
197+
<h2 className="text-2xl font-bold mb-4 text-center text-blue-700">
198+
Edit Project
199+
</h2>
200+
166201
<form onSubmit={handleSubmit} className="space-y-4">
167-
{/* Project Name */}
168-
<div>
169-
<label className="block text-sm font-medium text-gray-700">
170-
Project Name
171-
</label>
172-
<input
173-
type="text"
174-
name="projectName"
175-
value={project.projectName}
176-
onChange={handleChange}
177-
required
178-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
179-
/>
180-
</div>
181-
182-
{/* Project Description */}
183-
<div>
184-
<label className="block text-sm font-medium text-gray-700">
185-
Project Description
186-
</label>
187-
<textarea
188-
name="projectDescription"
189-
value={project.projectDescription || ""}
190-
onChange={handleChange}
191-
rows={3}
192-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
193-
/>
194-
</div>
195-
196-
{/* Single Member */}
197-
<div>
198-
<label className="block text-sm font-medium text-gray-700">
199-
Owner Name
200-
</label>
201-
<input
202-
type="text"
203-
name="memberName"
204-
value={project.members[0].name}
205-
onChange={handleChange}
206-
required
207-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
208-
/>
209-
</div>
210-
211-
{/* LinkedIn */}
212-
<div>
213-
<label htmlFor="contactLinkedIn" className="block text-sm font-medium text-gray-700">
214-
LinkedIn
215-
</label>
216-
<input
217-
type="text"
218-
id="contactLinkedIn"
219-
name="contactLinkedIn"
220-
value={project.members[0].linkedin || ""}
221-
onChange={handleChange}
222-
className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
223-
placeholder="LinkedIn profile link"
224-
/>
225-
</div>
226-
227-
{/* Project Link */}
228-
<div>
229-
<label className="block text-sm font-medium text-gray-700">
230-
Project Link
231-
</label>
232-
<input
233-
type="url"
234-
name="projectLink"
235-
value={project.projectLink || ""}
236-
onChange={handleChange}
237-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
238-
/>
239-
</div>
240-
241-
{/* Created At */}
242-
<div>
243-
<label className="block text-sm font-medium text-gray-700">
244-
Created At
245-
</label>
246-
<input
247-
type="date"
248-
name="createdAt"
249-
value={project.createdAt}
250-
onChange={handleChange}
251-
required
252-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
253-
/>
254-
</div>
202+
<input
203+
name="projectName"
204+
value={project.projectName}
205+
onChange={handleChange}
206+
required
207+
className="w-full border p-2 rounded"
208+
placeholder="Project Name"
209+
/>
210+
211+
<textarea
212+
name="projectDescription"
213+
value={project.projectDescription}
214+
onChange={handleChange}
215+
rows={3}
216+
className="w-full border p-2 rounded"
217+
placeholder="Description"
218+
/>
219+
220+
<input
221+
name="memberName"
222+
value={project.members[0].name}
223+
onChange={handleChange}
224+
required
225+
className="w-full border p-2 rounded"
226+
placeholder="Owner Name"
227+
/>
228+
229+
<input
230+
name="contactLinkedIn"
231+
value={project.members[0].linkedin}
232+
onChange={handleChange}
233+
className="w-full border p-2 rounded"
234+
placeholder="LinkedIn URL"
235+
/>
236+
237+
<input
238+
name="projectLink"
239+
value={project.projectLink}
240+
onChange={handleChange}
241+
className="w-full border p-2 rounded"
242+
placeholder="Project Link"
243+
/>
244+
245+
<input
246+
type="date"
247+
name="createdAt"
248+
value={project.createdAt}
249+
onChange={handleChange}
250+
required
251+
className="w-full border p-2 rounded"
252+
/>
255253

256-
{/* Categories */}
257254
{categories.map((category) => (
258-
<div key={category.categoryId}>
259-
<label className="block text-sm font-medium text-gray-700">
260-
{category.categoryName}
261-
</label>
262-
<select
263-
name={`category-${category.categoryName}`}
264-
value={project.selectedCategoryOptions[category.categoryName] || ""}
265-
onChange={handleChange}
266-
required
267-
className="mt-1 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
268-
>
269-
<option value="">Select a {category.categoryName}</option>
270-
{category.options.map((opt) => (
271-
<option key={opt.optionId} value={opt.optionName}>
272-
{opt.optionName}
273-
</option>
274-
))}
275-
</select>
276-
{category.categoryName === "Domain" &&
277-
project.selectedCategoryOptions["Domain"] === "Other" && (
278-
<input
279-
type="text"
280-
name="customDomain"
281-
value={project.customDomain || ""}
282-
onChange={handleChange}
283-
placeholder="Enter custom domain"
284-
required
285-
className="mt-2 block w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
286-
/>
287-
)}
288-
</div>
255+
<select
256+
key={category.categoryId}
257+
name={`category-${category.categoryName}`}
258+
value={
259+
project.selectedCategoryOptions[category.categoryName] || ""
260+
}
261+
onChange={handleChange}
262+
required
263+
className="w-full border p-2 rounded"
264+
>
265+
<option value="">
266+
Select {category.categoryName}
267+
</option>
268+
{category.options.map((opt) => (
269+
<option key={opt.optionId} value={opt.optionName}>
270+
{opt.optionName}
271+
</option>
272+
))}
273+
</select>
289274
))}
290275

291-
<div className="flex flex-col sm:flex-row justify-end space-y-2 sm:space-y-0 sm:space-x-4 mt-6">
292-
<button
293-
type="button"
294-
onClick={() => router.push("/profile")}
295-
className="bg-gray-300 text-gray-800 px-4 py-2 rounded-md hover:bg-gray-400 w-full sm:w-auto"
296-
>
297-
Cancel
298-
</button>
299-
<button
300-
type="submit"
301-
className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700"
302-
>
303-
Save Changes
304-
</button>
305-
</div>
276+
<button
277+
type="submit"
278+
className="bg-blue-600 text-white px-4 py-2 rounded w-full"
279+
>
280+
Save Changes
281+
</button>
306282
</form>
307283
</div>
308284
</div>

0 commit comments

Comments
 (0)