Skip to content
Merged
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
53 changes: 30 additions & 23 deletions frontend/src/components/auth/SocialAuth.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { useAuth } from '../../context/AuthContext';
import { firebaseConfigured } from '../../config/firebase.js';

const GOOGLE_ICON = (
<svg width="18" height="18" viewBox="0 0 24 24">
Expand Down Expand Up @@ -41,30 +42,36 @@ export default function SocialAuth() {
<div className="flex-1 border-t border-surface-border" />
</div>

{error && (
<p className="text-sm text-red-500 mb-3 text-center">{error}</p>
)}
{!firebaseConfigured ? (
<p className="text-xs text-text-tertiary text-center">Social sign-in is not configured.</p>
) : (
<>
{error && (
<p className="text-sm text-red-500 mb-3 text-center">{error}</p>
)}

<div className="space-y-3">
<button
type="button"
onClick={() => handleProviderLogin('google')}
disabled={loadingProvider !== null}
className="w-full py-3 bg-surface text-text-primary text-sm font-medium rounded-lg border border-surface-border hover:bg-surface-secondary transition-colors flex items-center justify-center gap-3 disabled:opacity-60 disabled:cursor-not-allowed"
>
{GOOGLE_ICON}
{loadingProvider === 'google' ? 'Signing in...' : 'Continue with Google'}
</button>
<button
type="button"
onClick={() => handleProviderLogin('github')}
disabled={loadingProvider !== null}
className="w-full py-3 bg-surface text-text-primary text-sm font-medium rounded-lg border border-surface-border hover:bg-surface-secondary transition-colors flex items-center justify-center gap-3 disabled:opacity-60 disabled:cursor-not-allowed"
>
{GITHUB_ICON}
{loadingProvider === 'github' ? 'Signing in...' : 'Continue with GitHub'}
</button>
</div>
<div className="space-y-3">
<button
type="button"
onClick={() => handleProviderLogin('google')}
disabled={loadingProvider !== null}
className="w-full py-3 bg-surface text-text-primary text-sm font-medium rounded-lg border border-surface-border hover:bg-surface-secondary transition-colors flex items-center justify-center gap-3 disabled:opacity-60 disabled:cursor-not-allowed"
>
{GOOGLE_ICON}
{loadingProvider === 'google' ? 'Signing in...' : 'Continue with Google'}
</button>
<button
type="button"
onClick={() => handleProviderLogin('github')}
disabled={loadingProvider !== null}
className="w-full py-3 bg-surface text-text-primary text-sm font-medium rounded-lg border border-surface-border hover:bg-surface-secondary transition-colors flex items-center justify-center gap-3 disabled:opacity-60 disabled:cursor-not-allowed"
>
{GITHUB_ICON}
{loadingProvider === 'github' ? 'Signing in...' : 'Continue with GitHub'}
</button>
</div>
</>
)}
</div>
);
}
12 changes: 10 additions & 2 deletions frontend/src/config/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ import { getAuth, GoogleAuthProvider, GithubAuthProvider } from 'firebase/auth';

const getMeta = (name) => document.querySelector(`meta[name="${name}"]`)?.content || '';

const app = initializeApp({
const firebaseConfig = {
apiKey: import.meta.env.VITE_FIREBASE_API_KEY || getMeta('fb-api-key'),
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || getMeta('fb-auth-domain'),
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || getMeta('fb-project-id'),
});
};

export const firebaseConfigured = !!(firebaseConfig.apiKey && firebaseConfig.authDomain && firebaseConfig.projectId);

if (import.meta.env.DEV && !firebaseConfigured) {
console.warn('[Firebase] Missing env vars: VITE_FIREBASE_API_KEY, VITE_FIREBASE_AUTH_DOMAIN, VITE_FIREBASE_PROJECT_ID. Social sign-in will not work.');
}

const app = initializeApp(firebaseConfig);

export const auth = getAuth(app);
export const providers = {
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/context/AuthContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,23 @@ export function AuthProvider({ children }) {
dispatch({ type: 'AUTH_SUCCESS', payload: data.user });
} catch (err) {
await firebaseSignOut(auth).catch(() => {});
let message = err.message;
if (err.code === 'auth/cancelled-popup-request') {
dispatch({ type: 'LOADING' });
return;
}
let message = 'Sign-in failed. Please try again.';
if (err.code === 'auth/account-exists-with-different-credential') {
const other = providerName === 'google' ? 'GitHub' : 'Google';
message = `An account with this email already exists. Try signing in with ${other} instead.`;
} else if (err.code === 'auth/popup-blocked') {
message = 'Sign-in popup was blocked by your browser. Please allow popups for this site and try again.';
} else if (err.code === 'auth/popup-closed-by-user') {
message = 'Sign-in window was closed. If this keeps happening, check that your browser allows popups for this site.';
} else if (err.code === 'auth/unauthorized-domain') {
message = 'This domain is not authorized for sign-in. Add the deployment URL to Firebase Console → Authentication → Authorized domains.';
}
dispatch({ type: 'AUTH_ERROR', payload: message });
throw err;
throw new Error(message);
}
}, []);

Expand Down
Loading