feat(forklifts): added backend forklift stuff and frontend companies

This commit is contained in:
2025-11-02 16:16:35 -06:00
parent a6cc17ccb1
commit 50cde2d8d2
52 changed files with 20619 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
meta { meta {
name: Controller name: Controller
seq: 1 seq: 2
} }
auth { auth {

View File

@@ -1,6 +1,6 @@
meta { meta {
name: LstV2 name: LstV2
seq: 3 seq: 4
} }
auth { auth {

View File

@@ -16,13 +16,13 @@ headers {
body:json { body:json {
{ {
"name": "Dayton", "name": "St Peters",
"serverDNS": "USDAY1VS006", "serverDNS": "USSTP1VMS006",
"plantToken": "usday1", "plantToken": "usstp1",
"ipAddress": "10.44.0.26", "ipAddress": "10.37.0.26",
"greatPlainsPlantCode": 55, "greatPlainsPlantCode": 45,
"lstServerPort": 4000, "lstServerPort": 4000,
"serverLoc": "E$\\LST" "serverLoc": "E:\\LST"
} }
} }

View File

@@ -1,6 +1,6 @@
meta { meta {
name: app name: app
seq: 2 seq: 3
} }
auth { auth {

View File

@@ -0,0 +1,22 @@
meta {
name: Get Companies
type: http
seq: 2
}
get {
url: {{url}}/lst/api/forklifts/companies
body: none
auth: inherit
}
body:json {
{
"name":"Delage DLL"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,27 @@
meta {
name: Update Company
type: http
seq: 3
}
patch {
url: {{url}}/lst/api/forklifts/companies/:id
body: json
auth: inherit
}
params:path {
id: fbfba3df-8c0f-4994-adae-c03808cbccdc
}
body:json {
{
"name":"Delage DLL",
"active": true
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,22 @@
meta {
name: add company
type: http
seq: 1
}
post {
url: {{url}}/lst/api/forklifts/companies
body: json
auth: inherit
}
body:json {
{
"name":"Delage DLL"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,8 @@
meta {
name: companies
seq: 1
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,8 @@
meta {
name: forklifts
seq: 4
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,105 @@
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 {
forkliftCompanies,
insertForkliftCompanySchema,
} from "../../../../pkg/db/schema/forkliftLeaseCompanys.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 company" });
const parsed = insertForkliftCompanySchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ errors: parsed.error.flatten() });
}
const { data, error } = await tryCatch(
db
.insert(forkliftCompanies)
.values({
...parsed.data,
add_user: req.user?.username,
add_date: sql`NOW()`,
upd_user: req.user?.username,
upd_date: sql`NOW()`,
})
//.onConflictDoNothing()
.returning({
name: forkliftCompanies.name,
}),
);
if (error) {
const err: DrizzleError = error;
return res.status(400).json({
message: `Error adding the server`,
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/companies`,
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: `Server ${data[0]?.name} added`, data: data });
});
export default router;

View File

@@ -0,0 +1,22 @@
import { Router } from "express";
import { requireAuth } from "../../../../pkg/middleware/authMiddleware.js";
import { restrictToHosts } from "../../../../pkg/middleware/restrictToHosts.js";
import addCompany from "./addCompany.js";
import getCompanies from "./getCompanies.js";
import updateCompany from "./updateServer.js";
const router = Router();
router.use(
"/",
requireAuth("forklifts", ["systemAdmin", "admin"]),
getCompanies,
);
router.use("/", requireAuth("forklifts", ["systemAdmin", "admin"]), addCompany);
router.use(
"/",
requireAuth("forklifts", ["systemAdmin", "admin"]),
updateCompany,
);
export default router;

View File

@@ -0,0 +1,35 @@
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 { tryCatch } from "../../../../pkg/utils/tryCatch.js";
const router = Router();
router.get("/", async (req: Request, res: Response) => {
const name = req.query.name;
const conditions = [];
if (name !== undefined) {
conditions.push(eq(forkliftCompanies.name, `${name}`));
}
//conditions.push(eq(forkliftCompanies.active, true));
const { data, error } = await tryCatch(
db
.select()
.from(forkliftCompanies)
.where(and(...conditions))
.orderBy(asc(forkliftCompanies.name)),
);
if (error) {
return res.status(400).json({ error: error });
}
res.status(200).json({ message: "Current Active Companies", data: data });
});
export default router;

View File

@@ -0,0 +1,103 @@
import axios from "axios";
import { eq, 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 { forkliftCompanies } from "../../../../pkg/db/schema/forkliftLeaseCompanys.js";
import { serverData } from "../../../../pkg/db/schema/servers.js";
import { createLogger } from "../../../../pkg/logger/logger.js";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
const router = Router();
router.patch("/:id", async (req: Request, res: Response) => {
const log = createLogger({
module: "forklifts",
subModule: "update company",
});
// when a server is updated and 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, we want to insert with update on conflict.
const id = req.params.id;
const updates: Record<string, any> = {};
console.log(req.body);
if (req.body?.name !== undefined) {
updates.name = req.body.name;
}
if (req.body?.active !== undefined) {
updates.active = req.body.active;
}
updates.upd_user = req.user!.username || "lst_user";
updates.upd_date = sql`NOW()`;
try {
if (Object.keys(updates).length > 0) {
await db
.update(forkliftCompanies)
.set(updates)
.where(eq(forkliftCompanies.id, id));
}
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,
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];
//console.log(setCookie.split(";")[0].replace("__Secure-", ""));
if (!setCookie) {
throw new Error("Did not receive a Set-Cookie header from login");
}
const { data, error } = await tryCatch(
axios.patch(
`${process.env.MAIN_SERVER}/lst/api/forklifts/companies/${id}`,
updates,
{
headers: {
"Content-Type": "application/json",
Cookie: setCookie.split(";")[0],
},
withCredentials: true,
},
),
);
if (error) {
//console.log(error);
log.error(
{ stack: error },
"There was an error updating the company to Main Server",
);
}
log.info(
{ stack: data?.data },
"A new company was just updated to the server.",
);
}
res.status(200).json({ message: `${id} was just updated` });
} catch (error) {
//console.log(error);
res.status(200).json({ message: "Error Server updated", error });
}
});
export default router;

View File

@@ -0,0 +1,9 @@
import type { Express, Request, Response } from "express";
import { requireAuth } from "../../../pkg/middleware/authMiddleware.js";
import companies from "./companies/companiesRoutes.js";
export const setupForkliftRoutes = (app: Express, basePath: string) => {
app.use(
basePath + "/api/forklifts/companies", // will pass bc system admin but this is just telling us we need this
companies,
);
};

View File

@@ -1,23 +1,25 @@
import type { Express, Request, Response } from "express"; import type { Express, Request, Response } from "express";
import { setupAuthRoutes } from "../auth/routes/routes.js";
import { setupAdminRoutes } from "../admin/routes.js"; import { setupAdminRoutes } from "../admin/routes.js";
import { setupSystemRoutes } from "../system/routes.js"; import { setupAuthRoutes } from "../auth/routes/routes.js";
import { setupForkliftRoutes } from "../forklifts/routes/routes.js";
import { setupLogisticsRoutes } from "../logistics/routes.js"; import { setupLogisticsRoutes } from "../logistics/routes.js";
import { setupSystemRoutes } from "../system/routes.js";
export const setupRoutes = (app: Express, basePath: string) => { export const setupRoutes = (app: Express, basePath: string) => {
// all routes // all routes
setupAuthRoutes(app, basePath); setupAuthRoutes(app, basePath);
setupAdminRoutes(app, basePath); setupAdminRoutes(app, basePath);
setupSystemRoutes(app, basePath); setupSystemRoutes(app, basePath);
setupLogisticsRoutes(app, basePath); setupLogisticsRoutes(app, basePath);
setupForkliftRoutes(app, basePath);
// always try to go to the app weather we are in dev or in production. // always try to go to the app weather we are in dev or in production.
app.get(basePath + "/", (req: Request, res: Response) => { app.get(basePath + "/", (req: Request, res: Response) => {
res.redirect(basePath + "/app"); res.redirect(basePath + "/app");
}); });
// Fallback 404 handler // Fallback 404 handler
app.use((req: Request, res: Response) => { app.use((req: Request, res: Response) => {
res.status(404).json({ error: "Not Found" }); res.status(404).json({ error: "Not Found" });
}); });
}; };

View File

View File

@@ -0,0 +1,26 @@
import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import z from "zod";
export const forkliftCompanies = pgTable("forklift_companies", {
id: uuid("id").defaultRandom().primaryKey(),
name: text("name").notNull().unique(),
active: boolean("active").default(true),
add_date: timestamp("add_date").defaultNow(),
add_user: text("add_user").default("LST"),
upd_date: timestamp("upd_date").defaultNow(),
upd_user: text("upd_user").default("LST"),
});
export const selectForkliftCompanySchema =
createSelectSchema(forkliftCompanies);
export const insertForkliftCompanySchema = createInsertSchema(
forkliftCompanies,
).extend({
name: z.string().min(3),
// zipcode: z
// .string()
// .regex(/^\d{5}$/)
// .optional(),
});

View File

@@ -0,0 +1,13 @@
import { date, pgTable, text, uuid } from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
import { forkliftCompanies } from "./forkliftLeaseCompanys.js";
export const leases = pgTable("leases", {
id: uuid("id").defaultRandom().primaryKey(),
leaseNumber: text("lease_number").notNull(),
companyId: uuid("company_id").references(() => forkliftCompanies.id),
startDate: date("start_date"),
endDate: date("end_date"),
leaseLink: text("lease_link"),
});
export const selectLeasesDataSchema = createSelectSchema(leases);

View File

@@ -0,0 +1,14 @@
import { numeric, pgTable, serial, uuid } from "drizzle-orm/pg-core";
import { forklifts } from "./forklifts.js";
import { leaseInvoices } from "./leaseInvoices.js";
export const leaseInvoiceForklifts = pgTable("lease_invoice_forklifts", {
id: serial("id").primaryKey(),
invoiceId: uuid("invoice_id")
.notNull()
.references(() => leaseInvoices.id, { onDelete: "cascade" }),
forkliftId: uuid("forklift_id")
.notNull()
.references(() => forklifts.forklift_id, { onDelete: "cascade" }),
amount: numeric("amount"), // optional: amount of invoice allocated to this lift
});

View File

View File

@@ -0,0 +1,52 @@
import {
integer,
pgEnum,
pgTable,
serial,
text,
timestamp,
uuid,
} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import { leases } from "./forkliftLeases.js";
import { serverData } from "./servers.js";
const status = pgEnum("forklift_status", [
"active",
"inactive",
"sold",
"retired",
"transferred",
]);
export const forklifts = pgTable("forklifts", {
forklift_id: uuid("forklift_id").defaultRandom().primaryKey(),
forkliftNumber: serial("forklift_number").notNull(),
serialNumber: text("serial_number").notNull(),
model: text("model").notNull(),
plant: text("plant")
.notNull()
.references(() => serverData.name, { onDelete: "set null" }), // what plant the forklift is in.
forkliftStatus: text("forklift_status").default("active"), //["active","inactive","sold","retired","transferred",]
glCode: integer("gl_code").notNull(), // this will be updated on the onconflift update so we dont do anything funny.
profitCenter: integer("profit_center").notNull(), // should be updated if its changing profit centers per request by the plant
manufacturer: text("manufacturer").notNull(),
manufacturerYear: text("manufacturer_year").notNull(),
engine: text("engine").notNull(),
batteryType: text("battery_type").notNull(),
leaseId: uuid("lease_id").references(() => leases.id, {
onDelete: "set null",
}),
dataPlate: text("data_plate"),
add_date: timestamp("add_date").defaultNow(),
add_user: text("add_user").default("LST"),
upd_date: timestamp("add_date").defaultNow(),
upd_user: text("add_user").default("LST"),
});
export const forkliftsSchema = createSelectSchema(forklifts);
export const newForkliftsSchema = createInsertSchema(forklifts);
export type Forklift = z.infer<typeof forkliftsSchema>;
export type NewNewForklift = z.infer<typeof newForkliftsSchema>;

View File

@@ -0,0 +1,19 @@
import { date, numeric, pgTable, text, uuid } from "drizzle-orm/pg-core";
import { forkliftCompanies } from "./forkliftLeaseCompanys.js";
import { leases } from "./forkliftLeases.js";
import { forklifts } from "./forklifts.js";
export const leaseInvoices = pgTable("lease_invoices", {
id: uuid("id").defaultRandom().primaryKey(),
leaseId: uuid("lease_id")
.notNull()
.references(() => leases.id, { onDelete: "cascade" }),
companyId: uuid("company_id").references(() => forkliftCompanies.id),
invoiceNumber: text("invoice_number").notNull(),
invoiceDate: date("invoice_date").notNull(),
forkliftId: uuid("forklift_id")
.notNull()
.references(() => forklifts.forklift_id, { onDelete: "cascade" }),
totalAmount: numeric("total_amount"),
uploadedBy: text("uploaded_by"),
});

View File

@@ -0,0 +1,94 @@
import { Link } from "@tanstack/react-router";
import {
Building2,
Forklift,
Hourglass,
ReceiptText,
Wrench,
} from "lucide-react";
import { userAccess } from "@/lib/authClient";
import {
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "../ui/sidebar";
import type { Items } from "./SideBarNav";
export default function ForkliftSideBar() {
const items: Items[] = [
{
title: "Lease Companies",
url: "/lst/app/forklifts/companies",
icon: Building2,
role: ["systemAdmin", "admin"],
module: "forklifts",
active: true,
},
{
title: "Leases",
url: "/lst/app/admin/settings",
icon: ReceiptText,
role: ["systemAdmin", "admin"],
module: "forklifts",
active: true,
},
{
title: "Invoices",
url: "/lst/app/admin/settings",
icon: ReceiptText,
role: ["systemAdmin", "admin", "manager"],
module: "forklifts",
active: true,
},
{
title: "Repairs",
url: "/lst/app/admin/settings",
icon: Wrench,
role: ["systemAdmin", "admin", "manager"],
module: "forklifts",
active: true,
},
{
title: "Hours",
url: "/lst/app/admin/settings",
icon: Hourglass,
role: ["systemAdmin", "admin", "manager", "supervisor"],
module: "forklifts",
active: true,
},
{
title: "Forklifts",
url: "/lst/app/admin/modules",
icon: Forklift,
role: ["systemAdmin", "admin", "manager", "supervisor"],
module: "forklifts",
active: true,
},
];
return (
<SidebarGroup>
<SidebarGroupLabel>Forklifts</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<>
{userAccess(item.module, item.role) && item.active && (
<SidebarMenuButton asChild>
<Link to={item.url}>
<item.icon />
<span>{item.title}</span>
</Link>
</SidebarMenuButton>
)}
</>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
}

View File

@@ -1,8 +1,11 @@
import { Link, useRouterState } from "@tanstack/react-router"; import { Link, useRouterState } from "@tanstack/react-router";
import { useState } from "react";
import NewCompanyForm from "@/routes/_app/_forklifts/-components/NewCompany";
import { useAuth, useLogout } from "../../lib/authClient"; import { useAuth, useLogout } from "../../lib/authClient";
import { ModeToggle } from "../mode-toggle"; import { ModeToggle } from "../mode-toggle";
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { Dialog, DialogContent } from "../ui/dialog";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -17,6 +20,7 @@ export default function Nav() {
const logout = useLogout(); const logout = useLogout();
const router = useRouterState(); const router = useRouterState();
const currentPath = router.location.href; const currentPath = router.location.href;
const [openDialog, setOpenDialog] = 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">
@@ -33,6 +37,37 @@ export default function Nav() {
<Button className="m-1"> <Button className="m-1">
<Link to="/old">Old Version</Link> <Link to="/old">Old Version</Link>
</Button> </Button>
<div className="m-1">
{location.pathname.includes("forklifts") && (
<>
<DropdownMenu>
<DropdownMenuTrigger>
<Button>Forklifts</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Forklift links</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onSelect={() => {
// just open the dialog when clicked
setOpenDialog(true);
}}
>
New Company
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{/* Dialog mounted outside the menu */}
{openDialog && (
<Dialog open={openDialog} onOpenChange={setOpenDialog}>
<DialogContent className="sm:max-w-[425px]">
<NewCompanyForm setOpenDialog={setOpenDialog} />
</DialogContent>
</Dialog>
)}
</>
)}
</div>
{session ? ( {session ? (
<div className="m-1"> <div className="m-1">
<DropdownMenu> <DropdownMenu>

View File

@@ -1,5 +1,6 @@
import { Link } from "@tanstack/react-router"; import { Link } from "@tanstack/react-router";
import { userAccess } from "../../lib/authClient"; import type { LucideIcon } from "lucide-react";
import { type UserRoles, userAccess } from "@/lib/authClient";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
@@ -8,17 +9,32 @@ import {
SidebarTrigger, SidebarTrigger,
} from "../ui/sidebar"; } from "../ui/sidebar";
import Admin from "./Admin"; import Admin from "./Admin";
import ForkliftSideBar from "./ForkliftSideBar";
import { Header } from "./Header"; import { Header } from "./Header";
export type Items = {
title: string;
url: string;
icon: LucideIcon;
role: UserRoles["role"][];
module: string;
active: boolean;
};
export default function SideBarNav() { export default function SideBarNav() {
return ( return (
<div className="flex min-h-screen"> <div className="flex min-h-screen">
<Sidebar collapsible="icon"> <Sidebar collapsible="icon">
<Header /> <Header />
<SidebarContent> <SidebarContent>
{userAccess(null, [
"systemAdmin",
"admin",
"manager",
"supervisor",
]) && <ForkliftSideBar />}
{userAccess(null, ["systemAdmin", "admin"]) && <Admin />} {userAccess(null, ["systemAdmin", "admin"]) && <Admin />}
</SidebarContent> </SidebarContent>
<SidebarFooter> <SidebarFooter>
<SidebarMenuItem> <SidebarMenuItem>
<Link to={"/changelog"}>Changelog</Link> <Link to={"/changelog"}>Changelog</Link>

View File

@@ -16,16 +16,19 @@ import { Route as AppIndexRouteImport } from './routes/_app/index'
import { Route as AppChangelogRouteImport } from './routes/_app/changelog' import { Route as AppChangelogRouteImport } from './routes/_app/changelog'
import { Route as OldOldRouteRouteImport } from './routes/_old/old/route' import { Route as OldOldRouteRouteImport } from './routes/_old/old/route'
import { Route as MobileMobileLayoutRouteRouteImport } from './routes/_mobile/_mobileLayout/route' import { Route as MobileMobileLayoutRouteRouteImport } from './routes/_mobile/_mobileLayout/route'
import { Route as AppForkliftsRouteRouteImport } from './routes/_app/_forklifts/route'
import { Route as AppAdminLayoutRouteRouteImport } from './routes/_app/_adminLayout/route' import { Route as AppAdminLayoutRouteRouteImport } from './routes/_app/_adminLayout/route'
import { Route as OldOldIndexRouteImport } from './routes/_old/old/index' import { Route as OldOldIndexRouteImport } from './routes/_old/old/index'
import { Route as AppauthLoginRouteImport } from './routes/_app/(auth)/login' import { Route as AppauthLoginRouteImport } from './routes/_app/(auth)/login'
import { Route as OldOldRfidIndexRouteImport } from './routes/_old/old/rfid/index' import { Route as OldOldRfidIndexRouteImport } from './routes/_old/old/rfid/index'
import { Route as OldOldOcpIndexRouteImport } from './routes/_old/old/ocp/index' import { Route as OldOldOcpIndexRouteImport } from './routes/_old/old/ocp/index'
import { Route as MobileMobileLayoutMIndexRouteImport } from './routes/_mobile/_mobileLayout/m/index' import { Route as MobileMobileLayoutMIndexRouteImport } from './routes/_mobile/_mobileLayout/m/index'
import { Route as AppForkliftsForkliftsIndexRouteImport } from './routes/_app/_forklifts/forklifts/index'
import { Route as AppauthUserIndexRouteImport } from './routes/_app/(auth)/user/index' import { Route as AppauthUserIndexRouteImport } from './routes/_app/(auth)/user/index'
import { Route as MobileMobileLayoutMRelocateRouteImport } from './routes/_mobile/_mobileLayout/m/relocate' import { Route as MobileMobileLayoutMRelocateRouteImport } from './routes/_mobile/_mobileLayout/m/relocate'
import { Route as MobileMobileLayoutMDeliveryRouteImport } from './routes/_mobile/_mobileLayout/m/delivery' import { Route as MobileMobileLayoutMDeliveryRouteImport } from './routes/_mobile/_mobileLayout/m/delivery'
import { Route as MobileMobileLayoutMCyclecountsRouteImport } from './routes/_mobile/_mobileLayout/m/cyclecounts' import { Route as MobileMobileLayoutMCyclecountsRouteImport } from './routes/_mobile/_mobileLayout/m/cyclecounts'
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'
import { Route as AppauthUserSignupRouteImport } from './routes/_app/(auth)/user/signup' import { Route as AppauthUserSignupRouteImport } from './routes/_app/(auth)/user/signup'
@@ -74,6 +77,10 @@ const MobileMobileLayoutRouteRoute = MobileMobileLayoutRouteRouteImport.update({
id: '/_mobile/_mobileLayout', id: '/_mobile/_mobileLayout',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const AppForkliftsRouteRoute = AppForkliftsRouteRouteImport.update({
id: '/_forklifts',
getParentRoute: () => AppRouteRoute,
} as any)
const AppAdminLayoutRouteRoute = AppAdminLayoutRouteRouteImport.update({ const AppAdminLayoutRouteRoute = AppAdminLayoutRouteRouteImport.update({
id: '/_adminLayout', id: '/_adminLayout',
getParentRoute: () => AppRouteRoute, getParentRoute: () => AppRouteRoute,
@@ -109,6 +116,12 @@ const MobileMobileLayoutMIndexRoute =
path: '/m/', path: '/m/',
getParentRoute: () => MobileMobileLayoutRouteRoute, getParentRoute: () => MobileMobileLayoutRouteRoute,
} as any) } as any)
const AppForkliftsForkliftsIndexRoute =
AppForkliftsForkliftsIndexRouteImport.update({
id: '/forklifts/',
path: '/forklifts/',
getParentRoute: () => AppForkliftsRouteRoute,
} as any)
const AppauthUserIndexRoute = AppauthUserIndexRouteImport.update({ const AppauthUserIndexRoute = AppauthUserIndexRouteImport.update({
id: '/(auth)/user/', id: '/(auth)/user/',
path: '/user/', path: '/user/',
@@ -132,6 +145,12 @@ const MobileMobileLayoutMCyclecountsRoute =
path: '/m/cyclecounts', path: '/m/cyclecounts',
getParentRoute: () => MobileMobileLayoutRouteRoute, getParentRoute: () => MobileMobileLayoutRouteRoute,
} as any) } as any)
const AppForkliftsForkliftsCompaniesRoute =
AppForkliftsForkliftsCompaniesRouteImport.update({
id: '/forklifts/companies',
path: '/forklifts/companies',
getParentRoute: () => AppForkliftsRouteRoute,
} as any)
const AppAdminLayoutAdminServersRoute = const AppAdminLayoutAdminServersRoute =
AppAdminLayoutAdminServersRouteImport.update({ AppAdminLayoutAdminServersRouteImport.update({
id: '/servers', id: '/servers',
@@ -260,10 +279,12 @@ export interface FileRoutesByFullPath {
'/user/signup': typeof AppauthUserSignupRoute '/user/signup': typeof AppauthUserSignupRoute
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute '/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AppAdminLayoutAdminServersRoute '/admin/servers': typeof AppAdminLayoutAdminServersRoute
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute '/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
'/m/delivery': typeof MobileMobileLayoutMDeliveryRoute '/m/delivery': typeof MobileMobileLayoutMDeliveryRoute
'/m/relocate': typeof MobileMobileLayoutMRelocateRoute '/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/user': typeof AppauthUserIndexRoute '/user': typeof AppauthUserIndexRoute
'/forklifts': typeof AppForkliftsForkliftsIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute '/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute '/old/ocp': typeof OldOldOcpIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute '/old/rfid': typeof OldOldRfidIndexRoute
@@ -292,10 +313,12 @@ export interface FileRoutesByTo {
'/user/signup': typeof AppauthUserSignupRoute '/user/signup': typeof AppauthUserSignupRoute
'/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute '/logistics/deliverySchedule': typeof ApplogisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AppAdminLayoutAdminServersRoute '/admin/servers': typeof AppAdminLayoutAdminServersRoute
'/forklifts/companies': typeof AppForkliftsForkliftsCompaniesRoute
'/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute '/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
'/m/delivery': typeof MobileMobileLayoutMDeliveryRoute '/m/delivery': typeof MobileMobileLayoutMDeliveryRoute
'/m/relocate': typeof MobileMobileLayoutMRelocateRoute '/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/user': typeof AppauthUserIndexRoute '/user': typeof AppauthUserIndexRoute
'/forklifts': typeof AppForkliftsForkliftsIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute '/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute '/old/ocp': typeof OldOldOcpIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute '/old/rfid': typeof OldOldRfidIndexRoute
@@ -317,6 +340,7 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/_app': typeof AppRouteRouteWithChildren '/_app': typeof AppRouteRouteWithChildren
'/_app/_adminLayout': typeof AppAdminLayoutRouteRouteWithChildren '/_app/_adminLayout': typeof AppAdminLayoutRouteRouteWithChildren
'/_app/_forklifts': typeof AppForkliftsRouteRouteWithChildren
'/_mobile/_mobileLayout': typeof MobileMobileLayoutRouteRouteWithChildren '/_mobile/_mobileLayout': typeof MobileMobileLayoutRouteRouteWithChildren
'/_old/old': typeof OldOldRouteRouteWithChildren '/_old/old': typeof OldOldRouteRouteWithChildren
'/_app/changelog': typeof AppChangelogRoute '/_app/changelog': typeof AppChangelogRoute
@@ -331,10 +355,12 @@ export interface FileRoutesById {
'/_app/(auth)/user/signup': typeof AppauthUserSignupRoute '/_app/(auth)/user/signup': typeof AppauthUserSignupRoute
'/_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
'/_mobile/_mobileLayout/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute '/_mobile/_mobileLayout/m/cyclecounts': typeof MobileMobileLayoutMCyclecountsRoute
'/_mobile/_mobileLayout/m/delivery': typeof MobileMobileLayoutMDeliveryRoute '/_mobile/_mobileLayout/m/delivery': typeof MobileMobileLayoutMDeliveryRoute
'/_mobile/_mobileLayout/m/relocate': typeof MobileMobileLayoutMRelocateRoute '/_mobile/_mobileLayout/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/_app/(auth)/user/': typeof AppauthUserIndexRoute '/_app/(auth)/user/': typeof AppauthUserIndexRoute
'/_app/_forklifts/forklifts/': typeof AppForkliftsForkliftsIndexRoute
'/_mobile/_mobileLayout/m/': typeof MobileMobileLayoutMIndexRoute '/_mobile/_mobileLayout/m/': typeof MobileMobileLayoutMIndexRoute
'/_old/old/ocp/': typeof OldOldOcpIndexRoute '/_old/old/ocp/': typeof OldOldOcpIndexRoute
'/_old/old/rfid/': typeof OldOldRfidIndexRoute '/_old/old/rfid/': typeof OldOldRfidIndexRoute
@@ -366,10 +392,12 @@ export interface FileRouteTypes {
| '/user/signup' | '/user/signup'
| '/logistics/deliverySchedule' | '/logistics/deliverySchedule'
| '/admin/servers' | '/admin/servers'
| '/forklifts/companies'
| '/m/cyclecounts' | '/m/cyclecounts'
| '/m/delivery' | '/m/delivery'
| '/m/relocate' | '/m/relocate'
| '/user' | '/user'
| '/forklifts'
| '/m' | '/m'
| '/old/ocp' | '/old/ocp'
| '/old/rfid' | '/old/rfid'
@@ -398,10 +426,12 @@ export interface FileRouteTypes {
| '/user/signup' | '/user/signup'
| '/logistics/deliverySchedule' | '/logistics/deliverySchedule'
| '/admin/servers' | '/admin/servers'
| '/forklifts/companies'
| '/m/cyclecounts' | '/m/cyclecounts'
| '/m/delivery' | '/m/delivery'
| '/m/relocate' | '/m/relocate'
| '/user' | '/user'
| '/forklifts'
| '/m' | '/m'
| '/old/ocp' | '/old/ocp'
| '/old/rfid' | '/old/rfid'
@@ -422,6 +452,7 @@ export interface FileRouteTypes {
| '__root__' | '__root__'
| '/_app' | '/_app'
| '/_app/_adminLayout' | '/_app/_adminLayout'
| '/_app/_forklifts'
| '/_mobile/_mobileLayout' | '/_mobile/_mobileLayout'
| '/_old/old' | '/_old/old'
| '/_app/changelog' | '/_app/changelog'
@@ -436,10 +467,12 @@ export interface FileRouteTypes {
| '/_app/(auth)/user/signup' | '/_app/(auth)/user/signup'
| '/_app/(logistics)/logistics/deliverySchedule' | '/_app/(logistics)/logistics/deliverySchedule'
| '/_app/_adminLayout/admin/servers' | '/_app/_adminLayout/admin/servers'
| '/_app/_forklifts/forklifts/companies'
| '/_mobile/_mobileLayout/m/cyclecounts' | '/_mobile/_mobileLayout/m/cyclecounts'
| '/_mobile/_mobileLayout/m/delivery' | '/_mobile/_mobileLayout/m/delivery'
| '/_mobile/_mobileLayout/m/relocate' | '/_mobile/_mobileLayout/m/relocate'
| '/_app/(auth)/user/' | '/_app/(auth)/user/'
| '/_app/_forklifts/forklifts/'
| '/_mobile/_mobileLayout/m/' | '/_mobile/_mobileLayout/m/'
| '/_old/old/ocp/' | '/_old/old/ocp/'
| '/_old/old/rfid/' | '/_old/old/rfid/'
@@ -501,6 +534,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof MobileMobileLayoutRouteRouteImport preLoaderRoute: typeof MobileMobileLayoutRouteRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/_app/_forklifts': {
id: '/_app/_forklifts'
path: ''
fullPath: ''
preLoaderRoute: typeof AppForkliftsRouteRouteImport
parentRoute: typeof AppRouteRoute
}
'/_app/_adminLayout': { '/_app/_adminLayout': {
id: '/_app/_adminLayout' id: '/_app/_adminLayout'
path: '' path: ''
@@ -550,6 +590,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof MobileMobileLayoutMIndexRouteImport preLoaderRoute: typeof MobileMobileLayoutMIndexRouteImport
parentRoute: typeof MobileMobileLayoutRouteRoute parentRoute: typeof MobileMobileLayoutRouteRoute
} }
'/_app/_forklifts/forklifts/': {
id: '/_app/_forklifts/forklifts/'
path: '/forklifts'
fullPath: '/forklifts'
preLoaderRoute: typeof AppForkliftsForkliftsIndexRouteImport
parentRoute: typeof AppForkliftsRouteRoute
}
'/_app/(auth)/user/': { '/_app/(auth)/user/': {
id: '/_app/(auth)/user/' id: '/_app/(auth)/user/'
path: '/user' path: '/user'
@@ -578,6 +625,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof MobileMobileLayoutMCyclecountsRouteImport preLoaderRoute: typeof MobileMobileLayoutMCyclecountsRouteImport
parentRoute: typeof MobileMobileLayoutRouteRoute parentRoute: typeof MobileMobileLayoutRouteRoute
} }
'/_app/_forklifts/forklifts/companies': {
id: '/_app/_forklifts/forklifts/companies'
path: '/forklifts/companies'
fullPath: '/forklifts/companies'
preLoaderRoute: typeof AppForkliftsForkliftsCompaniesRouteImport
parentRoute: typeof AppForkliftsRouteRoute
}
'/_app/_adminLayout/admin/servers': { '/_app/_adminLayout/admin/servers': {
id: '/_app/_adminLayout/admin/servers' id: '/_app/_adminLayout/admin/servers'
path: '/servers' path: '/servers'
@@ -784,8 +838,22 @@ const AppAdminLayoutRouteRouteChildren: AppAdminLayoutRouteRouteChildren = {
const AppAdminLayoutRouteRouteWithChildren = const AppAdminLayoutRouteRouteWithChildren =
AppAdminLayoutRouteRoute._addFileChildren(AppAdminLayoutRouteRouteChildren) AppAdminLayoutRouteRoute._addFileChildren(AppAdminLayoutRouteRouteChildren)
interface AppForkliftsRouteRouteChildren {
AppForkliftsForkliftsCompaniesRoute: typeof AppForkliftsForkliftsCompaniesRoute
AppForkliftsForkliftsIndexRoute: typeof AppForkliftsForkliftsIndexRoute
}
const AppForkliftsRouteRouteChildren: AppForkliftsRouteRouteChildren = {
AppForkliftsForkliftsCompaniesRoute: AppForkliftsForkliftsCompaniesRoute,
AppForkliftsForkliftsIndexRoute: AppForkliftsForkliftsIndexRoute,
}
const AppForkliftsRouteRouteWithChildren =
AppForkliftsRouteRoute._addFileChildren(AppForkliftsRouteRouteChildren)
interface AppRouteRouteChildren { interface AppRouteRouteChildren {
AppAdminLayoutRouteRoute: typeof AppAdminLayoutRouteRouteWithChildren AppAdminLayoutRouteRoute: typeof AppAdminLayoutRouteRouteWithChildren
AppForkliftsRouteRoute: typeof AppForkliftsRouteRouteWithChildren
AppChangelogRoute: typeof AppChangelogRoute AppChangelogRoute: typeof AppChangelogRoute
AppIndexRoute: typeof AppIndexRoute AppIndexRoute: typeof AppIndexRoute
AppauthLoginRoute: typeof AppauthLoginRoute AppauthLoginRoute: typeof AppauthLoginRoute
@@ -798,6 +866,7 @@ interface AppRouteRouteChildren {
const AppRouteRouteChildren: AppRouteRouteChildren = { const AppRouteRouteChildren: AppRouteRouteChildren = {
AppAdminLayoutRouteRoute: AppAdminLayoutRouteRouteWithChildren, AppAdminLayoutRouteRoute: AppAdminLayoutRouteRouteWithChildren,
AppForkliftsRouteRoute: AppForkliftsRouteRouteWithChildren,
AppChangelogRoute: AppChangelogRoute, AppChangelogRoute: AppChangelogRoute,
AppIndexRoute: AppIndexRoute, AppIndexRoute: AppIndexRoute,
AppauthLoginRoute: AppauthLoginRoute, AppauthLoginRoute: AppauthLoginRoute,

View File

@@ -159,16 +159,25 @@ function RouteComponent() {
updateServer.mutate({ token, field, value: newValue }); updateServer.mutate({ token, field, value: newValue });
} }
}; };
let submitting = false;
return ( return (
<Input <Input
value={localValue} value={localValue}
onChange={(e) => setLocalValue(e.currentTarget.value)} onChange={(e) => setLocalValue(e.currentTarget.value)}
onBlur={(e) => handleSubmit(e.currentTarget.value.trim())} onBlur={(e) => {
if (!submitting) {
submitting = true;
handleSubmit(e.currentTarget.value.trim());
setTimeout(() => (submitting = false), 100); // reset after slight delay
}
}}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter") { if (e.key === "Enter") {
e.preventDefault(); e.preventDefault();
handleSubmit(e.currentTarget.value.trim()); handleSubmit(e.currentTarget.value.trim());
e.currentTarget.blur(); // exit edit mode e.currentTarget.blur(); // exit edit mode
setTimeout(() => (submitting = false), 100);
} }
}} }}
/> />

View File

@@ -0,0 +1,80 @@
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 { getCompanies } from "@/lib/querys/forklifts/getModules";
import { useAppForm } from "../../../../lib/formStuff";
export default function NewCompanyForm({
setOpenDialog,
}: {
setOpenDialog: any;
}) {
//const search = useSearch({ from: "/_app/(auth)/login" });
const { refetch } = useQuery(getCompanies());
const form = useAppForm({
defaultValues: {
name: "",
},
onSubmit: async ({ value }) => {
try {
await axios.post("/lst/api/forklifts/companies", {
name: value.name,
});
form.reset();
setOpenDialog(false);
refetch();
toast.success(`${value.name} 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);
}
}
},
});
return (
<>
<DialogHeader>
<DialogTitle>Create New Company</DialogTitle>
<DialogDescription>Add the new Leasing company</DialogDescription>
</DialogHeader>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<form.AppField
name="name"
children={(field) => (
<field.InputField
label="Company Name"
inputType="string"
required={true}
/>
)}
/>
</form>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button type="submit">Submit</Button>
</DialogFooter>
</>
);
}

View File

@@ -0,0 +1,282 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import {
createColumnHelper,
flexRender,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
type SortingState,
useReactTable,
} from "@tanstack/react-table";
import axios from "axios";
import { Activity, ArrowDown, ArrowUp } from "lucide-react";
import React, { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getCompanies } from "@/lib/querys/forklifts/getModules";
import { cn } from "@/lib/utils";
type Company = {
id: string;
name: string;
active: boolean;
};
export const Route = createFileRoute("/_app/_forklifts/forklifts/companies")({
component: RouteComponent,
});
const updateCompanyItem = async (
id: string,
data: Record<string, string | number | boolean | null>,
) => {
try {
const res = await axios.patch(`/lst/api/forklifts/companies/${id}`, data, {
withCredentials: true,
});
toast.success(`Company just updated`);
return res;
} catch (err) {
toast.error("Error in updating company");
return err;
}
};
function RouteComponent() {
const {
data: companyData = [],
isLoading,
refetch,
} = useQuery(getCompanies());
const [sorting, setSorting] = useState<SortingState>([]);
const columnHelper = createColumnHelper<Company>();
const submitting = useRef(false);
const updateCompany = useMutation({
mutationFn: ({
id,
field,
value,
}: {
id: string;
field: string;
value: string | number | boolean | null;
}) => updateCompanyItem(id, { [field]: value }),
onSuccess: () => {
// refetch or update cache
refetch();
},
});
const columns = [
columnHelper.accessor("name", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Name</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ row, getValue }) => {
const initialValue = String(getValue() ?? "");
const [localValue, setLocalValue] = useState(initialValue);
const id = row.original.id;
const field = "name";
useEffect(() => setLocalValue(initialValue), [initialValue]);
const handleSubmit = (newValue: string) => {
if (newValue !== initialValue) {
setLocalValue(newValue);
updateCompany.mutate({ id, field, value: newValue });
}
};
return (
<Input
value={localValue}
onChange={(e) => setLocalValue(e.currentTarget.value)}
onBlur={(e) => {
if (!submitting.current) {
submitting.current = true;
handleSubmit(e.currentTarget.value.trim());
setTimeout(() => (submitting.current = false), 100); // reset after slight delay
}
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
submitting.current = true;
handleSubmit(e.currentTarget.value.trim());
e.currentTarget.blur(); // will trigger blur, but we ignore it
setTimeout(() => (submitting.current = false), 100);
}
}}
/>
);
},
}),
columnHelper.accessor("active", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">
<Activity />
Active
</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ row, getValue }) => {
const active = getValue<boolean>();
const id = row.original.id;
const field = "active";
return (
<Select
value={active ? "true" : "false"}
onValueChange={(value) => {
const newValue = value === "true";
updateCompany.mutate({ id, field, value: newValue });
}}
>
<SelectTrigger
className={cn(
"w-[100px]",
active
? "border-green-500 text-green-600"
: "border-gray-400 text-gray-500",
)}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="true">True</SelectItem>
<SelectItem value="false">False</SelectItem>
</SelectContent>
</Select>
);
},
}),
];
const table = useReactTable({
data: companyData,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
//renderSubComponent: ({ row }: { row: any }) => <ExpandedRow row={row} />,
//getRowCanExpand: () => true,
state: {
sorting,
},
});
if (isLoading) {
return <div className="m-auto">Loading user data</div>;
}
return (
<div className="p-4">
<div className="w-fit">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<React.Fragment key={row.id}>
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
{/* {row.getIsExpanded() && (
<TableRow>
<TableCell colSpan={row.getVisibleCells().length}>
{renderSubComponent({ row })}
</TableCell>
</TableRow>
)} */}
</React.Fragment>
))}
</TableBody>
</Table>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_app/_forklifts/forklifts/')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_app/_forklifts/"!</div>
}

