146 lines
4.0 KiB
TypeScript
146 lines
4.0 KiB
TypeScript
/**
|
|
* @license
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { useEffect, useState } from "react";
|
|
import type { Session } from "@supabase/supabase-js";
|
|
import { AnimatePresence, motion } from "motion/react";
|
|
import { LoginScreen } from "./components/LoginScreen";
|
|
import { PortalPrincipal } from "./components/PortalPrincipal";
|
|
import { ALLOWED_EMAILS, isAllowedEmail } from "./lib/auth";
|
|
import { isSupabaseConfigured, supabase } from "./lib/supabase";
|
|
|
|
export default function App() {
|
|
const [session, setSession] = useState<Session | null>(null);
|
|
const [isLoadingSession, setIsLoadingSession] = useState(true);
|
|
const [authError, setAuthError] = useState("");
|
|
|
|
const validateAndSetSession = async (currentSession: Session | null) => {
|
|
const email = currentSession?.user?.email;
|
|
|
|
if (!currentSession) {
|
|
setSession(null);
|
|
return;
|
|
}
|
|
|
|
if (!isAllowedEmail(email)) {
|
|
setSession(null);
|
|
setAuthError(
|
|
"Este correo no tiene acceso al portal. Usa ymadera@gomezleemarketing.com o iaracena@gomezleemarketing.com."
|
|
);
|
|
await supabase?.auth.signOut();
|
|
return;
|
|
}
|
|
|
|
setAuthError("");
|
|
setSession(currentSession);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!isSupabaseConfigured || !supabase) {
|
|
setAuthError("Falta configurar Supabase en el archivo .env.local.");
|
|
setIsLoadingSession(false);
|
|
return;
|
|
}
|
|
|
|
let isMounted = true;
|
|
|
|
supabase.auth.getSession().then(async ({ data, error }) => {
|
|
if (!isMounted) return;
|
|
|
|
if (error) {
|
|
setAuthError("No se pudo validar la sesión. Intenta iniciar sesión nuevamente.");
|
|
setSession(null);
|
|
} else {
|
|
await validateAndSetSession(data.session);
|
|
}
|
|
|
|
setIsLoadingSession(false);
|
|
});
|
|
|
|
const { data: listener } = supabase.auth.onAuthStateChange(async (_event, currentSession) => {
|
|
await validateAndSetSession(currentSession);
|
|
setIsLoadingSession(false);
|
|
});
|
|
|
|
return () => {
|
|
isMounted = false;
|
|
listener.subscription.unsubscribe();
|
|
};
|
|
}, []);
|
|
|
|
const handleLogin = async () => {
|
|
setAuthError("");
|
|
|
|
if (!isSupabaseConfigured || !supabase) {
|
|
setAuthError("Falta configurar VITE_SUPABASE_URL y VITE_SUPABASE_ANON_KEY en .env.local.");
|
|
return;
|
|
}
|
|
|
|
const redirectTo = `${window.location.origin}${import.meta.env.BASE_URL}`;
|
|
|
|
const { error } = await supabase.auth.signInWithOAuth({
|
|
provider: "google",
|
|
options: {
|
|
redirectTo,
|
|
},
|
|
});
|
|
|
|
if (error) {
|
|
setAuthError("No se pudo iniciar sesión con Google. Revisa la configuración de Supabase Auth.");
|
|
}
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
setAuthError("");
|
|
await supabase?.auth.signOut();
|
|
setSession(null);
|
|
};
|
|
|
|
if (isLoadingSession) {
|
|
return (
|
|
<div className="min-h-screen bg-[#f5f3f3] flex items-center justify-center text-[#365c71] text-sm font-semibold">
|
|
Validando sesión...
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const isLoggedIn = Boolean(session && isAllowedEmail(session.user.email));
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[#fbf9f8]" id="app-container">
|
|
<AnimatePresence mode="wait">
|
|
{!isLoggedIn ? (
|
|
<motion.div
|
|
key="login"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="w-full h-full"
|
|
>
|
|
<LoginScreen
|
|
onLogin={handleLogin}
|
|
authError={authError}
|
|
isSupabaseConfigured={isSupabaseConfigured}
|
|
allowedEmails={ALLOWED_EMAILS}
|
|
/>
|
|
</motion.div>
|
|
) : (
|
|
<motion.div
|
|
key="portal"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="w-full h-full"
|
|
>
|
|
<PortalPrincipal onLogout={handleLogout} userEmail={session?.user.email ?? ""} />
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
}
|