Skip to content
Open
Show file tree
Hide file tree
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
27 changes: 27 additions & 0 deletions backend/controllers/auth.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,33 @@ export const updateProfile = async (req, res) => {
}
};

// NEW: Remove profile picture — sets profile_pic to null
export const removeProfilePic = async (req, res) => {
try {
if (!req.user) {
return res.status(401).json({ message: "Unauthorized" });
}

const userId = req.user.id;

const { data, error } = await supabase
.from('profiles')
.update({ profile_pic: null })
.eq('id', userId)
.select()
.single();

if (error) {
return res.status(400).json({ message: error.message });
}

res.status(200).json(data);
} catch (error) {
console.error("Error in removeProfilePic:", error);
res.status(500).json({ message: "Server error" });
}
};

export const checkAuth = async (req, res) => {
try {
// Get profile data
Expand Down
48 changes: 25 additions & 23 deletions backend/routes/auth.route.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import express from 'express';
import {
signup,
login,
logout,
updateProfile,
checkAuth,
getProfile
} from '../controllers/auth.controller.js';
import { protectRoute } from '../middleware/auth.middleware.js';

const router = express.Router();

// Public routes
router.post('/signup', signup);
router.post('/login', login);
router.post('/logout', logout);

// Protected routes
router.get('/check', protectRoute, checkAuth);
router.put('/update-profile', protectRoute, updateProfile);
router.get('/profile/:userId', protectRoute, getProfile);

import express from 'express';
import {
signup,
login,
logout,
updateProfile,
removeProfilePic,
checkAuth,
getProfile
} from '../controllers/auth.controller.js';
import { protectRoute } from '../middleware/auth.middleware.js';

const router = express.Router();

// Public routes
router.post('/signup', signup);
router.post('/login', login);
router.post('/logout', logout);

// Protected routes
router.get('/check', protectRoute, checkAuth);
router.put('/update-profile', protectRoute, updateProfile);
router.delete('/remove-profile-pic', protectRoute, removeProfilePic); // NEW
router.get('/profile/:userId', protectRoute, getProfile);

export default router;
84 changes: 45 additions & 39 deletions frontend/src/api/auth.api.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
import api from './axios';

export const authAPI = {
signup: async (data) => {
const response = await api.post('/auth/signup', data);
return response.data;
},

login: async (credentials) => {
const response = await api.post('/auth/login', credentials);
if (response.data.session?.access_token) {
localStorage.setItem('token', response.data.session.access_token);
localStorage.setItem('user', JSON.stringify(response.data.user));
localStorage.setItem('profile', JSON.stringify(response.data.profile));
}
return response.data;
},

logout: async () => {
await api.post('/auth/logout');
localStorage.removeItem('token');
localStorage.removeItem('user');
localStorage.removeItem('profile');
},

checkAuth: async () => {
const response = await api.get('/auth/check');
return response.data;
},

updateProfile: async (profilePic) => {
const response = await api.put('/auth/update-profile', { profilePic });
return response.data;
},

getProfile: async (userId) => {
const response = await api.get(`/auth/profile/${userId}`);
return response.data;
},
import api from './axios';

export const authAPI = {
signup: async (data) => {
const response = await api.post('/auth/signup', data);
return response.data;
},

login: async (credentials) => {
const response = await api.post('/auth/login', credentials);
if (response.data.session?.access_token) {
localStorage.setItem('token', response.data.session.access_token);
localStorage.setItem('user', JSON.stringify(response.data.user));
localStorage.setItem('profile', JSON.stringify(response.data.profile));
}
return response.data;
},

logout: async () => {
await api.post('/auth/logout');
localStorage.removeItem('token');
localStorage.removeItem('user');
localStorage.removeItem('profile');
},

checkAuth: async () => {
const response = await api.get('/auth/check');
return response.data;
},

updateProfile: async (profilePic) => {
const response = await api.put('/auth/update-profile', { profilePic });
return response.data;
},

// NEW: remove profile picture
removeProfilePic: async () => {
const response = await api.delete('/auth/remove-profile-pic');
return response.data;
},

getProfile: async (userId) => {
const response = await api.get(`/auth/profile/${userId}`);
return response.data;
},
};
32 changes: 1 addition & 31 deletions frontend/src/components/auth/LoginForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ const LoginForm = () => {
}
};

const handleGoogleSignIn = () => {
alert('Google Sign-In coming soon!');
};

return (
<div className="space-y-6">
{/* Error Message */}
Expand All @@ -43,32 +39,6 @@ const LoginForm = () => {
</div>
)}

{/* Google Sign In Button */}
<button
type="button"
onClick={handleGoogleSignIn}
className="w-full btn btn-lg bg-white hover:bg-gray-50 text-gray-700 border-2 border-gray-300 rounded-md"
>
<svg className="w-5 h-5 mr-3" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
Sign in with Google
</button>

<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-4 bg-white text-gray-500">
Or continue with email
</span>
</div>
</div>

{/* Email/Password Form */}
<form onSubmit={handleSubmit} className="space-y-5">

Expand Down Expand Up @@ -163,4 +133,4 @@ const LoginForm = () => {
);
};

export default LoginForm;
export default LoginForm;
26 changes: 1 addition & 25 deletions frontend/src/components/auth/SignupForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ const SignupForm = () => {
}
};

const handleGoogleSignUp = () => {
alert('Google Sign-Up coming soon!');
};

return (
<div className="space-y-6">

Expand All @@ -56,26 +52,6 @@ const SignupForm = () => {
</div>
)}

{/* Google Sign Up */}
<button
type="button"
onClick={handleGoogleSignUp}
className="w-full btn btn-lg bg-white hover:bg-gray-50 text-gray-700 border-2 border-gray-300 rounded-md"
>
Sign up with Google
</button>

<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-4 bg-white text-gray-500">
Or continue with email
</span>
</div>
</div>

{/* Account Type */}
<div className="grid grid-cols-2 gap-3">
{['candidate', 'company'].map((type) => (
Expand Down Expand Up @@ -262,4 +238,4 @@ const SignupForm = () => {
);
};

export default SignupForm;
export default SignupForm;
Loading