Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 143 additions & 88 deletions src/Pages/Profile.jsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,56 @@
import { useEffect, useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/Components/ui/card";
import { Input } from "@/Components/ui/input";
import { Label } from "@/Components/ui/label";
import { Avatar } from "@/Components/ui/avatar";
import { Button } from "@/Components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Avatar } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { SideNav, Navbar } from "../Components/compIndex";
import axios from "axios";
import { useNavigate } from "react-router-dom";

export default function AccountDetails() {
const [user, setUser] = useState(null); // Holds raw API response
const [loading, setLoading] = useState(true); // Loading state for API call
const [saveStatus, setSaveStatus] = useState(""); // Status after save attempt
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [saveStatus, setSaveStatus] = useState("");
const [formDetails, setFormDetails] = useState({
fullName: "",
email: "",
studying: "",
currentRole: "",
githubLink: "",
linkedinLink: "",
phoneNumber: "",
countryCode: "+1", // Default country code
profilePicture: "",
bio: "", // New field for user bio
});
const [profilePreview, setProfilePreview] = useState(null);

// Fetch user details and set form state
useEffect(() => {
const fetchUserProfile = async () => {
try {
const response = await axios.get(
`${import.meta.env.VITE_BASE_URL}/api/auth/user/${localStorage.getItem(
"userId"
)}`
`${import.meta.env.VITE_BASE_URL}/api/auth/user/${localStorage.getItem("userId")}`
);
const data = response.data;

setUser(data); // Set raw user data
setUser(data);
setFormDetails({
fullName: data.name || "",
email: data.email || "",
studying: "", // Field not in API response
studying: data.studying || "",
currentRole: data.role || "",
githubLink: data.githubLink || "",
linkedinLink: data.linkedinLink || "",
phoneNumber: data.mnumber?.toString() || "",
countryCode: data.countryCode || "+1",
profilePicture: data.profilePicture || "",
bio: data.bio || "",
});
setProfilePreview(data.profilePicture || null);
} catch (error) {
console.error(`Error fetching user details: ${error}`);
} finally {
setLoading(false); // Stop loading spinner
setLoading(false);
}
};

Expand All @@ -55,31 +59,33 @@ export default function AccountDetails() {

const navigate = useNavigate();

// Function to generate initials
const getInitials = (name) => {
const words = name?.trim().split(" ") || [];
if (words.length < 2) return words[0]?.[0]?.toUpperCase() || "";
return `${words[0][0]?.toUpperCase() || ""}${
words[1][0]?.toUpperCase() || ""
}`;
};

const handleInputChange = (field, value) => {
setFormDetails((prev) => ({ ...prev, [field]: value }));
};

const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
setProfilePreview(URL.createObjectURL(file));
setFormDetails((prev) => ({ ...prev, profilePicture: file }));
}
};

const handleSave = async () => {
setSaveStatus(""); // Reset save status
setSaveStatus("");
const formData = new FormData();
for (const [key, value] of Object.entries(formDetails)) {
formData.append(key, value);
}

try {
const response = await fetch("/api/save-account-details", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formDetails),
});

if (response.ok) {
const response = await axios.post(
`${import.meta.env.VITE_BASE_URL}/api/save-account-details`,
formData,
{ headers: { "Content-Type": "multipart/form-data" } }
);

if (response.status === 200) {
setSaveStatus("Details saved successfully!");
} else {
setSaveStatus("Failed to save changes. Please try again.");
Expand All @@ -95,9 +101,7 @@ export default function AccountDetails() {
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="flex flex-col items-center text-center space-y-4">
<div className="animate-spin rounded-full h-16 w-16 border-t-4 border-blue-600 border-opacity-75"></div>
<p className="text-lg font-medium text-gray-700">
Loading account details...
</p>
<p className="text-lg font-medium text-gray-700">Loading account details...</p>
</div>
</div>
);
Expand All @@ -110,71 +114,124 @@ export default function AccountDetails() {
<div className="min-h-screen bg-gray-50 flex items-center justify-center py-8 px-4">
<Card className="w-full max-w-4xl bg-white shadow-lg rounded-lg p-8">
<CardHeader className="text-center mb-6">
<CardTitle className="text-3xl font-bold text-gray-800">
Account Details
</CardTitle>
<p className="text-gray-500">
Manage your account information below.
</p>
<CardTitle className="text-3xl font-bold text-gray-800">Account Details</CardTitle>
<p className="text-gray-500">Manage your account information below.</p>
</CardHeader>
<CardContent className="space-y-8">
{/* Profile Photo Section */}
<div className="flex flex-col items-center">
<Avatar className="w-32 h-32 bg-gray-200 text-gray-600 flex items-center justify-center font-bold text-3xl rounded-full">
{getInitials(formDetails.fullName)}
<Avatar className="w-32 h-32 bg-gray-200 text-gray-600 flex items-center justify-center font-bold text-3xl rounded-full overflow-hidden">
{profilePreview ? (
<img src={profilePreview} alt="Profile" className="w-full h-full object-cover" />
) : (
formDetails.fullName
.split(" ")
.map((name) => name[0])
.join("")
)}
</Avatar>
<p className="mt-4 text-xl font-semibold text-gray-800">
{formDetails.fullName || "Your Name"}
</p>
<p className="text-gray-600">{formDetails.email}</p>
<label htmlFor="profile-upload" className="mt-4 cursor-pointer">
<span className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors">
Upload Profile Picture
</span>
<input
id="profile-upload"
type="file"
accept="image/*"
onChange={handleFileChange}
className="hidden"
/>
</label>
</div>

{/* Input Fields */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">
College Study Year
</Label>
<Label className="text-sm font-medium text-gray-700">Full Name</Label>
<Input
type="text"
value={formDetails.fullName}
onChange={(e) => handleInputChange("fullName", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>

<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">Email</Label>
<Input
type="email"
value={formDetails.email}
onChange={(e) => handleInputChange("email", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>

<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">College Study Year</Label>
<Input
type="text"
value={formDetails.studying}
placeholder="E.g., 2nd Year"
onChange={(e) =>
handleInputChange("studying", e.target.value)
}
onChange={(e) => handleInputChange("studying", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>

{/* Other Input Fields */}
{["currentRole", "githubLink", "linkedinLink", "phoneNumber"].map(
(key) => (
<div key={key} className="flex flex-col">
<Label className="text-sm font-medium text-gray-700 capitalize">
{key.replace(/([A-Z])/g, " $1").trim()}
</Label>
<Input
type="text"
value={formDetails[key]}
placeholder={`Enter your ${key
.replace(/([A-Z])/g, " $1")
.trim()}`}
onChange={(e) => handleInputChange(key, e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>
)
)}
</div>
<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">Current Role</Label>
<Input
type="text"
value={formDetails.currentRole}
onChange={(e) => handleInputChange("currentRole", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>

{/* Change Password Button */}
<div className="flex justify-center mt-4">
<Button
onClick={() => navigate("/reset-account-password")}
className="bg-yellow-500 text-white hover:bg-yellow-600"
>
Change Password
</Button>
<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">LinkedIn Profile</Label>
<Input
type="text"
value={formDetails.linkedinLink}
onChange={(e) => handleInputChange("linkedinLink", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>

<div className="flex flex-col">
<Label className="text-sm font-medium text-gray-700">Phone Number</Label>
<div className="flex mt-2">
<Select
value={formDetails.countryCode}
onValueChange={(value) => handleInputChange("countryCode", value)}
>
<SelectTrigger className="w-[100px]">
<SelectValue placeholder="Code" />
</SelectTrigger>
<SelectContent>
<SelectItem value="+1">+1 (US)</SelectItem>
<SelectItem value="+44">+44 (UK)</SelectItem>
<SelectItem value="+91">+91 (IN)</SelectItem>
{/* Add more country codes as needed */}
</SelectContent>
</Select>
<Input
type="tel"
value={formDetails.phoneNumber}
onChange={(e) => handleInputChange("phoneNumber", e.target.value)}
className="flex-1 ml-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md"
/>
</div>
</div>

<div className="flex flex-col col-span-2">
<Label className="text-sm font-medium text-gray-700">Bio</Label>
<textarea
value={formDetails.bio}
onChange={(e) => handleInputChange("bio", e.target.value)}
className="mt-2 bg-gray-50 border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 rounded-md h-24"
placeholder="Tell us about yourself..."
/>
</div>
</div>

{/* Save All Changes Button */}
Expand All @@ -189,9 +246,7 @@ export default function AccountDetails() {
{saveStatus && (
<p
className={`mt-4 text-sm ${
saveStatus.includes("successfully")
? "text-green-600"
: "text-red-600"
saveStatus.includes("successfully") ? "text-green-600" : "text-red-600"
}`}
>
{saveStatus}
Expand Down