feat(forklifts): added the ability to add new forklifts in

This commit is contained in:
2025-11-20 17:51:06 -06:00
parent 7b28f4e9ef
commit 7b6c9bdfbf
9 changed files with 710 additions and 1 deletions

View File

@@ -0,0 +1,114 @@
import axios from "axios";
import { type DrizzleError, sql } from "drizzle-orm";
import type { Request, Response } from "express";
import { Router } from "express";
import https from "https";
import { db } from "../../../../pkg/db/db.js";
import {
insertLeasesCompanySchema,
leases,
} from "../../../../pkg/db/schema/forkliftLeases.js";
import { createLogger } from "../../../../pkg/logger/logger.js";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
const router = Router();
router.post("/", async (req: Request, res: Response) => {
// when a new server is posted from localhost or 127.0.0.1 we also want to post it to the test server so we can see it from there
//res.status(200).json({ message: "Server added", ip: req.hostname });
const log = createLogger({ module: "forklift", subModule: "add lease" });
const parsed = insertLeasesCompanySchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ errors: parsed.error.flatten() });
}
const { data, error } = await tryCatch(
db
.insert(leases)
.values({
...parsed.data,
add_user: req.user?.username,
add_date: sql`NOW()`,
upd_user: req.user?.username,
upd_date: sql`NOW()`,
})
.onConflictDoUpdate({
target: leases.leaseNumber,
set: {
...parsed.data,
add_user: req.user?.username,
add_date: sql`NOW()`,
upd_user: req.user?.username,
upd_date: sql`NOW()`,
},
})
.returning({
leaseNumber: leases.leaseNumber,
}),
);
if (error) {
const err: DrizzleError = error;
return res.status(400).json({
message: `Error adding lease`,
error: err.cause,
});
}
// if (req.hostname === "localhost" && process.env.MAIN_SERVER) {
// log.info({}, "Running in dev server about to add in a new server");
// const axiosInstance = axios.create({
// httpsAgent: new https.Agent({ rejectUnauthorized: false }),
// baseURL: process.env.MAIN_SERVER, // e.g. "https://example.com"
// withCredentials: true,
// });
// const loginRes = (await axiosInstance.post(
// `${process.env.MAIN_SERVER}/lst/api/auth/sign-in/username`,
// {
// username: process.env.MAIN_SERVER_USERNAME,
// password: process.env.MAIN_SERVER_PASSWORD,
// },
// {
// headers: { "Content-Type": "application/json" },
// },
// )) as any;
// const setCookie = loginRes.headers["set-cookie"][0];
// if (!setCookie) {
// throw new Error("Did not receive a Set-Cookie header from login");
// }
// const { data, error } = await tryCatch(
// axios.post(
// `${process.env.MAIN_SERVER}/lst/api/forklifts/leases`,
// parsed.data,
// {
// headers: {
// "Content-Type": "application/json",
// Cookie: setCookie.split(";")[0],
// },
// withCredentials: true,
// },
// ),
// );
// if (error) {
// log.error(
// { stack: error },
// "There was an error adding the company to Main Server",
// );
// }
// log.info(
// { stack: data?.data },
// "A new Company was just added to the server.",
// );
// }
return res
.status(201)
.json({ message: `lease ${data[0]?.leaseNumber} added`, data: data });
});
export default router;

View File

