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

@ -1,11 +1,19 @@
"use client";
import { FC } from "react";
import { FC, useState, useEffect } from "react";
import { useFormState } from "react-dom";
import { useRouter } from "next/navigation";
import { Grid } from "@mui/material";
import { Dialog, Button, TextField, Autocomplete } from "@link-stack/ui";
import {
Dialog,
Button,
TextField,
Autocomplete,
Select,
} from "@link-stack/ui";
import { createTicketAction } from "app/_actions/tickets";
import useSWR from "swr";
import { getCustomersAction } from "app/_actions/users";
import { getGroupsAction } from "app/_actions/groups";
interface TicketCreateDialogProps {
open: boolean;
@ -16,6 +24,8 @@ export const TicketCreateDialog: FC<TicketCreateDialogProps> = ({
open,
closeDialog,
}) => {
const [customers, setCustomers] = useState([]);
const [groups, setGroups] = useState([]);
const initialState = {
messages: [],
errors: [],
@ -38,16 +48,41 @@ export const TicketCreateDialog: FC<TicketCreateDialogProps> = ({
createTicketAction,
initialState,
);
const { data: users, error: usersError }: any = useSWR({
url: "/api/v1/users",
method: "GET",
});
const customers =
users?.filter((user: any) => user.role_ids.includes(3)) ?? [];
const formattedCustomers = customers.map((customer: any) => ({
label: customer.login,
id: `${customer.id}`,
}));
const [liveFormState, setLiveFormState] = useState(formState);
const updateFormState = (field: string, value: any) => {
console.log({ value });
const newState = { ...liveFormState };
newState.values[field] = value;
setLiveFormState(newState);
};
useEffect(() => {
const fetchUsers = async () => {
const result = await getCustomersAction();
console.log({ result });
setCustomers(result);
};
fetchUsers();
}, []);
useEffect(() => {
const fetchGroups = async () => {
const result = await getGroupsAction();
console.log({ result });
setGroups(result);
};
fetchGroups();
}, []);
const router = useRouter();
useEffect(() => {
if (formState.success) {
closeDialog();
}
}, [formState.success, router]);
return (
<Dialog
@ -74,11 +109,21 @@ export const TicketCreateDialog: FC<TicketCreateDialogProps> = ({
>
<Grid container direction="column" spacing={3}>
<Grid item>
<Autocomplete
<Select
name="groupId"
label="Group"
getOptions={() => groups as any}
formState={liveFormState}
updateFormState={updateFormState}
/>
</Grid>
<Grid item>
<Select
name="customerId"
label="Customer"
options={formattedCustomers}
formState={formState}
getOptions={() => customers as any}
formState={liveFormState}
updateFormState={updateFormState}
/>
</Grid>
<Grid item>

View file

@ -1,113 +1,29 @@
"use client";
import { FC, useEffect, useState } from "react";
import useSWR from "swr";
import { getOverviewTicketsAction } from "app/_actions/overviews";
import { TicketList } from "./TicketList";
import { getTicketOverviewCountsQuery } from "app/_graphql/getTicketOverviewCountsQuery";
import { getTicketsByOverviewQuery } from "app/_graphql/getTicketsByOverviewQuery";
type ZammadOverviewProps = {
name: string;
};
export const ZammadOverview: FC<ZammadOverviewProps> = ({ name }) => {
const [overviewID, setOverviewID] = useState(null);
const [tickets, setTickets] = useState([]);
const [error, setError] = useState(null);
const { data: overviewData, error: overviewError }: any = useSWR(
{
document: getTicketOverviewCountsQuery,
},
{ refreshInterval: 10000 },
);
const { data: ticketData, error: ticketError }: any = useSWR(
{
document: getTicketsByOverviewQuery,
variables: { overviewId: overviewID, pageSize: 250 },
},
{ refreshInterval: 10000 },
);
const overviewLookup = {
Assigned: "My Assigned Tickets",
Open: "Open Tickets",
Urgent: "Escalated Tickets",
Unassigned: "Unassigned & Open Tickets",
};
const findOverviewByName = (name: string) => {
const fullName = overviewLookup[name];
return overviewData?.ticketOverviews?.edges?.find(
(overview: any) => overview.node.name === fullName,
)?.node?.id;
};
useEffect(() => {
if (overviewData) {
setOverviewID(findOverviewByName(name));
}
}, [overviewData, name]);
console.log({
name,
overviewID,
overviewData,
overviewError,
ticketData,
ticketError,
});
const restFetcher = (url: string) => fetch(url).then((r) => r.json());
const { data: recent } = useSWR("/api/v1/recent_view", restFetcher);
const sortTickets = (tickets: any) => {
return tickets.sort((a: any, b: any) => {
if (a.internalId < b.internalId) {
return 1;
}
if (a.internalId > b.internalId) {
return -1;
}
return 0;
});
};
useEffect(() => {
if (name != "Recent") {
const edges = ticketData?.ticketsByOverview?.edges;
if (edges) {
const nodes = edges.map((edge: any) => edge.node);
console.log({ nodes });
setError(null);
setTickets(sortTickets(nodes));
}
if (ticketError) {
setError(ticketError);
}
}
}, [ticketData, ticketError]);
useEffect(() => {
const fetchRecentTickets = async () => {
if (name === "Recent" && recent) {
let allTickets = [];
for (const rec of recent) {
const res = await fetch(`/api/v1/tickets/${rec.o_id}`);
const tkt = await res.json();
allTickets.push({
...tkt,
internalId: tkt.id,
createdAt: tkt.created_at,
updatedAt: tkt.updated_at,
});
}
setTickets(sortTickets(allTickets));
console.log({ allTickets });
}
const fetchTickets = async () => {
const { tickets } = await getOverviewTicketsAction(name);
setTickets(tickets);
};
fetchRecentTickets();
fetchTickets();
const interval = setInterval(fetchTickets, 20000);
return () => clearInterval(interval);
}, [name]);
const shouldRender = tickets && !error;
return shouldRender && <TicketList title={name} tickets={tickets} />;
return <TicketList title={name} tickets={tickets} />;
};

View file

@ -17,7 +17,7 @@ export async function generateMetadata({
const section = getSection(overview);
return {
title: `Link - ${section} Tickets`,
title: `CDR Link - ${section} Tickets`,
};
}