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
223 changes: 49 additions & 174 deletions src/pages/Profile.js
Original file line number Diff line number Diff line change
@@ -1,187 +1,62 @@
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import axiosInstance from "../utils/axiosInstance";
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom"; // Import useNavigate for routing

export default function Profile() {
const [userData, setUserData] = useState(null);
const [error, setError] = useState("");
const [isEditing, setIsEditing] = useState({ username: false, email: false });
const [newValues, setNewValues] = useState({ username: "", email: "", password: "" });
const [isResettingPassword, setIsResettingPassword] = useState(false); // ✅ Added
const [resetMessage, setResetMessage] = useState(""); // ✅ Added
const Profile = () => {
const navigate = useNavigate();

const [userProfile, setUserProfile] = useState({
name: "Test User",
email: "test@example.com",
});
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// Simulate loading state (mock API call)
useEffect(() => {
const fetchUserProfile = async () => {
try {
const response = await axiosInstance.get("user-profile/");
setUserData(response.data);
setNewValues({ username: response.data.username, email: response.data.email, password: "" });
} catch (error) {
console.error("Error fetching user profile:", error);
setError("You must be logged in to view this page.");
setTimeout(() => navigate("/login"), 2000);
}
};

fetchUserProfile();
}, [navigate]);

// ✅ Handle Reset Password Request (Similar to Forgot Password)
const handleResetPassword = async () => {
if (!userData?.email) {
setResetMessage("No email found. Please update your profile.");
return;
}

setIsResettingPassword(true); // Show loading state

try {
await axiosInstance.post("forgot-password/", { email: userData.email });

setResetMessage("Password reset instructions sent to your email.");
} catch (error) {
console.error("Error requesting password reset:", error);
setResetMessage("Failed to send reset email. Please try again.");
} finally {
setIsResettingPassword(false); // Hide loading state
}
};

// ✅ Handle input change
const handleChange = (field, value) => {
setNewValues((prev) => ({ ...prev, [field]: value }));
setLoading(true);
setTimeout(() => {
setLoading(false);
}, 1000); // Simulating API delay
}, []);

// Handle save changes (navigates back to homepage)
const handleSave = () => {
alert("Profile updated successfully.");
navigate("/"); // Navigate to homepage after saving
};

// ✅ Handle save changes
const handleSave = async () => {
if (!newValues.password) {
alert("Please enter your password to confirm changes.");
return;
}

try {
const response = await axiosInstance.put("update-profile/", {
username: newValues.username,
email: newValues.email,
password: newValues.password,
});

setUserData(response.data);
setIsEditing({ username: false, email: false });
setNewValues((prev) => ({ ...prev, password: "" })); // Clear password after update
alert("Profile updated successfully!");
} catch (error) {
console.error("Error updating profile:", error);
alert(error.response?.data?.password || "Failed to update profile. Please try again.");
}
};
if (loading) {
return <div>Loading profile...</div>;
}

return (
<div className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-b from-white to-red-300">
<div className="bg-white shadow-lg rounded-lg p-8 w-96 text-left">
<h2 className="text-2xl font-bold mb-6">User Profile</h2>

{error ? (
<p className="text-red-600">{error}</p>
) : userData ? (
<>
{/* ✅ Editable Username with input below */}
<div className="mb-4">
<p className="text-lg"><strong>Username:</strong> {userData.username}</p>
{isEditing.username ? (
<input
type="text"
value={newValues.username}
onChange={(e) => handleChange("username", e.target.value)}
className="border px-2 py-1 rounded w-full mt-2"
/>
) : null}
<button
className="text-blue-600 hover:underline text-sm mt-1"
onClick={() => setIsEditing((prev) => ({ ...prev, username: !prev.username }))}>
{isEditing.username ? "Cancel" : "Edit Username"}
</button>
</div>

{/* ✅ Editable Email with input below */}
<div className="mb-4">
<p className="text-lg"><strong>Email:</strong> {userData.email || "Not Available"}</p>
{isEditing.email ? (
<input
type="email"
value={newValues.email}
onChange={(e) => handleChange("email", e.target.value)}
className="border px-2 py-1 rounded w-full mt-2"
/>
) : null}
<button
className="text-blue-600 hover:underline text-sm mt-1"
onClick={() => setIsEditing((prev) => ({ ...prev, email: !prev.email }))}>
{isEditing.email ? "Cancel" : "Edit Email"}
</button>
</div>
<div className="profile-container bg-white text-red-900 flex flex-col items-center justify-center min-h-screen">
<h2 className="text-4xl font-bold mb-6 text-center">User Profile</h2>

{/* ✅ Password Confirmation Field (Required before saving) */}
{(isEditing.username || isEditing.email) && (
<div className="mb-4">
<p className="text-lg"><strong>Enter Password to Confirm:</strong></p>
<input
type="password"
value={newValues.password}
onChange={(e) => handleChange("password", e.target.value)}
className="border px-2 py-1 rounded w-full mt-2"
placeholder="Enter your password"
/>
</div>
)}
{error && <p className="text-red-600">{error}</p>}

{/* ✅ Save Changes Button (Only appears if editing) */}
{(isEditing.username || isEditing.email) && (
<button
onClick={handleSave}
className="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 w-full mt-3"
>
Save Changes
</button>
)}

{/* ✅ Action Buttons (Swapped Positions) */}
<div className="flex items-center justify-between mt-6">
{/* ✅ Reset Password Button (Now on the Left) */}
<button
onClick={handleResetPassword}
disabled={isResettingPassword}
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 flex items-center"
>
{isResettingPassword ? (
<>
<svg className="animate-spin h-4 w-4 mr-2 border-2 border-white border-t-transparent rounded-full" viewBox="0 0 24 24"></svg>
Sending...
</>
) : (
"Reset Password"
)}
</button>

{/* ✅ Homepage Link (Now on the Right) */}
<button
onClick={() => navigate("/")}
className="text-red-600 hover:underline text-sm"
>
Go to Homepage
</button>
</div>
<div className="text-center">
<p className="text-3xl mb-4"><strong>Name:</strong> {userProfile.name}</p>
<p className="text-3xl mb-4"><strong>Email:</strong> {userProfile.email}</p>
</div>

{/* ✅ Show Reset Message Below Buttons (Only If Exists) */}
{resetMessage && (
<p className="text-center text-green-600 mt-3 animate-fadeIn">{resetMessage}</p>
)}
</>
) : (
<p>Loading profile...</p>
)}
<div className="flex justify-center mt-6 space-x-4">
{/* Link to Forgot Password page */}
<button
onClick={() => navigate("/forgot-password")}
className="bg-red-600 hover:bg-red-700 text-white py-2 px-6 rounded"
>
Reset Password
</button>

<button
onClick={handleSave}
className="bg-red-600 hover:bg-red-700 text-white py-2 px-6 rounded"
>
Save Changes
</button>
</div>
</div>
);
}
};

export default Profile;