diff --git a/frontend/app/components/ProjectDialog.tsx b/frontend/app/components/ProjectDialog.tsx index 27b442f..d2b3968 100644 --- a/frontend/app/components/ProjectDialog.tsx +++ b/frontend/app/components/ProjectDialog.tsx @@ -1,4 +1,5 @@ "use client"; + import { useEffect, useRef, useState } from "react"; import { supabase } from "@/app/lib/supabase"; @@ -18,98 +19,205 @@ type Props = { onCreated: (project: Project) => void; }; +function resetProjectForm( + setPname: (value: string) => void, + setPDesc: (value: string) => void, + setPTeamSize: (value: number) => void, + setPDeadline: (value: string) => void, + setError: (value: string) => void +) { + setError(""); + setPname(""); + setPDesc(""); + setPTeamSize(0); + setPDeadline(""); +} + +async function resolveSessionToken() { + if (!supabase) { + throw new Error( + "Supabase client not available" + ); + } + + const { + data: { session }, + error, + } = await supabase.auth.getSession(); + + if ( + error || + !session?.access_token + ) { + throw new Error( + "Unauthorized, please sign in to create a project." + ); + } + + return session.access_token; +} + export default function ProjectDialog({ isOpen, onClose, onCreated, }: Props) { - const [Pname, setPname] = useState(""); - const [Pdesc, setPDesc] = useState(""); - const [PteamSize, setPTeamSize] = useState(0); - const [Pdeadline, setPDeadline] = useState(""); - const [error, setError] = useState(""); - const [loading, setLoading] = useState(false); - const initialFocusRef = useRef(null); + const [Pname, setPname] = + useState(""); + + const [Pdesc, setPDesc] = + useState(""); + + const [ + PteamSize, + setPTeamSize, + ] = useState(0); + + const [ + Pdeadline, + setPDeadline, + ] = useState(""); + + const [error, setError] = + useState(""); + + const [loading, setLoading] = + useState(false); + + const initialFocusRef = + useRef( + null + ); useEffect(() => { if (isOpen) { - setTimeout(() => initialFocusRef.current?.focus(), 0); - const onKey = (e: KeyboardEvent) => { - if (e.key === "Escape" && !loading) onClose(); + setTimeout( + () => + initialFocusRef.current?.focus(), + 0 + ); + + const onKey = ( + e: KeyboardEvent + ) => { + if ( + e.key === "Escape" && + !loading + ) { + onClose(); + } }; - window.addEventListener("keydown", onKey); - return () => window.removeEventListener("keydown", onKey); + + window.addEventListener( + "keydown", + onKey + ); + + return () => + window.removeEventListener( + "keydown", + onKey + ); } - }, [isOpen, loading, onClose]); + }, [ + isOpen, + loading, + onClose, + ]); const close = () => { if (loading) return; - setError(""); - setPname(""); - setPDesc(""); - setPTeamSize(0); - setPDeadline(""); + + resetProjectForm( + setPname, + setPDesc, + setPTeamSize, + setPDeadline, + setError + ); + onClose(); }; const submit = async () => { setError(""); + if (!Pname.trim()) { - setError("Project name is required."); + setError( + "Project name is required." + ); return; } setLoading(true); + try { - if (!supabase) { - setError("Supabase client not available"); + let token: string; + + try { + token = + await resolveSessionToken(); + } catch (error) { + setError( + (error as Error).message + ); setLoading(false); return; } - // 1. Get the session properly - const { data: { session }, error: sessionError } = await supabase.auth.getSession(); - const token = session?.access_token; + const res = await fetch( + "/api/projects", + { + method: "POST", + headers: { + "Content-Type": + "application/json", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + name: Pname.trim(), + desc: Pdesc.trim(), + members: PteamSize, + due: Pdeadline + ? new Date( + Pdeadline + ).toISOString() + : null, + }), + } + ); - if (!token || sessionError) { - setError("Unauthorized, please sign in to create a project."); - setLoading(false); - return; - } + const payload = + await res.json(); - const res = await fetch("/api/projects", { - method: "POST", - headers: { - "Content-Type": "application/json", - // FIX: Use the 'token' variable defined above - "Authorization": `Bearer ${token}`, - }, - body: JSON.stringify({ - name: Pname.trim(), - desc: Pdesc.trim(), - members: PteamSize, - due: Pdeadline ? new Date(Pdeadline).toISOString() : null, - }), - }); - - const payload = await res.json(); - if (!res.ok) { - setError(payload.error || "Failed to create project."); + setError( + payload.error || + "Failed to create project." + ); setLoading(false); return; } - // Successfully created! - onCreated?.(payload.project); + onCreated?.( + payload.project + ); + close(); } catch (err) { - setError("An unexpected error occurred."); - console.error("Project creation error:", err); + setError( + "An unexpected error occurred." + ); + + console.error( + "Project creation error:", + err + ); } finally { setLoading(false); } }; + if (!isOpen) return null; return ( @@ -124,46 +232,79 @@ export default function ProjectDialog({ if (!loading) close(); }} /> +
-

Add Project

+

+ Add Project +

+ + - setPname(e.target.value)} + onChange={(e) => + setPname( + e.target.value + ) + } className="w-full p-2 mb-3 bg-#FFFFFF rounded border border-zinc-700 focus:outline-none focus:border-indigo-500" placeholder="Enter project name" disabled={loading} /> - + +