feat(forklifts): added the ability to add new forklifts in
This commit is contained in:
114
app/src/internal/forklifts/routes/hours/addHours.ts
Normal file
114
app/src/internal/forklifts/routes/hours/addHours.ts
Normal 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;
|
||||||
59
app/src/internal/forklifts/routes/hours/getHours.ts
Normal file
59
app/src/internal/forklifts/routes/hours/getHours.ts
Normal 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;
|
||||||
20
app/src/internal/forklifts/routes/hours/leaseRoutes.ts
Normal file
20
app/src/internal/forklifts/routes/hours/leaseRoutes.ts
Normal 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;
|
||||||
@@ -61,7 +61,7 @@ export default function ForkliftSideBar() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Forklifts",
|
title: "Forklifts",
|
||||||
url: "/lst/app/admin/modules",
|
url: "/lst/app/forklifts/forklifts",
|
||||||
icon: Forklift,
|
icon: Forklift,
|
||||||
role: ["systemAdmin", "admin", "manager", "supervisor"],
|
role: ["systemAdmin", "admin", "manager", "supervisor"],
|
||||||
module: "forklifts",
|
module: "forklifts",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Link, useRouterState } from "@tanstack/react-router";
|
import { Link, useRouterState } from "@tanstack/react-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import NewCompanyForm from "@/routes/_app/_forklifts/-components/NewCompany";
|
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 NewInvoice from "@/routes/_app/_forklifts/-components/NewInvoice";
|
||||||
import NewLeaseForm from "@/routes/_app/_forklifts/-components/NewLease";
|
import NewLeaseForm from "@/routes/_app/_forklifts/-components/NewLease";
|
||||||
import { useAuth, useLogout } from "../../lib/authClient";
|
import { useAuth, useLogout } from "../../lib/authClient";
|
||||||
@@ -25,6 +26,7 @@ export default function Nav() {
|
|||||||
const [openDialog, setOpenDialog] = useState(false);
|
const [openDialog, setOpenDialog] = useState(false);
|
||||||
const [openLeaseDialog, setOpenLeaseDialog] = useState(false);
|
const [openLeaseDialog, setOpenLeaseDialog] = useState(false);
|
||||||
const [openInvoiceDialog, setOpenInvoiceDialog] = useState(false);
|
const [openInvoiceDialog, setOpenInvoiceDialog] = useState(false);
|
||||||
|
const [openForkliftDialog, setOpenForkliftDialog] = useState(false);
|
||||||
return (
|
return (
|
||||||
<nav className="flex justify-end w-full shadow ">
|
<nav className="flex justify-end w-full shadow ">
|
||||||
<div className="m-2 flex flex-row gap-1">
|
<div className="m-2 flex flex-row gap-1">
|
||||||
@@ -75,6 +77,14 @@ export default function Nav() {
|
|||||||
>
|
>
|
||||||
New Invoice
|
New Invoice
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onSelect={() => {
|
||||||
|
// just open the dialog when clicked
|
||||||
|
setOpenForkliftDialog(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
New Forklift
|
||||||
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
{/* Company */}
|
{/* Company */}
|
||||||
@@ -105,6 +115,16 @@ export default function Nav() {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)}
|
)}
|
||||||
|
{openForkliftDialog && (
|
||||||
|
<Dialog
|
||||||
|
open={openForkliftDialog}
|
||||||
|
onOpenChange={setOpenForkliftDialog}
|
||||||
|
>
|
||||||
|
<DialogContent className="sm:max-w-fit">
|
||||||
|
<NewForklift setOpenDialog={setOpenForkliftDialog} />
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
17
frontend/src/lib/querys/forklifts/getForklifts.ts
Normal file
17
frontend/src/lib/querys/forklifts/getForklifts.ts
Normal 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;
|
||||||
|
};
|
||||||
@@ -31,6 +31,7 @@ import { Route as MobileMobileLayoutMDeliveryRouteImport } from './routes/_mobil
|
|||||||
import { Route as MobileMobileLayoutMCyclecountsRouteImport } from './routes/_mobile/_mobileLayout/m/cyclecounts'
|
import { Route as MobileMobileLayoutMCyclecountsRouteImport } from './routes/_mobile/_mobileLayout/m/cyclecounts'
|
||||||
import { Route as AppForkliftsForkliftsLeasesRouteImport } from './routes/_app/_forklifts/forklifts/leases'
|
import { Route as AppForkliftsForkliftsLeasesRouteImport } from './routes/_app/_forklifts/forklifts/leases'
|
||||||
import { Route as AppForkliftsForkliftsInvoicesRouteImport } from './routes/_app/_forklifts/forklifts/invoices'
|
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 AppForkliftsForkliftsCompaniesRouteImport } from './routes/_app/_forklifts/forklifts/companies'
|
||||||
import { Route as AppAdminLayoutAdminServersRouteImport } from './routes/_app/_adminLayout/admin/servers'
|
import { Route as AppAdminLayoutAdminServersRouteImport } from './routes/_app/_adminLayout/admin/servers'
|
||||||
import { Route as ApplogisticsLogisticsDeliveryScheduleRouteImport } from './routes/_app/(logistics)/logistics/deliverySchedule'
|
import { Route as ApplogisticsLogisticsDeliveryScheduleRouteImport } from './routes/_app/(logistics)/logistics/deliverySchedule'
|
||||||
@@ -165,6 +166,12 @@ const AppForkliftsForkliftsInvoicesRoute =
|
|||||||
path: '/forklifts/invoices',
|
path: '/forklifts/invoices',
|
||||||
getParentRoute: () => AppForkliftsRouteRoute,
|
getParentRoute: () => AppForkliftsRouteRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
const AppForkliftsForkliftsForkliftsRoute =
|
||||||
|
AppForkliftsForkliftsForkliftsRouteImport.update({
|
||||||
|
id: '/forklifts/forklifts',
|
||||||
|
path: '/forklifts/forklifts',
|
||||||
|
getParentRoute: () => AppForkliftsRouteRoute,
|
||||||
|
} as any)
|
||||||
const AppForkliftsForkliftsCompaniesRoute =
|
const AppForkliftsForkliftsCompaniesRoute =
|
||||||
AppForkliftsForkliftsCompaniesRouteImport.update({
|
AppForkliftsForkliftsCompaniesRouteImport.update({
|
||||||
id: '/forklifts/companies',
|
id: '/forklifts/companies',
|
||||||
@@ -300,6 +307,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
||||||
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
||||||
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
||||||
|
'/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
|
||||||
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
||||||
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
||||||
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
||||||
@@ -337,6 +345,7 @@ export interface FileRoutesByTo {
|
|||||||
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
||||||
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
'/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
||||||
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
||||||
|
'/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
|
||||||
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
'/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
||||||
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
'/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
||||||
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
||||||
@@ -382,6 +391,7 @@ export interface FileRoutesById {
|
|||||||
'/_app/(logistics)/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
'/_app/(logistics)/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
|
||||||
'/_app/_adminLayout/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
'/_app/_adminLayout/admin/servers': typeof AppAdminLayoutAdminServersRoute
|
||||||
'/_app/_forklifts/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
'/_app/_forklifts/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
|
||||||
|
'/_app/_forklifts/forklifts/forklifts': typeof AppForkliftsForkliftsForkliftsRoute
|
||||||
'/_app/_forklifts/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
'/_app/_forklifts/forklifts/invoices': typeof AppForkliftsForkliftsInvoicesRoute
|
||||||
'/_app/_forklifts/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
'/_app/_forklifts/forklifts/leases': typeof AppForkliftsForkliftsLeasesRoute
|
||||||
'/_mobile/_mobileLayout/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
'/_mobile/_mobileLayout/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
|
||||||
@@ -422,6 +432,7 @@ export interface FileRouteTypes {
|
|||||||
| '/logistics/deliverySchedule'
|
| '/logistics/deliverySchedule'
|
||||||
| '/admin/servers'
|
| '/admin/servers'
|
||||||
| '/forklifts/companies'
|
| '/forklifts/companies'
|
||||||
|
| '/forklifts/forklifts'
|
||||||
| '/forklifts/invoices'
|
| '/forklifts/invoices'
|
||||||
| '/forklifts/leases'
|
| '/forklifts/leases'
|
||||||
| '/m/cyclecounts'
|
| '/m/cyclecounts'
|
||||||
@@ -459,6 +470,7 @@ export interface FileRouteTypes {
|
|||||||
| '/logistics/deliverySchedule'
|
| '/logistics/deliverySchedule'
|
||||||
| '/admin/servers'
|
| '/admin/servers'
|
||||||
| '/forklifts/companies'
|
| '/forklifts/companies'
|
||||||
|
| '/forklifts/forklifts'
|
||||||
| '/forklifts/invoices'
|
| '/forklifts/invoices'
|
||||||
| '/forklifts/leases'
|
| '/forklifts/leases'
|
||||||
| '/m/cyclecounts'
|
| '/m/cyclecounts'
|
||||||
@@ -503,6 +515,7 @@ export interface FileRouteTypes {
|
|||||||
| '/_app/(logistics)/logistics/deliverySchedule'
|
| '/_app/(logistics)/logistics/deliverySchedule'
|
||||||
| '/_app/_adminLayout/admin/servers'
|
| '/_app/_adminLayout/admin/servers'
|
||||||
| '/_app/_forklifts/forklifts/companies'
|
| '/_app/_forklifts/forklifts/companies'
|
||||||
|
| '/_app/_forklifts/forklifts/forklifts'
|
||||||
| '/_app/_forklifts/forklifts/invoices'
|
| '/_app/_forklifts/forklifts/invoices'
|
||||||
| '/_app/_forklifts/forklifts/leases'
|
| '/_app/_forklifts/forklifts/leases'
|
||||||
| '/_mobile/_mobileLayout/m/cyclecounts'
|
| '/_mobile/_mobileLayout/m/cyclecounts'
|
||||||
@@ -684,6 +697,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppForkliftsForkliftsInvoicesRouteImport
|
preLoaderRoute: typeof AppForkliftsForkliftsInvoicesRouteImport
|
||||||
parentRoute: typeof AppForkliftsRouteRoute
|
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': {
|
'/_app/_forklifts/forklifts/companies': {
|
||||||
id: '/_app/_forklifts/forklifts/companies'
|
id: '/_app/_forklifts/forklifts/companies'
|
||||||
path: '/forklifts/companies'
|
path: '/forklifts/companies'
|
||||||
@@ -899,6 +919,7 @@ const AppAdminLayoutRouteRouteWithChildren =
|
|||||||
|
|
||||||
interface AppForkliftsRouteRouteChildren {
|
interface AppForkliftsRouteRouteChildren {
|
||||||
AppForkliftsForkliftsCompaniesRoute: typeof AppForkliftsForkliftsCompaniesRoute
|
AppForkliftsForkliftsCompaniesRoute: typeof AppForkliftsForkliftsCompaniesRoute
|
||||||
|
AppForkliftsForkliftsForkliftsRoute: typeof AppForkliftsForkliftsForkliftsRoute
|
||||||
AppForkliftsForkliftsInvoicesRoute: typeof AppForkliftsForkliftsInvoicesRoute
|
AppForkliftsForkliftsInvoicesRoute: typeof AppForkliftsForkliftsInvoicesRoute
|
||||||
AppForkliftsForkliftsLeasesRoute: typeof AppForkliftsForkliftsLeasesRoute
|
AppForkliftsForkliftsLeasesRoute: typeof AppForkliftsForkliftsLeasesRoute
|
||||||
AppForkliftsForkliftsIndexRoute: typeof AppForkliftsForkliftsIndexRoute
|
AppForkliftsForkliftsIndexRoute: typeof AppForkliftsForkliftsIndexRoute
|
||||||
@@ -906,6 +927,7 @@ interface AppForkliftsRouteRouteChildren {
|
|||||||
|
|
||||||
const AppForkliftsRouteRouteChildren: AppForkliftsRouteRouteChildren = {
|
const AppForkliftsRouteRouteChildren: AppForkliftsRouteRouteChildren = {
|
||||||
AppForkliftsForkliftsCompaniesRoute: AppForkliftsForkliftsCompaniesRoute,
|
AppForkliftsForkliftsCompaniesRoute: AppForkliftsForkliftsCompaniesRoute,
|
||||||
|
AppForkliftsForkliftsForkliftsRoute: AppForkliftsForkliftsForkliftsRoute,
|
||||||
AppForkliftsForkliftsInvoicesRoute: AppForkliftsForkliftsInvoicesRoute,
|
AppForkliftsForkliftsInvoicesRoute: AppForkliftsForkliftsInvoicesRoute,
|
||||||
AppForkliftsForkliftsLeasesRoute: AppForkliftsForkliftsLeasesRoute,
|
AppForkliftsForkliftsLeasesRoute: AppForkliftsForkliftsLeasesRoute,
|
||||||
AppForkliftsForkliftsIndexRoute: AppForkliftsForkliftsIndexRoute,
|
AppForkliftsForkliftsIndexRoute: AppForkliftsForkliftsIndexRoute,
|
||||||
|
|||||||
244
frontend/src/routes/_app/_forklifts/-components/NewForklift.tsx
Normal file
244
frontend/src/routes/_app/_forklifts/-components/NewForklift.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
213
frontend/src/routes/_app/_forklifts/forklifts/forklifts.tsx
Normal file
213
frontend/src/routes/_app/_forklifts/forklifts/forklifts.tsx
Normal 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} />;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user