feat(frontend): migrated old > new silo adjustments
moved the apps around so we can use 1 url for cors bs
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
import { ReactNode } from "react";
|
||||
import { Card } from "../ui/card";
|
||||
|
||||
interface LstCardProps {
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export function LstCard({
|
||||
children,
|
||||
className = "",
|
||||
style = {},
|
||||
}: LstCardProps) {
|
||||
return (
|
||||
<Card
|
||||
className={`border-solid border-1 border-[#00659c] ${className}`}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import { useSessionStore } from "../../lib/store/sessionStore";
|
||||
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||
import { moduleActive } from "../../utils/moduleActive";
|
||||
import { hasAccess } from "../../utils/userAccess";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarTrigger,
|
||||
} from "../ui/sidebar";
|
||||
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 { LogisticsSideBar } from "./side-components/logistics";
|
||||
import { ProductionSideBar } from "./side-components/production";
|
||||
import { QualitySideBar } from "./side-components/quality";
|
||||
|
||||
export function AppSidebar() {
|
||||
const { user } = useSessionStore();
|
||||
const { modules } = useModuleStore();
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarContent>
|
||||
<Header />
|
||||
{moduleActive("production") && (
|
||||
<ProductionSideBar
|
||||
user={user}
|
||||
moduleID={
|
||||
modules.filter((n) => n.name === "production")[0]
|
||||
.module_id as string
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{moduleActive("logistics") && hasAccess(user, "logistics") && (
|
||||
<LogisticsSideBar user={user} />
|
||||
)}
|
||||
{moduleActive("forklift") && hasAccess(user, "forklift") && (
|
||||
<ForkliftSideBar />
|
||||
)}
|
||||
{moduleActive("eom") && hasAccess(user, "eom") && <EomSideBar />}
|
||||
{moduleActive("quality") && hasAccess(user, "quality") && (
|
||||
<QualitySideBar />
|
||||
)}
|
||||
{moduleActive("admin") && hasAccess(user || [], "admin") && (
|
||||
<AdminSideBar />
|
||||
)}
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarTrigger />
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import {Moon, Sun} from "lucide-react";
|
||||
|
||||
import {Button} from "../ui/button";
|
||||
import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from "../ui/dropdown-menu";
|
||||
import {useTheme} from "../layout/theme-provider";
|
||||
|
||||
export function ModeToggle() {
|
||||
const {setTheme} = useTheme();
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="icon">
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme("dark")}>Dark</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme("system")}>System</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
import {
|
||||
AlignJustify,
|
||||
Atom,
|
||||
Logs,
|
||||
Minus,
|
||||
Plus,
|
||||
Server,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Users,
|
||||
Webhook,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "../../ui/sidebar";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "../../ui/collapsible";
|
||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
|
||||
const iconMap: any = {
|
||||
ShieldCheck: ShieldCheck,
|
||||
AlignJustify: AlignJustify,
|
||||
Settings: Settings,
|
||||
Atom: Atom,
|
||||
Logs: Logs,
|
||||
Users: Users,
|
||||
Webhook: Webhook,
|
||||
Server: Server,
|
||||
};
|
||||
|
||||
export function AdminSideBar() {
|
||||
const { subModules } = useSubModuleStore();
|
||||
const { settings } = useSettingStore();
|
||||
|
||||
const plantToken = settings.filter((n) => n.name === "plantToken");
|
||||
|
||||
const items = subModules.filter((m) => m.moduleName === "admin");
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Admin section</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
{items.map((item: any, index) => {
|
||||
const Icon = iconMap[item.icon] || AlignJustify;
|
||||
// drop down menu setup
|
||||
return (
|
||||
<SidebarMenu key={item.name}>
|
||||
{item.link === "#" ? (
|
||||
<Collapsible
|
||||
key={item.name}
|
||||
defaultOpen={index === 1}
|
||||
className="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<Icon />
|
||||
{item.name}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.subSubModule?.length > 0 ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.subSubModule.map(
|
||||
(i: any) => {
|
||||
const SubIcon =
|
||||
iconMap[
|
||||
i.icon
|
||||
] ||
|
||||
AlignJustify;
|
||||
return (
|
||||
<SidebarMenuSubItem
|
||||
key={i.name}
|
||||
>
|
||||
{i.isActive && (
|
||||
<SidebarMenuSubButton
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={
|
||||
i.name ===
|
||||
"Swagger"
|
||||
? `https://${plantToken[0].value}prod.alpla.net/application/swagger/index.html`
|
||||
: i.link
|
||||
}
|
||||
target={
|
||||
i.newWindow
|
||||
? "_blank"
|
||||
: "_self"
|
||||
}
|
||||
>
|
||||
<SubIcon />
|
||||
<span>
|
||||
{
|
||||
i.name
|
||||
}
|
||||
</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
)}
|
||||
</SidebarMenuSubItem>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
) : (
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
if (item.link === "#") return;
|
||||
return (
|
||||
<SidebarMenuItem key={item.name}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.link}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
)}
|
||||
</SidebarMenu>
|
||||
);
|
||||
})}
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
/* <SidebarMenu>
|
||||
{data.navMain.map((item, index) => (
|
||||
<Collapsible
|
||||
key={item.title}
|
||||
defaultOpen={index === 1}
|
||||
className="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<item.icon />
|
||||
{item.title}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.items?.length ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((item) => (
|
||||
<SidebarMenuSubItem
|
||||
key={item.title}
|
||||
>
|
||||
{item.isActive && (
|
||||
<SidebarMenuSubButton
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={item.url}
|
||||
target={
|
||||
item.newWindow
|
||||
? "_blank"
|
||||
: "_self"
|
||||
}
|
||||
>
|
||||
<item.icon />
|
||||
<span>
|
||||
{item.title}
|
||||
</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
)}
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu> */
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import {FileText} from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "End Of Month",
|
||||
url: "/eom",
|
||||
icon: FileText,
|
||||
},
|
||||
];
|
||||
|
||||
export function EomSideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>End of month</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import {Forklift, Hourglass, Minus, Plus, Signature} from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "../../ui/sidebar";
|
||||
import {Collapsible, CollapsibleTrigger} from "../../ui/collapsible";
|
||||
import {CollapsibleContent} from "@radix-ui/react-collapsible";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Gemone",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
isActive: false,
|
||||
},
|
||||
];
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
{
|
||||
title: "Forklift Management",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
items: [
|
||||
{
|
||||
title: "All Forklifts",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
},
|
||||
{
|
||||
title: "Leasing data",
|
||||
url: "#",
|
||||
isActive: false,
|
||||
icon: Signature,
|
||||
},
|
||||
{
|
||||
title: "Forklift Hours",
|
||||
url: "#",
|
||||
isActive: false,
|
||||
icon: Hourglass,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function ForkliftSideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Forklift Section</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{data.navMain.map((item, index) => (
|
||||
<Collapsible key={item.title} defaultOpen={index === 1} className="group/collapsible">
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<item.icon />
|
||||
{item.title}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.items?.length ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((item) => (
|
||||
<SidebarMenuSubItem key={item.title}>
|
||||
<SidebarMenuSubButton asChild isActive={item.isActive}>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import {
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
|
||||
export function Header() {
|
||||
return (
|
||||
<SidebarHeader>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<Link to="/">
|
||||
<SidebarMenuButton size="lg" asChild>
|
||||
<div className="flex flex-row">
|
||||
<img
|
||||
src={"imgs/dkLst.png"}
|
||||
alt="Description"
|
||||
className="size-8"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-0.5 leading-none">
|
||||
<span className="font-semibold">
|
||||
Logistics Support Tool
|
||||
</span>
|
||||
<span className="">v2.0.0</span>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</Link>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Barcode, Command, Cylinder, Package, Truck } from "lucide-react";
|
||||
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
|
||||
import { User } from "@/types/users";
|
||||
import { hasPageAccess } from "@/utils/userAccess";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
|
||||
const iconMap: any = {
|
||||
Package: Package,
|
||||
Truck: Truck,
|
||||
Cylinder: Cylinder,
|
||||
Barcode: Barcode,
|
||||
Command: Command,
|
||||
};
|
||||
|
||||
export function LogisticsSideBar({ user }: { user: User | null }) {
|
||||
const { subModules } = useSubModuleStore();
|
||||
|
||||
const items = subModules.filter((m) => m.moduleName === "logistics");
|
||||
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
const Icon = iconMap[item.icon];
|
||||
return (
|
||||
<SidebarMenuItem key={item.submodule_id}>
|
||||
<>
|
||||
{hasPageAccess(user, item.roles, item.name) && (
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.link}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
import { Printer, Tag } from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
import { hasPageAccess } from "@/utils/userAccess";
|
||||
import { User } from "@/types/users";
|
||||
|
||||
export function ProductionSideBar({
|
||||
user,
|
||||
moduleID,
|
||||
}: {
|
||||
user: User | null;
|
||||
moduleID: string;
|
||||
}) {
|
||||
const url: string = window.location.host.split(":")[0];
|
||||
const items = [
|
||||
{
|
||||
title: "One Click Print",
|
||||
url: "/ocp",
|
||||
icon: Printer,
|
||||
role: ["viewer"],
|
||||
module: "ocp",
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
title: "Rfid Readers",
|
||||
url: "/rfid",
|
||||
icon: Tag,
|
||||
role: ["viewer"],
|
||||
module: "production",
|
||||
active:
|
||||
url === "usday1vms006" || url === "localhost" ? true : false,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Production</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<>
|
||||
{hasPageAccess(user, item.role, moduleID) &&
|
||||
item.active && (
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import {Printer} from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../ui/sidebar";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Qaulity Request",
|
||||
url: "#",
|
||||
icon: Printer,
|
||||
},
|
||||
];
|
||||
|
||||
export function QualitySideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Quality</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import {createContext, useContext, useEffect, useState} from "react";
|
||||
|
||||
type Theme = "dark" | "light" | "system";
|
||||
|
||||
type ThemeProviderProps = {
|
||||
children: React.ReactNode;
|
||||
defaultTheme?: Theme;
|
||||
storageKey?: string;
|
||||
};
|
||||
|
||||
type ThemeProviderState = {
|
||||
theme: Theme;
|
||||
setTheme: (theme: Theme) => void;
|
||||
};
|
||||
|
||||
const initialState: ThemeProviderState = {
|
||||
theme: "system",
|
||||
setTheme: () => null,
|
||||
};
|
||||
|
||||
const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
|
||||
|
||||
export function ThemeProvider({
|
||||
children,
|
||||
defaultTheme = "system",
|
||||
storageKey = "vite-ui-theme",
|
||||
...props
|
||||
}: ThemeProviderProps) {
|
||||
const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem(storageKey) as Theme) || defaultTheme);
|
||||
|
||||
useEffect(() => {
|
||||
const root = window.document.documentElement;
|
||||
|
||||
root.classList.remove("light", "dark");
|
||||
|
||||
if (theme === "system") {
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
|
||||
root.classList.add(systemTheme);
|
||||
return;
|
||||
}
|
||||
|
||||
root.classList.add(theme);
|
||||
}, [theme]);
|
||||
|
||||
const value = {
|
||||
theme,
|
||||
setTheme: (theme: Theme) => {
|
||||
localStorage.setItem(storageKey, theme);
|
||||
setTheme(theme);
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProviderContext.Provider {...props} value={value}>
|
||||
{children}
|
||||
</ThemeProviderContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useTheme = () => {
|
||||
const context = useContext(ThemeProviderContext);
|
||||
|
||||
if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider");
|
||||
|
||||
return context;
|
||||
};
|
||||
@@ -1,163 +0,0 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
|
||||
import { useAppForm } from "@/utils/formStuff";
|
||||
import { getMachineConnected } from "@/utils/querys/logistics/machineConnected";
|
||||
import { getMachineNotConnected } from "@/utils/querys/logistics/notConnected";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export function AttachSilo(props: any) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, isError, isLoading, refetch } = useQuery(
|
||||
getMachineNotConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "detached",
|
||||
})
|
||||
);
|
||||
const { refetch: attached } = useQuery(
|
||||
getMachineConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "connected",
|
||||
})
|
||||
);
|
||||
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
laneId: props.silo.LocationID,
|
||||
productionLotId: "",
|
||||
machineId: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/api/logistics/attachsilo",
|
||||
value
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
attached();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
} else {
|
||||
console.log(res.data);
|
||||
toast.error(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(
|
||||
"There was an error attaching the silo please try again, if persist please enter a helpdesk ticket."
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (isError)
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error loading data</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (isLoading)
|
||||
return (
|
||||
<div>
|
||||
<p>Loading....</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// convert the array that comes over to label and value
|
||||
const tranMachine = data.map((i: any) => ({
|
||||
value: i.machineId.toString(),
|
||||
label: i.name,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(!open)}>
|
||||
Attach Silo
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Attach silo for: {props.silo.Description}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Enter the new lotnumber, select the machine you
|
||||
would like to attach.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div>
|
||||
<p className="text-sm">
|
||||
NOTE: If the machine you are trying to attach is not
|
||||
showing in the drop down this means it is already
|
||||
attached to this silo.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<form.AppField
|
||||
name="productionLotId"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Lot Number"
|
||||
inputType="number"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<form.AppField
|
||||
name="machineId"
|
||||
children={(field) => (
|
||||
<field.SelectField
|
||||
label="Select Machine"
|
||||
options={tranMachine}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="mt-2">
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Attach</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
|
||||
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
|
||||
import {
|
||||
ChartConfig,
|
||||
ChartContainer,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { format } from "date-fns";
|
||||
|
||||
export default function ChartData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
const chartConfig = {
|
||||
stock: {
|
||||
label: "Stock",
|
||||
color: "rgb(255, 99, 132)",
|
||||
},
|
||||
actual: {
|
||||
label: "Actual",
|
||||
color: "rgb(53, 162, 235)",
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
if (isLoading) return <div>Loading chart data</div>;
|
||||
if (isError) return <div>Error in loading chart data</div>;
|
||||
|
||||
let adjustments: any = data.filter(
|
||||
(l: any) => l.locationID === props.laneId
|
||||
);
|
||||
adjustments = adjustments.splice(0, 10).map((s: any) => {
|
||||
return {
|
||||
date: format(s.dateAdjusted.replace("Z", ""), "M/d/yyyy hh:mm"),
|
||||
stock: s.currentStockLevel,
|
||||
actual: s.newLevel,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<LstCard className="w-[425px] h-[250px] m-1">
|
||||
<CardContent>
|
||||
{adjustments.length === 0 ? (
|
||||
<span>No silo data has been entered for this silo.</span>
|
||||
) : (
|
||||
<ChartContainer config={chartConfig}>
|
||||
<AreaChart
|
||||
accessibilityLayer
|
||||
data={adjustments}
|
||||
margin={{
|
||||
left: 35,
|
||||
right: 45,
|
||||
bottom: 50,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickMargin={14}
|
||||
angle={-45}
|
||||
textAnchor="end"
|
||||
dy={10}
|
||||
tickFormatter={(value) =>
|
||||
format(value, "M/d/yyyy")
|
||||
}
|
||||
/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={
|
||||
<ChartTooltipContent indicator="dot" />
|
||||
}
|
||||
/>
|
||||
<Area
|
||||
dataKey="stock"
|
||||
type="natural"
|
||||
fill="rgba(53, 162, 235, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(53, 162, 235, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
<Area
|
||||
dataKey="actual"
|
||||
type="natural"
|
||||
fill="rgba(255, 99, 132, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(255, 99, 132, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)}
|
||||
</CardContent>
|
||||
{/* <CardFooter>
|
||||
<div className="flex w-full items-start gap-2 text-sm">
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center gap-2 font-medium leading-none">
|
||||
Trending up by 5.2% this month{" "}
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex items-center gap-2 leading-none text-muted-foreground">
|
||||
January - June 2024
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardFooter> */}
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useRouter } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function Comment(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
comment: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
`/api/logistics/postcomment/${data.id.split("&")[0]}`,
|
||||
{
|
||||
comment: value.comment,
|
||||
key: data.id.split("&")[1],
|
||||
},
|
||||
{ headers: { Authorization: `Bearer ${token}` } }
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
form.reset();
|
||||
router.navigate({ to: "/siloAdjustments" });
|
||||
}
|
||||
|
||||
if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
form.reset();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(`There was an error posting your comment.`);
|
||||
}
|
||||
setIsSubmitting(false);
|
||||
},
|
||||
});
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard>
|
||||
<CardHeader>
|
||||
Please enter your comment for the silo adjust
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="comment"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 10
|
||||
? undefined
|
||||
: "Comment must be longer than 10 characters.",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label
|
||||
htmlFor="comment"
|
||||
className="mb-2"
|
||||
>
|
||||
Comment
|
||||
</Label>
|
||||
<Textarea
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
//type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>
|
||||
{field.state.meta.errors.join(
|
||||
","
|
||||
)}
|
||||
</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
onClick={form.handleSubmit}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
|
||||
import { useAppForm } from "@/utils/formStuff";
|
||||
import { getMachineConnected } from "@/utils/querys/logistics/machineConnected";
|
||||
import { getMachineNotConnected } from "@/utils/querys/logistics/notConnected";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export function DetachSilo(props: any) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, isError, isLoading, refetch } = useQuery(
|
||||
getMachineConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "connected",
|
||||
})
|
||||
);
|
||||
|
||||
const { refetch: notConnected } = useQuery(
|
||||
getMachineNotConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "detached",
|
||||
})
|
||||
);
|
||||
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
laneId: props.silo.LocationID,
|
||||
machineId: 0,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/api/logistics/detachsilo",
|
||||
value
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
console.log(res.data.data);
|
||||
toast.success(res.data.message);
|
||||
|
||||
refetch();
|
||||
notConnected();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
} else {
|
||||
console.log(res.data);
|
||||
toast.error(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(
|
||||
"There was an error detaching the silo please try again, if persist please enter a helpdesk ticket."
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (isError)
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error loading data</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (isLoading)
|
||||
return (
|
||||
<div>
|
||||
<p>Loading....</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// convert the array that comes over to label and value
|
||||
const tranMachine = data.map((i: any) => ({
|
||||
value: i.machineId.toString(),
|
||||
label: i.name,
|
||||
}));
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(!open)}
|
||||
disabled={data.length === 0}
|
||||
>
|
||||
Detach Silo
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Attach silo for: {props.silo.Description}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Select the machine you would like to detach.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<div className="mt-2">
|
||||
<form.AppField
|
||||
name="machineId"
|
||||
children={(field) => (
|
||||
<field.SelectField
|
||||
label="Select Machine"
|
||||
options={tranMachine}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Detach</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
import { columns } from "@/utils/tableData/siloAdjustmentHist/siloAdjHistColumns";
|
||||
import { SiloTable } from "@/utils/tableData/siloAdjustmentHist/siloData";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export default function HistoricalData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
|
||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the adjustments.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
//console.log(data[0].locationID, parseInt(props.laneId));
|
||||
const adjustments: any = data.filter(
|
||||
(l: any) => l.locationID === parseInt(props.laneId)
|
||||
);
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
<SiloTable columns={columns} data={adjustments} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { CircleAlert } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CardHeader } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { AttachSilo } from "./AttachSilo";
|
||||
import ChartData from "./ChartData";
|
||||
import { DetachSilo } from "./DetachSilo";
|
||||
|
||||
export default function SiloCard(data: any) {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const { refetch } = useQuery(getStockSilo());
|
||||
const { user } = useSessionStore();
|
||||
const { userRoles } = useGetUserRoles();
|
||||
const { modules } = useModuleStore();
|
||||
const silo = data.silo;
|
||||
|
||||
// roles that can do the silo adjustments
|
||||
const roles = ["systemAdmin", "technician", "admin", "manager"];
|
||||
|
||||
const module = modules.filter((n) => n.name === "logistics");
|
||||
|
||||
const accessRoles = userRoles.filter(
|
||||
(n: any) => n.module === module[0]?.name,
|
||||
) as any;
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
newLevel: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setSubmitting(true);
|
||||
const dataToSubmit = {
|
||||
quantity: parseFloat(value.newLevel),
|
||||
warehouseId: silo.WarehouseID,
|
||||
laneId: silo.LocationID,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/api/logistics/createsiloadjustment",
|
||||
dataToSubmit,
|
||||
{ withCredentials: true },
|
||||
);
|
||||
//console.log(res.data);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
}
|
||||
if (!res.data.success && res.data.data?.status === 400) {
|
||||
if (res.data.data.status === 400) {
|
||||
toast.error(res.data.data.data.errors[0].message);
|
||||
}
|
||||
} else if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
}
|
||||
setSubmitting(false);
|
||||
} catch (error: any) {
|
||||
//console.log(error);
|
||||
if (error.status === 401) {
|
||||
toast.error(error.response.statusText);
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<LstCard>
|
||||
<div className="flex flex-row">
|
||||
<LstCard className="grow m-1 max-w-[400px]">
|
||||
<CardHeader>{silo.Description}</CardHeader>
|
||||
<div className="m-1">
|
||||
<hr className="m-2" />
|
||||
<span>Current Stock: </span>
|
||||
{silo.Stock_Total}
|
||||
<hr className="m-2" />
|
||||
<span>Last date adjusted </span>
|
||||
{format(silo.LastAdjustment, "M/dd/yyyy")}
|
||||
<hr className="m-2" />
|
||||
</div>
|
||||
<div>
|
||||
{silo.Stock_Total === 0 ? (
|
||||
<div className="flex justify-center flex-col">
|
||||
<span>
|
||||
The silo is currently empty you will not be able to do an
|
||||
adjustment until you have received material in.
|
||||
</span>
|
||||
<hr />
|
||||
<ul>
|
||||
<li>
|
||||
-Someone click "Take inventory on a empty location" in
|
||||
stock.
|
||||
</li>
|
||||
<li>
|
||||
-Silo virtualy ran empty due to production over consumption.
|
||||
</li>
|
||||
<li>
|
||||
-Someone forgot to move a railcar compartment over to this
|
||||
location.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{user && roles.includes(accessRoles[0]?.role) && (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="newLevel"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 1
|
||||
? undefined
|
||||
: "You must enter a value greate than 1",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<div className="flex flex-row">
|
||||
<Label htmlFor="newLevel">New level</Label>
|
||||
<div>
|
||||
<Disclaimer />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
type="decimal"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-1"
|
||||
variant="outline"
|
||||
type="submit"
|
||||
onClick={form.handleSubmit}
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? (
|
||||
<span className="w-24">Submitting...</span>
|
||||
) : (
|
||||
<span className="w-24">Submit</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</LstCard>
|
||||
<div className="grow max-w-[600px]">
|
||||
<ChartData laneId={silo.LocationID} />
|
||||
|
||||
<div className="flex justify-end m-1 gap-3">
|
||||
<AttachSilo silo={silo} />
|
||||
<DetachSilo silo={silo} />
|
||||
<Button variant="outline">
|
||||
<Link
|
||||
to={"/siloAdjustments/$hist"}
|
||||
params={{ hist: silo.LocationID }}
|
||||
>
|
||||
Historical Data
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
const Disclaimer = () => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CircleAlert className="ml-1 w-[14px]" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-48">
|
||||
<p className="text-pretty">
|
||||
If you have had this page open for a period of time before
|
||||
submitting your data, there is a chance that the stock levels will
|
||||
be different from the ones you see above
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import SiloCard from "./SiloCard";
|
||||
|
||||
export default function SiloPage() {
|
||||
const { data, isError, error, isLoading } = useQuery(getStockSilo());
|
||||
|
||||
if (isLoading) return;
|
||||
|
||||
if (isError) return;
|
||||
|
||||
if (error)
|
||||
return (
|
||||
<div>
|
||||
{" "}
|
||||
There was an error getting the silos please notify your admin if
|
||||
this continues to be an issue
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap">
|
||||
{data?.map((s: any) => (
|
||||
<div key={s.LocationID} className="grow m-2 max-w-[800px]">
|
||||
<SiloCard silo={s} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function ExportInventoryData() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
age: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setSaving(true);
|
||||
try {
|
||||
const res = await axios.get(
|
||||
`/api/logistics/getcyclecount?age=${value.age}`,
|
||||
{
|
||||
responseType: "blob",
|
||||
}
|
||||
);
|
||||
|
||||
const blob = new Blob([res.data], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = `CycleCount-${format(new Date(Date.now()), "M-d-yyyy")}.xlsx`; // You can make this dynamic
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
// Clean up
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
toast.success(`File Downloaded`);
|
||||
setSaving(false);
|
||||
setOpen(false);
|
||||
form.reset();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.log(`There was an error getting cycle counts.`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(isOpen) => {
|
||||
if (!open) {
|
||||
form.reset();
|
||||
}
|
||||
setOpen(isOpen);
|
||||
// toast.message("Model was something", {
|
||||
// description: isOpen ? "Modal is open" : "Modal is closed",
|
||||
// });
|
||||
}}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Export Inventory Check</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Export Inventory lane check</DialogTitle>
|
||||
<DialogDescription>
|
||||
Exports all lanes based on the age you enter, except
|
||||
empty lanes.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<>
|
||||
<form.Field
|
||||
name="age"
|
||||
// validators={{
|
||||
// // We can choose between form-wide and field-specific validators
|
||||
// onChange: ({ value }) =>
|
||||
// value.length > 3
|
||||
// ? undefined
|
||||
// : "Username must be longer than 3 letters",
|
||||
// }}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
|
||||
<Label htmlFor="active">
|
||||
Age
|
||||
</Label>
|
||||
<Input
|
||||
className="ml-2"
|
||||
name={field.name}
|
||||
onBlur={field.handleBlur}
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={saving}
|
||||
onClick={form.handleSubmit}
|
||||
>
|
||||
{saving ? (
|
||||
<>
|
||||
<span>Saving....</span>
|
||||
</>
|
||||
) : (
|
||||
<span>Save setting</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { getinventoryCheck } from "@/utils/querys/logistics/getInventoryCheck";
|
||||
import { invColumns } from "@/utils/tableData/InventoryCards/inventoryColumns";
|
||||
import { InvTable } from "@/utils/tableData/InventoryCards/inventoryData";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function INVCheckCard(props: any) {
|
||||
const { age, rowType } = props.data;
|
||||
|
||||
//console.log(props.data);
|
||||
const { data, isError, isLoading } = useQuery(
|
||||
getinventoryCheck({ age: age })
|
||||
);
|
||||
|
||||
if (isLoading) return <div>Loading inventory data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the inv.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let laneData: any = data;
|
||||
if (props.type != "") {
|
||||
laneData = laneData.filter(
|
||||
(l: any) => l.rowType === rowType.toUpperCase()
|
||||
);
|
||||
|
||||
// age
|
||||
laneData = laneData.filter((l: any) => l.DaysSinceLast >= age);
|
||||
}
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return <InvTable columns={invColumns} data={laneData} info={props.data} />;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
//import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { getPPOO } from "@/utils/querys/logistics/getPPOO";
|
||||
import { columns } from "@/utils/tableData/ppoo/ppooColumns";
|
||||
import { PPOOTable } from "@/utils/tableData/ppoo/ppooData";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function PPOO() {
|
||||
//{ style = {} }
|
||||
const { data, isError, isLoading } = useQuery(getPPOO());
|
||||
|
||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the adjustments.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return (
|
||||
<PPOOTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
//style={style}
|
||||
/>
|
||||
);
|
||||
// return (
|
||||
// <div style={style}>
|
||||
// <LstCard style={style}>
|
||||
// <Suspense fallback={<p>Loading PPOO...</p>}>
|
||||
// <div className={`flex justify-center`}>
|
||||
// <p
|
||||
// className={`drag-handle w-fit`}
|
||||
// style={{ cursor: "move", padding: "5px" }}
|
||||
// >
|
||||
// PPOO
|
||||
// </p>
|
||||
|
||||
// <button onClick={handleCloseCard}>
|
||||
// <CircleX />
|
||||
// </button>
|
||||
// </div>
|
||||
// <PPOOTable
|
||||
// columns={columns}
|
||||
// data={data}
|
||||
// //style={style}
|
||||
// />
|
||||
// </Suspense>
|
||||
// </LstCard>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
//import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
|
||||
import { getOpenOrders } from "@/utils/querys/logistics/getOpenOrders";
|
||||
import { openOrderColumns } from "@/utils/tableData/openorders/ooColumns";
|
||||
import { OpenOrderTable } from "@/utils/tableData/openorders/ooData";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function OpenOrders() {
|
||||
//{ style = {} }
|
||||
const { data, isError, isLoading } = useQuery(getOpenOrders());
|
||||
|
||||
if (isLoading) return <div>Loading openOrder data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the openorders.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let openOrders: any = data;
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return <OpenOrderTable columns={openOrderColumns} data={openOrders} />;
|
||||
}
|
||||
202
lstV2/frontend/src/lib/authClient.ts
Normal file
202
lstV2/frontend/src/lib/authClient.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { redirect, useNavigate, useRouter } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { createAuthClient } from "better-auth/client";
|
||||
import { usernameClient } from "better-auth/client/plugins";
|
||||
import { useEffect } from "react";
|
||||
import { create } from "zustand";
|
||||
|
||||
// ---- TYPES ----
|
||||
export type Session = typeof authClient.$Infer.Session | null;
|
||||
|
||||
// Zustand store type
|
||||
type SessionState = {
|
||||
session: Session;
|
||||
setSession: (session: Session) => void;
|
||||
clearSession: () => void;
|
||||
};
|
||||
|
||||
export type UserRoles = {
|
||||
userRoleId: string;
|
||||
userId: string;
|
||||
module: string;
|
||||
role: "systemAdmin" | "admin" | "manager" | "user" | "viewer";
|
||||
};
|
||||
|
||||
type UserRoleState = {
|
||||
userRoles: UserRoles[] | null;
|
||||
fetchRoles: () => Promise<void>;
|
||||
clearRoles: () => void;
|
||||
};
|
||||
|
||||
// ---- ZUSTAND STORE ----
|
||||
export const useAuth = create<SessionState>((set) => ({
|
||||
session: null,
|
||||
setSession: (session) => set({ session }),
|
||||
clearSession: () => set({ session: null }),
|
||||
}));
|
||||
|
||||
export const useUserRoles = create<UserRoleState>((set) => ({
|
||||
userRoles: null,
|
||||
fetchRoles: async () => {
|
||||
try {
|
||||
const res = await axios.get(`/lst/api/user/roles`);
|
||||
const roles = res.data;
|
||||
set({ userRoles: roles.data });
|
||||
} catch (err) {
|
||||
console.error("Error fetching roles:", err);
|
||||
set({ userRoles: null });
|
||||
}
|
||||
},
|
||||
clearRoles: () => set({ userRoles: null }),
|
||||
}));
|
||||
|
||||
export function userAccess(
|
||||
moduleName: string | null,
|
||||
roles: UserRoles["role"] | UserRoles["role"][],
|
||||
): boolean {
|
||||
const { userRoles } = useUserRoles();
|
||||
|
||||
if (!userRoles) return false;
|
||||
|
||||
const roleArray = Array.isArray(roles) ? roles : [roles];
|
||||
|
||||
return userRoles.some(
|
||||
(m) =>
|
||||
(moduleName ? m.module === moduleName : true) &&
|
||||
roleArray.includes(m.role),
|
||||
);
|
||||
}
|
||||
|
||||
export async function checkUserAccess({
|
||||
allowedRoles,
|
||||
moduleName,
|
||||
}: {
|
||||
allowedRoles: UserRoles["role"][];
|
||||
moduleName?: string;
|
||||
//location: { pathname: string; search: string };
|
||||
}) {
|
||||
try {
|
||||
// fetch roles from your API (credentials required)
|
||||
const res = await axios.get("/lst/api/user/roles", {
|
||||
withCredentials: true,
|
||||
});
|
||||
const roles = res.data.data as UserRoles[];
|
||||
|
||||
const hasAccess = roles.some(
|
||||
(r) =>
|
||||
(moduleName ? r.module === moduleName : true) &&
|
||||
allowedRoles.includes(r.role),
|
||||
);
|
||||
|
||||
if (!hasAccess) {
|
||||
throw redirect({
|
||||
to: "/",
|
||||
search: { from: location.pathname + location.search },
|
||||
});
|
||||
}
|
||||
|
||||
// return roles so the route component can use them if needed
|
||||
return roles;
|
||||
} catch {
|
||||
throw redirect({
|
||||
to: "/login",
|
||||
search: { redirect: location.pathname + location.search },
|
||||
});
|
||||
}
|
||||
}
|
||||
// ---- BETTER AUTH CLIENT ----
|
||||
|
||||
export const authClient = createAuthClient({
|
||||
baseURL: `${window.location.origin}/lst/api/auth`,
|
||||
plugins: [usernameClient()],
|
||||
fetchOptions: {
|
||||
credentials: "include", // <--- required!
|
||||
},
|
||||
callbacks: {
|
||||
callbacks: {
|
||||
onUpdate: (res: any) => {
|
||||
// res has strong type
|
||||
// res.data is `Session | null`
|
||||
useAuth.getState().setSession(res?.data ?? null);
|
||||
},
|
||||
onSignIn: (res: any) => {
|
||||
console.log("Setting session to ", res?.data);
|
||||
useAuth.getState().setSession(res?.data ?? null);
|
||||
},
|
||||
onSignOut: () => {
|
||||
useAuth.getState().clearSession();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// ---- AUTH API HELPERS ----
|
||||
export async function signin(data: { username: string; password: string }) {
|
||||
const res = await authClient.signIn.username(data);
|
||||
|
||||
if (res.error) throw res.error;
|
||||
await authClient.getSession();
|
||||
return res.data;
|
||||
}
|
||||
|
||||
export const useLogout = () => {
|
||||
const { clearSession } = useAuth();
|
||||
const { clearRoles } = useUserRoles();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const router = useRouter();
|
||||
const logout = async () => {
|
||||
await authClient.signOut();
|
||||
|
||||
router.invalidate();
|
||||
router.clearCache();
|
||||
clearSession();
|
||||
clearRoles();
|
||||
navigate({ to: "/" });
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
return logout;
|
||||
};
|
||||
|
||||
export async function getSession() {
|
||||
const res = await authClient.getSession({
|
||||
query: { disableCookieCache: true },
|
||||
});
|
||||
|
||||
console.log(res);
|
||||
if (res.error) return null;
|
||||
return res.data;
|
||||
}
|
||||
|
||||
// ---- REACT QUERY INTEGRATION ----
|
||||
export function useSession() {
|
||||
const { setSession, clearSession } = useAuth();
|
||||
const qc = useQueryClient();
|
||||
|
||||
const query = useQuery({
|
||||
queryKey: ["session"],
|
||||
queryFn: getSession,
|
||||
refetchInterval: 60_000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
|
||||
//console.log("Auth Check", query.data);
|
||||
// react to data change
|
||||
useEffect(() => {
|
||||
if (query.data !== undefined) {
|
||||
setSession(query.data);
|
||||
}
|
||||
}, [query.data, setSession]);
|
||||
|
||||
// react to error
|
||||
useEffect(() => {
|
||||
if (query.error) {
|
||||
clearSession();
|
||||
qc.removeQueries({ queryKey: ["session"] });
|
||||
}
|
||||
}, [query.error, qc, clearSession]);
|
||||
|
||||
return query;
|
||||
}
|
||||
6
lstV2/frontend/src/lib/axiosAPI.ts
Normal file
6
lstV2/frontend/src/lib/axiosAPI.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import axios from "axios";
|
||||
|
||||
export const api = axios.create({
|
||||
baseURL: "/lst",
|
||||
withCredentials: true, // ✅ always send credentials (cookies)
|
||||
});
|
||||
@@ -30,17 +30,14 @@ import { Route as AdminNotificationMGTRouteImport } from './routes/_admin/notifi
|
||||
import { Route as AdminModulesRouteImport } from './routes/_admin/modules'
|
||||
import { Route as userPasswordChangeRouteImport } from './routes/(user)/passwordChange'
|
||||
import { Route as ocmeCyclecountIndexRouteImport } from './routes/(ocme)/cyclecount/index'
|
||||
import { Route as logisticsSiloAdjustmentsIndexRouteImport } from './routes/(logistics)/siloAdjustments/index'
|
||||
import { Route as logisticsOpenOrdersIndexRouteImport } from './routes/(logistics)/openOrders/index'
|
||||
import { Route as logisticsMaterialHelperIndexRouteImport } from './routes/(logistics)/materialHelper/index'
|
||||
import { Route as logisticsHelperCommandsIndexRouteImport } from './routes/(logistics)/helperCommands/index'
|
||||
import { Route as logisticsDmIndexRouteImport } from './routes/(logistics)/dm/index'
|
||||
import { Route as logisticsBarcodegenIndexRouteImport } from './routes/(logistics)/barcodegen/index'
|
||||
import { Route as EomArticleAvRouteImport } from './routes/_eom/article/$av'
|
||||
import { Route as logisticsSiloAdjustmentsHistRouteImport } from './routes/(logistics)/siloAdjustments/$hist'
|
||||
import { Route as logisticsMaterialHelperSiloLinkIndexRouteImport } from './routes/(logistics)/materialHelper/siloLink/index'
|
||||
import { Route as logisticsMaterialHelperConsumptionIndexRouteImport } from './routes/(logistics)/materialHelper/consumption/index'
|
||||
import { Route as logisticsSiloAdjustmentsCommentCommentRouteImport } from './routes/(logistics)/siloAdjustments/comment/$comment'
|
||||
|
||||
const RegisterRoute = RegisterRouteImport.update({
|
||||
id: '/register',
|
||||
@@ -144,12 +141,6 @@ const ocmeCyclecountIndexRoute = ocmeCyclecountIndexRouteImport.update({
|
||||
path: '/cyclecount/',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const logisticsSiloAdjustmentsIndexRoute =
|
||||
logisticsSiloAdjustmentsIndexRouteImport.update({
|
||||
id: '/(logistics)/siloAdjustments/',
|
||||
path: '/siloAdjustments/',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const logisticsOpenOrdersIndexRoute =
|
||||
logisticsOpenOrdersIndexRouteImport.update({
|
||||
id: '/(logistics)/openOrders/',
|
||||
@@ -184,12 +175,6 @@ const EomArticleAvRoute = EomArticleAvRouteImport.update({
|
||||
path: '/article/$av',
|
||||
getParentRoute: () => EomRoute,
|
||||
} as any)
|
||||
const logisticsSiloAdjustmentsHistRoute =
|
||||
logisticsSiloAdjustmentsHistRouteImport.update({
|
||||
id: '/(logistics)/siloAdjustments/$hist',
|
||||
path: '/siloAdjustments/$hist',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const logisticsMaterialHelperSiloLinkIndexRoute =
|
||||
logisticsMaterialHelperSiloLinkIndexRouteImport.update({
|
||||
id: '/(logistics)/materialHelper/siloLink/',
|
||||
@@ -202,12 +187,6 @@ const logisticsMaterialHelperConsumptionIndexRoute =
|
||||
path: '/materialHelper/consumption/',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const logisticsSiloAdjustmentsCommentCommentRoute =
|
||||
logisticsSiloAdjustmentsCommentCommentRouteImport.update({
|
||||
id: '/(logistics)/siloAdjustments/comment/$comment',
|
||||
path: '/siloAdjustments/comment/$comment',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
@@ -227,16 +206,13 @@ export interface FileRoutesByFullPath {
|
||||
'/eom': typeof EomEomRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
'/rfid': typeof RfidIndexRoute
|
||||
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
|
||||
'/article/$av': typeof EomArticleAvRoute
|
||||
'/barcodegen': typeof logisticsBarcodegenIndexRoute
|
||||
'/dm': typeof logisticsDmIndexRoute
|
||||
'/helperCommands': typeof logisticsHelperCommandsIndexRoute
|
||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||
'/openOrders': typeof logisticsOpenOrdersIndexRoute
|
||||
'/siloAdjustments': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/cyclecount': typeof ocmeCyclecountIndexRoute
|
||||
'/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/materialHelper/consumption': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/materialHelper/siloLink': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -258,16 +234,13 @@ export interface FileRoutesByTo {
|
||||
'/eom': typeof EomEomRoute
|
||||
'/ocp': typeof OcpIndexRoute
|
||||
'/rfid': typeof RfidIndexRoute
|
||||
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
|
||||
'/article/$av': typeof EomArticleAvRoute
|
||||
'/barcodegen': typeof logisticsBarcodegenIndexRoute
|
||||
'/dm': typeof logisticsDmIndexRoute
|
||||
'/helperCommands': typeof logisticsHelperCommandsIndexRoute
|
||||
'/materialHelper': typeof logisticsMaterialHelperIndexRoute
|
||||
'/openOrders': typeof logisticsOpenOrdersIndexRoute
|
||||
'/siloAdjustments': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/cyclecount': typeof ocmeCyclecountIndexRoute
|
||||
'/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/materialHelper/consumption': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/materialHelper/siloLink': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -293,16 +266,13 @@ export interface FileRoutesById {
|
||||
'/_eom/eom': typeof EomEomRoute
|
||||
'/ocp/': typeof OcpIndexRoute
|
||||
'/rfid/': typeof RfidIndexRoute
|
||||
'/(logistics)/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
|
||||
'/_eom/article/$av': typeof EomArticleAvRoute
|
||||
'/(logistics)/barcodegen/': typeof logisticsBarcodegenIndexRoute
|
||||
'/(logistics)/dm/': typeof logisticsDmIndexRoute
|
||||
'/(logistics)/helperCommands/': typeof logisticsHelperCommandsIndexRoute
|
||||
'/(logistics)/materialHelper/': typeof logisticsMaterialHelperIndexRoute
|
||||
'/(logistics)/openOrders/': typeof logisticsOpenOrdersIndexRoute
|
||||
'/(logistics)/siloAdjustments/': typeof logisticsSiloAdjustmentsIndexRoute
|
||||
'/(ocme)/cyclecount/': typeof ocmeCyclecountIndexRoute
|
||||
'/(logistics)/siloAdjustments/comment/$comment': typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
'/(logistics)/materialHelper/consumption/': typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
'/(logistics)/materialHelper/siloLink/': typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -326,16 +296,13 @@ export interface FileRouteTypes {
|
||||
| '/eom'
|
||||
| '/ocp'
|
||||
| '/rfid'
|
||||
| '/siloAdjustments/$hist'
|
||||
| '/article/$av'
|
||||
| '/barcodegen'
|
||||
| '/dm'
|
||||
| '/helperCommands'
|
||||
| '/materialHelper'
|
||||
| '/openOrders'
|
||||
| '/siloAdjustments'
|
||||
| '/cyclecount'
|
||||
| '/siloAdjustments/comment/$comment'
|
||||
| '/materialHelper/consumption'
|
||||
| '/materialHelper/siloLink'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
@@ -357,16 +324,13 @@ export interface FileRouteTypes {
|
||||
| '/eom'
|
||||
| '/ocp'
|
||||
| '/rfid'
|
||||
| '/siloAdjustments/$hist'
|
||||
| '/article/$av'
|
||||
| '/barcodegen'
|
||||
| '/dm'
|
||||
| '/helperCommands'
|
||||
| '/materialHelper'
|
||||
| '/openOrders'
|
||||
| '/siloAdjustments'
|
||||
| '/cyclecount'
|
||||
| '/siloAdjustments/comment/$comment'
|
||||
| '/materialHelper/consumption'
|
||||
| '/materialHelper/siloLink'
|
||||
id:
|
||||
@@ -391,16 +355,13 @@ export interface FileRouteTypes {
|
||||
| '/_eom/eom'
|
||||
| '/ocp/'
|
||||
| '/rfid/'
|
||||
| '/(logistics)/siloAdjustments/$hist'
|
||||
| '/_eom/article/$av'
|
||||
| '/(logistics)/barcodegen/'
|
||||
| '/(logistics)/dm/'
|
||||
| '/(logistics)/helperCommands/'
|
||||
| '/(logistics)/materialHelper/'
|
||||
| '/(logistics)/openOrders/'
|
||||
| '/(logistics)/siloAdjustments/'
|
||||
| '/(ocme)/cyclecount/'
|
||||
| '/(logistics)/siloAdjustments/comment/$comment'
|
||||
| '/(logistics)/materialHelper/consumption/'
|
||||
| '/(logistics)/materialHelper/siloLink/'
|
||||
fileRoutesById: FileRoutesById
|
||||
@@ -417,15 +378,12 @@ export interface RootRouteChildren {
|
||||
userPasswordChangeRoute: typeof userPasswordChangeRoute
|
||||
OcpIndexRoute: typeof OcpIndexRoute
|
||||
RfidIndexRoute: typeof RfidIndexRoute
|
||||
logisticsSiloAdjustmentsHistRoute: typeof logisticsSiloAdjustmentsHistRoute
|
||||
logisticsBarcodegenIndexRoute: typeof logisticsBarcodegenIndexRoute
|
||||
logisticsDmIndexRoute: typeof logisticsDmIndexRoute
|
||||
logisticsHelperCommandsIndexRoute: typeof logisticsHelperCommandsIndexRoute
|
||||
logisticsMaterialHelperIndexRoute: typeof logisticsMaterialHelperIndexRoute
|
||||
logisticsOpenOrdersIndexRoute: typeof logisticsOpenOrdersIndexRoute
|
||||
logisticsSiloAdjustmentsIndexRoute: typeof logisticsSiloAdjustmentsIndexRoute
|
||||
ocmeCyclecountIndexRoute: typeof ocmeCyclecountIndexRoute
|
||||
logisticsSiloAdjustmentsCommentCommentRoute: typeof logisticsSiloAdjustmentsCommentCommentRoute
|
||||
logisticsMaterialHelperConsumptionIndexRoute: typeof logisticsMaterialHelperConsumptionIndexRoute
|
||||
logisticsMaterialHelperSiloLinkIndexRoute: typeof logisticsMaterialHelperSiloLinkIndexRoute
|
||||
}
|
||||
@@ -579,13 +537,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ocmeCyclecountIndexRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/(logistics)/siloAdjustments/': {
|
||||
id: '/(logistics)/siloAdjustments/'
|
||||
path: '/siloAdjustments'
|
||||
fullPath: '/siloAdjustments'
|
||||
preLoaderRoute: typeof logisticsSiloAdjustmentsIndexRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/(logistics)/openOrders/': {
|
||||
id: '/(logistics)/openOrders/'
|
||||
path: '/openOrders'
|
||||
@@ -628,13 +579,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof EomArticleAvRouteImport
|
||||
parentRoute: typeof EomRoute
|
||||
}
|
||||
'/(logistics)/siloAdjustments/$hist': {
|
||||
id: '/(logistics)/siloAdjustments/$hist'
|
||||
path: '/siloAdjustments/$hist'
|
||||
fullPath: '/siloAdjustments/$hist'
|
||||
preLoaderRoute: typeof logisticsSiloAdjustmentsHistRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/(logistics)/materialHelper/siloLink/': {
|
||||
id: '/(logistics)/materialHelper/siloLink/'
|
||||
path: '/materialHelper/siloLink'
|
||||
@@ -649,13 +593,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof logisticsMaterialHelperConsumptionIndexRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/(logistics)/siloAdjustments/comment/$comment': {
|
||||
id: '/(logistics)/siloAdjustments/comment/$comment'
|
||||
path: '/siloAdjustments/comment/$comment'
|
||||
fullPath: '/siloAdjustments/comment/$comment'
|
||||
preLoaderRoute: typeof logisticsSiloAdjustmentsCommentCommentRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,16 +652,12 @@ const rootRouteChildren: RootRouteChildren = {
|
||||
userPasswordChangeRoute: userPasswordChangeRoute,
|
||||
OcpIndexRoute: OcpIndexRoute,
|
||||
RfidIndexRoute: RfidIndexRoute,
|
||||
logisticsSiloAdjustmentsHistRoute: logisticsSiloAdjustmentsHistRoute,
|
||||
logisticsBarcodegenIndexRoute: logisticsBarcodegenIndexRoute,
|
||||
logisticsDmIndexRoute: logisticsDmIndexRoute,
|
||||
logisticsHelperCommandsIndexRoute: logisticsHelperCommandsIndexRoute,
|
||||
logisticsMaterialHelperIndexRoute: logisticsMaterialHelperIndexRoute,
|
||||
logisticsOpenOrdersIndexRoute: logisticsOpenOrdersIndexRoute,
|
||||
logisticsSiloAdjustmentsIndexRoute: logisticsSiloAdjustmentsIndexRoute,
|
||||
ocmeCyclecountIndexRoute: ocmeCyclecountIndexRoute,
|
||||
logisticsSiloAdjustmentsCommentCommentRoute:
|
||||
logisticsSiloAdjustmentsCommentCommentRoute,
|
||||
logisticsMaterialHelperConsumptionIndexRoute:
|
||||
logisticsMaterialHelperConsumptionIndexRoute,
|
||||
logisticsMaterialHelperSiloLinkIndexRoute:
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import HistoricalData from "@/components/logistics/siloAdjustments/HistoricalData";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(logistics)/siloAdjustments/$hist")({
|
||||
component: RouteComponent,
|
||||
beforeLoad: async () => {
|
||||
const auth = localStorage.getItem("auth_token");
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// In a loader
|
||||
loader: ({ params }) => params.hist,
|
||||
// Or in a component
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { hist } = Route.useParams();
|
||||
return (
|
||||
<div>
|
||||
<HistoricalData laneId={hist} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import Comment from "@/components/logistics/siloAdjustments/Comment";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/(logistics)/siloAdjustments/comment/$comment"
|
||||
)({
|
||||
beforeLoad: async () => {
|
||||
const auth = localStorage.getItem("auth_token");
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// In a loader
|
||||
loader: ({ params }) => params.comment,
|
||||
// Or in a component
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { comment } = Route.useParams();
|
||||
return (
|
||||
<div className="ml-20 mt-20">
|
||||
<Comment id={comment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import SiloPage from "@/components/logistics/siloAdjustments/SiloPage";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(logistics)/siloAdjustments/")({
|
||||
component: RouteComponent,
|
||||
beforeLoad: async () => {
|
||||
const auth = localStorage.getItem("auth_token");
|
||||
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>
|
||||
<SiloPage />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [{"path": "./tsconfig.app.json"}, {"path": "./tsconfig.node.json"}],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
"version": "2.27.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||
"dev:both": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||
"dev": "npm run dev:server",
|
||||
"dev:server": "dotenvx run -f .env -- tsx watch server/index.ts",
|
||||
"dev:frontend": "cd frontend && npm run dev",
|
||||
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
|
||||
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
|
||||
"build": "npm run build:server && npm run build:frontend",
|
||||
"build": "npm run build:server",
|
||||
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y ",
|
||||
"build:frontend": "cd frontend && npm run build",
|
||||
"build:iisNet": "rimraf dotnetwrapper\\bin && xcopy frontend\\dist dotnetwrapper\\wwwroot /E /I /Y && cd dotnetwrapper && dotnet publish lst-wrapper.csproj --configuration Release --output ../prodBuild",
|
||||
@@ -21,7 +22,7 @@
|
||||
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
|
||||
"deploy": "standard-version --conventional-commits && npm run build",
|
||||
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"newBuild": "npm run build:server && npm run build:frontend",
|
||||
"newBuild": "npm run build:server",
|
||||
"copyToNew": "powershell -ExecutionPolicy Bypass -File server/scripts/copyToLst.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"removeOld": "rimraf dist && rimraf frontend/dist",
|
||||
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { serve } from "@hono/node-server";
|
||||
import { serveStatic } from "@hono/node-server/serve-static";
|
||||
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { cors } from "hono/cors";
|
||||
import { html } from "hono/html";
|
||||
import { logger } from "hono/logger";
|
||||
import os from "os";
|
||||
import auth from "./services/auth/authService.js";
|
||||
@@ -152,9 +153,66 @@ app.route("/ocme/", ocme);
|
||||
// the catch all api route
|
||||
app.all("/api/*", (c) => c.json({ error: "API route not found" }, 404));
|
||||
|
||||
const newPageDoc = `
|
||||
<!doctype html>
|
||||
<h1>Hello!</h1>
|
||||
`;
|
||||
|
||||
app.all("*", (c) => {
|
||||
const testServers = ["test1", "test2", "test3"];
|
||||
const server = serverIntialized.filter((n: any) => n.name === "plantToken");
|
||||
|
||||
let url = "";
|
||||
if (testServers.includes(server[0].value)) {
|
||||
const dbServer = serverIntialized.filter((n: any) => n.name === "dbServer");
|
||||
url = `https://${dbServer[0].value}.alpla.net/lst/app/old${c.req.path}`;
|
||||
} else {
|
||||
url = `https://${server[0].value}prod.alpla.net/lst/app/old${c.req.path}`;
|
||||
}
|
||||
const target = url;
|
||||
const waitSeconds = 10;
|
||||
return c.html(html`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Lst Moved</title>
|
||||
<style>
|
||||
body{font-family:sans-serif;display:flex;flex-direction:column;
|
||||
align-items:center;justify-content:center;height:100vh;}
|
||||
button{margin-top:1rem;padding:0.6rem 1.2rem;font-size:1rem;cursor:pointer;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>We’ve moved!</h1>
|
||||
<p>With new security and updating to mobile version the app had to be moved. You will be redirected to.</p>
|
||||
<p><a href="${target}">${target}</a></p>
|
||||
<p>Redirecting in <span id="countdown">${waitSeconds}</span> seconds…</p>
|
||||
<button id="goNow">Go now</button>
|
||||
<script>
|
||||
let s = ${waitSeconds};
|
||||
const el = document.getElementById('countdown');
|
||||
const btn = document.getElementById('goNow');
|
||||
const timer = setInterval(()=>{
|
||||
s--;
|
||||
el.textContent = s;
|
||||
if(s <= 0){ clearInterval(timer); window.location.href='${target}'; }
|
||||
},1000);
|
||||
btn.addEventListener('click',()=>{
|
||||
clearInterval(timer); window.location.href='${target}';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>`);
|
||||
});
|
||||
|
||||
// app.all("/*", (c) => {
|
||||
// console.log(c.req.path);
|
||||
// return c.html(html`${newPageDoc}`);
|
||||
// });
|
||||
|
||||
// front end static files
|
||||
app.use("/*", serveStatic({ root: "./frontend/dist" }));
|
||||
app.use("*", serveStatic({ path: "./frontend/dist/index.html" }));
|
||||
//app.use("/*", serveStatic({ root: "./frontend/dist" }));
|
||||
//app.use("*", serveStatic({ path: "./frontend/dist/index.html" }));
|
||||
|
||||
// Handle app exit signals
|
||||
process.on("SIGINT", async () => {
|
||||
|
||||
@@ -13,7 +13,7 @@ const newSubModules = [
|
||||
name: "RFID",
|
||||
moduleName: "prodcution",
|
||||
description: "RFID stuff",
|
||||
link: "/rfid",
|
||||
link: "/lst/app/old/rfid",
|
||||
icon: "Tags",
|
||||
active: true,
|
||||
roles: [
|
||||
@@ -30,7 +30,7 @@ const newSubModules = [
|
||||
name: "siloAdjustments",
|
||||
moduleName: "logistics",
|
||||
description: "Do a silo adjustments",
|
||||
link: "/siloAdjustments",
|
||||
link: "/lst/app/old/siloAdjustments",
|
||||
icon: "Cylinder",
|
||||
active: false,
|
||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
@@ -40,7 +40,7 @@ const newSubModules = [
|
||||
name: "demandManagement",
|
||||
moduleName: "logistics",
|
||||
description: "Bulk order and Forecast imports",
|
||||
link: "/dm",
|
||||
link: "/lst/app/old/dm",
|
||||
icon: "Truck",
|
||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
active: false,
|
||||
@@ -60,7 +60,7 @@ const newSubModules = [
|
||||
name: "Material Helper",
|
||||
moduleName: "logistics",
|
||||
description: "",
|
||||
link: "/materialHelper/consumption",
|
||||
link: "/lst/app/old/materialHelper/consumption",
|
||||
icon: "Package",
|
||||
roles: [
|
||||
"viewer",
|
||||
@@ -77,7 +77,7 @@ const newSubModules = [
|
||||
name: "Ocme Cyclecount",
|
||||
moduleName: "logistics",
|
||||
description: "",
|
||||
link: "/cyclecount",
|
||||
link: "/lst/app/old/cyclecount",
|
||||
icon: "Package",
|
||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
active: false,
|
||||
@@ -87,7 +87,7 @@ const newSubModules = [
|
||||
name: "Open Orders",
|
||||
moduleName: "logistics",
|
||||
description: "Open orders",
|
||||
link: "/openOrders",
|
||||
link: "/lst/app/old/openOrders",
|
||||
icon: "Truck",
|
||||
roles: [
|
||||
"viewer",
|
||||
@@ -104,7 +104,7 @@ const newSubModules = [
|
||||
name: "Barcodes",
|
||||
moduleName: "logistics",
|
||||
description: "Barcodes, lanes and scanable",
|
||||
link: "/barcodegen",
|
||||
link: "/lst/app/old/barcodegen",
|
||||
icon: "Barcode",
|
||||
roles: [
|
||||
"viewer",
|
||||
@@ -121,7 +121,7 @@ const newSubModules = [
|
||||
name: "Helper Commands",
|
||||
moduleName: "logistics",
|
||||
description: "Commands to assist when a scanner is not avalible",
|
||||
link: "/helpercommands",
|
||||
link: "/lst/app/old/helpercommands",
|
||||
icon: "Command",
|
||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
active: true,
|
||||
@@ -222,6 +222,7 @@ const newSubModules = [
|
||||
},
|
||||
];
|
||||
export const areSubModulesIn = async () => {
|
||||
await db.delete(subModules);
|
||||
try {
|
||||
for (let i = 0; i < newSubModules.length; i++) {
|
||||
const subModuleUpdate = await db
|
||||
|
||||
Reference in New Issue
Block a user