feat(cards): migrated cards over
This commit is contained in:
67
frontend/package-lock.json
generated
67
frontend/package-lock.json
generated
@@ -23,6 +23,7 @@
|
|||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
"@radix-ui/react-tabs": "^1.1.3",
|
"@radix-ui/react-tabs": "^1.1.3",
|
||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@tailwindcss/vite": "^4.0.15",
|
"@tailwindcss/vite": "^4.0.15",
|
||||||
"@tanstack/react-form": "^1.2.1",
|
"@tanstack/react-form": "^1.2.1",
|
||||||
"@tanstack/react-query": "^5.69.0",
|
"@tanstack/react-query": "^5.69.0",
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lucide-react": "^0.483.0",
|
"lucide-react": "^0.483.0",
|
||||||
|
"marked": "^15.0.8",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"npm-check-updates": "^17.1.16",
|
"npm-check-updates": "^17.1.16",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@@ -2937,6 +2939,21 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/typography": {
|
||||||
|
"version": "0.5.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz",
|
||||||
|
"integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.castarray": "^4.4.0",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.merge": "^4.6.2",
|
||||||
|
"postcss-selector-parser": "6.0.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/vite": {
|
"node_modules/@tailwindcss/vite": {
|
||||||
"version": "4.0.15",
|
"version": "4.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.0.15.tgz",
|
||||||
@@ -4177,6 +4194,18 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cssesc": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"cssesc": "bin/cssesc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
@@ -5717,6 +5746,12 @@
|
|||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.castarray": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.includes": {
|
"node_modules/lodash.includes": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
@@ -5757,7 +5792,6 @@
|
|||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash.once": {
|
"node_modules/lodash.once": {
|
||||||
@@ -5797,6 +5831,18 @@
|
|||||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/marked": {
|
||||||
|
"version": "15.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.8.tgz",
|
||||||
|
"integrity": "sha512-rli4l2LyZqpQuRve5C0rkn6pj3hT8EWPC+zkAxFTAJLxRbENfTAhEQq9itrmf1Y81QtAX5D/MYlGlIomNgj9lA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"marked": "bin/marked.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/math-intrinsics": {
|
"node_modules/math-intrinsics": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
@@ -6075,6 +6121,19 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postcss-selector-parser": {
|
||||||
|
"version": "6.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||||
|
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cssesc": "^3.0.0",
|
||||||
|
"util-deprecate": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
@@ -7029,6 +7088,12 @@
|
|||||||
"which-typed-array": "^1.1.2"
|
"which-typed-array": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/victory-vendor": {
|
"node_modules/victory-vendor": {
|
||||||
"version": "36.9.2",
|
"version": "36.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lucide-react": "^0.483.0",
|
"lucide-react": "^0.483.0",
|
||||||
|
"marked": "^15.0.8",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"npm-check-updates": "^17.1.16",
|
"npm-check-updates": "^17.1.16",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|||||||
@@ -3,55 +3,37 @@ import {
|
|||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
|
import Cards from "./Cards";
|
||||||
import { useCardStore } from "@/lib/store/useCardStore";
|
//import { toast } from "sonner";
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
export function AddCards() {
|
export function AddCards() {
|
||||||
const { cards, addCard } = useCardStore();
|
|
||||||
|
|
||||||
const handleAddPPOO = () => {
|
|
||||||
const existingCard = cards.filter((c) => c.i === "PPOO");
|
|
||||||
//console.log(existingCard.length);
|
|
||||||
//console.log(data);
|
|
||||||
if (existingCard.length != 0) {
|
|
||||||
toast.error(`PPOO already exists no card will be added`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addCard({
|
|
||||||
i: "PPOO",
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
w: 5,
|
|
||||||
h: 3,
|
|
||||||
isResizable: true,
|
|
||||||
isDraggable: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline">Add Cards</Button>
|
<Button variant="outline">Add Cards</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
<DialogContent className="min-w-fit ">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Cards</DialogTitle>
|
<DialogTitle>Cards</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Please add a card below.
|
Manage Cards and there settings.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<Button onClick={handleAddPPOO} className="w-48">
|
|
||||||
PPOO
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<DialogFooter>
|
<Cards name={"ppoo"} inventory />
|
||||||
|
<Cards name={"inv-empty"} rowType={"empty"} />
|
||||||
|
<Cards name={"inv-fg"} rowType={"fg"} />
|
||||||
|
<Cards name={"inv-materials"} rowType={"materials"} />
|
||||||
|
<Cards name={"inv-packaging"} rowType={"packaging"} />
|
||||||
|
<Cards name={"inv-waste"} rowType={"waste"} />
|
||||||
|
|
||||||
|
{/* <DialogFooter>
|
||||||
<Button type="submit">Save changes</Button>
|
<Button type="submit">Save changes</Button>
|
||||||
</DialogFooter>
|
</DialogFooter> */}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|||||||
183
frontend/src/components/dashboard/Cards.tsx
Normal file
183
frontend/src/components/dashboard/Cards.tsx
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import { useCardStore } from "@/lib/store/useCardStore";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
import { Checkbox } from "../ui/checkbox";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
// import {
|
||||||
|
// Select,
|
||||||
|
// SelectContent,
|
||||||
|
// SelectGroup,
|
||||||
|
// SelectItem,
|
||||||
|
// SelectLabel,
|
||||||
|
// SelectTrigger,
|
||||||
|
// SelectValue,
|
||||||
|
// } from "../ui/select";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function Cards(card: any) {
|
||||||
|
const { addCard, removeCard, cards } = useCardStore();
|
||||||
|
let existing: any = cards.filter((n: any) => n.name === card.name);
|
||||||
|
|
||||||
|
console.log(existing);
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
name: existing?.name || card.name,
|
||||||
|
rowType: existing?.type ?? card.rowType,
|
||||||
|
age: existing?.age ?? 90,
|
||||||
|
active: existing.active ? existing.active : false,
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
console.log(value);
|
||||||
|
const testCard: any = cards.filter(
|
||||||
|
(i: any) => i.name === value.name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (value.active) {
|
||||||
|
if (testCard.length > 0) {
|
||||||
|
toast.error("Card already exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// change the name for a type card
|
||||||
|
const newCard = {
|
||||||
|
name: `${value.name}`,
|
||||||
|
rowType: value.rowType,
|
||||||
|
age: value.age ?? 90,
|
||||||
|
active: value.active,
|
||||||
|
};
|
||||||
|
addCard(newCard);
|
||||||
|
} else {
|
||||||
|
removeCard(value.name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className="border-solid border-2">
|
||||||
|
<p>{card.name}</p>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
className="flex flex-row"
|
||||||
|
>
|
||||||
|
<form.Field
|
||||||
|
name="active"
|
||||||
|
// 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 p-2 flex flex-row">
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="active">
|
||||||
|
<span>Active</span>
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Checkbox
|
||||||
|
className="ml-2"
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
checked={field.state.value}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
field.handleChange(e)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!card.inventory && (
|
||||||
|
<>
|
||||||
|
<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 p-2">
|
||||||
|
<Label htmlFor="active" className="">
|
||||||
|
Age
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
name={field.name}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <form.Field
|
||||||
|
name="rowType"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Row Type
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>
|
||||||
|
Row Type
|
||||||
|
</SelectLabel>
|
||||||
|
<SelectItem value="empty">
|
||||||
|
Empty
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="fg">
|
||||||
|
Finished Goods
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="materials">
|
||||||
|
Materials
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="waste">
|
||||||
|
Waste
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="packaging">
|
||||||
|
Packaging
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="mt-7">
|
||||||
|
<Button type="submit" onClick={() => form.handleSubmit()}>
|
||||||
|
Save Card
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,68 +1,74 @@
|
|||||||
export default function DashBoard() {
|
import { useCardStore } from "@/lib/store/useCardStore";
|
||||||
// const handleResizeStop = (newLayout: any, newItem: any) => {
|
import INVCheckCard from "../logistics/warehouse/InventoryCard";
|
||||||
// updateCard(
|
import PPOO from "../logistics/warehouse/PPOOCard";
|
||||||
// newItem.i,
|
|
||||||
// newLayout.filter((n: any) => n.i === newItem.i)[0]
|
|
||||||
// ); // Store the new layout in state
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const handleDragStop = (newLayout: any, newItem: any) => {
|
const componentsMap: any = {
|
||||||
// updateCard(
|
ppoo: PPOO,
|
||||||
// newItem.i,
|
inv: INVCheckCard,
|
||||||
// newLayout.filter((n: any) => n.i === newItem.i)[0]
|
//QualityRequest,
|
||||||
// ); // Persist the updated layout with custom name
|
};
|
||||||
// };
|
|
||||||
|
export default function DashBoard() {
|
||||||
|
const { cards } = useCardStore();
|
||||||
|
|
||||||
|
//console.log(cards);
|
||||||
|
return (
|
||||||
|
<div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
|
||||||
|
{cards.map((a: any) => {
|
||||||
|
const name = a.name; //.filter((c) => c.i === card.i)[0].i || "name";
|
||||||
|
|
||||||
|
const Component = componentsMap[name.split("-")[0]];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ml-5 w-11/12 h-9/10">
|
<div key={a.name} className="col-span-3">
|
||||||
<p>Comming soon...</p>
|
<Component age={a.age} type={a.rowType} />{" "}
|
||||||
{/* <ResizablePanelGroup
|
|
||||||
direction="horizontal"
|
|
||||||
//className="rounded-lg border"
|
|
||||||
autoSaveId="persistence"
|
|
||||||
>
|
|
||||||
<ResizablePanel>
|
|
||||||
<ResizablePanelGroup direction="vertical">
|
|
||||||
<ResizablePanel>
|
|
||||||
<div className="overflow: auto">
|
|
||||||
<Lots />
|
|
||||||
</div>
|
|
||||||
</ResizablePanel>
|
|
||||||
<ResizableHandle />
|
|
||||||
<ResizablePanel>
|
|
||||||
<ResizablePanelGroup direction="horizontal">
|
|
||||||
<ResizablePanel>
|
|
||||||
<LabelLog />
|
|
||||||
</ResizablePanel>
|
|
||||||
<ResizableHandle />
|
|
||||||
<ResizablePanel>
|
|
||||||
<OcpLogs />
|
|
||||||
</ResizablePanel>
|
|
||||||
</ResizablePanelGroup>
|
|
||||||
</ResizablePanel>
|
|
||||||
</ResizablePanelGroup>
|
|
||||||
</ResizablePanel>
|
|
||||||
<ResizableHandle />
|
|
||||||
<ResizablePanel defaultSize={25}>
|
|
||||||
<ResizablePanelGroup direction="vertical">
|
|
||||||
{server[0].value === "usday1vms006" && (
|
|
||||||
<ResizablePanel className="max-h-[300px]">
|
|
||||||
<WrapperManualTrigger />
|
|
||||||
</ResizablePanel>
|
|
||||||
)}
|
|
||||||
{server[0].value === "usday1vms006" && (
|
|
||||||
<ResizablePanel className="max-h-[300px]">
|
|
||||||
<WrapperManualTrigger />
|
|
||||||
</ResizablePanel>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<ResizableHandle />
|
|
||||||
<ResizablePanel>
|
|
||||||
<PrinterStatus />
|
|
||||||
</ResizablePanel>
|
|
||||||
</ResizablePanelGroup>
|
|
||||||
</ResizablePanel>
|
|
||||||
</ResizablePanelGroup> */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <PPOO />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={90} type={"empty"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={75} type={"fg"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={30} type={"materials"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={7} type={"waste"} />
|
||||||
|
// </div>
|
||||||
|
// <div className="col-span-3">
|
||||||
|
// <INVCheckCard age={7} type={"packaging"} />
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div className="col-span-3">
|
||||||
|
<PPOO />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"empty"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"fg"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"materials"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"waste"} />
|
||||||
|
</div>
|
||||||
|
<div className="col-span-3">
|
||||||
|
<INVCheckCard age={30} type={"packaging"} />
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
//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) {
|
||||||
|
//{ style = {} }
|
||||||
|
const { data, isError, isLoading } = useQuery(getinventoryCheck(props));
|
||||||
|
|
||||||
|
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 === props.type.toUpperCase()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// const handleCloseCard = () => {
|
||||||
|
// //removeCard("PPOO");
|
||||||
|
|
||||||
|
// toast.success("card removed");
|
||||||
|
// };
|
||||||
|
|
||||||
|
return <InvTable columns={invColumns} data={laneData} info={props} />;
|
||||||
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
//import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
import { useCardStore } from "@/lib/store/useCardStore";
|
|
||||||
import { getPPOO } from "@/utils/querys/logistics/getPPOO";
|
import { getPPOO } from "@/utils/querys/logistics/getPPOO";
|
||||||
import { columns } from "@/utils/tableData/ppoo/ppooColumns";
|
import { columns } from "@/utils/tableData/ppoo/ppooColumns";
|
||||||
import { PPOOTable } from "@/utils/tableData/ppoo/ppooData";
|
import { PPOOTable } from "@/utils/tableData/ppoo/ppooData";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { CircleX } from "lucide-react";
|
//import { CircleX } from "lucide-react";
|
||||||
import { Suspense } from "react";
|
//import { Suspense } from "react";
|
||||||
import { toast } from "sonner";
|
//import { toast } from "sonner";
|
||||||
|
|
||||||
export default function PPOO({ style = {} }) {
|
export default function PPOO() {
|
||||||
const { removeCard } = useCardStore();
|
//{ style = {} }
|
||||||
const { data, isError, isLoading } = useQuery(getPPOO());
|
const { data, isError, isLoading } = useQuery(getPPOO());
|
||||||
|
|
||||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||||
@@ -21,30 +20,42 @@ export default function PPOO({ style = {} }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCloseCard = () => {
|
// const handleCloseCard = () => {
|
||||||
removeCard("PPOO");
|
// //removeCard("PPOO");
|
||||||
|
|
||||||
|
// toast.success("card removed");
|
||||||
|
// };
|
||||||
|
|
||||||
toast.success("card removed");
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div style={style}>
|
<PPOOTable
|
||||||
<LstCard style={style}>
|
columns={columns}
|
||||||
<Suspense fallback={<p>Loading PPOO...</p>}>
|
data={data}
|
||||||
<div className={`flex justify-center`}>
|
//style={style}
|
||||||
<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>
|
|
||||||
);
|
);
|
||||||
|
// 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,31 +1,23 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { devtools, persist } from "zustand/middleware";
|
import { devtools, persist } from "zustand/middleware";
|
||||||
|
|
||||||
interface CardSettings {
|
// interface CardSettings {
|
||||||
daysSinceLast?: number;
|
// daysSinceLast?: number;
|
||||||
rowType?: string;
|
// rowType?: string;
|
||||||
}
|
// }
|
||||||
|
|
||||||
export interface Card {
|
export interface Card {
|
||||||
i: string;
|
name: string;
|
||||||
x: number;
|
rowType: string;
|
||||||
y: number;
|
age: string;
|
||||||
w: number;
|
active: boolean;
|
||||||
h: number;
|
|
||||||
minW?: number;
|
|
||||||
maxW?: number;
|
|
||||||
minH?: number;
|
|
||||||
maxH?: number;
|
|
||||||
isResizable: boolean;
|
|
||||||
isDraggable: boolean;
|
|
||||||
cardSettings?: CardSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CardStore {
|
interface CardStore {
|
||||||
cards: Card[]; // Array of card objects
|
cards: Card[]; // Array of card objects
|
||||||
addCard: (card: Card) => void;
|
addCard: (card: Card) => void;
|
||||||
updateCard: (id: string, updatedCard: Partial<Card>) => void;
|
updateCard: (name: string, updatedCard: Partial<Card>) => void;
|
||||||
removeCard: (id: string) => void;
|
removeCard: (name: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCardStore = create<CardStore>()(
|
export const useCardStore = create<CardStore>()(
|
||||||
@@ -37,16 +29,18 @@ export const useCardStore = create<CardStore>()(
|
|||||||
addCard: (card) =>
|
addCard: (card) =>
|
||||||
set((state) => ({ cards: [...state.cards, card] })),
|
set((state) => ({ cards: [...state.cards, card] })),
|
||||||
|
|
||||||
updateCard: (id, updatedCard) =>
|
updateCard: (name, updatedCard) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
cards: state.cards.map((card) =>
|
cards: state.cards.map((card) =>
|
||||||
card.i === id ? { ...card, ...updatedCard } : card
|
card.name === name
|
||||||
|
? { ...card, ...updatedCard }
|
||||||
|
: card
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
|
|
||||||
removeCard: (id) =>
|
removeCard: (name) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
cards: state.cards.filter((card) => card.i !== id),
|
cards: state.cards.filter((card) => card.name !== name),
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
{ name: "card-storage" }
|
{ name: "card-storage" }
|
||||||
|
|||||||
25
frontend/src/utils/querys/logistics/getInventoryCheck.tsx
Normal file
25
frontend/src/utils/querys/logistics/getInventoryCheck.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { queryOptions } from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getinventoryCheck(data: any) {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["getInvCheck"],
|
||||||
|
queryFn: () => fetchStockSilo(data),
|
||||||
|
//enabled:
|
||||||
|
staleTime: 1000,
|
||||||
|
refetchInterval: 60 * 1000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchStockSilo = async (info: any) => {
|
||||||
|
console.log(info);
|
||||||
|
const { data } = await axios.post(`/api/logistics/cyclecountcheck`, {
|
||||||
|
age: info.age ? parseInt(info.age) : null,
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
return data.data ?? [];
|
||||||
|
};
|
||||||
@@ -7,7 +7,7 @@ export function getPPOO() {
|
|||||||
queryFn: () => fetchStockSilo(),
|
queryFn: () => fetchStockSilo(),
|
||||||
//enabled:
|
//enabled:
|
||||||
staleTime: 1000,
|
staleTime: 1000,
|
||||||
refetchInterval: 2 * 2000,
|
refetchInterval: 60 * 1000,
|
||||||
refetchOnWindowFocus: true,
|
refetchOnWindowFocus: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
|
|
||||||
|
// 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 invColumns: ColumnDef<Adjustmnets>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "Description",
|
||||||
|
header: () => <div className="text-left">Lane</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "DaysSinceLast",
|
||||||
|
header: "Age",
|
||||||
|
//enableSorting: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
166
frontend/src/utils/tableData/InventoryCards/inventoryData.tsx
Normal file
166
frontend/src/utils/tableData/InventoryCards/inventoryData.tsx
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
useReactTable,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
//import { Button } from "@/components/ui/button";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
|
||||||
|
interface DataTableProps<TData, TValue> {
|
||||||
|
columns: ColumnDef<TData, TValue>[];
|
||||||
|
data: TData[];
|
||||||
|
info: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColumnSort = {
|
||||||
|
id: string;
|
||||||
|
desc: boolean;
|
||||||
|
};
|
||||||
|
type SortingState = ColumnSort[];
|
||||||
|
|
||||||
|
export function InvTable<TData, TValue>({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
info,
|
||||||
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
pageIndex: 0, //initial page index
|
||||||
|
pageSize: 5, //default page size
|
||||||
|
});
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
state: {
|
||||||
|
//...
|
||||||
|
pagination,
|
||||||
|
sorting,
|
||||||
|
},
|
||||||
|
manualSorting: true,
|
||||||
|
onSortingChange: setSorting,
|
||||||
|
initialState: {
|
||||||
|
sorting: [
|
||||||
|
{
|
||||||
|
id: "DaysSinceLast",
|
||||||
|
desc: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
//console.log(table.getState().sorting);
|
||||||
|
//console.log(parseInt(style.height.replace("px", "")) - 50);
|
||||||
|
return (
|
||||||
|
<LstCard
|
||||||
|
className="p-3"
|
||||||
|
// style={{
|
||||||
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
|
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
|
||||||
|
// cursor: "move",
|
||||||
|
// }}
|
||||||
|
//style={{ overflow: "auto" }}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div className="flex flex-row justify-between">
|
||||||
|
<p className="text-center text-pretty">
|
||||||
|
{info.type} {data.length > 0 ? "lanes" : "lane"} older
|
||||||
|
than: {info.age}, needing to be completed
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ScrollArea className="h-72 rounded-md border m-2">
|
||||||
|
<Table
|
||||||
|
// style={{
|
||||||
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
|
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
||||||
|
// cursor: "move",
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</ScrollArea>
|
||||||
|
</div>
|
||||||
|
{/* <div className="flex items-center justify-end space-x-2">
|
||||||
|
<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> */}
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
68
frontend/src/utils/tableData/notifications/notifyColumns.tsx
Normal file
68
frontend/src/utils/tableData/notifications/notifyColumns.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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 notifyColumns: ColumnDef<Adjustmnets>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: "name",
|
||||||
|
header: () => <div className="text-left">Name</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "description",
|
||||||
|
header: "Description",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return (
|
||||||
|
<div className="text-left font-medium">
|
||||||
|
<p className="max-w-48 text-pretty">
|
||||||
|
{row.getValue("description")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
accessorKey: "checkInterval",
|
||||||
|
header: "Check Interval",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "timeType",
|
||||||
|
header: "Time tpye",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "emails",
|
||||||
|
header: "Emails",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "active",
|
||||||
|
header: "Active",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "lastRan",
|
||||||
|
header: "Last Ran",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
if (row.getValue("lastRan")) {
|
||||||
|
const correctDate = format(
|
||||||
|
row.getValue("lastRan"),
|
||||||
|
"M/d/yyyy hh:mm"
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="text-left font-medium">{correctDate}</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
134
frontend/src/utils/tableData/notifications/notifyData.tsx
Normal file
134
frontend/src/utils/tableData/notifications/notifyData.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
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";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
interface DataTableProps<TData, TValue> {
|
||||||
|
columns: ColumnDef<TData, TValue>[];
|
||||||
|
data: TData[];
|
||||||
|
//style: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NotifyTable<TData, TValue>({
|
||||||
|
columns,
|
||||||
|
data,
|
||||||
|
//style,
|
||||||
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
pageIndex: 0, //initial page index
|
||||||
|
pageSize: 5, //default page size
|
||||||
|
});
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
//...
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// console.log(parseInt(style.height.replace("px", "")) - 50);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
// style={{
|
||||||
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
|
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
|
||||||
|
// cursor: "move",
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
// style={{
|
||||||
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
|
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
||||||
|
// cursor: "move",
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,41 +14,93 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useState } from "react";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
|
||||||
interface DataTableProps<TData, TValue> {
|
interface DataTableProps<TData, TValue> {
|
||||||
columns: ColumnDef<TData, TValue>[];
|
columns: ColumnDef<TData, TValue>[];
|
||||||
data: TData[];
|
data: TData[];
|
||||||
style: any;
|
//style: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PPOOTable<TData, TValue>({
|
export function PPOOTable<TData, TValue>({
|
||||||
columns,
|
columns,
|
||||||
data,
|
data,
|
||||||
style,
|
//style,
|
||||||
}: DataTableProps<TData, TValue>) {
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
const [pagination, setPagination] = useState({
|
||||||
|
pageIndex: 0, //initial page index
|
||||||
|
pageSize: 5, //default page size
|
||||||
|
});
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data,
|
data,
|
||||||
columns,
|
columns,
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
getPaginationRowModel: getPaginationRowModel(),
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
state: {
|
||||||
|
//...
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(parseInt(style.height.replace("px", "")) - 50);
|
//console.log(parseInt(style.height.replace("px", "")) - 50);
|
||||||
return (
|
return (
|
||||||
<div
|
<LstCard
|
||||||
style={{
|
className="p-3"
|
||||||
width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
// style={{
|
||||||
height: `${parseInt(style.height.replace("px", "")) - 150}px`,
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
cursor: "move",
|
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
|
||||||
}}
|
// cursor: "move",
|
||||||
|
// }}
|
||||||
|
//style={{ overflow: "auto" }}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
<div className="flex flex-row justify-between">
|
||||||
|
<p className="text-center">PPOO Data </p>
|
||||||
|
<Select
|
||||||
|
value={pagination.pageSize.toString()}
|
||||||
|
onValueChange={(e) =>
|
||||||
|
setPagination({
|
||||||
|
...pagination,
|
||||||
|
pageSize: parseInt(e),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
//id={field.name}
|
||||||
|
placeholder="Select Page"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Page Size</SelectLabel>
|
||||||
|
<SelectItem value="5">5</SelectItem>
|
||||||
|
<SelectItem value="10">10</SelectItem>
|
||||||
|
<SelectItem value="50">50</SelectItem>
|
||||||
|
<SelectItem value="100">100</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<ScrollArea className="h-72 rounded-md border m-2">
|
||||||
<Table
|
<Table
|
||||||
style={{
|
// style={{
|
||||||
width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
||||||
cursor: "move",
|
// cursor: "move",
|
||||||
}}
|
// }}
|
||||||
>
|
>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
@@ -59,8 +111,8 @@ export function PPOOTable<TData, TValue>({
|
|||||||
{header.isPlaceholder
|
{header.isPlaceholder
|
||||||
? null
|
? null
|
||||||
: flexRender(
|
: flexRender(
|
||||||
header.column.columnDef
|
header.column
|
||||||
.header,
|
.columnDef.header,
|
||||||
header.getContext()
|
header.getContext()
|
||||||
)}
|
)}
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@@ -100,8 +152,9 @@ export function PPOOTable<TData, TValue>({
|
|||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-end space-x-2 py-4">
|
<div className="flex items-center justify-end space-x-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -119,6 +172,6 @@ export function PPOOTable<TData, TValue>({
|
|||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</LstCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,41 @@
|
|||||||
import { lanes } from "./cyclecountCheck.js";
|
import { lanes } from "./cyclecountCheck.js";
|
||||||
|
|
||||||
export const getCycleCountCheck = async (
|
export const getCycleCountCheck = async (age: number = 1000, type: any) => {
|
||||||
age: number = 1000,
|
|
||||||
type: string = ""
|
|
||||||
) => {
|
|
||||||
/**
|
/**
|
||||||
* Get the lane data based on the age and type
|
* Get the lane data based on the age and type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let filteredLanes = lanes.filter((t: any) => t.DaysSinceLast >= age);
|
let filteredLanes = lanes;
|
||||||
|
|
||||||
|
if (type === "empty") {
|
||||||
|
let empty = lanes.filter((t: any) => t.rowType === type.toUpperCase());
|
||||||
|
|
||||||
if (type != "") {
|
|
||||||
return {
|
return {
|
||||||
sucess: true,
|
sucess: true,
|
||||||
message: `${filteredLanes.length} lanes that are of type ${type} and have not been cycle counted in the last ${age} days.`,
|
message: `${empty.length} lanes that are of type ${type}.`,
|
||||||
data: filteredLanes.filter(
|
data: empty.sort(
|
||||||
(t: any) => t.rowType === type.toUpperCase()
|
(a: any, b: any) => b.DaysSinceLast - a.DaysSinceLast
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (type != "") {
|
||||||
|
let noType = lanes.filter((t: any) => t.DaysSinceLast >= age);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sucess: true,
|
||||||
|
message: `${noType.length} lanes that are of type ${type} and have not been cycle counted in the last ${age} days.`,
|
||||||
|
data: noType
|
||||||
|
.filter((t: any) => t.rowType === type?.toUpperCase())
|
||||||
|
.sort((a: any, b: any) => b.DaysSinceLast - a.DaysSinceLast),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: `${filteredLanes.length} lanes grabed that have not been cycle counted in the last ${age} days.`,
|
message: `${filteredLanes.length} lanes grabed that have not been cycle counted in the last ${age} days.`,
|
||||||
data: filteredLanes,
|
data: filteredLanes.sort(
|
||||||
|
(a: any, b: any) => b.DaysSinceLast - a.DaysSinceLast
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ app.openapi(
|
|||||||
return c.json({ success: false, message: "Missing Data." });
|
return c.json({ success: false, message: "Missing Data." });
|
||||||
}
|
}
|
||||||
|
|
||||||
const check: any = body;
|
const check: any = body ?? { age: 90, type: null };
|
||||||
const { data: lanes, error: le } = await tryCatch(
|
const { data: lanes, error: le } = await tryCatch(
|
||||||
getCycleCountCheck(check.age, check.type)
|
getCycleCountCheck(check.age, check.type)
|
||||||
);
|
);
|
||||||
|
|||||||
66
server/services/logistics/route/getCycleCountLanes.ts
Normal file
66
server/services/logistics/route/getCycleCountLanes.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { lanesToExcel } from "../controller/warehouse/cycleCountChecks/exportCycleCountData.js";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
// const Body = z
|
||||||
|
// .object({
|
||||||
|
// age: z.number().optional().openapi({ example: 90 }),
|
||||||
|
// //email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
||||||
|
// type: z.string().optional().openapi({ example: "fg" }),
|
||||||
|
// })
|
||||||
|
// .openapi("User");
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["logistics"],
|
||||||
|
summary: "Returns the lanes that need to be counted",
|
||||||
|
method: "get",
|
||||||
|
path: "/getcyclecount",
|
||||||
|
// request: {
|
||||||
|
// body: {
|
||||||
|
// content: {
|
||||||
|
// "application/json": { schema: Body },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// description:
|
||||||
|
// "Provided a running number and lot number you can consume material.",
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c: any) => {
|
||||||
|
//apiHit(c, { endpoint: "api/sqlProd/close" });
|
||||||
|
const defaultFilename = `cycleCount-${format(
|
||||||
|
new Date(Date.now()),
|
||||||
|
"M-d-yyyy"
|
||||||
|
)}.xlsx`;
|
||||||
|
const filename = c.req.query("filename") || defaultFilename;
|
||||||
|
const age = c.req.query("age") || null;
|
||||||
|
const { data, error } = await tryCatch(lanesToExcel(age));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message: "Error getting lane data.",
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(data, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type":
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
"Content-Disposition": `attachment; filename="${filename}"`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// return c.json({
|
||||||
|
// success: data.success,
|
||||||
|
// message: data.message,
|
||||||
|
// data: data.data,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
Reference in New Issue
Block a user