diff --git a/packages/frontend/src/Index.tsx b/packages/frontend/src/Index.tsx index 3b42548..8c66c2c 100644 --- a/packages/frontend/src/Index.tsx +++ b/packages/frontend/src/Index.tsx @@ -1,6 +1,9 @@ +/** biome-ignore-all lint/correctness/useExhaustiveDependencies: <> */ import type { IssueResponse, OrganisationResponse, ProjectResponse, UserRecord } from "@issue/shared"; import { useEffect, useRef, useState } from "react"; import { Link } from "react-router-dom"; +import { CreateOrganisation } from "@/components/create-organisation"; +import { CreateProject } from "@/components/create-project"; import { IssueDetailPane } from "@/components/issue-detail-pane"; import { IssuesTable } from "@/components/issues-table"; import LogOutButton from "@/components/log-out-button"; @@ -13,8 +16,16 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { + Select, + SelectContent, + SelectItem, + SelectSeparator, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; import { getAuthHeaders } from "@/lib/utils"; +import { Button } from "./components/ui/button"; import { ResizablePanel, ResizablePanelGroup, ResizableSeparator } from "./components/ui/resizable"; function Index() { @@ -34,21 +45,55 @@ function Index() { const [issues, setIssues] = useState([]); const [selectedIssue, setSelectedIssue] = useState(null); + const refetchOrganisations = async () => { + try { + const res = await fetch(`${serverURL}/organisation/by-user?userId=${user.id}`, { + headers: getAuthHeaders(), + }); + const data = (await res.json()) as Array; + + setOrganisations(data); + + // attempt to retain selected organisation (avoid re-fetching projects and issues) + setSelectedOrganisation((prev) => { + if (!prev) return data[0] || null; + const stillExists = data.find((o) => o.Organisation.id === prev.Organisation.id); + return stillExists || data[0] || null; + }); + } catch (err) { + console.error("error fetching organisations:", err); + } + }; + useEffect(() => { if (organisationsRef.current) return; organisationsRef.current = true; - - fetch(`${serverURL}/organisation/by-user?userId=${user.id}`, { headers: getAuthHeaders() }) - .then((res) => res.json()) - .then((data: Array) => { - setOrganisations(data); - setSelectedOrganisation(data[0] || null); - }) - .catch((err) => { - console.error("error fetching organisations:", err); - }); + void refetchOrganisations(); }, [user.id]); + const refetchProjects = async (organisationId: number) => { + try { + const res = await fetch( + `${serverURL}/projects/by-organisation?organisationId=${organisationId}`, + { + headers: getAuthHeaders(), + }, + ); + + const data = (await res.json()) as ProjectResponse[]; + setProjects(data); + + setSelectedProject((prev) => { + if (!prev) return data[0] || null; + const stillExists = data.find((p) => p.Project.id === prev.Project.id); + return stillExists || data[0] || null; + }); + } catch (err) { + console.error("error fetching projects:", err); + setProjects([]); + } + }; + // fetch projects when organisation is selected useEffect(() => { setProjects([]); @@ -59,20 +104,7 @@ function Index() { return; } - fetch( - `${serverURL}/projects/by-organisation?organisationId=${selectedOrganisation.Organisation.id}`, - { - headers: getAuthHeaders(), - }, - ) - .then((res) => res.json()) - .then((data: ProjectResponse[]) => { - setProjects(data); - }) - .catch((err) => { - console.error("error fetching projects:", err); - setProjects([]); - }); + void refetchProjects(selectedOrganisation.Organisation.id); }, [selectedOrganisation]); // fetch issues when project is selected @@ -90,9 +122,7 @@ function Index() { }, [selectedProject]); useEffect(() => { - if (projects.length > 0) { - setSelectedProject(projects[0]); - } + setSelectedProject((prev) => prev || projects[0] || null); }, [projects]); return ( @@ -137,7 +167,16 @@ function Index() { {organisation.Organisation.name} ))} - {organisations.length === 0 && <>No organisations} + + {organisations.length > 0 && } + + Create Organisation + + } + completeAction={refetchOrganisations} + /> @@ -177,7 +216,24 @@ function Index() { {project.Project.name} ))} - {projects.length === 0 && <>No projects in this organisation} + {projects.length > 0 && } + + Create Project + + } + completeAction={async () => { + if (!selectedOrganisation) return; + await refetchProjects(selectedOrganisation.Organisation.id); + }} + /> )} diff --git a/todo.md b/todo.md index 8dccf3f..b0042c9 100644 --- a/todo.md +++ b/todo.md @@ -1,7 +1,5 @@ - user settings/profile page -- create organisation -- create project - create issue - add user(s) to project -- replace "no projects" text with create project button - rename Project.blob to Project.key +- pressing on the left side of log out button does nothing (in user menu)