feat(quality): priority ranking added

This commit is contained in:
2025-11-14 11:49:57 -06:00
parent c509c7fe28
commit c777395b03
18 changed files with 3137 additions and 103 deletions

View File

@@ -40,7 +40,7 @@ export default function TableNoExpand({
}); });
return ( return (
<div className="p-4"> <div className="p-4">
<div className="w-fit"> <div className="">
<Table> <Table>
<TableHeader> <TableHeader>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (

View File

@@ -21,6 +21,7 @@ import { Route as AppAdminLayoutRouteRouteImport } from './routes/_app/_adminLay
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 OldOldQualityIndexRouteImport } from './routes/_old/old/quality/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 AppForkliftsForkliftsIndexRouteImport } from './routes/_app/_forklifts/forklifts/index'
@@ -107,6 +108,11 @@ const OldOldRfidIndexRoute = OldOldRfidIndexRouteImport.update({
path: '/rfid/', path: '/rfid/',
getParentRoute: () => OldOldRouteRoute, getParentRoute: () => OldOldRouteRoute,
} as any) } as any)
const OldOldQualityIndexRoute = OldOldQualityIndexRouteImport.update({
id: '/quality/',
path: '/quality/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldOcpIndexRoute = OldOldOcpIndexRouteImport.update({ const OldOldOcpIndexRoute = OldOldOcpIndexRouteImport.update({
id: '/ocp/', id: '/ocp/',
path: '/ocp/', path: '/ocp/',
@@ -303,6 +309,7 @@ export interface FileRoutesByFullPath {
'/forklifts': typeof AppForkliftsForkliftsIndexRoute '/forklifts': typeof AppForkliftsForkliftsIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute '/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute '/old/ocp': typeof OldOldOcpIndexRoute
'/old/quality': typeof OldOldQualityIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute '/old/rfid': typeof OldOldRfidIndexRoute
'/admin/modules': typeof AppAdminLayoutAdminSystemModulesRoute '/admin/modules': typeof AppAdminLayoutAdminSystemModulesRoute
'/admin/settings': typeof AppAdminLayoutAdminSystemSettingsRoute '/admin/settings': typeof AppAdminLayoutAdminSystemSettingsRoute
@@ -339,6 +346,7 @@ export interface FileRoutesByTo {
'/forklifts': typeof AppForkliftsForkliftsIndexRoute '/forklifts': typeof AppForkliftsForkliftsIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute '/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute '/old/ocp': typeof OldOldOcpIndexRoute
'/old/quality': typeof OldOldQualityIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute '/old/rfid': typeof OldOldRfidIndexRoute
'/admin/modules': typeof AppAdminLayoutAdminSystemModulesRoute '/admin/modules': typeof AppAdminLayoutAdminSystemModulesRoute
'/admin/settings': typeof AppAdminLayoutAdminSystemSettingsRoute '/admin/settings': typeof AppAdminLayoutAdminSystemSettingsRoute
@@ -383,6 +391,7 @@ export interface FileRoutesById {
'/_app/_forklifts/forklifts/': typeof AppForkliftsForkliftsIndexRoute '/_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/quality/': typeof OldOldQualityIndexRoute
'/_old/old/rfid/': typeof OldOldRfidIndexRoute '/_old/old/rfid/': typeof OldOldRfidIndexRoute
'/_app/_adminLayout/admin/_system/modules': typeof AppAdminLayoutAdminSystemModulesRoute '/_app/_adminLayout/admin/_system/modules': typeof AppAdminLayoutAdminSystemModulesRoute
'/_app/_adminLayout/admin/_system/settings': typeof AppAdminLayoutAdminSystemSettingsRoute '/_app/_adminLayout/admin/_system/settings': typeof AppAdminLayoutAdminSystemSettingsRoute
@@ -422,6 +431,7 @@ export interface FileRouteTypes {
| '/forklifts' | '/forklifts'
| '/m' | '/m'
| '/old/ocp' | '/old/ocp'
| '/old/quality'
| '/old/rfid' | '/old/rfid'
| '/admin/modules' | '/admin/modules'
| '/admin/settings' | '/admin/settings'
@@ -458,6 +468,7 @@ export interface FileRouteTypes {
| '/forklifts' | '/forklifts'
| '/m' | '/m'
| '/old/ocp' | '/old/ocp'
| '/old/quality'
| '/old/rfid' | '/old/rfid'
| '/admin/modules' | '/admin/modules'
| '/admin/settings' | '/admin/settings'
@@ -501,6 +512,7 @@ export interface FileRouteTypes {
| '/_app/_forklifts/forklifts/' | '/_app/_forklifts/forklifts/'
| '/_mobile/_mobileLayout/m/' | '/_mobile/_mobileLayout/m/'
| '/_old/old/ocp/' | '/_old/old/ocp/'
| '/_old/old/quality/'
| '/_old/old/rfid/' | '/_old/old/rfid/'
| '/_app/_adminLayout/admin/_system/modules' | '/_app/_adminLayout/admin/_system/modules'
| '/_app/_adminLayout/admin/_system/settings' | '/_app/_adminLayout/admin/_system/settings'
@@ -602,6 +614,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof OldOldRfidIndexRouteImport preLoaderRoute: typeof OldOldRfidIndexRouteImport
parentRoute: typeof OldOldRouteRoute parentRoute: typeof OldOldRouteRoute
} }
'/_old/old/quality/': {
id: '/_old/old/quality/'
path: '/quality'
fullPath: '/old/quality'
preLoaderRoute: typeof OldOldQualityIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/ocp/': { '/_old/old/ocp/': {
id: '/_old/old/ocp/' id: '/_old/old/ocp/'
path: '/ocp' path: '/ocp'
@@ -949,6 +968,7 @@ const MobileMobileLayoutRouteRouteWithChildren =
interface OldOldRouteRouteChildren { interface OldOldRouteRouteChildren {
OldOldIndexRoute: typeof OldOldIndexRoute OldOldIndexRoute: typeof OldOldIndexRoute
OldOldOcpIndexRoute: typeof OldOldOcpIndexRoute OldOldOcpIndexRoute: typeof OldOldOcpIndexRoute
OldOldQualityIndexRoute: typeof OldOldQualityIndexRoute
OldOldRfidIndexRoute: typeof OldOldRfidIndexRoute OldOldRfidIndexRoute: typeof OldOldRfidIndexRoute
OldOldlogisticsSiloAdjustmentsHistRoute: typeof OldOldlogisticsSiloAdjustmentsHistRoute OldOldlogisticsSiloAdjustmentsHistRoute: typeof OldOldlogisticsSiloAdjustmentsHistRoute
OldOldlogisticsBarcodegenIndexRoute: typeof OldOldlogisticsBarcodegenIndexRoute OldOldlogisticsBarcodegenIndexRoute: typeof OldOldlogisticsBarcodegenIndexRoute
@@ -964,6 +984,7 @@ interface OldOldRouteRouteChildren {
const OldOldRouteRouteChildren: OldOldRouteRouteChildren = { const OldOldRouteRouteChildren: OldOldRouteRouteChildren = {
OldOldIndexRoute: OldOldIndexRoute, OldOldIndexRoute: OldOldIndexRoute,
OldOldOcpIndexRoute: OldOldOcpIndexRoute, OldOldOcpIndexRoute: OldOldOcpIndexRoute,
OldOldQualityIndexRoute: OldOldQualityIndexRoute,
OldOldRfidIndexRoute: OldOldRfidIndexRoute, OldOldRfidIndexRoute: OldOldRfidIndexRoute,
OldOldlogisticsSiloAdjustmentsHistRoute: OldOldlogisticsSiloAdjustmentsHistRoute:
OldOldlogisticsSiloAdjustmentsHistRoute, OldOldlogisticsSiloAdjustmentsHistRoute,

View File

@@ -29,6 +29,7 @@ export function AddCards() {
<Cards name={"ppoo"} inventory /> <Cards name={"ppoo"} inventory />
<Cards name={"inv-empty"} rowType={"empty"} /> <Cards name={"inv-empty"} rowType={"empty"} />
<Cards name={"inv-fg"} rowType={"fg"} /> <Cards name={"inv-fg"} rowType={"fg"} />
<Cards name={"qualityCard"} />
</div> </div>
<div className=""> <div className="">
<Cards name={"inv-materials"} rowType={"materials"} /> <Cards name={"inv-materials"} rowType={"materials"} />

View File

@@ -1,4 +1,5 @@
import { useCardStore } from "../../-lib/store/useCardStore"; import { useCardStore } from "../../-lib/store/useCardStore";
import Quality from "../../quality/-components/WarehouseCard";
import INVCheckCard from "../logistics/warehouse/InventoryCard"; import INVCheckCard from "../logistics/warehouse/InventoryCard";
import OpenOrders from "../logistics/warehouse/openOrders"; import OpenOrders from "../logistics/warehouse/openOrders";
import PPOO from "../logistics/warehouse/PPOOCard"; import PPOO from "../logistics/warehouse/PPOOCard";
@@ -7,6 +8,7 @@ const componentsMap: any = {
ppoo: PPOO, ppoo: PPOO,
inv: INVCheckCard, inv: INVCheckCard,
openOrder: OpenOrders, openOrder: OpenOrders,
qualityCard: Quality,
//QualityRequest, //QualityRequest,
}; };
@@ -26,14 +28,21 @@ export default function DashBoard() {
<Component age={a.age} type={a.rowType} /> <Component age={a.age} type={a.rowType} />
</div> </div>
); );
} else { }
//console.log(name.split("-")[0], a);
if (name === "qualityCard") {
return ( return (
<div key={a.name} className="col-span-3"> <div key={a.name} className="col-span-6">
<Component data={a} /> <Component />
</div> </div>
); );
} }
//console.log(name.split("-")[0], a);
return (
<div key={a.name} className="col-span-3">
<Component data={a} />
</div>
);
})} })}
</div> </div>
); );

View File

@@ -17,6 +17,7 @@ import { AdminSideBar } from "./side-components/admin";
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();
@@ -31,11 +32,12 @@ export function AppSidebar() {
{/* userAccess("logistics", ["systemAdmin", "admin","manager","viewer"]) */} {/* userAccess("logistics", ["systemAdmin", "admin","manager","viewer"]) */}
<LogisticsSideBar user={session?.user as any} userRoles={userRoles} /> <LogisticsSideBar user={session?.user as any} userRoles={userRoles} />
<QualitySideBar user={session?.user as any} userRoles={userRoles} />
{userAccess(null, ["systemAdmin"]) && ( {userAccess(null, ["systemAdmin"]) && (
<> <>
{/* <ForkliftSideBar /> {/* <ForkliftSideBar />
<EomSideBar /> <EomSideBar />
<QualitySideBar /> */} */}
<AdminSideBar /> <AdminSideBar />
</> </>
)} )}

View File

@@ -1,4 +1,6 @@
import { Printer } from "lucide-react"; import { Cat, Printer } from "lucide-react";
import type { UserRoles } from "@/lib/authClient";
import type { User } from "@/types";
import { import {
SidebarGroup, SidebarGroup,
SidebarGroupContent, SidebarGroupContent,
@@ -7,31 +9,49 @@ import {
SidebarMenuButton, SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
} from "../../../../../../components/ui/sidebar"; } from "../../../../../../components/ui/sidebar";
import { useModuleStore } from "../../../-lib/store/useModuleStore";
import { hasPageAccess } from "../../../-utils/userAccess";
const items = [ const iconMap: any = {
{ Printer: Printer,
title: "Qaulity Request", Cat: Cat,
url: "#", };
icon: Printer,
}, export function QualitySideBar({
]; user,
userRoles,
}: {
user: User | null;
userRoles: UserRoles[] | null;
}) {
const { modules } = useModuleStore();
const items = modules?.filter((m) => m.category === "quality" && m.active);
const userUpdate = { ...user, roles: userRoles };
export function QualitySideBar() {
return ( return (
<SidebarGroup> <SidebarGroup>
<SidebarGroupLabel>Quality</SidebarGroupLabel> <SidebarGroupLabel>Quality</SidebarGroupLabel>
<SidebarGroupContent> <SidebarGroupContent>
<SidebarMenu> <SidebarMenu>
{items.map((item) => ( {items.map((item) => {
<SidebarMenuItem key={item.title}> if (!item.active) return;
<SidebarMenuButton asChild> const Icon = iconMap[item.icon === "" ? "Cat" : item.icon];
<a href={item.url}> return (
<item.icon /> <SidebarMenuItem key={item.module_id}>
<span>{item.title}</span> <>
</a> {hasPageAccess(userUpdate as any, item.roles, item.name) && (
</SidebarMenuButton> <SidebarMenuButton asChild>
</SidebarMenuItem> <a href={item.link}>
))} <Icon />
<span>{item.name}</span>
</a>
</SidebarMenuButton>
)}
</>
</SidebarMenuItem>
);
})}
</SidebarMenu> </SidebarMenu>
</SidebarGroupContent> </SidebarGroupContent>
</SidebarGroup> </SidebarGroup>

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getPallets() {
return queryOptions({
queryKey: ["getPallets"],
queryFn: () => fetch(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
}
const fetch = async () => {
const { data } = await axios.get(`/lst/old/api/quality/getrequest`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,331 @@
import { useQuery } from "@tanstack/react-query";
import { useNavigate, useRouterState } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table";
import axios from "axios";
import { ArrowDown, ArrowUp } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useAuth, userAccess } from "@/lib/authClient";
import TableNoExpand from "@/lib/tableStuff/TableNoExpand";
import { getPallets } from "../../-utils/querys/quality/getPallets";
type Pallets = {
request_id: string;
article: string;
description: string;
runningNr: string;
lotNr: string;
warehouseAtRequest: string;
locationAtRequest: string;
warehouseMovedTo: string;
locationMovedTo: string;
durationToMove: null;
qualityDurationToInspect: number;
returnDurationToInspect: number;
locationDropOff: string;
palletStatus: number;
palletStatusText: string;
palletRequest: number;
priority: number;
add_date: Date;
add_user: string;
upd_date: Date;
upd_user: string;
};
export default function QualityRequest() {
const { data, isLoading, refetch } = useQuery(getPallets());
const columnHelper = createColumnHelper<Pallets>();
const { session } = useAuth();
const navigate = useNavigate();
const router = useRouterState();
const currentPath = router.location.href;
const palletCompleted = async (e: any) => {
if (!session || !session.user) {
toast.error("You are allowed to do this unless you are logged in");
navigate({ to: "/login", search: { redirect: currentPath } });
return;
}
const data = {
username: session?.user.username,
runningNr: Number(e.original.runningNr),
palletStatusText: "return",
};
try {
const res = await axios.post("/lst/old/api/quality/newrequest", data);
//console.log(res.data);
if (res.data.success) {
toast.success(res.data.message);
refetch();
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
toast.error("Encountered and error please try again");
}
};
const columns = [
columnHelper.accessor("article", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Article</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("description", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Alias</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("runningNr", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Running Number</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("lotNr", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Lot Number</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("locationAtRequest", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Location At Request</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("locationDropOff", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Drop off Location</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() ? getValue() : "missing dropoff location"}</span>
</>
);
},
}),
columnHelper.accessor("palletStatusText", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Pallet Status</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("palletRequest", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Check Completed</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ row }) => {
// if pending
const okToCompleteStats = [2, 4, 5];
return (
<>
{okToCompleteStats.includes(row.original.palletStatus) ? (
<Button variant="outline" onClick={() => palletCompleted(row)}>
Check Complete
</Button>
) : (
<span>Pending to be completed</span>
)}
</>
);
},
}),
];
let adminColumns: any = [];
if (userAccess("quality", ["systemAdmin", "admin", "supervisor"])) {
adminColumns = [
...columns,
columnHelper.accessor("priority", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() =>
column.toggleSorting(column.getIsSorted() === "asc")
}
>
<span className="flex flex-row gap-2">Priority</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ row, getValue }) => {
// if pending
const [p, setP] = useState(`${getValue()}`);
console.log(getValue());
return (
<>
<Select
value={p}
onValueChange={async (value) => {
setP(value);
const data = {
username: session?.user.username,
runningNr: Number(row.original.runningNr),
priority: value,
};
try {
const res = await axios.post(
"/lst/old/api/quality/newrequest",
data,
);
//console.log(res.data);
if (res.data.success) {
toast.success(res.data.message);
refetch();
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
toast.error("Encountered and error please try again");
}
}}
>
<SelectTrigger
// className={cn(
// "w-[100px]",
// active
// ? "border-green-500 text-green-600"
// : "border-gray-400 text-gray-500",
// )}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Urgent</SelectItem>
<SelectItem value="2">High</SelectItem>
<SelectItem value="3">Medium</SelectItem>
<SelectItem value="4">Low</SelectItem>
</SelectContent>
</Select>
</>
);
},
}),
];
}
if (isLoading) {
return <div className="m-auto">Loading user data</div>;
}
return <TableNoExpand data={data} columns={adminColumns} />;
}

View File

@@ -0,0 +1,161 @@
import { useQuery } from "@tanstack/react-query";
import { useNavigate, useRouterState } from "@tanstack/react-router";
import axios from "axios";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { useAuth } from "@/lib/authClient";
import { useAppForm } from "@/lib/formStuff";
import { getPallets } from "../../-utils/querys/quality/getPallets";
const areaSelection = [
{ value: "rework", label: "Rework" },
{ value: "holdArea", label: "Hold Area" },
{ value: "inspectionArea", label: "Inspection Area" },
];
export default function RequestPallet() {
const { session } = useAuth();
const navigate = useNavigate();
const router = useRouterState();
const { refetch } = useQuery(getPallets());
const currentPath = router.location.href;
const form = useAppForm({
defaultValues: {
username: "",
runningNr: 0,
moveTo: "",
},
onSubmit: async ({ value }) => {
if (!session || !session.user) {
toast.error("You are allowed to do this unless you are logged in");
navigate({ to: "/login", search: { redirect: currentPath } });
return;
}
if (value.runningNr === 0) {
return toast.error(
"You did not change the running number, please add a valid running number",
);
}
const postData = {
runningNr: Number(value.runningNr),
moveTo: value.moveTo,
username: session?.user.username,
};
console.log(postData);
try {
const res = await axios.post(
"/lst/old/api/quality/newrequest",
postData,
);
console.log(res.data);
if (res.data.success) {
toast.success(res.data.message);
form.reset();
refetch();
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
toast.error("Encountered and error please try again");
}
},
});
return (
<Dialog>
<DialogTrigger>
<Button variant="outline">Request Pallet</Button>
</DialogTrigger>
<DialogContent className="w-5/6 m-2">
<DialogHeader>
<DialogTitle>
Request a pallet for the warehouse to retrieve{" "}
</DialogTitle>
<DialogDescription>
This form is used to request a pallet to be brought up to be
inspected, reworked, placed on hold, or please fill out and the
warehouse will see and bring to the designated location. Once
finished click done or cancel.
</DialogDescription>
</DialogHeader>
<div>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="w-5/6 m-2">
<form.AppField
name="runningNr"
children={(field) => (
<field.InputField
label="Pallet Running Number"
inputType="number"
required={true}
/>
)}
/>
</div>
<div className="w-5/6 m-2">
<form.AppField
name="moveTo"
// listeners={{
// onChange: ({ value }) => {
// onValueChange(value);
// },
// }}
children={(field) => (
<field.SelectField
label="Select Area"
placeholder="Quality Areas"
options={areaSelection}
/>
)}
/>
</div>
<div className="w-5/6 m-2">
<DialogFooter>
<DialogClose asChild>
<Button
variant="outline"
onClick={() => {
form.reset();
}}
>
Cancel
</Button>
</DialogClose>
<DialogClose asChild>
<Button
variant="outline"
onClick={() => {
form.reset();
}}
>
Done
</Button>
</DialogClose>
<Button type="submit">Submit</Button>
</DialogFooter>
</div>
</form>
</div>
</DialogContent>
</Dialog>
);
}

View File

@@ -0,0 +1,121 @@
//import { LstCard } from "@/components/extendedUI/LstCard";
import { useQuery } from "@tanstack/react-query";
import { createColumnHelper } from "@tanstack/react-table";
import { ArrowDown, ArrowUp } from "lucide-react";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import TableNoExpand from "@/lib/tableStuff/TableNoExpand";
import { LstCard } from "../../-components/extendedUi/LstCard";
import { getPallets } from "../../-utils/querys/quality/getPallets";
//import { CircleX } from "lucide-react";
//import { Suspense } from "react";
//import { toast } from "sonner";
type Pallets = {
article: string;
runningNr: string;
warehouseAtRequest: string;
locationAtRequest: string;
locationDropOff: string;
};
export default function PPOO() {
//{ style = {} }
const { data, isError, isLoading } = useQuery(getPallets());
const columnHelper = createColumnHelper<Pallets>();
if (isLoading) return <div>Loading pallet data...</div>;
if (isError) {
return (
<div>
<p>There was an error getting the pallets.</p>
</div>
);
}
const monitoring = [1, 4, 6, 7];
const filteredData = data.filter((n: any) =>
monitoring.includes(n.palletStatus),
);
const columns = [
columnHelper.accessor("article", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Article</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("runningNr", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Running Number</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("locationAtRequest", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Location</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("locationDropOff", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">Drop off at</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
];
return (
<LstCard className="w-fit">
<CardHeader>
Quality Request Card Total Pallets {filteredData.length}
</CardHeader>
<TableNoExpand data={filteredData} columns={columns} />
</LstCard>
);
}

View File

@@ -0,0 +1,44 @@
import { createFileRoute, redirect } from "@tanstack/react-router";
import { checkUserAccess } from "@/lib/authClient";
import QualityRequest from "./-components/QualityRequest";
import RequestPallet from "./-components/RequestPallet";
export const Route = createFileRoute("/_old/old/quality/")({
component: RouteComponent,
beforeLoad: async () => {
const auth = await checkUserAccess({
allowedRoles: [
"systemAdmin",
"technician",
"admin",
"manager",
"supervisor",
],
moduleName: "quality", // optional
});
if (!auth) {
throw redirect({
to: "/login",
search: {
// Use the current location to power a redirect after login
// (Do not use `router.state.resolvedLocation` as it can
// potentially lag behind the actual current location)
redirect: location.pathname + location.search,
},
});
}
},
});
function RouteComponent() {
return (
<div className="flex flex-col m-2">
<div className="flex justify-items-start ml-2">
<RequestPallet />
</div>
<QualityRequest />
</div>
);
}

View File

@@ -0,0 +1 @@
ALTER TABLE "qualityRequest" ADD COLUMN "priority" integer DEFAULT 4;

File diff suppressed because it is too large Load Diff

View File

@@ -533,6 +533,13 @@
"when": 1762983466464, "when": 1762983466464,
"tag": "0075_tan_unicorn", "tag": "0075_tan_unicorn",
"breakpoints": true "breakpoints": true
},
{
"idx": 76,
"version": "7",
"when": 1763134709763,
"tag": "0076_stiff_champions",
"breakpoints": true
} }
] ]
} }

View File

@@ -1,45 +1,46 @@
import { import {
text, boolean,
pgTable, index,
numeric, integer,
index, numeric,
timestamp, pgTable,
boolean, text,
uuid, timestamp,
uniqueIndex, uniqueIndex,
integer, uuid,
} from "drizzle-orm/pg-core"; } from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod"; import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod"; import { z } from "zod";
export const qualityRequest = pgTable( export const qualityRequest = pgTable(
"qualityRequest", "qualityRequest",
{ {
request_id: uuid("request_id").defaultRandom().primaryKey(), request_id: uuid("request_id").defaultRandom().primaryKey(),
article: numeric("article"), article: numeric("article"),
description: text("description"), description: text("description"),
runningNr: text("runningNr"), runningNr: text("runningNr"),
lotNr: numeric("lotNr"), lotNr: numeric("lotNr"),
warehouseAtRequest: text("warehouseAtRequest"), warehouseAtRequest: text("warehouseAtRequest"),
locationAtRequest: text("locationAtRequest"), locationAtRequest: text("locationAtRequest"),
warehouseMovedTo: text("warehouseMovedTo"), warehouseMovedTo: text("warehouseMovedTo"),
locationMovedTo: text("locationMovedTo"), locationMovedTo: text("locationMovedTo"),
durationToMove: integer("durationToMove"), durationToMove: integer("durationToMove"),
qualityDurationToInspect: integer("qualityDurationToInspect"), qualityDurationToInspect: integer("qualityDurationToInspect"),
returnDurationToInspect: integer("returnDurationToInspect"), returnDurationToInspect: integer("returnDurationToInspect"),
locationDropOff: text("locationDropOff"), locationDropOff: text("locationDropOff"),
palletStatus: integer("palletStatus"), palletStatus: integer("palletStatus"),
palletStatusText: text("palletStatusText"), palletStatusText: text("palletStatusText"),
palletRequest: integer("palletRequest"), palletRequest: integer("palletRequest"),
add_date: timestamp("add_date").defaultNow(), priority: integer("priority").default(4), // 1,2,3,4
add_user: text("add_user").default("LST"), add_date: timestamp("add_date").defaultNow(),
upd_date: timestamp("upd_date").defaultNow(), add_user: text("add_user").default("LST"),
upd_user: text("upd_user").default("LST"), upd_date: timestamp("upd_date").defaultNow(),
}, upd_user: text("upd_user").default("LST"),
(table) => [ },
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`), (table) => [
// uniqueIndex("role_name").on(table.name), // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
] // uniqueIndex("role_name").on(table.name),
],
); );
// Schema for inserting a user - can be used to validate API requests // Schema for inserting a user - can be used to validate API requests

View File

@@ -1,5 +1,6 @@
import { differenceInMinutes } from "date-fns"; import { differenceInMinutes } from "date-fns";
import { eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import { priority } from "st-ethernet-ip/dist/enip/cip/connection-manager/index.js";
import { db } from "../../../../database/dbclient.js"; import { db } from "../../../../database/dbclient.js";
import { qualityRequest } from "../../../../database/schema/qualityRequest.js"; import { qualityRequest } from "../../../../database/schema/qualityRequest.js";
import { timeZoneFix } from "../../../globalUtils/timeZoneFix.js"; import { timeZoneFix } from "../../../globalUtils/timeZoneFix.js";
@@ -39,11 +40,13 @@ export const addNewPallet = async (data: any) => {
const palletData: any = c; const palletData: any = c;
// if the pallet exist then tell the user to check on it // if the pallet exist then tell the user to check on it
const pStatus = [1, 4, 6]; const pStatus = [1, 4, 6];
if (palletData && pStatus.includes(palletData[0]?.palletStatus)) { if (!data.priority) {
return { if (palletData && pStatus.includes(palletData[0]?.palletStatus)) {
success: false, return {
message: `Running number ${data.runningNr} is already pending or reactivated please follow up with the warehouse team on status to be moved.`, success: false,
}; message: `Running number ${data.runningNr} is already pending or reactivated please follow up with the warehouse team on status to be moved.`,
};
}
} }
// update the existing pallet if already in the system // update the existing pallet if already in the system
@@ -61,25 +64,36 @@ export const addNewPallet = async (data: any) => {
data: pe, data: pe,
}; };
} }
const pData = {
warehouseAtRequest: p[0].warehouseAtRequest, let pData = {};
locationAtRequest: p[0].locationAtRequest,
warehouseMovedTo: null, if (data.priority) {
locationMovedTo: null, pData = {
palletStatus: data.palletStatusText === "return" ? 6 : 4, priority: data.priority,
//durationToMove: 0, upd_user: data.user,
palletStatusText: upd_date: sql`NOW()`,
data.palletStatusText === "return" ? "return" : "reactivated", };
qualityDurationToInspect: } else {
data.palletStatusText === "return" pData = {
? differenceInMinutes(new Date(Date.now()), p[0].lastMove) warehouseAtRequest: p[0].warehouseAtRequest,
: 0, locationAtRequest: p[0].locationAtRequest,
locationDropOff: warehouseMovedTo: null,
data.palletStatusText === "return" ? "Return to warhouse" : "", locationMovedTo: null,
palletRequest: palletData[0].palletStatus + 1, palletStatus: data.palletStatusText === "return" ? 6 : 4,
upd_user: data.user, //durationToMove: 0,
upd_date: sql`NOW()`, palletStatusText:
}; data.palletStatusText === "return" ? "return" : "reactivated",
qualityDurationToInspect:
data.palletStatusText === "return"
? differenceInMinutes(new Date(Date.now()), p[0].lastMove)
: 0,
locationDropOff:
data.palletStatusText === "return" ? "Return to warhouse" : "",
palletRequest: palletData[0].palletStatus + 1,
upd_user: data.user,
upd_date: sql`NOW()`,
};
}
const { data: u, error } = await tryCatch( const { data: u, error } = await tryCatch(
db db

View File

@@ -1,25 +1,28 @@
import { desc } from "drizzle-orm"; import { asc, desc } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js"; import { db } from "../../../../database/dbclient.js";
import { qualityRequest } from "../../../../database/schema/qualityRequest.js"; import { qualityRequest } from "../../../../database/schema/qualityRequest.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js"; import { tryCatch } from "../../../globalUtils/tryCatch.js";
import qualityBlockingMonitor from "../../notifications/controller/notifications/qualityBlocking.js"; import qualityBlockingMonitor from "../../notifications/controller/notifications/qualityBlocking.js";
export const getRequest = async () => { export const getRequest = async () => {
const { data, error } = await tryCatch( const { data, error } = await tryCatch(
db.select().from(qualityRequest).orderBy(desc(qualityRequest.add_date)) db
); .select()
.from(qualityRequest)
.orderBy(asc(qualityRequest.priority), asc(qualityRequest.add_date)),
);
if (error) { if (error) {
return { return {
success: false, success: false,
message: "There was an error getting the quality request", message: "There was an error getting the quality request",
data: error, data: error,
}; };
} }
return { return {
success: true, success: true,
message: "Quality request pallets.", message: "Quality request pallets.",
data, data,
}; };
}; };

View File

@@ -105,7 +105,7 @@ export const qualityCycle = async () => {
); );
} else { } else {
createLog( createLog(
"info", "debug",
"lst", "lst",
"quality", "quality",
`Pallet ${ `Pallet ${
@@ -119,7 +119,7 @@ export const qualityCycle = async () => {
} }
await delay(150); await delay(150);
} else { } else {
createLog("info", "lst", "quality", "nothing to update"); //createLog("info", "lst", "quality", "nothing to update");
} }
}, },
5 * 60 * 1000, 5 * 60 * 1000,