Use server actions instead of client-side API calls
This commit is contained in:
parent
5a3127dcb0
commit
aa453954ed
30 changed files with 703 additions and 462 deletions
|
|
@ -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"
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
29
apps/link/app/(main)/_components/SetupModeWarning.tsx
Normal file
29
apps/link/app/(main)/_components/SetupModeWarning.tsx
Normal 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;
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue