Sidebar and edit updates

This commit is contained in:
Darren Clarke 2023-10-16 09:20:40 +02:00
parent d73b194d1f
commit f13530f043
32 changed files with 3057 additions and 1114 deletions

View file

@ -0,0 +1,150 @@
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 { colors } from "@/app/_styles/theme";
type SearchResultProps = {
props: any;
option: any;
};
const SearchInput = (params: any) => (
<TextField
{...params}
placeholder="Search"
sx={{
backgroundColor: "white",
borderRadius: 10,
"& .MuiOutlinedInput-root": {
borderRadius: 10,
py: 0,
legend: {
marginLeft: "30px",
},
},
"& .MuiAutocomplete-inputRoot": {
paddingLeft: "20px !important",
borderRadius: 10,
},
"& .MuiInputLabel-outlined": {
paddingLeft: "20px",
},
"& .MuiInputLabel-shrink": {
marginLeft: "20px",
paddingLeft: "10px",
paddingRight: 0,
background: "white",
},
}}
/>
);
const SearchResult: FC<SearchResultProps> = ({ props, option }) => {
console.log({ option });
const { lightGrey, mediumGray, black, white } = colors;
return (
<Box
{...props}
sx={{
px: 2,
py: 1.25,
":hover": {
background: `${lightGrey}`,
},
a: {
color: `${black} !important`,
},
borderBottom: `1px solid ${mediumGray}`,
}}
>
<Grid container direction="column" spacing={0.1}>
<Grid item container direction="row" justifyContent="space-between">
<Grid item>
<Box
sx={{
py: 0,
fontSize: 13,
fontWeight: 500,
}}
>
{option.title}
</Box>
</Grid>
</Grid>
<Grid item>
<Box sx={{ width: "100%" }}>
<Box
sx={{
color: "#999",
fontSize: 13,
wrap: "break-word",
}}
>
{option.note}
</Box>
</Box>
</Grid>
</Grid>
</Box>
);
};
export const SearchBox: FC = () => {
const [open, setOpen] = useState(false);
const [selectedValue, setSelectedValue] = useState(null);
const [searchTerms, setSearchTerms] = useState(null);
const pathname = usePathname();
const router = useRouter();
const { data, error }: any = useSWR({
document: searchQuery,
variables: {
search: searchTerms ?? "",
limit: 50,
},
refreshInterval: 10000,
});
useEffect(() => {
setOpen(false);
}, [pathname]);
return (
<Autocomplete
forcePopupIcon={false}
openOnFocus
blurOnSelect
value={selectedValue}
onBlur={() => setOpen(false)}
inputValue={searchTerms}
onChange={(_event, option, reason) => {
if (!option) return;
const url = `/tickets/${option.internalId}`;
setSelectedValue("");
router.push(url);
}}
onInputChange={(_event, value) => {
setSearchTerms(value);
}}
open={open}
onOpen={() => setOpen(true)}
noOptionsText="No results"
options={data?.search ?? []}
getOptionLabel={(option: any) => {
if (option) {
return option.title;
} else {
return "";
}
}}
renderOption={(props, option: any) => (
<SearchResult props={props} key={option.id} option={option} />
)}
sx={{ width: "100%" }}
renderInput={(params: any) => <SearchInput {...params} />}
/>
);
};

View file

@ -1,6 +1,6 @@
"use client";
import { FC, useState } from "react";
import { FC, useEffect, useState } from "react";
import useSWR from "swr";
import {
Box,
@ -26,6 +26,7 @@ import {
Assessment as AssessmentIcon,
LibraryBooks as LibraryBooksIcon,
School as SchoolIcon,
Search as SearchIcon,
} from "@mui/icons-material";
import { usePathname } from "next/navigation";
import Link from "next/link";
@ -33,8 +34,8 @@ 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 { SearchBox } from "./SearchBox";
console.log;
const openWidth = 270;
const closedWidth = 100;
@ -174,13 +175,15 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
},
{ refreshInterval: 10000 },
);
console.log({ overviewData });
const findOverviewCountByID = (id: number) =>
overviewData?.ticketOverviews?.edges?.find((overview: any) =>
overview.node.id.endsWith(`/${id}`),
)?.node?.ticketCount ?? 0;
const recentCount = 0;
const assignedCount = findOverviewCountByID(1);
const openCount = findOverviewCountByID(5);
const urgentCount = findOverviewCountByID(7);
const pendingCount = findOverviewCountByID(3);
const unassignedCount = findOverviewCountByID(2);
const logout = () => {
@ -227,6 +230,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
direction="column"
justifyContent="space-between"
wrap="nowrap"
spacing={0}
sx={{ backgroundColor: "#25272A", height: "100%", p: 2 }}
>
<Grid item container>
@ -313,9 +317,17 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
</Grid>
<Grid item>
<Box
sx={{ height: "0.5px", width: "100%", backgroundColor: "#666" }}
sx={{
height: "0.5px",
width: "100%",
backgroundColor: "#666",
mb: 2,
}}
/>
</Grid>
<Grid item>
<SearchBox />
</Grid>
<Grid
item
container
@ -377,7 +389,7 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
/>
<MenuItem
name="Tickets"
href="/overview/assigned"
href="/overview/recent"
Icon={FeaturedPlayListIcon}
selected={
pathname.startsWith("/overview") ||
@ -397,12 +409,21 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
>
<List component="div" disablePadding>
<MenuItem
name="Assigned"
href="/overview/assigned"
name="Recent"
href="/overview/recent"
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/overview/assigned")}
badge={assignedCount}
selected={pathname.endsWith("/overview/recent")}
badge={recentCount}
open={open}
/>
<MenuItem
name="Open"
href="/overview/open"
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/overview/open")}
badge={openCount}
open={open}
/>
<MenuItem
@ -415,12 +436,12 @@ export const Sidebar: FC<SidebarProps> = ({ open, setOpen }) => {
open={open}
/>
<MenuItem
name="Pending"
href="/overview/pending"
name="Assigned"
href="/overview/assigned"
Icon={FeaturedPlayListIcon}
iconSize={0}
selected={pathname.endsWith("/overview/pending")}
badge={pendingCount}
selected={pathname.endsWith("/overview/assigned")}
badge={assignedCount}
open={open}
/>
<MenuItem

View file

@ -1,6 +1,6 @@
"use client";
import { FC, useState, useEffect } from "react";
import { FC, useState, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import Iframe from "react-iframe";
import { useSession } from "next-auth/react";
@ -16,7 +16,8 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
hideSidebar = true,
}) => {
const router = useRouter();
const { data: session } = useSession();
const { data: session } = useSession({ required: true });
const timeoutRef = useRef(null);
const [authenticated, setAuthenticated] = useState(false);
const [display, setDisplay] = useState("none");
const url = `/zammad${path}`;
@ -28,7 +29,7 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
method: "GET",
redirect: "manual",
});
console.log({ res });
if (res.type === "opaqueredirect") {
setAuthenticated(true);
} else {
@ -39,8 +40,24 @@ export const ZammadWrapper: FC<ZammadWrapperProps> = ({
checkAuthenticated();
}, [path]);
if (!session) {
console.log("No session");
useEffect(() => {
if (session === null) {
timeoutRef.current = setTimeout(() => {
if (session === null) {
router.push("/login");
}
}, 3000);
}
if (session !== null) {
clearTimeout(timeoutRef.current);
}
return () => clearTimeout(timeoutRef.current);
}, [session]);
if (!session || !authenticated) {
console.log("Not authenticated");
return (
<Box sx={{ width: "100%" }}>
<Grid