feat(silo): added in charts and historical data

This commit is contained in:
2025-04-09 17:48:03 -05:00
parent efc630f5f8
commit bad390ec17
14 changed files with 495 additions and 92 deletions

View File

@@ -1,19 +1,24 @@
import {Sidebar, SidebarContent, SidebarFooter, SidebarTrigger} from "../ui/sidebar";
import {ProductionSideBar} from "./side-components/production";
import {Header} from "./side-components/header";
import {LogisticsSideBar} from "./side-components/logistics";
import {QualitySideBar} from "./side-components/quality";
import {ForkliftSideBar} from "./side-components/forklift";
import {EomSideBar} from "./side-components/eom";
import {AdminSideBar} from "./side-components/admin";
import {useSessionStore} from "../../lib/store/sessionStore";
import {hasAccess} from "../../utils/userAccess";
import {moduleActive} from "../../utils/moduleActive";
import {useModuleStore} from "../../lib/store/useModuleStore";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarTrigger,
} from "../ui/sidebar";
import { ProductionSideBar } from "./side-components/production";
import { Header } from "./side-components/header";
import { LogisticsSideBar } from "./side-components/logistics";
import { QualitySideBar } from "./side-components/quality";
import { ForkliftSideBar } from "./side-components/forklift";
import { EomSideBar } from "./side-components/eom";
import { AdminSideBar } from "./side-components/admin";
import { useSessionStore } from "../../lib/store/sessionStore";
import { hasAccess } from "../../utils/userAccess";
import { moduleActive } from "../../utils/moduleActive";
import { useModuleStore } from "../../lib/store/useModuleStore";
export function AppSidebar() {
const {user} = useSessionStore();
const {modules} = useModuleStore();
const { user } = useSessionStore();
const { modules } = useModuleStore();
return (
<Sidebar collapsible="icon">
@@ -22,19 +27,31 @@ export function AppSidebar() {
{moduleActive("production") && (
<ProductionSideBar
user={user}
moduleID={modules.filter((n) => n.name === "production")[0].module_id as string}
moduleID={
modules.filter((n) => n.name === "production")[0]
.module_id as string
}
/>
)}
{moduleActive("logistics") && (
<LogisticsSideBar
user={user}
moduleID={modules.filter((n) => n.name === "logistics")[0].module_id as string}
moduleID={
modules.filter((n) => n.name === "logistics")[0]
.module_id as string
}
/>
)}
{moduleActive("forklift") && hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
{moduleActive("eom") && hasAccess(user, "eom", modules) && <EomSideBar />}
{moduleActive("quality") && hasAccess(user, "quality", modules) && <QualitySideBar />}
{moduleActive("admin") && hasAccess(user, "admin", modules) && <AdminSideBar />}
{moduleActive("forklift") &&
hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
<EomSideBar />
)}
{moduleActive("quality") &&
hasAccess(user, "quality", modules) && <QualitySideBar />}
{moduleActive("admin") && hasAccess(user, "admin", modules) && (
<AdminSideBar />
)}
</SidebarContent>
<SidebarFooter>
<SidebarTrigger />

View File

@@ -0,0 +1,113 @@
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>
);
}

View File

@@ -0,0 +1,28 @@
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
import { columns } from "@/utils/tableData/siloAdjustmentHist/siloAdjHist";
import { DataTable } from "@/utils/tableData/siloAdjustmentHist/siloDate";
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)
);
console.log(adjustments);
return (
<div className="container mx-auto py-10">
<DataTable columns={columns} data={adjustments} />
</div>
);
}

View File

@@ -12,11 +12,13 @@ import {
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
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 ChartData from "./ChartData";
export default function SiloCard(data: any) {
const token = localStorage.getItem("auth_token");
@@ -183,9 +185,17 @@ export default function SiloCard(data: any) {
)}
</div>
</LstCard>
<div className="grow max-w-[400px]">
<LstCard className="m-1 ">charts go here</LstCard>
<LstCard className="m-1">extra options here</LstCard>
<div className="grow max-w-[600px]">
<ChartData laneId={silo.LocationID} />
<div className="flex justify-end m-1">
<Link
to={"/siloAdjustments/$hist"}
params={{ hist: silo.LocationID }}
>
Historical Data
</Link>
</div>
</div>
</div>
</LstCard>

View File

@@ -1,3 +1,4 @@
import HistoricalData from "@/components/logistics/siloAdjustments/HistoricalData";
import { createFileRoute, redirect } from "@tanstack/react-router";
export const Route = createFileRoute("/(logistics)/siloAdjustments/$hist")({
@@ -22,10 +23,10 @@ export const Route = createFileRoute("/(logistics)/siloAdjustments/$hist")({
});
function RouteComponent() {
const { hist } = Route.useParams();
return (
<div>
Hello "/(logistics)/siloAdjustments/$hist"! where the historical
data will be shown in a table alone with a graph
<HistoricalData laneId={hist} />
</div>
);
}

View File

@@ -1,14 +1,14 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getStockSilo() {
export function getAdjustments() {
const token = localStorage.getItem("auth_token");
return queryOptions({
queryKey: ["getUsers"],
queryKey: ["getAdjustments"],
queryFn: () => fetchStockSilo(token),
enabled: !!token, // Prevents query if token is null
staleTime: 1000,
//refetchInterval: 2 * 2000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}

View File

@@ -0,0 +1,84 @@
import { ColumnDef } from "@tanstack/react-table";
import { format } from "date-fns";
// This type is used to define the shape of our data.
// You can use a Zod schema here if you want.
export type Adjustmnets = {
siloAdjust_id: string;
currentStockLevel: string;
newLevel: number;
dateAdjusted: string;
lastDateAdjusted: string;
comment: string;
commentAddedBy: string;
commentDate: string;
add_user: string;
};
export const columns: ColumnDef<Adjustmnets>[] = [
{
accessorKey: "currentStockLevel",
header: () => <div className="text-right">Stock At Post</div>,
},
{
accessorKey: "newLevel",
header: "Level Entered",
},
{
accessorKey: "dateAdjusted",
header: "Adjustmnet",
cell: ({ row }) => {
if (row.getValue("dateAdjusted")) {
const correctDate = format(
row.original.dateAdjusted?.replace("Z", ""),
"M/d/yyyy hh:mm"
);
return (
<div className="text-right font-medium">{correctDate}</div>
);
}
},
},
{
accessorKey: "lastDateAdjusted",
header: "Last Adjusted",
cell: ({ row }) => {
if (row.getValue("lastDateAdjusted")) {
const correctDate = format(
row.original.lastDateAdjusted?.replace("Z", ""),
"M/d/yyyy hh:mm"
);
return (
<div className="text-right font-medium">{correctDate}</div>
);
}
},
},
{
accessorKey: "comment",
header: "Comment",
},
{
accessorKey: "commentAddedBy",
header: "Commenter ",
},
{
accessorKey: "commentDate",
header: "Comment Date ",
cell: ({ row }) => {
if (row.getValue("commentDate")) {
const correctDate = format(
row.original.commentDate?.replace("Z", ""),
"M/d/yyyy hh:mm"
);
return (
<div className="text-right font-medium">{correctDate}</div>
);
}
},
},
{
accessorKey: "add_user",
header: "Creator",
},
];

View File

@@ -0,0 +1,110 @@
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getPaginationRowModel,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
//console.log(data);
return (
<div className="rounded-md border w-[1028px]">
<div>
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef
.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={
row.getIsSelected() && "selected"
}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
);
}