feat(eom): frame work added in for eom

This commit is contained in:
2025-03-05 20:15:38 -06:00
parent 50cf87380d
commit fda0719d87
14 changed files with 708 additions and 6 deletions

View 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>
);
}

View 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>
);
}

View File

@@ -1,4 +1,4 @@
import {Printer} from "lucide-react";
import {FileText} from "lucide-react";
import {
SidebarGroup,
SidebarGroupContent,
@@ -10,9 +10,9 @@ import {
const items = [
{
title: "Qaulity Request",
url: "#",
icon: Printer,
title: "End Of Month",
url: "/eom",
icon: FileText,
},
];

View 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 }

View 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};

View 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 }

View 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 }