Use server actions instead of client-side API calls

This commit is contained in:
Darren Clarke 2024-08-05 23:31:15 +02:00
parent 5a3127dcb0
commit aa453954ed
30 changed files with 703 additions and 462 deletions

View file

@ -4,6 +4,8 @@ import { FC } from "react";
import { OpenSearchWrapper } from "@link-stack/leafcutter-ui";
export const Home: FC = () => (
<OpenSearchWrapper url="/app/visualize#/edit/237b8f00-e6a0-11ee-94b3-d7b7409294e7?embed=true" marginTop="0"
<OpenSearchWrapper
url="/app/visualize#/edit/237b8f00-e6a0-11ee-94b3-d7b7409294e7?embed=true"
marginTop="0"
/>
);

View file

@ -1,21 +1,32 @@
"use client";
import { FC, PropsWithChildren, useState } from "react";
import { Grid } from "@mui/material";
import { Grid, Box } from "@mui/material";
import { Sidebar } from "./Sidebar";
import { SetupModeWarning } from "./SetupModeWarning";
export const InternalLayout: FC<PropsWithChildren> = ({ children }) => {
interface InternalLayoutProps extends PropsWithChildren {
setupModeActive: boolean;
}
export const InternalLayout: FC<InternalLayoutProps> = ({
children,
setupModeActive,
}) => {
const [open, setOpen] = useState(true);
return (
<Grid container direction="row">
<Sidebar open={open} setOpen={setOpen} />
<Grid
item
sx={{ ml: open ? "270px" : "70px", width: "100%", height: "100vh" }}
>
{children as any}
<Box sx={{ position: "relative" }}>
<SetupModeWarning setupModeActive={setupModeActive} />
<Grid container direction="row">
<Sidebar open={open} setOpen={setOpen} />
<Grid
item
sx={{ ml: open ? "270px" : "70px", width: "100%", height: "100vh" }}
>
{children as any}
</Grid>
</Grid>
</Grid>
</Box>
);
};

View file

@ -1,8 +1,7 @@
import { FC, useState, useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import useSWR from "swr";
import { Grid, Box, TextField, Autocomplete } from "@mui/material";
import { searchQuery } from "@/app/_graphql/searchQuery";
import { searchAllAction } from "@/app/_actions/search";
import { colors } from "@link-stack/ui";
type SearchResultProps = {
@ -42,8 +41,6 @@ const SearchInput = (params: any) => (
);
const SearchResult: FC<SearchResultProps> = ({ props, option }) => {
console.log({ option });
const { lightGrey, mediumGray, black, white } = colors;
return (
@ -95,22 +92,20 @@ const SearchResult: FC<SearchResultProps> = ({ props, option }) => {
export const SearchBox: FC = () => {
const [open, setOpen] = useState(false);
const [searchResults, setSearchResults] = useState([]);
const [selectedValue, setSelectedValue] = useState(null);
const [searchTerms, setSearchTerms] = useState("");
const pathname = usePathname();
const router = useRouter();
const { data, error }: any = useSWR({
document: searchQuery,
variables: {
search: searchTerms ?? "",
limit: 50,
},
refreshInterval: 10000,
});
useEffect(() => {
setOpen(false);
}, [pathname]);
const fetchSearchResults = async () => {
const results = await searchAllAction(searchTerms ?? "", 50);
setSearchResults(results);
};
fetchSearchResults();
}, [searchTerms]);
return (
<Autocomplete
@ -132,7 +127,7 @@ export const SearchBox: FC = () => {
open={open}
onOpen={() => setOpen(true)}
noOptionsText="No results"
options={data?.search ?? []}
options={searchResults ?? []}
getOptionLabel={(option: any) => {
if (option) {
return option.title;

View file

@ -0,0 +1,29 @@
"use client";
import { FC } from "react";
import { Box } from "@mui/material";
interface SetupModeWarningProps {
setupModeActive: boolean;
}
export const SetupModeWarning: FC<SetupModeWarningProps> = ({
setupModeActive,
}) =>
setupModeActive ? (
<Box
sx={{
backgroundColor: "red",
textAlign: "center",
zIndex: 10000,
position: "absolute",
width: "100vw",
top: 0,
left: 0,
}}
>
<Box component="h2" sx={{ color: "white", m: 0, p: 0 }}>
Setup Mode Active
</Box>
</Box>
) : null;

View file

@ -1,7 +1,6 @@
"use client";
import { FC, useEffect, useState } from "react";
import useSWR from "swr";
import {
Box,
Grid,
@ -33,7 +32,7 @@ import Link from "next/link";
import Image from "next/image";
import LinkLogo from "public/link-logo-small.png";
import { useSession, signOut } from "next-auth/react";
import { getTicketOverviewCountsQuery } from "app/_graphql/getTicketOverviewCountsQuery";
import { getOverviewTicketCountsAction } from "app/_actions/overviews";
import { SearchBox } from "./SearchBox";
import { fonts } from "@link-stack/ui";
@ -185,33 +184,32 @@ interface SidebarProps {
export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
const pathname = usePathname();
const { data: session } = useSession();
const [overviewCounts, setOverviewCounts] = useState<any>(null);
const { poppins } = fonts;
const username = session?.user?.name || "User";
// @ts-ignore
const roles = session?.user?.roles || [];
const { data: overviewData, error: overviewError }: any = useSWR(
{
document: getTicketOverviewCountsQuery,
},
{ refreshInterval: 10000 },
);
const findOverviewByName = (name: string) =>
overviewData?.ticketOverviews?.edges?.find(
(overview: any) => overview.node.name === name,
)?.node?.id;
const findOverviewCountByID = (id: string) =>
overviewData?.ticketOverviews?.edges?.find(
(overview: any) => overview.node.id === id,
)?.node?.ticketCount ?? 0;
const leafcutterEnabled = false;
useEffect(() => {
const fetchCounts = async () => {
const counts = await getOverviewTicketCountsAction();
console.log({ counts });
setOverviewCounts(counts);
};
fetchCounts();
const interval = setInterval(fetchCounts, 10000);
return () => clearInterval(interval);
}, []);
const recentCount = 0;
const assignedID = findOverviewByName("My Assigned Tickets");
const assignedCount = findOverviewCountByID(assignedID);
const openID = findOverviewByName("Open Tickets");
const openCount = findOverviewCountByID(openID);
const urgentID = findOverviewByName("Escalated Tickets");
const urgentCount = findOverviewCountByID(urgentID);
const unassignedID = findOverviewByName("Unassigned & Open Tickets");
const unassignedCount = findOverviewCountByID(unassignedID);
const assignedCount = overviewCounts?.["My Assigned Tickets"] ?? 0;
const openCount = overviewCounts?.["Open Tickets"] ?? 0;
const urgentCount = overviewCounts?.["Escalated Tickets"] ?? 0;
const unassignedCount = overviewCounts?.["Unassigned & Open Tickets"] ?? 0;
const logout = () => {
signOut({ callbackUrl: "/login" });
@ -404,14 +402,16 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
},
}}
>
<MenuItem
name="Home"
href="/"
Icon={CottageIcon}
iconSize={20}
selected={pathname.endsWith("/")}
open={open}
/>
{leafcutterEnabled && (
<MenuItem
name="Home"
href="/"
Icon={CottageIcon}
iconSize={20}
selected={pathname.endsWith("/")}
open={open}
/>
)}
<MenuItem
name="Tickets"
href="/overview/recent"
@ -504,14 +504,16 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
selected={pathname.endsWith("/reporting")}
open={open}
/>
<MenuItem
name="Leafcutter"
href="/leafcutter"
Icon={InsightsIcon}
iconSize={20}
selected={false}
open={open}
/>
{leafcutterEnabled && (
<MenuItem
name="Leafcutter"
href="/leafcutter"
Icon={InsightsIcon}
iconSize={20}
selected={false}
open={open}
/>
)}
<Collapse
in={pathname.startsWith("/leafcutter")}
timeout="auto"