@@ -0,0 +1,59 @@
import { and, asc, eq } from "drizzle-orm";
import type { Request, Response } from "express";
import { Router } from "express";
import { db } from "../../../../pkg/db/db.js";
import { forkliftCompanies } from "../../../../pkg/db/schema/forkliftLeaseCompanys.js";
import { leases } from "../../../../pkg/db/schema/forkliftLeases.js";
import { forklifts } from "../../../../pkg/db/schema/forklifts.js";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
const router = Router();
router.get("/", async (req: Request, res: Response) => {
const conditions = [];
if (req.query.lease !== undefined) {
conditions.push(eq(leases.leaseNumber, `${req.query.lease}`));
}
if (req.query.companyId !== undefined) {
conditions.push(eq(leases.companyId, `${req.query.companyId}`));
}
//conditions.push(eq(forkliftCompanies.active, true));
const { data, error } = (await tryCatch(
db
.select({
id: leases.id,
leaseNumber: leases.leaseNumber,
startDate: leases.startDate,
endDate: leases.endDate,
leaseLink: leases.leaseLink,
companyName: forkliftCompanies.name,
add_user: leases.add_user,
add_date: leases.add_date,
upd_user: leases.upd_user,
upd_date: leases.upd_date,
})
.from(leases)
.innerJoin(forkliftCompanies, eq(forkliftCompanies.id, leases.companyId))
.where(and(...conditions))
.orderBy(asc(leases.leaseNumber)),
)) as any;
// add the forklifts that are in this lease
const forkliftData = await db.select().from(forklifts);
if (error) {
return res.status(400).json({ error: error });
}
const leaseData = data.map((i: any) => ({
...i,
forklifts: forkliftData.filter((x) => x.leaseId === i.id),
}));
res.status(200).json({ message: "Current Leases", data: leaseData });
});
export default router;

View File

@@ -0,0 +1,20 @@
import { Router } from "express";
import { requireAuth } from "../../../../pkg/middleware/authMiddleware.js";
import addHours from "./addHours.js";
import gethours from "./getHours.js";
const router = Router();
router.use(
"/",
requireAuth("forklifts", ["systemAdmin", "admin", "manager", "supervisor"]),
addHours,
);
router.use(
"/",
requireAuth("forklifts", ["systemAdmin", "admin", "manager", "supervisor"]),
gethours,
);
export default router;

View File

@@ -61,7 +61,7 @@ export default function ForkliftSideBar() {
},
{
title: "Forklifts",
url: "/lst/app/admin/modules",
url: "/lst/app/forklifts/forklifts",
icon: Forklift,
role: ["systemAdmin", "admin", "manager", "supervisor"],
module: "forklifts",

View File

@@ -1,6 +1,7 @@
import { Link, useRouterState } from "@tanstack/react-router";
import { useState } from "react";
import NewCompanyForm from "@/routes/_app/_forklifts/-components/NewCompany";
import NewForklift from "@/routes/_app/_forklifts/-components/NewForklift";
import NewInvoice from "@/routes/_app/_forklifts/-components/NewInvoice";
import NewLeaseForm from "@/routes/_app/_forklifts/-components/NewLease";
import { useAuth, useLogout } from "../../lib/authClient";
@@ -25,6 +26,7 @@ export default function Nav() {
const [openDialog, setOpenDialog] = useState(false);
const [openLeaseDialog, setOpenLeaseDialog] = useState(false);
const [openInvoiceDialog, setOpenInvoiceDialog] = useState(false);
const [openForkliftDialog, setOpenForkliftDialog] = useState(false);
return (
<nav className="flex justify-end w-full shadow ">
<div className="m-2 flex flex-row gap-1">
@@ -75,6 +77,14 @@ export default function Nav() {
>
New Invoice
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => {
// just open the dialog when clicked
setOpenForkliftDialog(true);
}}
>
New Forklift
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{/* Company */}
@@ -105,6 +115,16 @@ export default function Nav() {
</DialogContent>
</Dialog>
)}
{openForkliftDialog && (
<Dialog
open={openForkliftDialog}
onOpenChange={setOpenForkliftDialog}
>
<DialogContent className="sm:max-w-fit">
<NewForklift setOpenDialog={setOpenForkliftDialog} />
</DialogContent>
</Dialog>
)}
</>
)}
</div>

View File

@@ -0,0 +1,17 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getForklifts() {
return queryOptions({
queryKey: ["getForklifts"],
queryFn: () => fetch(),
staleTime: 5000,
refetchOnWindowFocus: true,
});
}
const fetch = async () => {
const { data } = await axios.get("/lst/api/forklifts");
return data.data;
};

View File

