Compare commits
16 Commits
9baeb1ceff
...
2a6af066bc
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a6af066bc | |||
| acd89d926c | |||
| bb20046890 | |||
| ae7ea2bb90 | |||
| 17773e9a23 | |||
| 25785703db | |||
| 087d14c585 | |||
| 328b61f6cc | |||
| c02d289b80 | |||
| e0e7e03d37 | |||
| 5fb7b5c59e | |||
| aabcf12bee | |||
| f0a5d6e949 | |||
| bdeea6bd1a | |||
| 89ace4343c | |||
| 242b90c75a |
23
database/migrations/0049_certain_tarot.sql
Normal file
23
database/migrations/0049_certain_tarot.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
CREATE TABLE "qualityRequest" (
|
||||||
|
"request_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"article" numeric,
|
||||||
|
"description" text,
|
||||||
|
"runningNr" text,
|
||||||
|
"lotNr" numeric,
|
||||||
|
"warehouseAtRequest" text,
|
||||||
|
"locationAtRequest" text,
|
||||||
|
"warehouseMovedTo" text,
|
||||||
|
"locationMovedTo" text,
|
||||||
|
"durationToMove" numeric,
|
||||||
|
"locationDropOff" text,
|
||||||
|
"palletStatus" numeric,
|
||||||
|
"palletStatusText" text,
|
||||||
|
"palletRequest" numeric,
|
||||||
|
"add_date" timestamp DEFAULT now(),
|
||||||
|
"add_user" text DEFAULT 'LST',
|
||||||
|
"upd_date" timestamp DEFAULT now(),
|
||||||
|
"upd_user" text DEFAULT 'LST'
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "rfidReaders" ADD COLUMN "lastTagScanned" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "logs" DROP COLUMN "checkedAt";
|
||||||
1699
database/migrations/meta/0049_snapshot.json
Normal file
1699
database/migrations/meta/0049_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -344,6 +344,13 @@
|
|||||||
"when": 1743946411873,
|
"when": 1743946411873,
|
||||||
"tag": "0048_tearful_bushwacker",
|
"tag": "0048_tearful_bushwacker",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 49,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1744649552936,
|
||||||
|
"tag": "0049_certain_tarot",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
47
database/schema/qualityRequest.ts
Normal file
47
database/schema/qualityRequest.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const qualityRequest = pgTable(
|
||||||
|
"qualityRequest",
|
||||||
|
{
|
||||||
|
request_id: uuid("request_id").defaultRandom().primaryKey(),
|
||||||
|
article: numeric("article"),
|
||||||
|
description: text("description"),
|
||||||
|
runningNr: text("runningNr"),
|
||||||
|
lotNr: numeric("lotNr"),
|
||||||
|
warehouseAtRequest: text("warehouseAtRequest"),
|
||||||
|
locationAtRequest: text("locationAtRequest"),
|
||||||
|
warehouseMovedTo: text("warehouseMovedTo"),
|
||||||
|
locationMovedTo: text("locationMovedTo"),
|
||||||
|
durationToMove: numeric("durationToMove"),
|
||||||
|
locationDropOff: text("locationDropOff"),
|
||||||
|
palletStatus: numeric("palletStatus"),
|
||||||
|
palletStatusText: text("palletStatusText"),
|
||||||
|
palletRequest: numeric("palletRequest"),
|
||||||
|
add_date: timestamp("add_date").defaultNow(),
|
||||||
|
add_user: text("add_user").default("LST"),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
upd_user: text("upd_user").default("LST"),
|
||||||
|
},
|
||||||
|
(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(qualityRequest);
|
||||||
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",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function ChangeModule({ module }: { module: any }) {
|
|||||||
active: module.active,
|
active: module.active,
|
||||||
},
|
},
|
||||||
onSubmit: async ({ value }) => {
|
onSubmit: async ({ value }) => {
|
||||||
console.log(value);
|
//console.log(value);
|
||||||
try {
|
try {
|
||||||
const result = await axios.patch(
|
const result = await axios.patch(
|
||||||
`/api/server/modules/${module.module_id}`,
|
`/api/server/modules/${module.module_id}`,
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
|
import { getnotifications } from "@/utils/querys/admin/notifications";
|
||||||
|
import { notifyColumns } from "@/utils/tableData/notifications/notifyColumns";
|
||||||
|
import { NotifyTable } from "@/utils/tableData/notifications/notifyData";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
export default function NotificationMGT() {
|
export default function NotificationMGT() {
|
||||||
|
const { data, isError, isLoading } = useQuery(getnotifications());
|
||||||
|
|
||||||
|
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>There was an error getting the adjustments.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
Manage all notifications from here instad of going to the db,
|
<NotifyTable columns={notifyColumns} data={data} />
|
||||||
locking some items that are auto updated on server restarts
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
33
frontend/src/components/changelog/ChangeLog.tsx
Normal file
33
frontend/src/components/changelog/ChangeLog.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// src/components/Changelog.jsx
|
||||||
|
import { marked } from "marked";
|
||||||
|
import changelog from "../../../../CHANGELOG.md?raw"; // assuming changelog.md is in root
|
||||||
|
|
||||||
|
const Changelog = () => {
|
||||||
|
const html: any = marked.parse(changelog);
|
||||||
|
const recentChanges = html.split("<h2>")[1];
|
||||||
|
// const [htmlContent, setHtmlContent] = useState("");
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// fetch("/changelog.md")
|
||||||
|
// .then((res) => res.text())
|
||||||
|
// .then((md) => {
|
||||||
|
// const versionBlocks = md.split(/^##\s+/gm); // Split on headings
|
||||||
|
// if (versionBlocks.length > 1) {
|
||||||
|
// const latestBlock = `## ${versionBlocks[1]}`;
|
||||||
|
// const html: any = marked.parse(latestBlock, {
|
||||||
|
// breaks: true,
|
||||||
|
// gfm: true,
|
||||||
|
// });
|
||||||
|
// setHtmlContent(html);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }, []);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="prose m-3"
|
||||||
|
dangerouslySetInnerHTML={{ __html: `<h2>${recentChanges}` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Changelog;
|
||||||
@@ -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 @@
|
|||||||
|
import { useCardStore } from "@/lib/store/useCardStore";
|
||||||
|
import INVCheckCard from "../logistics/warehouse/InventoryCard";
|
||||||
|
import PPOO from "../logistics/warehouse/PPOOCard";
|
||||||
|
|
||||||
|
const componentsMap: any = {
|
||||||
|
ppoo: PPOO,
|
||||||
|
inv: INVCheckCard,
|
||||||
|
//QualityRequest,
|
||||||
|
};
|
||||||
|
|
||||||
export default function DashBoard() {
|
export default function DashBoard() {
|
||||||
// const handleResizeStop = (newLayout: any, newItem: any) => {
|
const { cards } = useCardStore();
|
||||||
// updateCard(
|
|
||||||
// newItem.i,
|
|
||||||
// newLayout.filter((n: any) => n.i === newItem.i)[0]
|
|
||||||
// ); // Store the new layout in state
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const handleDragStop = (newLayout: any, newItem: any) => {
|
|
||||||
// updateCard(
|
|
||||||
// newItem.i,
|
|
||||||
// newLayout.filter((n: any) => n.i === newItem.i)[0]
|
|
||||||
// ); // Persist the updated layout with custom name
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
//console.log(cards);
|
||||||
return (
|
return (
|
||||||
<div className="ml-5 w-11/12 h-9/10">
|
<div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
|
||||||
<p>Comming soon...</p>
|
{cards.map((a: any) => {
|
||||||
{/* <ResizablePanelGroup
|
const name = a.name; //.filter((c) => c.i === card.i)[0].i || "name";
|
||||||
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 />
|
const Component = componentsMap[name.split("-")[0]];
|
||||||
<ResizablePanel>
|
|
||||||
<PrinterStatus />
|
return (
|
||||||
</ResizablePanel>
|
<div key={a.name} className="col-span-3">
|
||||||
</ResizablePanelGroup>
|
<Component age={a.age} type={a.rowType} />{" "}
|
||||||
</ResizablePanel>
|
</div>
|
||||||
</ResizablePanelGroup> */}
|
);
|
||||||
|
})}
|
||||||
</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" }
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
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 ChangelogImport } from './routes/changelog'
|
||||||
import { Route as AboutImport } from './routes/about'
|
import { Route as AboutImport } from './routes/about'
|
||||||
import { Route as EomImport } from './routes/_eom'
|
import { Route as EomImport } from './routes/_eom'
|
||||||
import { Route as AuthImport } from './routes/_auth'
|
import { Route as AuthImport } from './routes/_auth'
|
||||||
@@ -43,6 +44,12 @@ const LoginRoute = LoginImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const ChangelogRoute = ChangelogImport.update({
|
||||||
|
id: '/changelog',
|
||||||
|
path: '/changelog',
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const AboutRoute = AboutImport.update({
|
const AboutRoute = AboutImport.update({
|
||||||
id: '/about',
|
id: '/about',
|
||||||
path: '/about',
|
path: '/about',
|
||||||
@@ -217,6 +224,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AboutImport
|
preLoaderRoute: typeof AboutImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
|
'/changelog': {
|
||||||
|
id: '/changelog'
|
||||||
|
path: '/changelog'
|
||||||
|
fullPath: '/changelog'
|
||||||
|
preLoaderRoute: typeof ChangelogImport
|
||||||
|
parentRoute: typeof rootRoute
|
||||||
|
}
|
||||||
'/login': {
|
'/login': {
|
||||||
id: '/login'
|
id: '/login'
|
||||||
path: '/login'
|
path: '/login'
|
||||||
@@ -394,6 +408,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'': typeof EomRouteWithChildren
|
'': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/changelog': typeof ChangelogRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/modules': typeof AdminModulesRoute
|
'/modules': typeof AdminModulesRoute
|
||||||
'/notificationMGT': typeof AdminNotificationMGTRoute
|
'/notificationMGT': typeof AdminNotificationMGTRoute
|
||||||
@@ -418,6 +433,7 @@ export interface FileRoutesByTo {
|
|||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'': typeof EomRouteWithChildren
|
'': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/changelog': typeof ChangelogRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/modules': typeof AdminModulesRoute
|
'/modules': typeof AdminModulesRoute
|
||||||
'/notificationMGT': typeof AdminNotificationMGTRoute
|
'/notificationMGT': typeof AdminNotificationMGTRoute
|
||||||
@@ -445,6 +461,7 @@ export interface FileRoutesById {
|
|||||||
'/_auth': typeof AuthRouteWithChildren
|
'/_auth': typeof AuthRouteWithChildren
|
||||||
'/_eom': typeof EomRouteWithChildren
|
'/_eom': typeof EomRouteWithChildren
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/changelog': typeof ChangelogRoute
|
||||||
'/login': typeof LoginRoute
|
'/login': typeof LoginRoute
|
||||||
'/_admin/modules': typeof AdminModulesRoute
|
'/_admin/modules': typeof AdminModulesRoute
|
||||||
'/_admin/notificationMGT': typeof AdminNotificationMGTRoute
|
'/_admin/notificationMGT': typeof AdminNotificationMGTRoute
|
||||||
@@ -471,6 +488,7 @@ export interface FileRouteTypes {
|
|||||||
| '/'
|
| '/'
|
||||||
| ''
|
| ''
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/changelog'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/modules'
|
| '/modules'
|
||||||
| '/notificationMGT'
|
| '/notificationMGT'
|
||||||
@@ -494,6 +512,7 @@ export interface FileRouteTypes {
|
|||||||
| '/'
|
| '/'
|
||||||
| ''
|
| ''
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/changelog'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/modules'
|
| '/modules'
|
||||||
| '/notificationMGT'
|
| '/notificationMGT'
|
||||||
@@ -519,6 +538,7 @@ export interface FileRouteTypes {
|
|||||||
| '/_auth'
|
| '/_auth'
|
||||||
| '/_eom'
|
| '/_eom'
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/changelog'
|
||||||
| '/login'
|
| '/login'
|
||||||
| '/_admin/modules'
|
| '/_admin/modules'
|
||||||
| '/_admin/notificationMGT'
|
| '/_admin/notificationMGT'
|
||||||
@@ -546,6 +566,7 @@ export interface RootRouteChildren {
|
|||||||
AuthRoute: typeof AuthRouteWithChildren
|
AuthRoute: typeof AuthRouteWithChildren
|
||||||
EomRoute: typeof EomRouteWithChildren
|
EomRoute: typeof EomRouteWithChildren
|
||||||
AboutRoute: typeof AboutRoute
|
AboutRoute: typeof AboutRoute
|
||||||
|
ChangelogRoute: typeof ChangelogRoute
|
||||||
LoginRoute: typeof LoginRoute
|
LoginRoute: typeof LoginRoute
|
||||||
OcpIndexRoute: typeof OcpIndexRoute
|
OcpIndexRoute: typeof OcpIndexRoute
|
||||||
logisticsSiloAdjustmentsHistRoute: typeof logisticsSiloAdjustmentsHistRoute
|
logisticsSiloAdjustmentsHistRoute: typeof logisticsSiloAdjustmentsHistRoute
|
||||||
@@ -563,6 +584,7 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
AuthRoute: AuthRouteWithChildren,
|
AuthRoute: AuthRouteWithChildren,
|
||||||
EomRoute: EomRouteWithChildren,
|
EomRoute: EomRouteWithChildren,
|
||||||
AboutRoute: AboutRoute,
|
AboutRoute: AboutRoute,
|
||||||
|
ChangelogRoute: ChangelogRoute,
|
||||||
LoginRoute: LoginRoute,
|
LoginRoute: LoginRoute,
|
||||||
OcpIndexRoute: OcpIndexRoute,
|
OcpIndexRoute: OcpIndexRoute,
|
||||||
logisticsSiloAdjustmentsHistRoute: logisticsSiloAdjustmentsHistRoute,
|
logisticsSiloAdjustmentsHistRoute: logisticsSiloAdjustmentsHistRoute,
|
||||||
@@ -592,6 +614,7 @@ export const routeTree = rootRoute
|
|||||||
"/_auth",
|
"/_auth",
|
||||||
"/_eom",
|
"/_eom",
|
||||||
"/about",
|
"/about",
|
||||||
|
"/changelog",
|
||||||
"/login",
|
"/login",
|
||||||
"/ocp/",
|
"/ocp/",
|
||||||
"/(logistics)/siloAdjustments/$hist",
|
"/(logistics)/siloAdjustments/$hist",
|
||||||
@@ -633,6 +656,9 @@ export const routeTree = rootRoute
|
|||||||
"/about": {
|
"/about": {
|
||||||
"filePath": "about.tsx"
|
"filePath": "about.tsx"
|
||||||
},
|
},
|
||||||
|
"/changelog": {
|
||||||
|
"filePath": "changelog.tsx"
|
||||||
|
},
|
||||||
"/login": {
|
"/login": {
|
||||||
"filePath": "login.tsx"
|
"filePath": "login.tsx"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import { createRootRoute, Link, Outlet } from "@tanstack/react-router";
|
import {
|
||||||
|
createRootRoute,
|
||||||
|
Link,
|
||||||
|
Outlet,
|
||||||
|
useLocation,
|
||||||
|
} from "@tanstack/react-router";
|
||||||
//import {TanStackRouterDevtools} from "@tanstack/router-devtools";
|
//import {TanStackRouterDevtools} from "@tanstack/router-devtools";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { SidebarProvider } from "../components/ui/sidebar";
|
import { SidebarProvider } from "../components/ui/sidebar";
|
||||||
@@ -17,11 +22,12 @@ import {
|
|||||||
import { SessionProvider } from "../components/providers/Providers";
|
import { SessionProvider } from "../components/providers/Providers";
|
||||||
import { Toaster } from "sonner";
|
import { Toaster } from "sonner";
|
||||||
//import { Button } from "../components/ui/button";
|
//import { Button } from "../components/ui/button";
|
||||||
|
|
||||||
import { useSessionStore } from "../lib/store/sessionStore";
|
import { useSessionStore } from "../lib/store/sessionStore";
|
||||||
import { useSession } from "@/hooks/useSession";
|
import { useSession } from "@/hooks/useSession";
|
||||||
import { useLogout } from "@/hooks/useLogout";
|
import { useLogout } from "@/hooks/useLogout";
|
||||||
|
import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData";
|
||||||
import { AddCards } from "@/components/dashboard/AddCards";
|
import { AddCards } from "@/components/dashboard/AddCards";
|
||||||
|
//import { AddCards } from "@/components/dashboard/AddCards";
|
||||||
|
|
||||||
// same as the layout
|
// same as the layout
|
||||||
export const Route = createRootRoute({
|
export const Route = createRootRoute({
|
||||||
@@ -30,16 +36,20 @@ export const Route = createRootRoute({
|
|||||||
const { session } = useSession();
|
const { session } = useSession();
|
||||||
const { user } = useSessionStore();
|
const { user } = useSessionStore();
|
||||||
const logout = useLogout();
|
const logout = useLogout();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="overflow-hidden">
|
||||||
<SessionProvider>
|
<SessionProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<nav className="flex justify-end">
|
<nav className="flex justify-end w-full shadow ">
|
||||||
<div className="m-2 flex flex-row">
|
<div className="m-2 flex flex-row">
|
||||||
<div className="m-auto pr-2">
|
{location.pathname === "/" && (
|
||||||
<AddCards />
|
<div className="m-auto pr-2 flex flex-row gap-2">
|
||||||
</div>
|
<ExportInventoryData />
|
||||||
|
<AddCards />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="m-1">
|
<div className="m-1">
|
||||||
<ModeToggle />
|
<ModeToggle />
|
||||||
</div>
|
</div>
|
||||||
@@ -88,16 +98,18 @@ export const Route = createRootRoute({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<SidebarProvider defaultOpen={sidebarState}>
|
<main>
|
||||||
<AppSidebar />
|
<SidebarProvider defaultOpen={sidebarState}>
|
||||||
<Toaster expand={true} richColors closeButton />
|
<AppSidebar />
|
||||||
<Outlet />
|
<Toaster expand={true} richColors closeButton />
|
||||||
</SidebarProvider>
|
<Outlet />
|
||||||
|
</SidebarProvider>
|
||||||
|
</main>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
|
|
||||||
{/* <TanStackRouterDevtools position="bottom-right" /> */}
|
{/* <TanStackRouterDevtools position="bottom-right" /> */}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
14
frontend/src/routes/changelog.tsx
Normal file
14
frontend/src/routes/changelog.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import Changelog from "@/components/changelog/ChangeLog";
|
||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/changelog")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Changelog />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,120 +5,120 @@
|
|||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: oklch(1 0 0);
|
--background: oklch(1 0 0);
|
||||||
--foreground: oklch(0.145 0 0);
|
--foreground: oklch(0.145 0 0);
|
||||||
--card: oklch(1 0 0);
|
--card: oklch(1 0 0);
|
||||||
--card-foreground: oklch(0.145 0 0);
|
--card-foreground: oklch(0.145 0 0);
|
||||||
--popover: oklch(1 0 0);
|
--popover: oklch(1 0 0);
|
||||||
--popover-foreground: oklch(0.145 0 0);
|
--popover-foreground: oklch(0.145 0 0);
|
||||||
--primary: oklch(0.205 0 0);
|
--primary: oklch(0.205 0 0);
|
||||||
--primary-foreground: oklch(0.985 0 0);
|
--primary-foreground: oklch(0.985 0 0);
|
||||||
--secondary: oklch(0.97 0 0);
|
--secondary: oklch(0.97 0 0);
|
||||||
--secondary-foreground: oklch(0.205 0 0);
|
--secondary-foreground: oklch(0.205 0 0);
|
||||||
--muted: oklch(0.97 0 0);
|
--muted: oklch(0.97 0 0);
|
||||||
--muted-foreground: oklch(0.556 0 0);
|
--muted-foreground: oklch(0.556 0 0);
|
||||||
--accent: oklch(0.97 0 0);
|
--accent: oklch(0.97 0 0);
|
||||||
--accent-foreground: oklch(0.205 0 0);
|
--accent-foreground: oklch(0.205 0 0);
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
--destructive-foreground: oklch(0.577 0.245 27.325);
|
--destructive-foreground: oklch(0.577 0.245 27.325);
|
||||||
--border: oklch(0.922 0 0);
|
--border: oklch(0.922 0 0);
|
||||||
--input: oklch(0.922 0 0);
|
--input: oklch(0.922 0 0);
|
||||||
--ring: oklch(0.87 0 0);
|
--ring: oklch(0.87 0 0);
|
||||||
--chart-1: oklch(0.646 0.222 41.116);
|
--chart-1: oklch(0.646 0.222 41.116);
|
||||||
--chart-2: oklch(0.6 0.118 184.704);
|
--chart-2: oklch(0.6 0.118 184.704);
|
||||||
--chart-3: oklch(0.398 0.07 227.392);
|
--chart-3: oklch(0.398 0.07 227.392);
|
||||||
--chart-4: oklch(0.828 0.189 84.429);
|
--chart-4: oklch(0.828 0.189 84.429);
|
||||||
--chart-5: oklch(0.769 0.188 70.08);
|
--chart-5: oklch(0.769 0.188 70.08);
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0.145 0 0);
|
||||||
--sidebar-primary: oklch(0.205 0 0);
|
--sidebar-primary: oklch(0.205 0 0);
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-accent: oklch(0.97 0 0);
|
--sidebar-accent: oklch(0.97 0 0);
|
||||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||||
--sidebar-border: oklch(0.922 0 0);
|
--sidebar-border: oklch(0.922 0 0);
|
||||||
--sidebar-ring: oklch(0.87 0 0);
|
--sidebar-ring: oklch(0.87 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.145 0 0);
|
--background: oklch(0.145 0 0);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.985 0 0);
|
||||||
--card: oklch(0.145 0 0);
|
--card: oklch(0.145 0 0);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card-foreground: oklch(0.985 0 0);
|
||||||
--popover: oklch(0.145 0 0);
|
--popover: oklch(0.145 0 0);
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
--popover-foreground: oklch(0.985 0 0);
|
||||||
--primary: oklch(0.985 0 0);
|
--primary: oklch(0.985 0 0);
|
||||||
--primary-foreground: oklch(0.205 0 0);
|
--primary-foreground: oklch(0.205 0 0);
|
||||||
--secondary: oklch(0.269 0 0);
|
--secondary: oklch(0.269 0 0);
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
--secondary-foreground: oklch(0.985 0 0);
|
||||||
--muted: oklch(0.269 0 0);
|
--muted: oklch(0.269 0 0);
|
||||||
--muted-foreground: oklch(0.708 0 0);
|
--muted-foreground: oklch(0.708 0 0);
|
||||||
--accent: oklch(0.269 0 0);
|
--accent: oklch(0.269 0 0);
|
||||||
--accent-foreground: oklch(0.985 0 0);
|
--accent-foreground: oklch(0.985 0 0);
|
||||||
--destructive: oklch(0.396 0.141 25.723);
|
--destructive: oklch(0.396 0.141 25.723);
|
||||||
--destructive-foreground: oklch(0.637 0.237 25.331);
|
--destructive-foreground: oklch(0.637 0.237 25.331);
|
||||||
--border: oklch(0.269 0 0);
|
--border: oklch(0.269 0 0);
|
||||||
--input: oklch(0.269 0 0);
|
--input: oklch(0.269 0 0);
|
||||||
--ring: oklch(0.439 0 0);
|
--ring: oklch(0.439 0 0);
|
||||||
--chart-1: oklch(0.488 0.243 264.376);
|
--chart-1: oklch(0.488 0.243 264.376);
|
||||||
--chart-2: oklch(0.696 0.17 162.48);
|
--chart-2: oklch(0.696 0.17 162.48);
|
||||||
--chart-3: oklch(0.769 0.188 70.08);
|
--chart-3: oklch(0.769 0.188 70.08);
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
--chart-4: oklch(0.627 0.265 303.9);
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
--chart-5: oklch(0.645 0.246 16.439);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--sidebar: oklch(0.205 0 0);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-accent: oklch(0.269 0 0);
|
--sidebar-accent: oklch(0.269 0 0);
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-border: oklch(0.269 0 0);
|
--sidebar-border: oklch(0.269 0 0);
|
||||||
--sidebar-ring: oklch(0.439 0 0);
|
--sidebar-ring: oklch(0.439 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
--color-card: var(--card);
|
--color-card: var(--card);
|
||||||
--color-card-foreground: var(--card-foreground);
|
--color-card-foreground: var(--card-foreground);
|
||||||
--color-popover: var(--popover);
|
--color-popover: var(--popover);
|
||||||
--color-popover-foreground: var(--popover-foreground);
|
--color-popover-foreground: var(--popover-foreground);
|
||||||
--color-primary: var(--primary);
|
--color-primary: var(--primary);
|
||||||
--color-primary-foreground: var(--primary-foreground);
|
--color-primary-foreground: var(--primary-foreground);
|
||||||
--color-secondary: var(--secondary);
|
--color-secondary: var(--secondary);
|
||||||
--color-secondary-foreground: var(--secondary-foreground);
|
--color-secondary-foreground: var(--secondary-foreground);
|
||||||
--color-muted: var(--muted);
|
--color-muted: var(--muted);
|
||||||
--color-muted-foreground: var(--muted-foreground);
|
--color-muted-foreground: var(--muted-foreground);
|
||||||
--color-accent: var(--accent);
|
--color-accent: var(--accent);
|
||||||
--color-accent-foreground: var(--accent-foreground);
|
--color-accent-foreground: var(--accent-foreground);
|
||||||
--color-destructive: var(--destructive);
|
--color-destructive: var(--destructive);
|
||||||
--color-destructive-foreground: var(--destructive-foreground);
|
--color-destructive-foreground: var(--destructive-foreground);
|
||||||
--color-border: var(--border);
|
--color-border: var(--border);
|
||||||
--color-input: var(--input);
|
--color-input: var(--input);
|
||||||
--color-ring: var(--ring);
|
--color-ring: var(--ring);
|
||||||
--color-chart-1: var(--chart-1);
|
--color-chart-1: var(--chart-1);
|
||||||
--color-chart-2: var(--chart-2);
|
--color-chart-2: var(--chart-2);
|
||||||
--color-chart-3: var(--chart-3);
|
--color-chart-3: var(--chart-3);
|
||||||
--color-chart-4: var(--chart-4);
|
--color-chart-4: var(--chart-4);
|
||||||
--color-chart-5: var(--chart-5);
|
--color-chart-5: var(--chart-5);
|
||||||
--radius-sm: calc(var(--radius) - 4px);
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
--radius-md: calc(var(--radius) - 2px);
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
--radius-lg: var(--radius);
|
--radius-lg: var(--radius);
|
||||||
--radius-xl: calc(var(--radius) + 4px);
|
--radius-xl: calc(var(--radius) + 4px);
|
||||||
--color-sidebar: var(--sidebar);
|
--color-sidebar: var(--sidebar);
|
||||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
--color-sidebar-primary: var(--sidebar-primary);
|
--color-sidebar-primary: var(--sidebar-primary);
|
||||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||||
--color-sidebar-accent: var(--sidebar-accent);
|
--color-sidebar-accent: var(--sidebar-accent);
|
||||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
--color-sidebar-border: var(--sidebar-border);
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border outline-ring/50;
|
@apply border-border outline-ring/50;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
frontend/src/utils/querys/admin/notifications.tsx
Normal file
26
frontend/src/utils/querys/admin/notifications.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { queryOptions } from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getnotifications() {
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["getNotifications"],
|
||||||
|
queryFn: () => fetchUsers(token),
|
||||||
|
enabled: !!token, // Prevents query if token is null
|
||||||
|
staleTime: 1000,
|
||||||
|
refetchInterval: 2 * 2000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchUsers = async (token: string | null) => {
|
||||||
|
const { data } = await axios.get(`/api/notify/notifications`, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
return data.data ?? [];
|
||||||
|
};
|
||||||
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,94 +14,147 @@ 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>
|
||||||
<Table
|
<div className="flex flex-row justify-between">
|
||||||
style={{
|
<p className="text-center">PPOO Data </p>
|
||||||
width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
<Select
|
||||||
height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
value={pagination.pageSize.toString()}
|
||||||
cursor: "move",
|
onValueChange={(e) =>
|
||||||
}}
|
setPagination({
|
||||||
>
|
...pagination,
|
||||||
<TableHeader>
|
pageSize: parseInt(e),
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
})
|
||||||
<TableRow key={headerGroup.id}>
|
}
|
||||||
{headerGroup.headers.map((header) => {
|
>
|
||||||
return (
|
<SelectTrigger className="w-[180px]">
|
||||||
<TableHead key={header.id}>
|
<SelectValue
|
||||||
{header.isPlaceholder
|
//id={field.name}
|
||||||
? null
|
placeholder="Select Page"
|
||||||
: flexRender(
|
/>
|
||||||
header.column.columnDef
|
</SelectTrigger>
|
||||||
.header,
|
<SelectContent>
|
||||||
header.getContext()
|
<SelectGroup>
|
||||||
)}
|
<SelectLabel>Page Size</SelectLabel>
|
||||||
</TableHead>
|
<SelectItem value="5">5</SelectItem>
|
||||||
);
|
<SelectItem value="10">10</SelectItem>
|
||||||
})}
|
<SelectItem value="50">50</SelectItem>
|
||||||
</TableRow>
|
<SelectItem value="100">100</SelectItem>
|
||||||
))}
|
</SelectGroup>
|
||||||
</TableHeader>
|
</SelectContent>
|
||||||
<TableBody>
|
</Select>
|
||||||
{table.getRowModel().rows?.length ? (
|
</div>
|
||||||
table.getRowModel().rows.map((row) => (
|
<ScrollArea className="h-72 rounded-md border m-2">
|
||||||
<TableRow
|
<Table
|
||||||
key={row.id}
|
// style={{
|
||||||
data-state={
|
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||||
row.getIsSelected() && "selected"
|
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
||||||
}
|
// cursor: "move",
|
||||||
>
|
// }}
|
||||||
{row.getVisibleCells().map((cell) => (
|
>
|
||||||
<TableCell key={cell.id}>
|
<TableHeader>
|
||||||
{flexRender(
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
cell.column.columnDef.cell,
|
<TableRow key={headerGroup.id}>
|
||||||
cell.getContext()
|
{headerGroup.headers.map((header) => {
|
||||||
)}
|
return (
|
||||||
</TableCell>
|
<TableHead key={header.id}>
|
||||||
))}
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(
|
||||||
|
header.column
|
||||||
|
.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))
|
))}
|
||||||
) : (
|
</TableHeader>
|
||||||
<TableRow>
|
<TableBody>
|
||||||
<TableCell
|
{table.getRowModel().rows?.length ? (
|
||||||
colSpan={columns.length}
|
table.getRowModel().rows.map((row) => (
|
||||||
className="h-24 text-center"
|
<TableRow
|
||||||
>
|
key={row.id}
|
||||||
No results.
|
data-state={
|
||||||
</TableCell>
|
row.getIsSelected() && "selected"
|
||||||
</TableRow>
|
}
|
||||||
)}
|
>
|
||||||
</TableBody>
|
{row.getVisibleCells().map((cell) => (
|
||||||
</Table>
|
<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>
|
||||||
<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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
68
frontend/src/utils/tableData/printers/printerColumns.tsx
Normal file
68
frontend/src/utils/tableData/printers/printerColumns.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/printers/printerData.tsx
Normal file
134
frontend/src/utils/tableData/printers/printerData.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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,22 @@
|
|||||||
import {defineConfig} from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react-swc";
|
import react from "@vitejs/plugin-react-swc";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import {TanStackRouterVite} from "@tanstack/router-plugin/vite";
|
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import {fileURLToPath} from "url";
|
import { fileURLToPath } from "url";
|
||||||
dotenv.config({path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.env")});
|
dotenv.config({
|
||||||
|
path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.env"),
|
||||||
|
});
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss(), TanStackRouterVite({target: "react", autoCodeSplitting: true})],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
tailwindcss(),
|
||||||
|
TanStackRouterVite({ target: "react", autoCodeSplitting: true }),
|
||||||
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
|||||||
104
package-lock.json
generated
104
package-lock.json
generated
@@ -40,6 +40,7 @@
|
|||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"st-ethernet-ip": "^2.7.3",
|
"st-ethernet-ip": "^2.7.3",
|
||||||
"ws": "^8.18.1",
|
"ws": "^8.18.1",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -2070,6 +2071,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/adler-32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/adm-zip": {
|
"node_modules/adm-zip": {
|
||||||
"version": "0.5.16",
|
"version": "0.5.16",
|
||||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
|
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
|
||||||
@@ -2452,6 +2462,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cfb": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"crc-32": "~1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
@@ -2532,6 +2555,15 @@
|
|||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/codepage": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
@@ -3239,6 +3271,18 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crc-32": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"crc32": "bin/crc32.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/croner": {
|
"node_modules/croner": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz",
|
||||||
@@ -4293,6 +4337,15 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/frac": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs-extra": {
|
"node_modules/fs-extra": {
|
||||||
"version": "11.3.0",
|
"version": "11.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
||||||
@@ -7781,6 +7834,18 @@
|
|||||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/ssf": {
|
||||||
|
"version": "0.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||||
|
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"frac": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/st-ethernet-ip": {
|
"node_modules/st-ethernet-ip": {
|
||||||
"version": "2.7.3",
|
"version": "2.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/st-ethernet-ip/-/st-ethernet-ip-2.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/st-ethernet-ip/-/st-ethernet-ip-2.7.3.tgz",
|
||||||
@@ -8824,6 +8889,24 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wmf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/word": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
@@ -8972,6 +9055,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xlsx": {
|
||||||
|
"version": "0.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||||
|
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"cfb": "~1.2.1",
|
||||||
|
"codepage": "~1.15.0",
|
||||||
|
"crc-32": "~1.2.1",
|
||||||
|
"ssf": "~0.11.2",
|
||||||
|
"wmf": "~1.0.1",
|
||||||
|
"word": "~0.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xlsx": "bin/xlsx.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admConfig": {
|
"admConfig": {
|
||||||
"build": 217,
|
"build": 224,
|
||||||
"oldBuild": "backend-0.1.3.zip"
|
"oldBuild": "backend-0.1.3.zip"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -88,6 +88,7 @@
|
|||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"st-ethernet-ip": "^2.7.3",
|
"st-ethernet-ip": "^2.7.3",
|
||||||
"ws": "^8.18.1",
|
"ws": "^8.18.1",
|
||||||
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@ import { sendEmail } from "./services/notifications/controller/sendMail.js";
|
|||||||
import notify from "./services/notifications/notifyService.js";
|
import notify from "./services/notifications/notifyService.js";
|
||||||
import eom from "./services/eom/eomService.js";
|
import eom from "./services/eom/eomService.js";
|
||||||
import dataMart from "./services/dataMart/dataMartService.js";
|
import dataMart from "./services/dataMart/dataMartService.js";
|
||||||
|
import qualityRequest from "./services/quality/qualityService.js";
|
||||||
|
|
||||||
// create the main prodlogin here
|
// create the main prodlogin here
|
||||||
const username = "lst_user";
|
const username = "lst_user";
|
||||||
@@ -104,6 +105,7 @@ const routes = [
|
|||||||
notify,
|
notify,
|
||||||
eom,
|
eom,
|
||||||
dataMart,
|
dataMart,
|
||||||
|
qualityRequest,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ import { cycleCountCheck } from "../../../../sqlServer/querys/warehouse/cycleCou
|
|||||||
// setting timer for updating stockCheck on a restart will always check.
|
// setting timer for updating stockCheck on a restart will always check.
|
||||||
let lastCheck = 0;
|
let lastCheck = 0;
|
||||||
|
|
||||||
export const lanes: any = [];
|
export let lanes: any = [];
|
||||||
|
|
||||||
export const getLanesToCycleCount = async () => {
|
export const getLanesToCycleCount = async () => {
|
||||||
const currentTime: any = timeZoneFix();
|
const currentTime: any = timeZoneFix();
|
||||||
// store the lanes in memeory
|
// store the lanes in memeory
|
||||||
createLog("info", "warehouse", "logistics", "Lane triggered update.");
|
createLog("info", "warehouse", "logistics", "Lane triggered update.");
|
||||||
lastCheck = currentTime;
|
lastCheck = currentTime;
|
||||||
const ageQuery = cycleCountCheck.replaceAll("[ageOfRow]", `1000`);
|
const ageQuery = cycleCountCheck.replaceAll("[ageOfRow]", "90");
|
||||||
const { data: prodLanes, error: pl } = await tryCatch(
|
const { data: prodLanes, error: pl } = await tryCatch(
|
||||||
query(ageQuery, "Get Stock lane date.")
|
query(ageQuery, "Get Stock lane date.")
|
||||||
);
|
);
|
||||||
@@ -39,23 +39,25 @@ export const getLanesToCycleCount = async () => {
|
|||||||
warehouseName: prodLanes[i]?.warehouseName || "na",
|
warehouseName: prodLanes[i]?.warehouseName || "na",
|
||||||
Description: prodLanes[i]?.Description,
|
Description: prodLanes[i]?.Description,
|
||||||
LastMoveDate: prodLanes[i]?.LastMoveDate
|
LastMoveDate: prodLanes[i]?.LastMoveDate
|
||||||
? format(prodLanes[i]?.LastInv, "M/d/yyyy")
|
? format(prodLanes[i]?.LastMoveDate, "M/d/yyyy")
|
||||||
: undefined,
|
: undefined,
|
||||||
LastInv: format(prodLanes[i]?.LastInv, "M/d/yyyy"),
|
LastInv: format(prodLanes[i]?.LastInv, "M/d/yyyy"),
|
||||||
rowType: prodLanes[i].rowType,
|
rowType: prodLanes[i].rowType,
|
||||||
DaysSinceLast:
|
DaysSinceLast: differenceInDays(
|
||||||
differenceInDays(
|
new Date(Date.now()),
|
||||||
new Date(prodLanes[i].LastInv),
|
new Date(prodLanes[i].LastInv)
|
||||||
new Date(prodLanes[i].LastMoveDate)
|
),
|
||||||
) <= 0
|
|
||||||
? 0
|
|
||||||
: differenceInDays(
|
|
||||||
new Date(prodLanes[i].LastInv),
|
|
||||||
new Date(prodLanes[i].LastMoveDate)
|
|
||||||
),
|
|
||||||
upd_date: format(new Date(Date.now()), "M/d/yyyy"),
|
upd_date: format(new Date(Date.now()), "M/d/yyyy"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const existing = lanes.filter(
|
||||||
|
(l: any) => l.laneID === prodLanes[i]?.laneID
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
lanes = lanes.filter((l: any) => l.laneID !== prodLanes[i]?.laneID);
|
||||||
|
}
|
||||||
|
|
||||||
lanes.push(createLane);
|
lanes.push(createLane);
|
||||||
createLog(
|
createLog(
|
||||||
"debug",
|
"debug",
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import * as XLSX from "xlsx";
|
||||||
|
import { lanes } from "./cyclecountCheck.js";
|
||||||
|
|
||||||
|
export const lanesToExcel = async (age: string | null) => {
|
||||||
|
// Convert JSON data to an array of arrays (AOA)
|
||||||
|
|
||||||
|
let processLanes = lanes;
|
||||||
|
if (age) {
|
||||||
|
processLanes = lanes.filter(
|
||||||
|
(l: any) => l.DaysSinceLast >= parseInt(age)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = Object.keys(processLanes[0]); // Get headers from JSON keys
|
||||||
|
const data = processLanes.map((item: any) =>
|
||||||
|
headers.map((header) => item[header])
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the workbook and worksheet
|
||||||
|
const wb = XLSX.utils.book_new();
|
||||||
|
const ws = XLSX.utils.aoa_to_sheet([headers, ...data]); // Combine headers and data
|
||||||
|
|
||||||
|
// Auto-resize columns based on the longest content in each column
|
||||||
|
const colWidths = headers.map((_, colIndex) => {
|
||||||
|
let maxLength = 0;
|
||||||
|
data.forEach((row: any) => {
|
||||||
|
const cellValue = row[colIndex] ? row[colIndex].toString() : "";
|
||||||
|
maxLength = Math.max(maxLength, cellValue.length);
|
||||||
|
});
|
||||||
|
return { wch: maxLength + 2 }; // Add a little padding
|
||||||
|
});
|
||||||
|
|
||||||
|
ws["!cols"] = colWidths; // Set the column widths
|
||||||
|
|
||||||
|
// Add the worksheet to the workbook
|
||||||
|
XLSX.utils.book_append_sheet(wb, ws, "CycleCount");
|
||||||
|
|
||||||
|
// Write the workbook to a buffer and return it
|
||||||
|
const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "buffer" });
|
||||||
|
|
||||||
|
return excelBuffer;
|
||||||
|
};
|
||||||
@@ -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 {
|
return {
|
||||||
success: true,
|
sucess: true,
|
||||||
message: `${filteredLanes.length} lanes grabed that have not been cycle counted in the last ${age} days.`,
|
message: `${noType.length} lanes that are of type ${type} and have not been cycle counted in the last ${age} days.`,
|
||||||
data: filteredLanes,
|
data: noType
|
||||||
|
.filter((t: any) => t.rowType === type?.toUpperCase())
|
||||||
|
.sort((a: any, b: any) => b.DaysSinceLast - a.DaysSinceLast),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `${filteredLanes.length} lanes grabed that have not been cycle counted in the last ${age} days.`,
|
||||||
|
data: filteredLanes.sort(
|
||||||
|
(a: any, b: any) => b.DaysSinceLast - a.DaysSinceLast
|
||||||
|
),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import getSiloAdjustments from "./route/siloAdjustments/getSiloAdjustments.js";
|
|||||||
import { getLanesToCycleCount } from "./controller/warehouse/cycleCountChecks/cyclecountCheck.js";
|
import { getLanesToCycleCount } from "./controller/warehouse/cycleCountChecks/cyclecountCheck.js";
|
||||||
import getCycleCountCheck from "./route/getCycleCountChecks.js";
|
import getCycleCountCheck from "./route/getCycleCountChecks.js";
|
||||||
import getPPOO from "./route/getPPOO.js";
|
import getPPOO from "./route/getPPOO.js";
|
||||||
|
import getcyclecount from "./route/getCycleCountLanes.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ const routes = [
|
|||||||
getCycleCountCheck,
|
getCycleCountCheck,
|
||||||
//warehouse
|
//warehouse
|
||||||
getPPOO,
|
getPPOO,
|
||||||
|
getcyclecount,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// app.route("/server", modules);
|
// app.route("/server", modules);
|
||||||
|
|||||||
@@ -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;
|
||||||
30
server/services/notifications/controller/getNotifications.ts
Normal file
30
server/services/notifications/controller/getNotifications.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { and, desc, eq, gte, inArray, lte, sql } from "drizzle-orm";
|
||||||
|
import { db } from "../../../../database/dbclient.js";
|
||||||
|
import { logs } from "../../../../database/schema/logs.js";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { notifications } from "../../../../database/schema/notifications.js";
|
||||||
|
|
||||||
|
export const getNotifications = async () => {
|
||||||
|
const { data, error } = await tryCatch(db.select().from(notifications));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"notify",
|
||||||
|
"notify",
|
||||||
|
`Error getting notifications: ${error}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting notifications.",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sucess: true,
|
||||||
|
message: "Current notifications.",
|
||||||
|
data: data,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -11,10 +11,11 @@ import { startNotificationMonitor } from "./utils/processNotifications.js";
|
|||||||
import notifyStats from "./routes/getActiveNotifications.js";
|
import notifyStats from "./routes/getActiveNotifications.js";
|
||||||
import tiTrigger from "./routes/manualTiggerTi.js";
|
import tiTrigger from "./routes/manualTiggerTi.js";
|
||||||
import blocking from "./routes/qualityBlocking.js";
|
import blocking from "./routes/qualityBlocking.js";
|
||||||
|
import notify from "./routes/getNotifications.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const routes = [sendemail, notifyStats, tiTrigger, blocking] as const;
|
const routes = [sendemail, notifyStats, tiTrigger, blocking, notify] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/notify", route);
|
app.route("/notify", route);
|
||||||
|
|||||||
44
server/services/notifications/routes/getNotifications.ts
Normal file
44
server/services/notifications/routes/getNotifications.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
//import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { getNotifications } from "../controller/getNotifications.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["notify"],
|
||||||
|
summary: "Gets notifications.",
|
||||||
|
method: "get",
|
||||||
|
path: "/notifications",
|
||||||
|
// description:
|
||||||
|
// "This might be a temp soltuin during the transtion between versions",
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c: any) => {
|
||||||
|
//apiHit(c, { endpoint: `api/logger/logs` });
|
||||||
|
const { data, error } = await tryCatch(getNotifications());
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error clearing the log.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: data?.success,
|
||||||
|
message: data?.message,
|
||||||
|
data: data?.data,
|
||||||
|
},
|
||||||
|
200
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -130,7 +130,7 @@ export const createLabel = async (data: any, userPrinted: any) => {
|
|||||||
|
|
||||||
// check if we can remove labels or not
|
// check if we can remove labels or not
|
||||||
//deleteLabels();
|
//deleteLabels();
|
||||||
return { sucess: true, message: "Label created", data: returnData }; // returning label data to be able to book in if active
|
return { success: true, message: "Label created", data: returnData }; // returning label data to be able to book in if active
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
|
|||||||
@@ -214,15 +214,15 @@ export const labelingProcess = async ({
|
|||||||
// create the label
|
// create the label
|
||||||
const label = await createLabel(filteredLot[0], userPrinted);
|
const label = await createLabel(filteredLot[0], userPrinted);
|
||||||
|
|
||||||
// if (!label.success) {
|
if (!label.success) {
|
||||||
// createLog(
|
createLog(
|
||||||
// "error",
|
"error",
|
||||||
// "labeling",
|
"labeling",
|
||||||
// "ocp",
|
"ocp",
|
||||||
// `There was an error creating the label: ${label.message}`
|
`There was an error creating the label: ${label.message}`
|
||||||
// );
|
);
|
||||||
// return { sucess: false, message: label.message, data: label.data };
|
return { sucess: false, message: label.message, data: label.data };
|
||||||
// }
|
}
|
||||||
|
|
||||||
// send over to be booked in if we can do it.
|
// send over to be booked in if we can do it.
|
||||||
const bookin = settingData.filter((s) => s.name === "bookin");
|
const bookin = settingData.filter((s) => s.name === "bookin");
|
||||||
|
|||||||
20
server/services/quality/qualityService.ts
Normal file
20
server/services/quality/qualityService.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
||||||
|
import { qualityRequest } from "../../../database/schema/qualityRequest.js";
|
||||||
|
import { db } from "../../../database/dbclient.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
const routes = [] as const;
|
||||||
|
|
||||||
|
const appRoutes = routes.forEach((route) => {
|
||||||
|
app.route("/quality", route);
|
||||||
|
});
|
||||||
|
app.all("/quality/*", (c) => {
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message: "You have encounters a quality route that dose not exist.",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.select().from(qualityRequest);
|
||||||
|
|
||||||
|
export default app;
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
export const deliveryByDateRange = `
|
export const deliveryByDateRange = `
|
||||||
|
|
||||||
use AlplaPROD_test1
|
use AlplaPROD_test1
|
||||||
DECLARE @StartDate DATE = ' [startDate] ' -- 2025-1-1
|
DECLARE @StartDate DATE = ' 1990-1-1 ' -- 2025-1-1
|
||||||
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
|
DECLARE @EndDate DATE = '2025-4-18' -- 2025-1-31
|
||||||
select * from
|
select * from
|
||||||
(select (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant,
|
(select (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant,
|
||||||
AuftragsNummer as OrderNumber,
|
AuftragsNummer as OrderNumber,
|
||||||
PositionsNummer as CustomerLineNumber,
|
PositionsNummer as CustomerLineNumber,
|
||||||
AbrufNummer as CustomerReleaseNumber,
|
AbrufNummer as CustomerReleaseNumber,
|
||||||
@@ -16,7 +15,7 @@ GelieferteMenge AS DeliveredQTY,
|
|||||||
GelieferteMengeVPK as DeliverdPallets,
|
GelieferteMengeVPK as DeliverdPallets,
|
||||||
JournalNummer as BOLNum,
|
JournalNummer as BOLNum,
|
||||||
ProdArtikelBez AS ProductFamily,
|
ProdArtikelBez AS ProductFamily,
|
||||||
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdKundenAdresse AS IdCustomer,
|
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdKundenAdresse AS IdCustomer,
|
||||||
dbo.V_LadePlanungenLadeAuftragAbruf.AdressBez AS CustName,
|
dbo.V_LadePlanungenLadeAuftragAbruf.AdressBez AS CustName,
|
||||||
dbo.T_EAIJournal.IdJournalStatus as bolStatus,
|
dbo.T_EAIJournal.IdJournalStatus as bolStatus,
|
||||||
V_TrackerAuftragsAbrufe.IdAuftragsAbruf as releaseNum,
|
V_TrackerAuftragsAbrufe.IdAuftragsAbruf as releaseNum,
|
||||||
@@ -24,20 +23,20 @@ V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag as truckPostion
|
|||||||
,'Base Plant' as plantType
|
,'Base Plant' as plantType
|
||||||
from dbo.V_TrackerAuftragsAbrufe (nolock)
|
from dbo.V_TrackerAuftragsAbrufe (nolock)
|
||||||
|
|
||||||
left join
|
left join
|
||||||
dbo.V_LadePlanungenLadeAuftragAbruf on V_TrackerAuftragsAbrufe.IdAuftragsAbruf =
|
dbo.V_LadePlanungenLadeAuftragAbruf on V_TrackerAuftragsAbrufe.IdAuftragsAbruf =
|
||||||
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdAuftragsAbruf
|
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdAuftragsAbruf
|
||||||
|
|
||||||
left join
|
|
||||||
dbo.T_EAIJournal on dbo.V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag =
|
|
||||||
dbo.T_EAIJournal.IdLadeAuftrag
|
|
||||||
|
|
||||||
left join
|
left join
|
||||||
dbo.V_ArtikelKomplett on V_TrackerAuftragsAbrufe.IdArtikelVarianten =
|
dbo.T_EAIJournal on dbo.V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag =
|
||||||
|
dbo.T_EAIJournal.IdLadeAuftrag
|
||||||
|
|
||||||
|
left join
|
||||||
|
dbo.V_ArtikelKomplett on V_TrackerAuftragsAbrufe.IdArtikelVarianten =
|
||||||
dbo.V_ArtikelKomplett.IdArtikelvarianten
|
dbo.V_ArtikelKomplett.IdArtikelvarianten
|
||||||
where GelieferteMengeVPK > 0 AND (
|
where GelieferteMengeVPK > 0 AND (
|
||||||
AbrufLiefertermin IS NULL
|
AbrufLiefertermin IS NULL
|
||||||
OR CONVERT(date, AbrufLiefertermin) BETWEEN @StartDate AND @EndDate
|
OR CONVERT(date, JournalDatum) BETWEEN @StartDate AND @EndDate
|
||||||
)
|
)
|
||||||
|
|
||||||
/*in house*/
|
/*in house*/
|
||||||
@@ -69,5 +68,5 @@ where CONVERT(date, Upd_Date) BETWEEN @StartDate AND @EndDate
|
|||||||
) x
|
) x
|
||||||
|
|
||||||
|
|
||||||
order by DeliveryDate desc
|
order by Bol_PrintDate desc
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user