View File

@@ -0,0 +1,19 @@
import { createFileRoute, Outlet } from "@tanstack/react-router";
import { checkUserAccess } from "@/lib/authClient";
export const Route = createFileRoute("/_app/_forklifts")({
beforeLoad: async () =>
checkUserAccess({
allowedRoles: ["admin", "systemAdmin", "manager", "supervisor"],
moduleName: "forklifts", // optional
}),
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<Outlet />
</div>
);
}

View File

@@ -14,12 +14,9 @@ import {
} from "../../../../../lib/authClient"; } from "../../../../../lib/authClient";
import { AdminSideBar } from "./side-components/admin"; import { AdminSideBar } from "./side-components/admin";
import { EomSideBar } from "./side-components/eom";
import { ForkliftSideBar } from "./side-components/forklift";
import { Header } from "./side-components/header"; import { Header } from "./side-components/header";
import { LogisticsSideBar } from "./side-components/logistics"; import { LogisticsSideBar } from "./side-components/logistics";
import { ProductionSideBar } from "./side-components/production"; import { ProductionSideBar } from "./side-components/production";
import { QualitySideBar } from "./side-components/quality";
export function AppSidebar() { export function AppSidebar() {
const { session } = useAuth(); const { session } = useAuth();
@@ -36,9 +33,9 @@ export function AppSidebar() {
<LogisticsSideBar user={session?.user as any} userRoles={userRoles} /> <LogisticsSideBar user={session?.user as any} userRoles={userRoles} />
{userAccess(null, ["systemAdmin"]) && ( {userAccess(null, ["systemAdmin"]) && (
<> <>
<ForkliftSideBar /> {/* <ForkliftSideBar />
<EomSideBar /> <EomSideBar />
<QualitySideBar /> <QualitySideBar /> */}
<AdminSideBar /> <AdminSideBar />
</> </>
)} )}

View File

@@ -0,0 +1,60 @@
CREATE TABLE "forklift_companies" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text NOT NULL,
CONSTRAINT "forklift_companies_name_unique" UNIQUE("name")
);
--> statement-breakpoint
CREATE TABLE "leases" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"lease_number" text NOT NULL,
"company_id" uuid,
"start_date" date,
"end_date" date,
"lease_link" text
);
--> statement-breakpoint
CREATE TABLE "lease_invoice_forklifts" (
"id" serial PRIMARY KEY NOT NULL,
"invoice_id" uuid NOT NULL,
"forklift_id" uuid NOT NULL,
"amount" numeric
);
--> statement-breakpoint
CREATE TABLE "forklifts" (
"forklift_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"forklift_number" serial NOT NULL,
"serial_number" text NOT NULL,
"model" text NOT NULL,
"plant" text NOT NULL,
"forklift_status" "forklift_status" DEFAULT 'active',
"gl_code" integer NOT NULL,
"profit_center" integer NOT NULL,
"manufacturer" text NOT NULL,
"manufacturer_year" text NOT NULL,
"engine" text NOT NULL,
"battery_type" text NOT NULL,
"lease_id" uuid,
"data_plate" text,
"add_date" timestamp DEFAULT now(),
"add_user" text DEFAULT 'LST'
);
--> statement-breakpoint
CREATE TABLE "lease_invoices" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"lease_id" uuid NOT NULL,
"company_id" uuid,
"invoice_number" text NOT NULL,
"invoice_date" date NOT NULL,
"forklift_id" uuid NOT NULL,
"total_amount" numeric,
"uploaded_by" text
);
--> statement-breakpoint
ALTER TABLE "leases" ADD CONSTRAINT "leases_company_id_forklift_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."forklift_companies"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "lease_invoice_forklifts" ADD CONSTRAINT "lease_invoice_forklifts_invoice_id_lease_invoices_id_fk" FOREIGN KEY ("invoice_id") REFERENCES "public"."lease_invoices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "lease_invoice_forklifts" ADD CONSTRAINT "lease_invoice_forklifts_forklift_id_forklifts_forklift_id_fk" FOREIGN KEY ("forklift_id") REFERENCES "public"."forklifts"("forklift_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_plant_serverData_name_fk" FOREIGN KEY ("plant") REFERENCES "public"."serverData"("name") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_lease_id_leases_id_fk" FOREIGN KEY ("lease_id") REFERENCES "public"."leases"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "lease_invoices" ADD CONSTRAINT "lease_invoices_lease_id_leases_id_fk" FOREIGN KEY ("lease_id") REFERENCES "public"."leases"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "lease_invoices" ADD CONSTRAINT "lease_invoices_company_id_forklift_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."forklift_companies"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "lease_invoices" ADD CONSTRAINT "lease_invoices_forklift_id_forklifts_forklift_id_fk" FOREIGN KEY ("forklift_id") REFERENCES "public"."forklifts"("forklift_id") ON DELETE cascade ON UPDATE no action;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "forklifts" ALTER COLUMN "forklift_status" SET DATA TYPE text;--> statement-breakpoint
ALTER TABLE "forklifts" ALTER COLUMN "forklift_status" SET DEFAULT 'active';

View File

@@ -0,0 +1 @@
CREATE UNIQUE INDEX "plant_name" ON "serverData" USING btree ("name");

View File

@@ -0,0 +1,4 @@
ALTER TABLE "forklifts" DROP CONSTRAINT "forklifts_plant_serverData_name_fk";
--> statement-breakpoint
DROP INDEX "plant_name";--> statement-breakpoint
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_plant_serverData_server_id_fk" FOREIGN KEY ("plant") REFERENCES "public"."serverData"("server_id") ON DELETE set null ON UPDATE no action;

View File

@@ -0,0 +1,4 @@
ALTER TABLE "forklifts" DROP CONSTRAINT "forklifts_plant_serverData_server_id_fk";
--> statement-breakpoint
ALTER TABLE "serverData" ADD CONSTRAINT "serverData_name_unique" UNIQUE("name");
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_plant_serverData_name_fk" FOREIGN KEY ("plant") REFERENCES "public"."serverData"("name") ON DELETE set null ON UPDATE no action;--> statement-breakpoint

View File

@@ -0,0 +1,3 @@
ALTER TABLE "forklifts" DROP CONSTRAINT "forklifts_plant_serverData_name_fk";
--> statement-breakpoint
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_plant_serverData_server_id_fk" FOREIGN KEY ("plant") REFERENCES "public"."serverData"("server_id") ON DELETE set null ON UPDATE no action;

View File

@@ -0,0 +1,3 @@
ALTER TABLE "forklifts" DROP CONSTRAINT "forklifts_plant_serverData_server_id_fk";
--> statement-breakpoint
ALTER TABLE "forklifts" ADD CONSTRAINT "forklifts_plant_serverData_name_fk" FOREIGN KEY ("plant") REFERENCES "public"."serverData"("name") ON DELETE set null ON UPDATE no action;

View File

@@ -0,0 +1,3 @@
ALTER TABLE "forklift_companies" ADD COLUMN "active" boolean DEFAULT true;--> statement-breakpoint
ALTER TABLE "forklift_companies" ADD COLUMN "add_date" timestamp DEFAULT now();--> statement-breakpoint
ALTER TABLE "forklift_companies" ADD COLUMN "add_user" text DEFAULT 'LST';

View File

@@ -0,0 +1,2 @@
ALTER TABLE "forklift_companies" ADD COLUMN "upd_date" timestamp DEFAULT now();--> statement-breakpoint
ALTER TABLE "forklift_companies" ADD COLUMN "upd_user" text DEFAULT 'LST';

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -197,6 +197,69 @@
"when": 1761938877395, "when": 1761938877395,
"tag": "0027_special_harpoon", "tag": "0027_special_harpoon",
"breakpoints": true "breakpoints": true
},
{
"idx": 28,
"version": "7",
"when": 1762110963295,
"tag": "0028_brown_praxagora",
"breakpoints": true
},
{
"idx": 29,
"version": "7",
"when": 1762111060465,
"tag": "0029_rapid_wallow",
"breakpoints": true
},
{
"idx": 30,
"version": "7",
"when": 1762111106977,
"tag": "0030_flawless_talisman",
"breakpoints": true
},
{
"idx": 31,
"version": "7",
"when": 1762111262895,
"tag": "0031_red_bug",
"breakpoints": true
},
{
"idx": 32,
"version": "7",
"when": 1762111388336,
"tag": "0032_eminent_james_howlett",
"breakpoints": true
},
{
"idx": 33,
"version": "7",
"when": 1762111567029,
"tag": "0033_luxuriant_marvel_zombies",
"breakpoints": true
},
{
"idx": 34,
"version": "7",
"when": 1762111614977,
"tag": "0034_living_war_machine",
"breakpoints": true
},
{
"idx": 35,
"version": "7",
"when": 1762112218732,
"tag": "0035_overrated_ben_parker",
"breakpoints": true
},
{
"idx": 36,
"version": "7",
"when": 1762112909957,
"tag": "0036_sticky_brood",
"breakpoints": true
} }
] ]
} }