feat(eom): frame work added in for eom
This commit is contained in:
22
database/schema/eom.ts
Normal file
22
database/schema/eom.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import {date, pgTable, text} from "drizzle-orm/pg-core";
|
||||||
|
import {createSelectSchema} from "drizzle-zod";
|
||||||
|
|
||||||
|
export const eom = pgTable(
|
||||||
|
"eom",
|
||||||
|
{
|
||||||
|
eomMonth: date().notNull(),
|
||||||
|
article: text().notNull(),
|
||||||
|
articleDescription: text().notNull(),
|
||||||
|
}
|
||||||
|
// (table) => [
|
||||||
|
// // 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
|
||||||
|
// export const insertRolesSchema = createInsertSchema(roles, {
|
||||||
|
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectRolesSchema = createSelectSchema(eom);
|
||||||
@@ -18,8 +18,10 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.6",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
|
"@radix-ui/react-popover": "^1.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@tailwindcss/vite": "^4.0.9",
|
"@tailwindcss/vite": "^4.0.9",
|
||||||
"@tanstack/react-query": "^5.66.9",
|
"@tanstack/react-query": "^5.66.9",
|
||||||
@@ -27,6 +29,7 @@
|
|||||||
"@tanstack/react-table": "^8.21.2",
|
"@tanstack/react-table": "^8.21.2",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"hono": "^4.7.2",
|
"hono": "^4.7.2",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
@@ -34,6 +37,7 @@
|
|||||||
"lucide-react": "^0.476.0",
|
"lucide-react": "^0.476.0",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.4",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
"react-day-picker": "^8.10.1",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-grid-layout": "^1.5.0",
|
"react-grid-layout": "^1.5.0",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
|
|||||||
131
frontend/src/components/eom/EomPage.tsx
Normal file
131
frontend/src/components/eom/EomPage.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
import {LstCard} from "../extendedUI/LstCard";
|
||||||
|
import {Tabs, TabsContent, TabsList, TabsTrigger} from "../ui/tabs";
|
||||||
|
import {useModuleStore} from "@/lib/store/useModuleStore";
|
||||||
|
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "../ui/table";
|
||||||
|
import {Skeleton} from "../ui/skeleton";
|
||||||
|
|
||||||
|
import {Link, useRouter} from "@tanstack/react-router";
|
||||||
|
import {Popover, PopoverContent, PopoverTrigger} from "../ui/popover";
|
||||||
|
import {Button} from "../ui/button";
|
||||||
|
import {cn} from "@/lib/utils";
|
||||||
|
import {CalendarIcon} from "lucide-react";
|
||||||
|
import {format, startOfMonth} from "date-fns";
|
||||||
|
import {Calendar} from "../ui/calendar";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {toast} from "sonner";
|
||||||
|
import KFP from "./KFP";
|
||||||
|
|
||||||
|
export default function EomPage() {
|
||||||
|
const {modules} = useModuleStore();
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const [date, setDate] = useState<Date>();
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
router.navigate({to: "/"});
|
||||||
|
}
|
||||||
|
const eomMod = modules.filter((m) => m.name === "eom");
|
||||||
|
// the users current role for eom is?
|
||||||
|
const role: any = user?.roles.filter((r) => r.module_id === eomMod[0].module_id) || "";
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{key: "kfp", label: "Key Figures", roles: ["admin", "systemAdmin"], content: <KFP />},
|
||||||
|
{key: "fg", label: "Finished Goods", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "mm", label: "Main Material", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "mb", label: "Master Batch", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "ab", label: "Additive", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "pp", label: "Purchased Preforms", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "pre", label: "Preforms", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "pkg", label: "Packaging", roles: ["admin", "systemAdmin"], content: <DummyContent />},
|
||||||
|
{key: "ui", label: "Undefined Items", roles: ["admin"], content: <DummyContent />},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="m-2 w-screen">
|
||||||
|
<div className="mb-2 flex flex-row">
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant={"outline"}
|
||||||
|
className={cn(
|
||||||
|
"w-[280px] justify-start text-left font-normal",
|
||||||
|
!date && "text-muted-foreground"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
|
{date ? format(date, "PPP") : <span>Pick a date</span>}
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-auto p-0">
|
||||||
|
<Calendar mode="single" selected={date} onSelect={setDate} initialFocus />
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<div className="ml-2">
|
||||||
|
<Button onClick={() => toast.success(`Getting data for ${startOfMonth(date!)}-${date}`)}>
|
||||||
|
<span className="text-sm">Update Data</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Tabs defaultValue="mm">
|
||||||
|
<TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return <TabsTrigger value={tab.key}>{tab.label}</TabsTrigger>;
|
||||||
|
})}
|
||||||
|
</TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return <TabsContent value={tab.key}>{tab.content}</TabsContent>;
|
||||||
|
})}
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DummyContent() {
|
||||||
|
return (
|
||||||
|
<LstCard className="w-5/6">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Av</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead>Material Type</TableHead>
|
||||||
|
<TableHead>Waste</TableHead>
|
||||||
|
<TableHead>Loss / Gain $$</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
|
<TableBody>
|
||||||
|
{Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium m-2">
|
||||||
|
<Link to="/article/$av" params={{av: `${i}`}}>
|
||||||
|
{i}
|
||||||
|
</Link>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
{/* <TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell> */}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
68
frontend/src/components/eom/KFP.tsx
Normal file
68
frontend/src/components/eom/KFP.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import {useModuleStore} from "@/lib/store/useModuleStore";
|
||||||
|
import {LstCard} from "../extendedUI/LstCard";
|
||||||
|
import {CardHeader} from "../ui/card";
|
||||||
|
import {Tabs, TabsContent, TabsList, TabsTrigger} from "../ui/tabs";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
|
||||||
|
export default function KFP() {
|
||||||
|
const {modules} = useModuleStore();
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
const eomMod = modules.filter((m) => m.name === "eom");
|
||||||
|
// the users current role for eom is?
|
||||||
|
const role: any = user?.roles.filter((r) => r.module_id === eomMod[0].module_id) || "";
|
||||||
|
const tabs = [
|
||||||
|
{key: "mat", label: "Materials", roles: ["admin", "systemAdmin"], content: <Materials />},
|
||||||
|
{key: "sbm", label: "Stretch Blow", roles: ["admin", "systemAdmin"]},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row w-full">
|
||||||
|
<Tabs defaultValue="mat">
|
||||||
|
<TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return <TabsTrigger value={tab.key}>{tab.label}</TabsTrigger>;
|
||||||
|
})}
|
||||||
|
</TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return (
|
||||||
|
<TabsContent value={tab.key} className="w-screen">
|
||||||
|
{tab.content}
|
||||||
|
</TabsContent>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Materials() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row w-[90%]">
|
||||||
|
<div className="w-1/5">
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>Resin</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>MasterBatch</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>Additive</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>Dose cups / Spigots / Spouts</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2">
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>Pre-Emis Material Consistency report</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/6">
|
||||||
|
<LstCard className="m-1">
|
||||||
|
<CardHeader>Regrind Report in kg</CardHeader>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Printer} from "lucide-react";
|
import {FileText} from "lucide-react";
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
SidebarGroupContent,
|
||||||
@@ -10,9 +10,9 @@ import {
|
|||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
title: "Qaulity Request",
|
title: "End Of Month",
|
||||||
url: "#",
|
url: "/eom",
|
||||||
icon: Printer,
|
icon: FileText,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
73
frontend/src/components/ui/calendar.tsx
Normal file
73
frontend/src/components/ui/calendar.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react"
|
||||||
|
import { DayPicker } from "react-day-picker"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { buttonVariants } from "@/components/ui/button"
|
||||||
|
|
||||||
|
function Calendar({
|
||||||
|
className,
|
||||||
|
classNames,
|
||||||
|
showOutsideDays = true,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof DayPicker>) {
|
||||||
|
return (
|
||||||
|
<DayPicker
|
||||||
|
showOutsideDays={showOutsideDays}
|
||||||
|
className={cn("p-3", className)}
|
||||||
|
classNames={{
|
||||||
|
months: "flex flex-col sm:flex-row gap-2",
|
||||||
|
month: "flex flex-col gap-4",
|
||||||
|
caption: "flex justify-center pt-1 relative items-center w-full",
|
||||||
|
caption_label: "text-sm font-medium",
|
||||||
|
nav: "flex items-center gap-1",
|
||||||
|
nav_button: cn(
|
||||||
|
buttonVariants({ variant: "outline" }),
|
||||||
|
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100"
|
||||||
|
),
|
||||||
|
nav_button_previous: "absolute left-1",
|
||||||
|
nav_button_next: "absolute right-1",
|
||||||
|
table: "w-full border-collapse space-x-1",
|
||||||
|
head_row: "flex",
|
||||||
|
head_cell:
|
||||||
|
"text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
|
||||||
|
row: "flex w-full mt-2",
|
||||||
|
cell: cn(
|
||||||
|
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-r-md",
|
||||||
|
props.mode === "range"
|
||||||
|
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
|
||||||
|
: "[&:has([aria-selected])]:rounded-md"
|
||||||
|
),
|
||||||
|
day: cn(
|
||||||
|
buttonVariants({ variant: "ghost" }),
|
||||||
|
"size-8 p-0 font-normal aria-selected:opacity-100"
|
||||||
|
),
|
||||||
|
day_range_start:
|
||||||
|
"day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground",
|
||||||
|
day_range_end:
|
||||||
|
"day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground",
|
||||||
|
day_selected:
|
||||||
|
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
|
||||||
|
day_today: "bg-accent text-accent-foreground",
|
||||||
|
day_outside:
|
||||||
|
"day-outside text-muted-foreground aria-selected:text-muted-foreground",
|
||||||
|
day_disabled: "text-muted-foreground opacity-50",
|
||||||
|
day_range_middle:
|
||||||
|
"aria-selected:bg-accent aria-selected:text-accent-foreground",
|
||||||
|
day_hidden: "invisible",
|
||||||
|
...classNames,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
IconLeft: ({ className, ...props }) => (
|
||||||
|
<ChevronLeft className={cn("size-4", className)} {...props} />
|
||||||
|
),
|
||||||
|
IconRight: ({ className, ...props }) => (
|
||||||
|
<ChevronRight className={cn("size-4", className)} {...props} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Calendar }
|
||||||
52
frontend/src/components/ui/passwordInput.tsx
Normal file
52
frontend/src/components/ui/passwordInput.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import {EyeIcon, EyeOffIcon} from "lucide-react";
|
||||||
|
|
||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {Input} from "@/components/ui/input";
|
||||||
|
import {cn} from "@/lib/utils";
|
||||||
|
|
||||||
|
const PasswordInput = React.forwardRef<HTMLInputElement, any>(({className, ...props}, ref) => {
|
||||||
|
const [showPassword, setShowPassword] = React.useState(false);
|
||||||
|
const disabled = props.value === "" || props.value === undefined || props.disabled;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative">
|
||||||
|
<Input
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
|
className={cn("hide-password-toggle pr-10", className)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
|
||||||
|
onClick={() => setShowPassword((prev) => !prev)}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
{showPassword && !disabled ? (
|
||||||
|
<EyeIcon className="h-4 w-4" aria-hidden="true" />
|
||||||
|
) : (
|
||||||
|
<EyeOffIcon className="h-4 w-4" aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
<span className="sr-only">{showPassword ? "Hide password" : "Show password"}</span>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{/* hides browsers password toggles */}
|
||||||
|
<style>{`
|
||||||
|
.hide-password-toggle::-ms-reveal,
|
||||||
|
.hide-password-toggle::-ms-clear {
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
PasswordInput.displayName = "PasswordInput";
|
||||||
|
|
||||||
|
export {PasswordInput};
|
||||||
46
frontend/src/components/ui/popover.tsx
Normal file
46
frontend/src/components/ui/popover.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Popover({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||||
|
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function PopoverTrigger({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||||
|
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function PopoverContent({
|
||||||
|
className,
|
||||||
|
align = "center",
|
||||||
|
sideOffset = 4,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<PopoverPrimitive.Portal>
|
||||||
|
<PopoverPrimitive.Content
|
||||||
|
data-slot="popover-content"
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-hidden",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</PopoverPrimitive.Portal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function PopoverAnchor({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||||
|
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
||||||
64
frontend/src/components/ui/tabs.tsx
Normal file
64
frontend/src/components/ui/tabs.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Tabs({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Root
|
||||||
|
data-slot="tabs"
|
||||||
|
className={cn("flex flex-col gap-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsList({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.List>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.List
|
||||||
|
data-slot="tabs-list"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsTrigger({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Trigger
|
||||||
|
data-slot="tabs-trigger"
|
||||||
|
className={cn(
|
||||||
|
"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsContent({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Content
|
||||||
|
data-slot="tabs-content"
|
||||||
|
className={cn("flex-1 outline-none", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||||
@@ -13,14 +13,17 @@
|
|||||||
import { Route as rootRoute } from './routes/__root'
|
import { Route as rootRoute } from './routes/__root'
|
||||||
import { Route as LoginImport } from './routes/login'
|
import { Route as LoginImport } from './routes/login'
|
||||||
import { Route as AboutImport } from './routes/about'
|
import { Route as AboutImport } from './routes/about'
|
||||||
|
import { Route as EomImport } from './routes/_eom'
|
||||||
import { Route as AuthImport } from './routes/_auth'
|
import { Route as AuthImport } from './routes/_auth'
|
||||||
import { Route as AdminImport } from './routes/_admin'
|
import { Route as AdminImport } from './routes/_admin'
|
||||||
import { Route as IndexImport } from './routes/index'
|
import { Route as IndexImport } from './routes/index'
|
||||||
import { Route as OcpIndexImport } from './routes/ocp/index'
|
import { Route as OcpIndexImport } from './routes/ocp/index'
|
||||||
import { Route as OcpLotsImport } from './routes/ocp/lots'
|
import { Route as OcpLotsImport } from './routes/ocp/lots'
|
||||||
|
import { Route as EomEomImport } from './routes/_eom/eom'
|
||||||
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
import { Route as AuthProfileImport } from './routes/_auth/profile'
|
||||||
import { Route as AdminSettingsImport } from './routes/_admin/settings'
|
import { Route as AdminSettingsImport } from './routes/_admin/settings'
|
||||||
import { Route as AdminModulesImport } from './routes/_admin/modules'
|
import { Route as AdminModulesImport } from './routes/_admin/modules'
|
||||||
|
import { Route as EomArticleAvImport } from './routes/_eom/article/$av'
|
||||||
|
|
||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
|
|
||||||
@@ -36,6 +39,11 @@ const AboutRoute = AboutImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const EomRoute = EomImport.update({
|
||||||
|
id: '/_eom',
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const AuthRoute = AuthImport.update({
|
const AuthRoute = AuthImport.update({
|
||||||
id: '/_auth',
|
id: '/_auth',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
@@ -64,6 +72,12 @@ const OcpLotsRoute = OcpLotsImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const EomEomRoute = EomEomImport.update({
|
||||||
|
id: '/eom',
|
||||||
|
path: '/eom',
|
||||||
|
getParentRoute: () => EomRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const AuthProfileRoute = AuthProfileImport.update({
|
const AuthProfileRoute = AuthProfileImport.update({
|
||||||
id: '/profile',
|
id: '/profile',
|
||||||
path: '/profile',
|
path: '/profile',
|
||||||
@@ -82,6 +96,12 @@ const AdminModulesRoute = AdminModulesImport.update({
|
|||||||
getParentRoute: () => AdminRoute,
|
getParentRoute: () => AdminRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const EomArticleAvRoute = EomArticleAvImport.update({
|
||||||
|
id: '/article/$av',
|
||||||
|
path: '/article/$av',
|
||||||
|
getParentRoute: () => EomRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
// Populate the FileRoutesByPath interface
|
// Populate the FileRoutesByPath interface
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
@@ -107,6 +127,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AuthImport
|
preLoaderRoute: typeof AuthImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
|
'/_eom': {
|
||||||
|
id: '/_eom'
|
||||||
|
path: ''
|
||||||
|
fullPath: ''
|
||||||
|
preLoaderRoute: typeof EomImport
|
||||||
|
parentRoute: typeof rootRoute
|
||||||
|
}
|
||||||
'/about': {
|
'/about': {
|
||||||
id: '/about'
|
id: '/about'
|
||||||
path: '/about'
|
path: '/about'
|
||||||
@@ -142,6 +169,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AuthProfileImport
|
preLoaderRoute: typeof AuthProfileImport
|
||||||
parentRoute: typeof AuthImport
|
parentRoute: typeof AuthImport
|
||||||
}
|
}
|
||||||
|
'/_eom/eom': {
|
||||||
|
id: '/_eom/eom'
|
||||||
|
path: '/eom'
|
||||||
|
fullPath: '/eom'
|
||||||
|
preLoaderRoute: typeof EomEomImport
|
||||||
|
parentRoute: typeof EomImport
|
||||||
|
}
|
||||||
'/ocp/lots': {
|
'/ocp/lots': {
|
||||||
id: '/ocp/lots'
|
id: '/ocp/lots'
|
||||||
path: '/ocp/lots'
|
path: '/ocp/lots'
|
||||||
@@ -156,6 +190,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof OcpIndexImport
|
preLoaderRoute: typeof OcpIndexImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
|
'/_eom/article/$av': {
|
||||||
|
id: '/_eom/article/$av'
|
||||||
|
path: '/article/$av'
|
||||||
|
fullPath: '/article/$av'
|
||||||
|
preLoaderRoute: typeof EomArticleAvImport
|
||||||
|
parentRoute: typeof EomImport
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,28 +224,44 @@ const AuthRouteChildren: AuthRouteChildren = {
|
|||||||
|
|
||||||
const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
||||||
|
|
||||||
|
interface EomRouteChildren {
|
||||||
|
EomEomRoute: typeof EomEomRoute
|
||||||
|
EomArticleAvRoute: typeof EomArticleAvRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
const EomRouteChildren: EomRouteChildren = {
|
||||||
|
EomEomRoute: EomEomRoute,
|
||||||
|
EomArticleAvRoute: EomArticleAvRoute,
|
||||||
|
}
|
||||||
|
|
||||||
|
const EomRouteWithChildren = EomRoute._addFileChildren(EomRouteChildren)
|
||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'': typeof AuthRouteWithChildren
|
'': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/modules': typeof AdminModulesRoute
|
'/modules': typeof AdminModulesRoute
|
||||||
'/settings': typeof AdminSettingsRoute
|
'/settings': typeof AdminSettingsRoute
|
||||||
'/profile': typeof AuthProfileRoute
|
'/profile': typeof AuthProfileRoute
|
||||||
|
'/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
'/ocp/lots': typeof OcpLotsRoute
|
||||||
'/ocp': typeof OcpIndexRoute
|
'/ocp': typeof OcpIndexRoute
|
||||||
|
'/article/$av': typeof EomArticleAvRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'': typeof AuthRouteWithChildren
|
'': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/modules': typeof AdminModulesRoute
|
'/modules': typeof AdminModulesRoute
|
||||||
'/settings': typeof AdminSettingsRoute
|
'/settings': typeof AdminSettingsRoute
|
||||||
'/profile': typeof AuthProfileRoute
|
'/profile': typeof AuthProfileRoute
|
||||||
|
'/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
'/ocp/lots': typeof OcpLotsRoute
|
||||||
'/ocp': typeof OcpIndexRoute
|
'/ocp': typeof OcpIndexRoute
|
||||||
|
'/article/$av': typeof EomArticleAvRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
@@ -212,13 +269,16 @@ export interface FileRoutesById {
|
|||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/_admin': typeof AdminRouteWithChildren
|
'/_admin': typeof AdminRouteWithChildren
|
||||||
'/_auth': typeof AuthRouteWithChildren
|
'/_auth': typeof AuthRouteWithChildren
|
||||||
|
'/_eom': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/_admin/modules': typeof AdminModulesRoute
|
'/_admin/modules': typeof AdminModulesRoute
|
||||||
'/_admin/settings': typeof AdminSettingsRoute
|
'/_admin/settings': typeof AdminSettingsRoute
|
||||||
'/_auth/profile': typeof AuthProfileRoute
|
'/_auth/profile': typeof AuthProfileRoute
|
||||||
|
'/_eom/eom': typeof EomEomRoute
|
||||||
'/ocp/lots': typeof OcpLotsRoute
|
'/ocp/lots': typeof OcpLotsRoute
|
||||||
'/ocp/': typeof OcpIndexRoute
|
'/ocp/': typeof OcpIndexRoute
|
||||||
|
'/_eom/article/$av': typeof EomArticleAvRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
@@ -231,8 +291,10 @@ export interface FileRouteTypes {
|
|||||||
| '/modules'
|
| '/modules'
|
||||||
| '/settings'
|
| '/settings'
|
||||||
| '/profile'
|
| '/profile'
|
||||||
|
| '/eom'
|
||||||
| '/ocp/lots'
|
| '/ocp/lots'
|
||||||
| '/ocp'
|
| '/ocp'
|
||||||
|
| '/article/$av'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to:
|
to:
|
||||||
| '/'
|
| '/'
|
||||||
@@ -242,20 +304,25 @@ export interface FileRouteTypes {
|
|||||||
| '/modules'
|
| '/modules'
|
||||||
| '/settings'
|
| '/settings'
|
||||||
| '/profile'
|
| '/profile'
|
||||||
|
| '/eom'
|
||||||
| '/ocp/lots'
|
| '/ocp/lots'
|
||||||
| '/ocp'
|
| '/ocp'
|
||||||
|
| '/article/$av'
|
||||||
id:
|
id:
|
||||||
| '__root__'
|
| '__root__'
|
||||||
| '/'
|
| '/'
|
||||||
| '/_admin'
|
| '/_admin'
|
||||||
| '/_auth'
|
| '/_auth'
|
||||||
|
| '/_eom'
|
||||||
| '/about'
|
| '/about'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/_admin/modules'
|
| '/_admin/modules'
|
||||||
| '/_admin/settings'
|
| '/_admin/settings'
|
||||||
| '/_auth/profile'
|
| '/_auth/profile'
|
||||||
|
| '/_eom/eom'
|
||||||
| '/ocp/lots'
|
| '/ocp/lots'
|
||||||
| '/ocp/'
|
| '/ocp/'
|
||||||
|
| '/_eom/article/$av'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +330,7 @@ export interface RootRouteChildren {
|
|||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
AdminRoute: typeof AdminRouteWithChildren
|
AdminRoute: typeof AdminRouteWithChildren
|
||||||
AuthRoute: typeof AuthRouteWithChildren
|
AuthRoute: typeof AuthRouteWithChildren
|
||||||
|
EomRoute: typeof EomRouteWithChildren
|
||||||
AboutRoute: typeof AboutRoute
|
AboutRoute: typeof AboutRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
OcpLotsRoute: typeof OcpLotsRoute
|
OcpLotsRoute: typeof OcpLotsRoute
|
||||||
@@ -273,6 +341,7 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
AdminRoute: AdminRouteWithChildren,
|
AdminRoute: AdminRouteWithChildren,
|
||||||
AuthRoute: AuthRouteWithChildren,
|
AuthRoute: AuthRouteWithChildren,
|
||||||
|
EomRoute: EomRouteWithChildren,
|
||||||
AboutRoute: AboutRoute,
|
AboutRoute: AboutRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
OcpLotsRoute: OcpLotsRoute,
|
OcpLotsRoute: OcpLotsRoute,
|
||||||
@@ -292,6 +361,7 @@ export const routeTree = rootRoute
|
|||||||
"/",
|
"/",
|
||||||
"/_admin",
|
"/_admin",
|
||||||
"/_auth",
|
"/_auth",
|
||||||
|
"/_eom",
|
||||||
"/about",
|
"/about",
|
||||||
"/login",
|
"/login",
|
||||||
"/ocp/lots",
|
"/ocp/lots",
|
||||||
@@ -314,6 +384,13 @@ export const routeTree = rootRoute
|
|||||||
"/_auth/profile"
|
"/_auth/profile"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"/_eom": {
|
||||||
|
"filePath": "_eom.tsx",
|
||||||
|
"children": [
|
||||||
|
"/_eom/eom",
|
||||||
|
"/_eom/article/$av"
|
||||||
|
]
|
||||||
|
},
|
||||||
"/about": {
|
"/about": {
|
||||||
"filePath": "about.tsx"
|
"filePath": "about.tsx"
|
||||||
},
|
},
|
||||||
@@ -332,11 +409,19 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "_auth/profile.tsx",
|
"filePath": "_auth/profile.tsx",
|
||||||
"parent": "/_auth"
|
"parent": "/_auth"
|
||||||
},
|
},
|
||||||
|
"/_eom/eom": {
|
||||||
|
"filePath": "_eom/eom.tsx",
|
||||||
|
"parent": "/_eom"
|
||||||
|
},
|
||||||
"/ocp/lots": {
|
"/ocp/lots": {
|
||||||
"filePath": "ocp/lots.tsx"
|
"filePath": "ocp/lots.tsx"
|
||||||
},
|
},
|
||||||
"/ocp/": {
|
"/ocp/": {
|
||||||
"filePath": "ocp/index.tsx"
|
"filePath": "ocp/index.tsx"
|
||||||
|
},
|
||||||
|
"/_eom/article/$av": {
|
||||||
|
"filePath": "_eom/article/$av.tsx",
|
||||||
|
"parent": "/_eom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
frontend/src/routes/_eom.tsx
Normal file
13
frontend/src/routes/_eom.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import {createFileRoute, redirect} from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/_eom")({
|
||||||
|
//component: RouteComponent,
|
||||||
|
beforeLoad: async () => {
|
||||||
|
const auth = localStorage.getItem("auth_token");
|
||||||
|
if (!auth) {
|
||||||
|
throw redirect({
|
||||||
|
to: "/login",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
125
frontend/src/routes/_eom/article/$av.tsx
Normal file
125
frontend/src/routes/_eom/article/$av.tsx
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {CardFooter, CardHeader} from "@/components/ui/card";
|
||||||
|
import {Input} from "@/components/ui/input";
|
||||||
|
import {Label} from "@radix-ui/react-dropdown-menu";
|
||||||
|
import {createFileRoute} from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/_eom/article/$av")({
|
||||||
|
component: RouteComponent,
|
||||||
|
loader: () => {
|
||||||
|
return [{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
const {av} = Route.useParams();
|
||||||
|
const loaded = Route.useLoaderData();
|
||||||
|
|
||||||
|
console.log(loaded, av);
|
||||||
|
return (
|
||||||
|
<div className="w-full m-2">
|
||||||
|
<form className="w-1/2">
|
||||||
|
<div>
|
||||||
|
<h1>AV - Description</h1>
|
||||||
|
</div>
|
||||||
|
<hr className="w-48"></hr>
|
||||||
|
<LstCard className="m-2">
|
||||||
|
<CardHeader className="place-content-center">
|
||||||
|
<h3>Inventory Data</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Starting Inv</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>At The Line</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Inhouse endinging</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>In transit</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Comments</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CardFooter>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Label>Total Inv</Label>
|
||||||
|
</div>
|
||||||
|
</CardFooter>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-2">
|
||||||
|
<CardHeader className="place-content-center">
|
||||||
|
<h3>Purchasing</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Purchased</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Recived in GP</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Varation</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Comments</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-2">
|
||||||
|
<CardHeader className="place-content-center">
|
||||||
|
<h3>Transfers</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Transfered in</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Transfered out</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-96 m-2">
|
||||||
|
<Label>Comments</Label>
|
||||||
|
<Input></Input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
<LstCard className="m-2">
|
||||||
|
<CardHeader className="place-content-center">
|
||||||
|
<h3>Calculations</h3>
|
||||||
|
</CardHeader>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="w-96 m-2 flex flex-col">
|
||||||
|
<Label>Actual Consumption: 1452541</Label>
|
||||||
|
<Label>Production Consumption: 146854</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-96 m-2 flex flex-col">
|
||||||
|
<Label>Difference: -2541</Label>
|
||||||
|
<Label>Waste: -5%</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-96 m-2 flex flex-col">
|
||||||
|
<Label>Price/Kg: $2.20</Label>
|
||||||
|
<Label>$Loss/$Gain: $35.00</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
14
frontend/src/routes/_eom/eom.tsx
Normal file
14
frontend/src/routes/_eom/eom.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import EomPage from "@/components/eom/EomPage";
|
||||||
|
import {createFileRoute} from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/_eom/eom")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<EomPage />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
5
server/services/eom/eomService.ts
Normal file
5
server/services/eom/eomService.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
export default app;
|
||||||
Reference in New Issue
Block a user