"use client" import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from "react" import { useSession, signIn, signOut } from "next-auth/react" import type { User, Ticket, TicketStatus, Room } from "./types" const API_URL = process.env.NEXT_PUBLIC_API_URL interface AuthContextType { user: User | null tickets: Ticket[] rooms: Room[] login: (email: string, password: string) => Promise register: (user: Omit & { firstname: string; lastname: string; password: string; roomIds?: number[] }) => Promise logout: () => void createTicket: (ticket: { roomId: number; title: string; description: string }) => Promise updateTicketStatus: (ticketId: number, status: TicketStatus) => Promise updateRooms: (roomIds: number[]) => Promise } const AuthContext = createContext(null) export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null) const [tickets, setTickets] = useState([]) const [rooms, setRooms] = useState([]) const [authHeader, setAuthHeader] = useState(null) // Fetch rooms on mount useEffect(() => { fetch(`${API_URL}/rooms`) .then(res => { if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`) return res.json() }) .then(data => setRooms(data)) .catch(err => console.error("Failed to fetch rooms", err)) }, []) const fetchTickets = useCallback(async (auth: string) => { try { const res = await fetch(`${API_URL}/tickets`, { headers: { "Authorization": auth } }) if (res.ok) { const data = await res.json() setTickets(data) } } catch (err) { console.error("Failed to fetch tickets", err) } }, []) // Sync with NextAuth session const { data: session, status } = useSession() useEffect(() => { if (session?.user && session?.authHeader) { // @ts-ignore setUser(session.user) // @ts-ignore setAuthHeader(session.authHeader) // @ts-ignore fetchTickets(session.authHeader) } else if (status === "unauthenticated") { setUser(null) setAuthHeader(null) setTickets([]) } }, [session, status, fetchTickets]) const login = useCallback(async (email: string, password: string) => { // We use next-auth signIn, which calls our authorize callback const result = await signIn("credentials", { email, password, redirect: false }) if (result?.ok) { // Session update will trigger useEffect return true } return false }, []) const register = useCallback(async (newUser: any) => { const payload = { firstname: newUser.firstname, lastname: newUser.lastname, email: newUser.email, password: newUser.password, role: newUser.role, // LEHRKRAFT or RAUMBETREUER roomIds: newUser.roomIds } try { const res = await fetch(`${API_URL}/auth/register`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }) if (res.ok) { // Auto login after register? Or just return true // Implementation requirement: "Alle Nutzer ... müssen sich registrieren ... Vor der Nutzung ... anmelden" // So we redirect to login. return true } } catch (e) { console.error(e) } return false }, []) const logout = useCallback(() => { signOut({ redirect: false }) setUser(null) setAuthHeader(null) setTickets([]) }, []) const createTicket = useCallback(async (ticket: { roomId: number; title: string; description: string }) => { if (!authHeader) return try { const res = await fetch(`${API_URL}/tickets`, { method: "POST", headers: { "Authorization": authHeader, "Content-Type": "application/json" }, body: JSON.stringify(ticket) }) if (res.ok) { fetchTickets(authHeader) // Refresh } } catch (e) { console.error(e) } }, [authHeader, fetchTickets]) const updateRooms = useCallback(async (roomIds: number[]) => { if (!session?.authHeader) return try { const res = await fetch(`${API_URL}/auth/profile/rooms`, { method: "PUT", headers: { "Authorization": session.authHeader as string, "Content-Type": "application/json" }, body: JSON.stringify({ roomIds }) }) if (res.ok) { const updatedUser = await res.json() setUser(updatedUser) // Note: session.user won't be updated automatically until next session fetch, but local state is updated. } } catch (e) { console.error(e) } }, [session]) const updateTicketStatus = useCallback(async (ticketId: number, status: TicketStatus) => { if (!authHeader) return try { const res = await fetch(`${API_URL}/tickets/${ticketId}/status`, { method: "PATCH", headers: { "Authorization": authHeader, "Content-Type": "application/json" }, body: JSON.stringify({ status }) }) if (res.ok) { fetchTickets(authHeader) // Refresh } } catch (e) { console.error(e) } }, [authHeader, fetchTickets]) return ( {children} ) } export function useAuth() { const context = useContext(AuthContext) if (!context) { throw new Error("useAuth must be used within an AuthProvider") } return context }