Skip to content

Commit 706cbc6

Browse files
some proble occured in the form data i fixed it
1 parent 7ccec63 commit 706cbc6

File tree

1 file changed

+205
-36
lines changed

1 file changed

+205
-36
lines changed

app/add-project/page.tsx

Lines changed: 205 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import { ArrowLeft, Save, XCircle } from "lucide-react";
55
import Link from "next/link";
66

77
const submissionYears = [2025, 2024, 2023, 2022, 2021];
8-
const projectTypes = ["Final Year Project", "Mini Project", "Research Project", "Personal Project", "Others"];
8+
const projectTypes = [
9+
"Final Year Project",
10+
"Mini Project",
11+
"Research Project",
12+
"Personal Project",
13+
"Others"
14+
];
915
const departments = ["CSE", "IT", "ECE", "EEE", "MECH", "CIVIL", "Other"];
1016
const availableDomains = [
1117
"Other",
@@ -83,55 +89,70 @@ const AddProjectPage = () => {
8389
projectName: "",
8490
projectDescription: "",
8591
yearOfSubmission: "2025",
86-
projectType: "Personal Project",
92+
projectType: "Personal project",
8793
department: "",
8894
domain: "Web Development",
8995
customDomain: "",
9096
projectLink: "",
91-
members: [{ name: "", linkedin: "" }],
97+
members: [{ name: "", linkedin: "" }]
9298
};
9399

94100
const [formData, setFormData] = useState(initialFormState);
95-
const [loading, setLoading] = useState(false); // Prevents duplicate submissions
96-
const [showPopup, setShowPopup] = useState(false);
101+
const [showPopup, setShowPopup] = useState(false); // State for pop-up visibility
102+
const [loading, setLoading] = useState(false); // Loading state to prevent duplicate submissions
97103

98104
const handleSubmit = async (e: React.FormEvent) => {
99105
e.preventDefault();
100106
if (loading) return; // Prevent multiple submissions
101-
setLoading(true);
102107

103-
const hasValidMember = formData.members.some(member => member.name.trim() !== "");
108+
// Ensure at least one member has a name
109+
const hasValidMember = formData.members.some(
110+
(member) => member.name.trim() !== ""
111+
);
104112
if (!hasValidMember) {
105113
alert("Please enter at least one member name.");
106-
setLoading(false);
107114
return;
108115
}
109116

110-
const filteredMembers = formData.members.filter(member => member.name.trim() !== "");
111-
const projectData = { ...formData, members: filteredMembers, createdAt: new Date().toISOString() };
117+
setLoading(true); // Begin submission
118+
119+
// Filter out empty members
120+
const filteredMembers = formData.members.filter(
121+
(member) => member.name.trim() !== ""
122+
);
123+
124+
const projectData = {
125+
...formData,
126+
members: filteredMembers,
127+
createdAt: new Date().toISOString()
128+
};
112129

113130
try {
114131
const response = await fetch("/api/saveProject", {
115132
method: "POST",
116133
headers: { "Content-Type": "application/json" },
117-
body: JSON.stringify(projectData),
134+
body: JSON.stringify(projectData)
118135
});
119136

120137
if (response.ok) {
121138
setFormData(initialFormState);
122-
setShowPopup(true);
123-
setTimeout(() => setShowPopup(false), 3000);
139+
setShowPopup(true); // Show the congratulatory pop-up
140+
setTimeout(() => setShowPopup(false), 3000); // Hide it after 3 seconds
124141
} else {
125142
alert("Failed to save project.");
126143
}
127144
} catch (error) {
128145
console.error("Error saving project:", error);
129146
} finally {
130-
setLoading(false); // Re-enable button
147+
setLoading(false); // End submission
131148
}
132149
};
133150

134-
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
151+
const handleChange = (
152+
e: React.ChangeEvent<
153+
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
154+
>
155+
) => {
135156
const { name, value } = e.target;
136157
setFormData((prev) => ({ ...prev, [name]: value }));
137158
};
@@ -143,7 +164,10 @@ const AddProjectPage = () => {
143164
};
144165

145166
const addMember = () => {
146-
setFormData({ ...formData, members: [...formData.members, { name: "", linkedin: "" }] });
167+
setFormData({
168+
...formData,
169+
members: [...formData.members, { name: "", linkedin: "" }]
170+
});
147171
};
148172

149173
const removeMember = (index: number) => {
@@ -166,49 +190,194 @@ const AddProjectPage = () => {
166190
</div>
167191
</div>
168192

193+
{/* Pop-up Message */}
169194
{showPopup && (
170-
<div className="fixed top-20 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-3 rounded-lg text-lg font-bold">
171-
🎉 Project saved successfully! 🎉
195+
<div
196+
style={{
197+
position: "fixed",
198+
top: "20%",
199+
left: "50%",
200+
transform: "translateX(-50%)",
201+
backgroundColor: "#4CAF50",
202+
color: "white",
203+
padding: "20px",
204+
borderRadius: "10px",
205+
fontSize: "20px",
206+
fontWeight: "bold",
207+
animation: "popIn 0.6s ease-in-out"
208+
}}
209+
>
210+
🎉 Congratulations! Your project was saved successfully! 🎉
172211
</div>
173212
)}
174213

175214
<div className="max-w-3xl mx-auto px-4 py-8">
176-
<form onSubmit={handleSubmit} className="bg-white rounded-xl shadow-lg p-6 space-y-6">
177-
<input type="text" name="projectName" required className="w-full px-4 py-2 border rounded-lg" placeholder="Project Name" onChange={handleChange} value={formData.projectName} />
178-
<textarea name="projectDescription" required rows={4} className="w-full px-4 py-2 border rounded-lg" placeholder="Project Description" onChange={handleChange} value={formData.projectDescription} />
179-
<select name="yearOfSubmission" required className="w-full px-4 py-2 border rounded-lg" onChange={handleChange} value={formData.yearOfSubmission}>
180-
{submissionYears.map((year) => (<option key={year} value={year}>{year}</option>))}
215+
<form
216+
onSubmit={handleSubmit}
217+
className="bg-white rounded-xl shadow-lg p-6 space-y-6"
218+
>
219+
<input
220+
type="text"
221+
name="projectName"
222+
required
223+
className="w-full px-4 py-2 border rounded-lg"
224+
placeholder="Project Name"
225+
onChange={handleChange}
226+
value={formData.projectName}
227+
/>
228+
<textarea
229+
name="projectDescription"
230+
required
231+
rows={4}
232+
className="w-full px-4 py-2 border rounded-lg"
233+
placeholder="Project Description"
234+
onChange={handleChange}
235+
value={formData.projectDescription}
236+
/>
237+
<select
238+
name="yearOfSubmission"
239+
required
240+
className="w-full px-4 py-2 border rounded-lg"
241+
onChange={handleChange}
242+
value={formData.yearOfSubmission}
243+
>
244+
{submissionYears.map((year) => (
245+
<option key={year} value={year}>
246+
{year}
247+
</option>
248+
))}
181249
</select>
182-
<select name="projectType" required className="w-full px-4 py-2 border rounded-lg" onChange={handleChange} value={formData.projectType}>
183-
{projectTypes.map((type) => (<option key={type} value={type}>{type}</option>))}
250+
<select
251+
name="projectType"
252+
required
253+
className="w-full px-4 py-2 border rounded-lg"
254+
onChange={handleChange}
255+
value={formData.projectType}
256+
>
257+
{projectTypes.map((type) => (
258+
<option key={type} value={type}>
259+
{type}
260+
</option>
261+
))}
184262
</select>
185-
<select name="department" required className="w-full px-4 py-2 border rounded-lg" onChange={handleChange} value={formData.department}>
186-
{departments.map((dept) => (<option key={dept} value={dept}>{dept}</option>))}
263+
<select
264+
name="department"
265+
required
266+
className="w-full px-4 py-2 border rounded-lg"
267+
onChange={handleChange}
268+
value={formData.department}
269+
>
270+
{departments.map((dept) => (
271+
<option key={dept} value={dept}>
272+
{dept}
273+
</option>
274+
))}
187275
</select>
188-
<input type="url" name="projectLink" required className="w-full px-4 py-2 border rounded-lg" placeholder="Project Link" onChange={handleChange} value={formData.projectLink} />
276+
<select
277+
name="domain"
278+
required
279+
className="w-full px-4 py-2 border rounded-lg"
280+
onChange={handleChange}
281+
value={formData.domain}
282+
>
283+
{availableDomains.map((domain) => (
284+
<option key={domain} value={domain}>
285+
{domain}
286+
</option>
287+
))}
288+
</select>
289+
{formData.domain === "Other" && (
290+
<input
291+
type="text"
292+
name="customDomain"
293+
className="w-full px-4 py-2 border rounded-lg"
294+
placeholder="Enter custom domain"
295+
onChange={handleChange}
296+
value={formData.customDomain}
297+
/>
298+
)}
299+
<input
300+
type="url"
301+
name="projectLink"
302+
required
303+
className="w-full px-4 py-2 border rounded-lg"
304+
placeholder="Github link or google drive link of project contents"
305+
onChange={handleChange}
306+
value={formData.projectLink}
307+
/>
189308

309+
{/* Members Section */}
190310
{formData.members.map((member, index) => (
191311
<div key={index} className="flex items-center gap-2">
192-
<input type="text" className="px-4 py-2 border rounded-lg w-1/2" placeholder="Member Name" value={member.name} onChange={(e) => handleMemberChange(index, "name", e.target.value)} />
193-
<input type="url" className="px-4 py-2 border rounded-lg w-1/2" placeholder="LinkedIn Profile" value={member.linkedin} onChange={(e) => handleMemberChange(index, "linkedin", e.target.value)} disabled={!member.name.trim()} />
312+
<input
313+
type="text"
314+
className="px-4 py-2 border rounded-lg w-1/2"
315+
placeholder="Member Name"
316+
value={member.name}
317+
onChange={(e) =>
318+
handleMemberChange(index, "name", e.target.value)
319+
}
320+
/>
321+
<input
322+
type="url"
323+
className="px-4 py-2 border rounded-lg w-1/2"
324+
placeholder="LinkedIn Profile"
325+
value={member.linkedin}
326+
onChange={(e) =>
327+
handleMemberChange(index, "linkedin", e.target.value)
328+
}
329+
disabled={!member.name.trim()}
330+
/>
194331
{formData.members.length > 1 && (
195-
<button type="button" className="text-red-500" onClick={() => removeMember(index)}>
332+
<button
333+
type="button"
334+
className="text-red-500"
335+
onClick={() => removeMember(index)}
336+
>
196337
<XCircle className="h-6 w-6" />
197338
</button>
198339
)}
199340
</div>
200341
))}
201342

202-
<button type="button" className="w-full bg-gray-200 px-4 py-2 rounded-lg" onClick={addMember}>
343+
<button
344+
type="button"
345+
className="w-full bg-gray-200 px-4 py-2 rounded-lg"
346+
onClick={addMember}
347+
>
203348
Add Member
204349
</button>
205350

206351
<div className="flex gap-4">
207-
<button type="submit" className={`flex-1 bg-blue-600 text-white px-4 py-3 rounded-lg flex items-center justify-center ${loading ? "opacity-50 cursor-not-allowed" : ""}`} disabled={loading}>
208-
{loading ? <Save className="h-5 w-5 mr-2 animate-spin" /> : <Save className="h-5 w-5 mr-2" />}
209-
{loading ? "Saving..." : "Save Project"}
352+
<button
353+
type="submit"
354+
className={`flex-1 bg-blue-600 text-white px-4 py-3 rounded-lg flex items-center justify-center ${
355+
loading ||
356+
formData.members.every((m) => m.name.trim() === "")
357+
? "opacity-50 cursor-not-allowed"
358+
: ""
359+
}`}
360+
disabled={
361+
loading || formData.members.every((m) => m.name.trim() === "")
362+
}
363+
>
364+
{loading ? (
365+
<>
366+
<Save className="h-5 w-5 mr-2 animate-spin" />
367+
<span>Saving...</span>
368+
</>
369+
) : (
370+
<>
371+
<Save className="h-5 w-5 mr-2" />
372+
<span>Save Project</span>
373+
</>
374+
)}
210375
</button>
211-
<button type="button" className="flex-1 bg-red-500 text-white px-4 py-3 rounded-lg flex items-center justify-center" onClick={clearForm}>
376+
<button
377+
type="button"
378+
className="flex-1 bg-red-500 text-white px-4 py-3 rounded-lg flex items-center justify-center"
379+
onClick={clearForm}
380+
>
212381
<XCircle className="h-5 w-5 mr-2" />
213382
<span>Clear</span>
214383
</button>

0 commit comments

Comments
 (0)