@@ -31,6 +31,7 @@ import { Route as MobileMobileLayoutMDeliveryRouteImport } from './routes/_mobil
import { Route as MobileMobileLayoutMCyclecountsRouteImport } from './routes/_mobile/_mobileLayout/m/cyclecounts'
import { Route as AppForkliftsForkliftsLeasesRouteImport } from './routes/_app/_forklifts/forklifts/leases'
import { Route as AppForkliftsForkliftsInvoicesRouteImport } from './routes/_app/_forklifts/forklifts/invoices'
import { Route as AppForkliftsForkliftsForkliftsRouteImport } from './routes/_app/_forklifts/forklifts/forklifts'
import { Route as AppForkliftsForkliftsCompaniesRouteImport } from './routes/_app/_forklifts/forklifts/companies'
import { Route as AppAdminLayoutAdminServersRouteImport } from './routes/_app/_adminLayout/admin/servers'
import { Route as ApplogisticsLogisticsDeliveryScheduleRouteImport } from './routes/_app/(logistics)/logistics/deliverySchedule'
@@ -165,6 +166,12 @@ const AppForkliftsForkliftsInvoicesRoute =
path: '/forklifts/invoices',
getParentRoute: () => AppForkliftsRouteRoute,
} as any)
const AppForkliftsForkliftsForkliftsRoute =
AppForkliftsForkliftsForkliftsRouteImport.update({
id: '/forklifts/forklifts',
path: '/forklifts/forklifts',
getParentRoute: () => AppForkliftsRouteRoute,
} as any)
const AppForkliftsForkliftsCompaniesRoute =
AppForkliftsForkliftsCompaniesRouteImport.update({
id: '/forklifts/companies',
@@ -300,6 +307,7 @@ export interface FileRoutesByFullPath {
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
'/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
@@ -337,6 +345,7 @@ export interface FileRoutesByTo {
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
'/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
@@ -382,6 +391,7 @@ export interface FileRoutesById {
'/_app/(logistics)/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
'/_app/_adminLayout/admin/servers': typeof AppAdminLayoutAdminServersRoute
'/_app/_forklifts/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
'/_app/_forklifts/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
'/_app/_forklifts/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
'/_app/_forklifts/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
'/_mobile/_mobileLayout/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
@@ -422,6 +432,7 @@ export interface FileRouteTypes {
| '/logistics/deliverySchedule'
| '/admin/servers'
| '/forklifts/companies'
| '/forklifts/forklifts'
| '/forklifts/invoices'
| '/forklifts/leases'
| '/m/cyclecounts'
@@ -459,6 +470,7 @@ export interface FileRouteTypes {
| '/logistics/deliverySchedule'
| '/admin/servers'
| '/forklifts/companies'
| '/forklifts/forklifts'
| '/forklifts/invoices'
| '/forklifts/leases'
| '/m/cyclecounts'
@@ -503,6 +515,7 @@ export interface FileRouteTypes {
| '/_app/(logistics)/logistics/deliverySchedule'
| '/_app/_adminLayout/admin/servers'
| '/_app/_forklifts/forklifts/companies'
| '/_app/_forklifts/forklifts/forklifts'
| '/_app/_forklifts/forklifts/invoices'
| '/_app/_forklifts/forklifts/leases'
| '/_mobile/_mobileLayout/m/cyclecounts'
@@ -684,6 +697,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppForkliftsForkliftsInvoicesRouteImport
parentRoute: typeof AppForkliftsRouteRoute
}
'/_app/_forklifts/forklifts/forklifts': {
id: '/_app/_forklifts/forklifts/forklifts'
path: '/forklifts/forklifts'
fullPath: '/forklifts/forklifts'
preLoaderRoute: typeof AppForkliftsForkliftsForkliftsRouteImport
parentRoute: typeof AppForkliftsRouteRoute
}
'/_app/_forklifts/forklifts/companies': {
id: '/_app/_forklifts/forklifts/companies'
path: '/forklifts/companies'
@@ -899,6 +919,7 @@ const AppAdminLayoutRouteRouteWithChildren =
interface AppForkliftsRouteRouteChildren {
AppForkliftsForkliftsCompaniesRoute: typeof AppForkliftsForkliftsCompaniesRoute
AppForkliftsForkliftsForkliftsRoute: typeof AppForkliftsForkliftsForkliftsRoute
AppForkliftsForkliftsInvoicesRoute: typeof AppForkliftsForkliftsInvoicesRoute
AppForkliftsForkliftsLeasesRoute: typeof AppForkliftsForkliftsLeasesRoute
AppForkliftsForkliftsIndexRoute: typeof AppForkliftsForkliftsIndexRoute
@@ -906,6 +927,7 @@ interface AppForkliftsRouteRouteChildren {
const AppForkliftsRouteRouteChildren: AppForkliftsRouteRouteChildren = {
AppForkliftsForkliftsCompaniesRoute: AppForkliftsForkliftsCompaniesRoute,
AppForkliftsForkliftsForkliftsRoute: AppForkliftsForkliftsForkliftsRoute,
AppForkliftsForkliftsInvoicesRoute: AppForkliftsForkliftsInvoicesRoute,
AppForkliftsForkliftsLeasesRoute: AppForkliftsForkliftsLeasesRoute,
AppForkliftsForkliftsIndexRoute: AppForkliftsForkliftsIndexRoute,

View File

@@ -0,0 +1,244 @@
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
DialogClose,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { getServers } from "@/lib/querys/admin/getServers";
import { getLeases } from "@/lib/querys/forklifts/getLeases";
import { useAppForm } from "../../../../lib/formStuff";
const forkliftManufacturer: any = [
{ value: "Jungheinrich", label: "Jungheinrich" },
{ value: "Toyota", label: "Toyota" },
{ value: "Caterpillar", label: "Caterpillar" },
{ value: "Mitsubishi", label: "Mitsubishi" },
{ value: "BigJoe", label: "BigJoe" },
{ value: "Yale", label: "Yale" },
{ value: "Hyster", label: "Hyster" },
{ value: "Global", label: "Global" },
{ value: "Wesco", label: "Wesco" },
{ value: "JLG", label: "JLG" },
{ value: "Genie", label: "Genie" },
{ value: "Linde", label: "Linde" },
{ value: "Skyjack", label: "Skyjack" },
{ value: "NilFisk", label: "NilFisk" },
{ value: "Boomer", label: "Boomer" },
{ value: "Crown", label: "Crown" },
];
const batteryType: any = [
{ value: "leadAcid", label: "Lead Acid" },
{ value: "lithium", label: "Lithium" },
{ value: "12v", label: "12v" },
];
const engineType: any = [
{ value: "electric", label: "Electric" },
{ value: "propane", label: "Propane" },
];
const pfc: any = [
{ value: "20", label: "EBM" },
{ value: "30", label: "SBM" },
{ value: "40", label: "PET" },
{ value: "50", label: "CAPS" },
];
export default function NewForklift({ setOpenDialog }: { setOpenDialog: any }) {
//const search = useSearch({ from: "/_app/(auth)/login" });
const { data: s, isLoading: es } = useQuery(getServers());
const {
data: leases,
isLoading: leaseError,
refetch,
} = useQuery(getLeases());
const form = useAppForm({
defaultValues: {
serialNumber: "",
model: "",
plant: "",
profitCenter: "",
manufacturer: "",
manufacturerYear: "",
engine: "",
batteryType: "lead acid",
leaseId: "",
},
onSubmit: async ({ value }) => {
// get the glcode
const glCode = s.filter((n: any) => n.name === value.plant);
const data = {
serialNumber: value.serialNumber,
model: value.model.toUpperCase(),
plant: value.plant,
glCode: Number(glCode[0].greatPlainsPlantCode),
profitCenter: Number(value.profitCenter),
manufacturer: value.manufacturer,
manufacturerYear: value.manufacturerYear,
engine: value.engine,
batteryType: value.batteryType,
leaseId: value.leaseId.trimStart().trimEnd(),
};
console.log(data);
try {
await axios.post("/lst/api/forklifts", data);
form.reset();
setOpenDialog(false);
refetch();
toast.success(`${value.serialNumber} was just created `);
} catch (error) {
// @ts-ignore
if (!error.response.data.success) {
// @ts-ignore
toast.error(error?.response?.data.message);
} else {
// @ts-ignore
toast.error(error?.message);
}
}
},
});
//const currentYear = new Date().getFullYear();
if (es) return <div>...Loading Servers</div>;
if (leaseError) return <div>...Loading Leases</div>;
const serverMap = s.map((i: any) => {
return { value: i.name, label: i.name };
});
const leaseMap = leases.map((i: any) => {
return { value: i.id, label: i.leaseNumber };
});
return (
<>
<DialogHeader>
<DialogTitle>Create New Forklift</DialogTitle>
<DialogDescription>Create a new forklift</DialogDescription>
</DialogHeader>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="flex flex-row gap-2 mt-2 mb-2">
<form.AppField
name="serialNumber"
children={(field) => (
<field.InputField
label="Forklift SN"
inputType="string"
required={true}
/>
)}
/>
<form.AppField
name="model"
children={(field) => (
<field.InputField
label="Model"
inputType="string"
required={true}
/>
)}
/>
</div>
<div className="flex flex-row gap-2 mt-2 mb-2">
<form.AppField
name="manufacturer"
children={(field) => (
<field.SelectField
label="Select Forklift Manufacturer"
placeholder="Manufacturer"
options={forkliftManufacturer}
/>
)}
/>
<form.AppField
name="manufacturerYear"
children={(field) => (
<field.InputField
label="Year Made"
inputType="string"
required={true}
/>
)}
/>
</div>
<div className="flex flex-row gap-2 mt-2 mb-2">
<form.AppField
name="engine"
children={(field) => (
<field.SelectField
label="Select Engine Type"
placeholder="Engine Type"
options={engineType}
/>
)}
/>
<form.AppField
name="batteryType"
children={(field) => (
<field.SelectField
label="Select battery type"
placeholder="Battery type"
options={batteryType}
/>
)}
/>
</div>
<div>
<form.AppField
name="profitCenter"
children={(field) => (
<field.SelectField
label="Select profit center"
placeholder="Profit Center"
options={pfc}
/>
)}
/>
</div>
<div className="flex flex-row gap-2 mt-2 mb-2">
<form.AppField
name="plant"
children={(field) => (
<field.SelectField
label="Select Plant"
placeholder="Plant"
options={serverMap}
/>
)}
/>
<form.AppField
name="leaseId"
children={(field) => (
<field.SelectField
label="Select Lease"
placeholder="Plant"
options={leaseMap}
/>
)}
/>
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button type="submit">Submit</Button>
</DialogFooter>
</form>
</>
);
}

View File

@@ -0,0 +1,213 @@
import { useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table";
import { ArrowDown, ArrowUp } from "lucide-react";
//import { useRef } from "react";
import { Button } from "@/components/ui/button";
import { getForklifts } from "@/lib/querys/forklifts/getForklifts";
import TableNoExpand from "@/lib/tableStuff/TableNoExpand";
type Forklifts = {
forklift_id: string;
forkliftNumber: number;
serialNumber: string;
model: string;
plant: string;
forkliftStatus: boolean;
glCode: number;
profitCenter: number;
manufacturer: string;
manufacturerYear: string;
engine: string;
batteryType: string;
};
export const Route = createFileRoute("/_app/_forklifts/forklifts/forklifts")({
component: RouteComponent,
});
function RouteComponent() {
const { data: leaseData = [], isLoading } = useQuery(getForklifts());
const columnHelper = createColumnHelper<Forklifts>();
//const submitting = useRef(false);
const columns = [
columnHelper.accessor("plant", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Plant</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("profitCenter", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">PFC</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("forkliftNumber", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Forklift Number</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("serialNumber", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">SN Number</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
columnHelper.accessor("model", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Model</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
columnHelper.accessor("manufacturer", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Manufacturer</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
columnHelper.accessor("manufacturerYear", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Year</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
columnHelper.accessor("engine", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Engine</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
columnHelper.accessor("batteryType", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Battery Type</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ getValue }) => {
return <span>{getValue()}</span>;
},
}),
];
if (isLoading) {
return <div className="m-auto">Loading user data</div>;
}
return <TableNoExpand data={leaseData} columns={columns} />;
}