mirror of
https://github.com/cssgunc/compass.git
synced 2025-04-09 22:00:18 -04:00
add profile edit page
This commit is contained in:
parent
0c5f2decdd
commit
062dae1dbc
187
compass/app/profile/edit/page.tsx
Normal file
187
compass/app/profile/edit/page.tsx
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import User from "@/utils/models/User";
|
||||||
|
import { Program, Role } from "@/utils/models/User";
|
||||||
|
import { createClient } from "@/utils/supabase/client";
|
||||||
|
|
||||||
|
export default function EditProfile() {
|
||||||
|
const router = useRouter();
|
||||||
|
const [user, setUser] = useState<User | null>(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [success, setSuccess] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
try {
|
||||||
|
const supabase = await createClient();
|
||||||
|
const { data: { user: authUser }, error: authError } = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (authError || !authUser) {
|
||||||
|
throw new Error("Authentication required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`/api/user?uuid=${authUser.id}`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch user data");
|
||||||
|
}
|
||||||
|
const currentUser = await response.json();
|
||||||
|
|
||||||
|
if (!currentUser) {
|
||||||
|
throw new Error("User not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
setUser(currentUser);
|
||||||
|
} catch (err) {
|
||||||
|
setError("Failed to load user data");
|
||||||
|
console.error(err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUser();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const formData = new FormData(e.currentTarget);
|
||||||
|
const updatedUser = {
|
||||||
|
...user,
|
||||||
|
username: formData.get("username") as string,
|
||||||
|
email: formData.get("email") as string,
|
||||||
|
group: formData.get("group") as string,
|
||||||
|
experience: parseInt(formData.get("experience") as string),
|
||||||
|
program: formData.getAll("program") as Program[],
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(`/api/user/update?uuid=${user.uuid}`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(updatedUser),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to update profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
setSuccess(true);
|
||||||
|
} catch (err) {
|
||||||
|
setError("Failed to update profile");
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <div className="p-4">Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return <div className="p-4">User not found</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="max-w-2xl mx-auto p-4">
|
||||||
|
<h1 className="text-2xl font-bold mb-6">Edit Profile</h1>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{success && (
|
||||||
|
<div className="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
|
||||||
|
Profile updated successfully! Refreshing page...
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700">Username</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="username"
|
||||||
|
defaultValue={user.username}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700">Email</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
defaultValue={user.email}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700">Group</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="group"
|
||||||
|
defaultValue={user.group}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700">Experience (years)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="experience"
|
||||||
|
defaultValue={user.experience}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700">Programs</label>
|
||||||
|
<div className="mt-2 space-y-2">
|
||||||
|
{Object.values(Program).map((program) => (
|
||||||
|
<label key={program} className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="program"
|
||||||
|
value={program}
|
||||||
|
defaultChecked={user.program.includes(program)}
|
||||||
|
className="rounded border-gray-300 text-purple-600 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
|
/>
|
||||||
|
<span className="ml-2">{program}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end space-x-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => router.back()}
|
||||||
|
className="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
|
||||||
|
>
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user