mirror of
https://github.com/marcogll/AnchorOS.git
synced 2026-03-15 16:24:30 +00:00
🚀 FASE 4 COMPLETADO: Comentarios auditables + Calendario funcional + Gestión staff/recursos
✅ COMENTARIOS AUDITABLES IMPLEMENTADOS: - 80+ archivos con JSDoc completo para auditoría manual - APIs críticas con validaciones business/security/performance - Componentes con reglas de negocio documentadas - Funciones core con edge cases y validaciones ✅ CALENDARIO MULTI-COLUMNA FUNCIONAL (95%): - Drag & drop con reprogramación automática - Filtros por sucursal/staff, tiempo real - Indicadores de conflictos y disponibilidad - APIs completas con validaciones de colisión ✅ GESTIÓN OPERATIVA COMPLETA: - CRUD staff: APIs + componente con validaciones - CRUD recursos: APIs + componente con disponibilidad - Autenticación completa con middleware seguro - Auditoría completa en todas las operaciones ✅ DOCUMENTACIÓN ACTUALIZADA: - TASKS.md: FASE 4 95% completado - README.md: Estado actual y funcionalidades - API.md: 40+ endpoints documentados ✅ SEGURIDAD Y VALIDACIONES: - RLS policies documentadas en comentarios - Business rules validadas manualmente - Performance optimizations anotadas - Error handling completo Próximos: Nómina/POS/CRM avanzado (FASE 4 final)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { User, Session } from '@supabase/supabase-js'
|
||||
import { supabase } from '@/lib/supabase/client'
|
||||
|
||||
@@ -16,38 +17,82 @@ type AuthContextType = {
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined)
|
||||
|
||||
/**
|
||||
* AuthProvider component that manages authentication state and provides it to children.
|
||||
* @description Authentication provider managing Supabase auth state and redirects
|
||||
* @param {Object} props - React children to render within auth context
|
||||
* @returns {JSX.Element} AuthContext provider with authentication state
|
||||
* @audit SECURITY: Handles session persistence and automatic refresh
|
||||
* @audit SECURITY: Implements bidirectional redirects (login ↔ protected routes)
|
||||
* @audit Validate: Session state synchronized with Supabase auth changes
|
||||
* @audit Validate: Protected routes redirect to login when unauthenticated
|
||||
* @audit PERFORMANCE: Auth state changes trigger immediate UI updates
|
||||
*/
|
||||
export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
const [session, setSession] = useState<Session | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const pathname = usePathname()
|
||||
|
||||
useEffect(() => {
|
||||
const getSession = async () => {
|
||||
const { data: { session }, error } = await supabase.auth.getSession()
|
||||
if (error) {
|
||||
console.error('Error getting session:', error)
|
||||
const checkSession = async () => {
|
||||
try {
|
||||
const { data: { session }, error } = await supabase.auth.getSession()
|
||||
if (error) {
|
||||
console.error('Error getting session:', error)
|
||||
// If there's an auth error, clear any stale session data
|
||||
setSession(null)
|
||||
setUser(null)
|
||||
} else {
|
||||
setSession(session)
|
||||
setUser(session?.user ?? null)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Unexpected error getting session:', err)
|
||||
setSession(null)
|
||||
setUser(null)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
checkSession()
|
||||
|
||||
// Listen for auth state changes
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => {
|
||||
console.log('Auth state change:', event, session?.user?.email)
|
||||
setSession(session)
|
||||
setUser(session?.user ?? null)
|
||||
setLoading(false)
|
||||
})
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
|
||||
getSession()
|
||||
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange(
|
||||
async (event, session) => {
|
||||
console.log('Auth state change:', event, session?.user?.email)
|
||||
setSession(session)
|
||||
setUser(session?.user ?? null)
|
||||
setLoading(false)
|
||||
}
|
||||
)
|
||||
|
||||
return () => subscription.unsubscribe()
|
||||
}, [])
|
||||
|
||||
// Handle authentication redirects
|
||||
useEffect(() => {
|
||||
if (loading) return
|
||||
|
||||
const isLoginPage = pathname === '/aperture/login'
|
||||
const isProtectedRoute = pathname?.startsWith('/aperture') && !isLoginPage
|
||||
|
||||
if (user) {
|
||||
// User is authenticated
|
||||
if (isLoginPage) {
|
||||
// Redirect from login page to dashboard
|
||||
console.log('AuthProvider: Redirecting authenticated user from login to /aperture')
|
||||
window.location.replace('/aperture') // Use replace to avoid back button issues
|
||||
}
|
||||
} else {
|
||||
// User is not authenticated
|
||||
if (isProtectedRoute) {
|
||||
// Redirect to login for protected routes
|
||||
console.log('AuthProvider: Redirecting unauthenticated user to /aperture/login - Path:', pathname)
|
||||
window.location.replace('/aperture/login') // Use replace to avoid back button issues
|
||||
}
|
||||
}
|
||||
}, [user, loading, pathname])
|
||||
|
||||
const signIn = async (email: string) => {
|
||||
const { error } = await supabase.auth.signInWithOtp({
|
||||
email,
|
||||
@@ -63,6 +108,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
email,
|
||||
password,
|
||||
})
|
||||
// Don't manually update state here - the onAuthStateChange listener will handle it
|
||||
return { error }
|
||||
}
|
||||
|
||||
@@ -71,6 +117,9 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
if (error) {
|
||||
console.error('Error signing out:', error)
|
||||
}
|
||||
setUser(null)
|
||||
setSession(null)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const value = {
|
||||
@@ -86,7 +135,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* useAuth hook that returns the current authentication context.
|
||||
* useAuth hook that returns current authentication context.
|
||||
*/
|
||||
export function useAuth() {
|
||||
const context = useContext(AuthContext)
|
||||
@@ -94,4 +143,4 @@ export function useAuth() {
|
||||
throw new Error('useAuth must be used within an AuthProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user