Compare commits

...

13 Commits

124 changed files with 4529 additions and 3621 deletions

View File

@@ -4,72 +4,77 @@ import { createLogger } from "../../../pkg/logger/logger.js";
import { tryCatch } from "../../../pkg/utils/tryCatch.js";
export const systemAdminRole = async (userId: string) => {
const log = createLogger({
module: "admin",
subModule: "systemAdminSetup",
});
const systemAdminRoles = [
{
userId: userId,
module: "users",
role: "systemAdmin",
},
{
userId: userId,
module: "admin",
role: "systemAdmin",
},
{
userId: userId,
module: "ocp",
role: "systemAdmin",
},
{
userId: userId,
module: "siloAdjustments",
role: "systemAdmin",
},
{
userId: userId,
module: "demandManagement",
role: "systemAdmin",
},
{
userId: userId,
module: "logistics",
role: "systemAdmin",
},
{
userId: userId,
module: "production",
role: "systemAdmin",
},
{
userId: userId,
module: "quality",
role: "systemAdmin",
},
{
userId: userId,
module: "eom",
role: "systemAdmin",
},
{
userId: userId,
module: "forklifts",
role: "systemAdmin",
},
];
const { data, error } = await tryCatch(
db.insert(userRoles).values(systemAdminRoles).onConflictDoNothing()
);
const log = createLogger({
module: "admin",
subModule: "systemAdminSetup",
});
const systemAdminRoles = [
{
userId: userId,
module: "users",
role: "systemAdmin",
},
{
userId: userId,
module: "admin",
role: "systemAdmin",
},
{
userId: userId,
module: "ocp",
role: "systemAdmin",
},
{
userId: userId,
module: "siloAdjustments",
role: "systemAdmin",
},
{
userId: userId,
module: "demandManagement",
role: "systemAdmin",
},
{
userId: userId,
module: "logistics",
role: "systemAdmin",
},
{
userId: userId,
module: "production",
role: "systemAdmin",
},
{
userId: userId,
module: "quality",
role: "systemAdmin",
},
{
userId: userId,
module: "eom",
role: "systemAdmin",
},
{
userId: userId,
module: "forklifts",
role: "systemAdmin",
},
{
userId: userId,
module: "helperCommands",
role: "systemAdmin",
},
];
const { data, error } = await tryCatch(
db.insert(userRoles).values(systemAdminRoles).onConflictDoNothing(),
);
if (error) {
log.error(
{ stack: { error: error } },
"There was an error creating the system admin roles"
);
}
if (error) {
log.error(
{ stack: { error: error } },
"There was an error creating the system admin roles",
);
}
log.info({ data }, "New system admin roles created");
log.info({ data }, "New system admin roles created");
};

View File

@@ -14,6 +14,7 @@ const roleSchema = z.object({
"siloAdjustments",
"demandManagement",
"logistics",
"helperCommands",
"production",
"quality",
"eom",

View File

@@ -20,7 +20,10 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@react-pdf/renderer": "^4.3.1",
"@tailwindcss/vite": "^4.1.13",
"@tanstack/react-form": "^1.23.0",
"@tanstack/react-query": "^5.89.0",
@@ -35,13 +38,18 @@
"date-fns": "^4.1.0",
"is-mobile": "^5.0.0",
"js-cookie": "^3.0.5",
"jsbarcode": "^3.12.1",
"lucide-react": "^0.542.0",
"marked": "^16.4.1",
"moment": "^2.30.1",
"r": "^0.0.5",
"react": "^19.1.1",
"react-barcode": "^1.6.1",
"react-calendar-timeline": "^0.30.0-beta.3",
"react-day-picker": "^9.11.1",
"react-dom": "^19.1.1",
"react-hook-form": "^7.65.0",
"react-resizable-panels": "^3.0.6",
"recharts": "^2.15.4",
"socket.io-client": "^4.8.1",
"sonner": "^2.0.7",
@@ -2255,6 +2263,65 @@
}
}
},
"node_modules/@radix-ui/react-switch": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
"integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-use-previous": "1.1.1",
"@radix-ui/react-use-size": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tabs": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
"integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-direction": "1.1.1",
"@radix-ui/react-id": "1.1.1",
"@radix-ui/react-presence": "1.1.5",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-roving-focus": "1.1.11",
"@radix-ui/react-use-controllable-state": "1.2.2"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tooltip": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
@@ -2472,6 +2539,180 @@
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
"license": "MIT"
},
"node_modules/@react-pdf/fns": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz",
"integrity": "sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==",
"license": "MIT"
},
"node_modules/@react-pdf/font": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-4.0.3.tgz",
"integrity": "sha512-N1qQDZr6phXYQOp033Hvm2nkUkx2LkszjGPbmRavs9VOYzi4sp31MaccMKptL24ii6UhBh/z9yPUhnuNe/qHwA==",
"license": "MIT",
"dependencies": {
"@react-pdf/pdfkit": "^4.0.4",
"@react-pdf/types": "^2.9.1",
"fontkit": "^2.0.2",
"is-url": "^1.2.4"
}
},
"node_modules/@react-pdf/image": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-3.0.3.tgz",
"integrity": "sha512-lvP5ryzYM3wpbO9bvqLZYwEr5XBDX9jcaRICvtnoRqdJOo7PRrMnmB4MMScyb+Xw10mGeIubZAAomNAG5ONQZQ==",
"license": "MIT",
"dependencies": {
"@react-pdf/png-js": "^3.0.0",
"jay-peg": "^1.1.1"
}
},
"node_modules/@react-pdf/layout": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-4.4.1.tgz",
"integrity": "sha512-GVzdlWoZWldRDzlWj3SttRXmVDxg7YfraAohwy+o9gb9hrbDJaaAV6jV3pc630Evd3K46OAzk8EFu8EgPDuVuA==",
"license": "MIT",
"dependencies": {
"@react-pdf/fns": "3.1.2",
"@react-pdf/image": "^3.0.3",
"@react-pdf/primitives": "^4.1.1",
"@react-pdf/stylesheet": "^6.1.1",
"@react-pdf/textkit": "^6.0.0",
"@react-pdf/types": "^2.9.1",
"emoji-regex-xs": "^1.0.0",
"queue": "^6.0.1",
"yoga-layout": "^3.2.1"
}
},
"node_modules/@react-pdf/pdfkit": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-4.0.4.tgz",
"integrity": "sha512-/nITLggsPlB66bVLnm0X7MNdKQxXelLGZG6zB5acF5cCgkFwmXHnLNyxYOUD4GMOMg1HOPShXDKWrwk2ZeHsvw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@react-pdf/png-js": "^3.0.0",
"browserify-zlib": "^0.2.0",
"crypto-js": "^4.2.0",
"fontkit": "^2.0.2",
"jay-peg": "^1.1.1",
"linebreak": "^1.1.0",
"vite-compatible-readable-stream": "^3.6.1"
}
},
"node_modules/@react-pdf/png-js": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-3.0.0.tgz",
"integrity": "sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==",
"license": "MIT",
"dependencies": {
"browserify-zlib": "^0.2.0"
}
},
"node_modules/@react-pdf/primitives": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-4.1.1.tgz",
"integrity": "sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==",
"license": "MIT"
},
"node_modules/@react-pdf/reconciler": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@react-pdf/reconciler/-/reconciler-1.1.4.tgz",
"integrity": "sha512-oTQDiR/t4Z/Guxac88IavpU2UgN7eR0RMI9DRKvKnvPz2DUasGjXfChAdMqDNmJJxxV26mMy9xQOUV2UU5/okg==",
"license": "MIT",
"dependencies": {
"object-assign": "^4.1.1",
"scheduler": "0.25.0-rc-603e6108-20241029"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/@react-pdf/reconciler/node_modules/scheduler": {
"version": "0.25.0-rc-603e6108-20241029",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-603e6108-20241029.tgz",
"integrity": "sha512-pFwF6H1XrSdYYNLfOcGlM28/j8CGLu8IvdrxqhjWULe2bPcKiKW4CV+OWqR/9fT52mywx65l7ysNkjLKBda7eA==",
"license": "MIT"
},
"node_modules/@react-pdf/render": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-4.3.1.tgz",
"integrity": "sha512-v1WAaAhQShQZGcBxfjkEThGCHVH9CSuitrZ1bIOLvB5iBKM14abYK5D6djKhWCwF6FTzYeT2WRjRMVgze/ND2A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@react-pdf/fns": "3.1.2",
"@react-pdf/primitives": "^4.1.1",
"@react-pdf/textkit": "^6.0.0",
"@react-pdf/types": "^2.9.1",
"abs-svg-path": "^0.1.1",
"color-string": "^1.9.1",
"normalize-svg-path": "^1.1.0",
"parse-svg-path": "^0.1.2",
"svg-arc-to-cubic-bezier": "^3.2.0"
}
},
"node_modules/@react-pdf/renderer": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-4.3.1.tgz",
"integrity": "sha512-dPKHiwGTaOsKqNWCHPYYrx8CDfAGsUnV4tvRsEu0VPGxuot1AOq/M+YgfN/Pb+MeXCTe2/lv6NvA8haUtj3tsA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.13",
"@react-pdf/fns": "3.1.2",
"@react-pdf/font": "^4.0.3",
"@react-pdf/layout": "^4.4.1",
"@react-pdf/pdfkit": "^4.0.4",
"@react-pdf/primitives": "^4.1.1",
"@react-pdf/reconciler": "^1.1.4",
"@react-pdf/render": "^4.3.1",
"@react-pdf/types": "^2.9.1",
"events": "^3.3.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"queue": "^6.0.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/@react-pdf/stylesheet": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-6.1.1.tgz",
"integrity": "sha512-Iyw0A3wRIeQLN4EkaKf8yF9MvdMxiZ8JjoyzLzDHSxnKYoOA4UGu84veCb8dT9N8MxY5x7a0BUv/avTe586Plg==",
"license": "MIT",
"dependencies": {
"@react-pdf/fns": "3.1.2",
"@react-pdf/types": "^2.9.1",
"color-string": "^1.9.1",
"hsl-to-hex": "^1.0.0",
"media-engine": "^1.0.3",
"postcss-value-parser": "^4.1.0"
}
},
"node_modules/@react-pdf/textkit": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-6.0.0.tgz",
"integrity": "sha512-fDt19KWaJRK/n2AaFoVm31hgGmpygmTV7LsHGJNGZkgzXcFyLsx+XUl63DTDPH3iqxj3xUX128t104GtOz8tTw==",
"license": "MIT",
"dependencies": {
"@react-pdf/fns": "3.1.2",
"bidi-js": "^1.0.2",
"hyphen": "^1.6.4",
"unicode-properties": "^1.4.1"
}
},
"node_modules/@react-pdf/types": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.9.1.tgz",
"integrity": "sha512-5GoCgG0G5NMgpPuHbKG2xcVRQt7+E5pg3IyzVIIozKG3nLcnsXW4zy25vG1ZBQA0jmo39q34au/sOnL/0d1A4w==",
"license": "MIT",
"dependencies": {
"@react-pdf/font": "^4.0.3",
"@react-pdf/primitives": "^4.1.1",
"@react-pdf/stylesheet": "^6.1.1"
}
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.32",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz",
@@ -2986,6 +3227,15 @@
"dev": true,
"license": "Apache-2.0"
},
"node_modules/@swc/helpers": {
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
"integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
}
},
"node_modules/@swc/types": {
"version": "0.1.24",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.24.tgz",
@@ -4025,6 +4275,12 @@
"vite": "^4 || ^5 || ^6 || ^7"
}
},
"node_modules/abs-svg-path": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz",
"integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==",
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -4189,6 +4445,26 @@
"dev": true,
"license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/batch-processor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz",
@@ -4272,6 +4548,15 @@
"uncrypto": "^0.1.3"
}
},
"node_modules/bidi-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
"integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
"license": "MIT",
"dependencies": {
"require-from-string": "^2.0.2"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -4309,6 +4594,24 @@
"node": ">=8"
}
},
"node_modules/brotli": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
"integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
"license": "MIT",
"dependencies": {
"base64-js": "^1.1.2"
}
},
"node_modules/browserify-zlib": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
"integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
"license": "MIT",
"dependencies": {
"pako": "~1.0.5"
}
},
"node_modules/browserslist": {
"version": "4.25.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz",
@@ -4469,6 +4772,15 @@
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
"license": "MIT"
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -4495,9 +4807,18 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4545,6 +4866,12 @@
"node": ">= 8"
}
},
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -4769,6 +5096,12 @@
"integrity": "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==",
"license": "MIT"
},
"node_modules/dfa": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
"integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
"license": "MIT"
},
"node_modules/diff": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
@@ -4819,6 +5152,12 @@
"batch-processor": "1.0.0"
}
},
"node_modules/emoji-regex-xs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
"integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==",
"license": "MIT"
},
"node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
@@ -5179,11 +5518,19 @@
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"license": "MIT"
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-equals": {
@@ -5333,6 +5680,23 @@
}
}
},
"node_modules/fontkit": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
"integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
"license": "MIT",
"dependencies": {
"@swc/helpers": "^0.5.12",
"brotli": "^1.3.2",
"clone": "^2.1.2",
"dfa": "^1.2.0",
"fast-deep-equal": "^3.1.3",
"restructure": "^3.0.0",
"tiny-inflate": "^1.0.3",
"unicode-properties": "^1.4.0",
"unicode-trie": "^2.0.0"
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
@@ -5550,6 +5914,27 @@
"node": ">= 0.4"
}
},
"node_modules/hsl-to-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz",
"integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==",
"license": "MIT",
"dependencies": {
"hsl-to-rgb-for-reals": "^1.1.0"
}
},
"node_modules/hsl-to-rgb-for-reals": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz",
"integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==",
"license": "ISC"
},
"node_modules/hyphen": {
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz",
"integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==",
"license": "ISC"
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -5587,6 +5972,12 @@
"node": ">=0.8.19"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/interactjs": {
"version": "1.10.27",
"resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.27.tgz",
@@ -5606,6 +5997,12 @@
"node": ">=12"
}
},
"node_modules/is-arrayish": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
"license": "MIT"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -5658,6 +6055,12 @@
"node": ">=0.12.0"
}
},
"node_modules/is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
"license": "MIT"
},
"node_modules/isbot": {
"version": "5.1.30",
"resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.30.tgz",
@@ -5674,6 +6077,15 @@
"dev": true,
"license": "ISC"
},
"node_modules/jay-peg": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz",
"integrity": "sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==",
"license": "MIT",
"dependencies": {
"restructure": "^3.0.0"
}
},
"node_modules/jiti": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
@@ -5720,6 +6132,12 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsbarcode": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/jsbarcode/-/jsbarcode-3.12.1.tgz",
"integrity": "sha512-QZQSqIknC2Rr/YOUyOkCBqsoiBAOTYK+7yNN3JsqfoUtJtkazxNw1dmPpxuv7VVvqW13kA3/mKiLq+s/e3o9hQ==",
"license": "MIT"
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -6028,6 +6446,25 @@
"url": "https://opencollective.com/parcel"
}
},
"node_modules/linebreak": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
"integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
"license": "MIT",
"dependencies": {
"base64-js": "0.0.8",
"unicode-trie": "^2.0.0"
}
},
"node_modules/linebreak/node_modules/base64-js": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
"integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -6097,6 +6534,18 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/marked": {
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.1.tgz",
"integrity": "sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 20"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -6106,6 +6555,12 @@
"node": ">= 0.4"
}
},
"node_modules/media-engine": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz",
"integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==",
"license": "MIT"
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
@@ -6278,6 +6733,15 @@
"node": ">=0.10.0"
}
},
"node_modules/normalize-svg-path": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz",
"integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==",
"license": "MIT",
"dependencies": {
"svg-arc-to-cubic-bezier": "^3.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -6337,6 +6801,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"license": "(MIT AND Zlib)"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -6350,6 +6820,12 @@
"node": ">=6"
}
},
"node_modules/parse-svg-path": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
"integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==",
"license": "MIT"
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -6417,6 +6893,12 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"license": "MIT"
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -6494,6 +6976,15 @@
"node": ">=6.0.0"
}
},
"node_modules/queue": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
"license": "MIT",
"dependencies": {
"inherits": "~2.0.3"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -6533,6 +7024,19 @@
"node": ">=0.10.0"
}
},
"node_modules/react-barcode": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/react-barcode/-/react-barcode-1.6.1.tgz",
"integrity": "sha512-pc4ftnO5syHa/UjCruEeRsomlhoxKSugIgTA8T4dH0fvc89UMHL+/1Sp25IAphqG44pJkE5hMXhv89iS09jQyw==",
"license": "ISC",
"dependencies": {
"jsbarcode": "^3.8.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": "16 - 19"
}
},
"node_modules/react-calendar-timeline": {
"version": "0.30.0-beta.3",
"resolved": "https://registry.npmjs.org/react-calendar-timeline/-/react-calendar-timeline-0.30.0-beta.3.tgz",
@@ -6585,6 +7089,22 @@
"react": "^19.1.1"
}
},
"node_modules/react-hook-form": {
"version": "7.65.0",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.65.0.tgz",
"integrity": "sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw==",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/react-hook-form"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18 || ^19"
}
},
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -6638,6 +7158,16 @@
}
}
},
"node_modules/react-resizable-panels": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.6.tgz",
"integrity": "sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew==",
"license": "MIT",
"peerDependencies": {
"react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc",
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
}
},
"node_modules/react-smooth": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
@@ -6769,6 +7299,15 @@
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
"license": "Apache-2.0"
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -6789,6 +7328,12 @@
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/restructure": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
"integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
"license": "MIT"
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -6869,6 +7414,26 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
@@ -6939,6 +7504,15 @@
"node": ">=8"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
"integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
@@ -7041,6 +7615,15 @@
"node": ">=0.10.0"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -7067,6 +7650,12 @@
"node": ">=8"
}
},
"node_modules/svg-arc-to-cubic-bezier": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
"integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==",
"license": "ISC"
},
"node_modules/tailwind-merge": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
@@ -7122,6 +7711,12 @@
"node": ">=18"
}
},
"node_modules/tiny-inflate": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
"license": "MIT"
},
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
@@ -7326,6 +7921,32 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/unicode-properties": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
"integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.0",
"unicode-trie": "^2.0.0"
}
},
"node_modules/unicode-trie": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
"integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
"license": "MIT",
"dependencies": {
"pako": "^0.2.5",
"tiny-inflate": "^1.0.0"
}
},
"node_modules/unicode-trie/node_modules/pako": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
"integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
"license": "MIT"
},
"node_modules/unplugin": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz",
@@ -7448,6 +8069,12 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"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/uuid": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
@@ -7558,6 +8185,20 @@
}
}
},
"node_modules/vite-compatible-readable-stream": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz",
"integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/vite/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -7670,6 +8311,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yoga-layout": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz",
"integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==",
"license": "MIT"
},
"node_modules/zod": {
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",

View File

@@ -22,7 +22,10 @@
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@react-pdf/renderer": "^4.3.1",
"@tailwindcss/vite": "^4.1.13",
"@tanstack/react-form": "^1.23.0",
"@tanstack/react-query": "^5.89.0",
@@ -37,13 +40,18 @@
"date-fns": "^4.1.0",
"is-mobile": "^5.0.0",
"js-cookie": "^3.0.5",
"jsbarcode": "^3.12.1",
"lucide-react": "^0.542.0",
"marked": "^16.4.1",
"moment": "^2.30.1",
"r": "^0.0.5",
"react": "^19.1.1",
"react-barcode": "^1.6.1",
"react-calendar-timeline": "^0.30.0-beta.3",
"react-day-picker": "^9.11.1",
"react-dom": "^19.1.1",
"react-hook-form": "^7.65.0",
"react-resizable-panels": "^3.0.6",
"recharts": "^2.15.4",
"socket.io-client": "^4.8.1",
"sonner": "^2.0.7",

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,34 @@
// src/components/Changelog.jsx
import { marked } from "marked";
import changelog from "../../../../CHANGELOG.md?raw"; // assuming changelog.md is in root ?raw
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;

View File

@@ -28,7 +28,9 @@ export default function Nav() {
</a>
</Button>
</div>
<Button className="m-1">
<Link to="/old">Old Version</Link>
</Button>
{session ? (
<div className="m-1">
<DropdownMenu>
@@ -49,9 +51,7 @@ export default function Nav() {
<DropdownMenuItem>
<Link to="/user/profile">Profile</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<Link to="/old">LST-Old</Link>
</DropdownMenuItem>
{/* <DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuItem>Subscription</DropdownMenuItem> */}

View File

@@ -1,8 +1,10 @@
import { Link } from "@tanstack/react-router";
import { userAccess } from "../../lib/authClient";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarMenuItem,
SidebarTrigger,
} from "../ui/sidebar";
import Admin from "./Admin";
@@ -18,6 +20,9 @@ export default function SideBarNav() {
</SidebarContent>
<SidebarFooter>
<SidebarMenuItem>
<Link to={"/changelog"}>Changelog</Link>
</SidebarMenuItem>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>

View File

@@ -0,0 +1,54 @@
import * as React from "react"
import { GripVerticalIcon } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"
import { cn } from "@/lib/utils"
function ResizablePanelGroup({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {
return (
<ResizablePrimitive.PanelGroup
data-slot="resizable-panel-group"
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
)}
{...props}
/>
)
}
function ResizablePanel({
...props
}: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
}
function ResizableHandle({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean
}) {
return (
<ResizablePrimitive.PanelResizeHandle
data-slot="resizable-handle"
className={cn(
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
<GripVerticalIcon className="size-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)
}
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }

View File

@@ -0,0 +1,29 @@
import * as React from "react"
import * as SwitchPrimitive from "@radix-ui/react-switch"
import { cn } from "@/lib/utils"
function Switch({
className,
...props
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
return (
<SwitchPrimitive.Root
data-slot="switch"
className={cn(
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<SwitchPrimitive.Thumb
data-slot="switch-thumb"
className={cn(
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitive.Root>
)
}
export { Switch }

View File

@@ -0,0 +1,64 @@
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn("flex flex-col gap-2", className)}
{...props}
/>
)
}
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
className
)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent }

View File

@@ -113,6 +113,10 @@ export async function checkUserAccess({
export const authClient = createAuthClient({
baseURL: `${window.location.origin}/lst/api/auth`,
plugins: [usernameClient()],
options: {
autoPopup: false,
requireAuth: false,
},
callbacks: {
callbacks: {
onUpdate: (res: any) => {
@@ -121,7 +125,7 @@ export const authClient = createAuthClient({
useAuth.getState().setSession(res?.data ?? null);
},
onSignIn: (res: any) => {
console.log("Setting session to ", res?.data);
//console.log("Setting session to ", res?.data);
useAuth.getState().setSession(res?.data ?? null);
},
onSignOut: () => {

View File

@@ -13,11 +13,14 @@ import { createFileRoute } from '@tanstack/react-router'
import { Route as rootRouteImport } from './routes/__root'
import { Route as AppRouteRouteImport } from './routes/_app/route'
import { Route as AppIndexRouteImport } from './routes/_app/index'
import { Route as AppChangelogRouteImport } from './routes/_app/changelog'
import { Route as OldOldRouteRouteImport } from './routes/_old/old/route'
import { Route as MobileMobileLayoutRouteRouteImport } from './routes/_mobile/_mobileLayout/route'
import { Route as AppAdminLayoutRouteRouteImport } from './routes/_app/_adminLayout/route'
import { Route as OldOldIndexRouteImport } from './routes/_old/old/index'
import { Route as AppauthLoginRouteImport } from './routes/_app/(auth)/login'
import { Route as OldOldRfidIndexRouteImport } from './routes/_old/old/rfid/index'
import { Route as OldOldOcpIndexRouteImport } from './routes/_old/old/ocp/index'
import { Route as MobileMobileLayoutMIndexRouteImport } from './routes/_mobile/_mobileLayout/m/index'
import { Route as AppauthUserIndexRouteImport } from './routes/_app/(auth)/user/index'
import { Route as MobileMobileLayoutMRelocateRouteImport } from './routes/_mobile/_mobileLayout/m/relocate'
@@ -30,10 +33,16 @@ import { Route as AppauthUserSignupRouteImport } from './routes/_app/(auth)/user
import { Route as AppauthUserResetpasswordRouteImport } from './routes/_app/(auth)/user/resetpassword'
import { Route as AppauthUserProfileRouteImport } from './routes/_app/(auth)/user/profile'
import { Route as AppAdminLayoutAdminUsersRouteRouteImport } from './routes/_app/_adminLayout/admin/_users/route'
import { Route as OldOldocmeCyclecountIndexRouteImport } from './routes/_old/old/(ocme)/cyclecount/index'
import { Route as OldOldlogisticsSiloAdjustmentsIndexRouteImport } from './routes/_old/old/(logistics)/siloAdjustments/index'
import { Route as OldOldlogisticsMaterialHelperIndexRouteImport } from './routes/_old/old/(logistics)/materialHelper/index'
import { Route as OldOldlogisticsHelperCommandsIndexRouteImport } from './routes/_old/old/(logistics)/helperCommands/index'
import { Route as OldOldlogisticsDmIndexRouteImport } from './routes/_old/old/(logistics)/dm/index'
import { Route as OldOldlogisticsBarcodegenIndexRouteImport } from './routes/_old/old/(logistics)/barcodegen/index'
import { Route as OldOldlogisticsSiloAdjustmentsHistRouteImport } from './routes/_old/old/(logistics)/siloAdjustments/$hist'
import { Route as AppAdminLayoutAdminUsersUsersRouteImport } from './routes/_app/_adminLayout/admin/_users/users'
import { Route as AppAdminLayoutAdminUsersProdUsersRouteImport } from './routes/_app/_adminLayout/admin/_users/prodUsers'
import { Route as OldOldlogisticsMaterialHelperConsumptionIndexRouteImport } from './routes/_old/old/(logistics)/materialHelper/consumption/index'
import { Route as OldOldlogisticsSiloAdjustmentsCommentCommentRouteImport } from './routes/_old/old/(logistics)/siloAdjustments/comment/$comment'
const AppAdminLayoutAdminRouteImport = createFileRoute(
@@ -49,6 +58,11 @@ const AppIndexRoute = AppIndexRouteImport.update({
path: '/',
getParentRoute: () => AppRouteRoute,
} as any)
const AppChangelogRoute = AppChangelogRouteImport.update({
id: '/changelog',
path: '/changelog',
getParentRoute: () => AppRouteRoute,
} as any)
const OldOldRouteRoute = OldOldRouteRouteImport.update({
id: '/_old/old',
path: '/old',
@@ -77,6 +91,16 @@ const AppauthLoginRoute = AppauthLoginRouteImport.update({
path: '/login',
getParentRoute: () => AppRouteRoute,
} as any)
const OldOldRfidIndexRoute = OldOldRfidIndexRouteImport.update({
id: '/rfid/',
path: '/rfid/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldOcpIndexRoute = OldOldOcpIndexRouteImport.update({
id: '/ocp/',
path: '/ocp/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const MobileMobileLayoutMIndexRoute =
MobileMobileLayoutMIndexRouteImport.update({
id: '/m/',
@@ -145,12 +169,41 @@ const AppAdminLayoutAdminUsersRouteRoute =
id: '/_users',
getParentRoute: () => AppAdminLayoutAdminRoute,
} as any)
const OldOldocmeCyclecountIndexRoute =
OldOldocmeCyclecountIndexRouteImport.update({
id: '/(ocme)/cyclecount/',
path: '/cyclecount/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsSiloAdjustmentsIndexRoute =
OldOldlogisticsSiloAdjustmentsIndexRouteImport.update({
id: '/(logistics)/siloAdjustments/',
path: '/siloAdjustments/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsMaterialHelperIndexRoute =
OldOldlogisticsMaterialHelperIndexRouteImport.update({
id: '/(logistics)/materialHelper/',
path: '/materialHelper/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsHelperCommandsIndexRoute =
OldOldlogisticsHelperCommandsIndexRouteImport.update({
id: '/(logistics)/helperCommands/',
path: '/helperCommands/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsDmIndexRoute = OldOldlogisticsDmIndexRouteImport.update({
id: '/(logistics)/dm/',
path: '/dm/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsBarcodegenIndexRoute =
OldOldlogisticsBarcodegenIndexRouteImport.update({
id: '/(logistics)/barcodegen/',
path: '/barcodegen/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsSiloAdjustmentsHistRoute =
OldOldlogisticsSiloAdjustmentsHistRouteImport.update({
id: '/(logistics)/siloAdjustments/$hist',
@@ -169,6 +222,12 @@ const AppAdminLayoutAdminUsersProdUsersRoute =
path: '/prodUsers',
getParentRoute: () => AppAdminLayoutAdminUsersRouteRoute,
} as any)
const OldOldlogisticsMaterialHelperConsumptionIndexRoute =
OldOldlogisticsMaterialHelperConsumptionIndexRouteImport.update({
id: '/(logistics)/materialHelper/consumption/',
path: '/materialHelper/consumption/',
getParentRoute: () => OldOldRouteRoute,
} as any)
const OldOldlogisticsSiloAdjustmentsCommentCommentRoute =
OldOldlogisticsSiloAdjustmentsCommentCommentRouteImport.update({
id: '/(logistics)/siloAdjustments/comment/$comment',
@@ -178,6 +237,7 @@ const OldOldlogisticsSiloAdjustmentsCommentCommentRoute =
export interface FileRoutesByFullPath {
'/old': typeof OldOldRouteRouteWithChildren
'/changelog': typeof AppChangelogRoute
'/': typeof AppIndexRoute
'/login': typeof AppauthLoginRoute
'/old/': typeof OldOldIndexRoute
@@ -193,13 +253,22 @@ export interface FileRoutesByFullPath {
'/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/user': typeof AppauthUserIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute
'/admin/prodUsers': typeof AppAdminLayoutAdminUsersProdUsersRoute
'/admin/users': typeof AppAdminLayoutAdminUsersUsersRoute
'/old/siloAdjustments/$hist': typeof OldOldlogisticsSiloAdjustmentsHistRoute
'/old/barcodegen': typeof OldOldlogisticsBarcodegenIndexRoute
'/old/dm': typeof OldOldlogisticsDmIndexRoute
'/old/helperCommands': typeof OldOldlogisticsHelperCommandsIndexRoute
'/old/materialHelper': typeof OldOldlogisticsMaterialHelperIndexRoute
'/old/siloAdjustments': typeof OldOldlogisticsSiloAdjustmentsIndexRoute
'/old/cyclecount': typeof OldOldocmeCyclecountIndexRoute
'/old/siloAdjustments/comment/$comment': typeof OldOldlogisticsSiloAdjustmentsCommentCommentRoute
'/old/materialHelper/consumption': typeof OldOldlogisticsMaterialHelperConsumptionIndexRoute
}
export interface FileRoutesByTo {
'/changelog': typeof AppChangelogRoute
'/': typeof AppIndexRoute
'/login': typeof AppauthLoginRoute
'/old': typeof OldOldIndexRoute
@@ -215,11 +284,19 @@ export interface FileRoutesByTo {
'/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/user': typeof AppauthUserIndexRoute
'/m': typeof MobileMobileLayoutMIndexRoute
'/old/ocp': typeof OldOldOcpIndexRoute
'/old/rfid': typeof OldOldRfidIndexRoute
'/admin/prodUsers': typeof AppAdminLayoutAdminUsersProdUsersRoute
'/admin/users': typeof AppAdminLayoutAdminUsersUsersRoute
'/old/siloAdjustments/$hist': typeof OldOldlogisticsSiloAdjustmentsHistRoute
'/old/barcodegen': typeof OldOldlogisticsBarcodegenIndexRoute
'/old/dm': typeof OldOldlogisticsDmIndexRoute
'/old/helperCommands': typeof OldOldlogisticsHelperCommandsIndexRoute
'/old/materialHelper': typeof OldOldlogisticsMaterialHelperIndexRoute
'/old/siloAdjustments': typeof OldOldlogisticsSiloAdjustmentsIndexRoute
'/old/cyclecount': typeof OldOldocmeCyclecountIndexRoute
'/old/siloAdjustments/comment/$comment': typeof OldOldlogisticsSiloAdjustmentsCommentCommentRoute
'/old/materialHelper/consumption': typeof OldOldlogisticsMaterialHelperConsumptionIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
@@ -227,6 +304,7 @@ export interface FileRoutesById {
'/_app/_adminLayout': typeof AppAdminLayoutRouteRouteWithChildren
'/_mobile/_mobileLayout': typeof MobileMobileLayoutRouteRouteWithChildren
'/_old/old': typeof OldOldRouteRouteWithChildren
'/_app/changelog': typeof AppChangelogRoute
'/_app/': typeof AppIndexRoute
'/_app/(auth)/login': typeof AppauthLoginRoute
'/_old/old/': typeof OldOldIndexRoute
@@ -243,16 +321,25 @@ export interface FileRoutesById {
'/_mobile/_mobileLayout/m/relocate': typeof MobileMobileLayoutMRelocateRoute
'/_app/(auth)/user/': typeof AppauthUserIndexRoute
'/_mobile/_mobileLayout/m/': typeof MobileMobileLayoutMIndexRoute
'/_old/old/ocp/': typeof OldOldOcpIndexRoute
'/_old/old/rfid/': typeof OldOldRfidIndexRoute
'/_app/_adminLayout/admin/_users/prodUsers': typeof AppAdminLayoutAdminUsersProdUsersRoute
'/_app/_adminLayout/admin/_users/users': typeof AppAdminLayoutAdminUsersUsersRoute
'/_old/old/(logistics)/siloAdjustments/$hist': typeof OldOldlogisticsSiloAdjustmentsHistRoute
'/_old/old/(logistics)/barcodegen/': typeof OldOldlogisticsBarcodegenIndexRoute
'/_old/old/(logistics)/dm/': typeof OldOldlogisticsDmIndexRoute
'/_old/old/(logistics)/helperCommands/': typeof OldOldlogisticsHelperCommandsIndexRoute
'/_old/old/(logistics)/materialHelper/': typeof OldOldlogisticsMaterialHelperIndexRoute
'/_old/old/(logistics)/siloAdjustments/': typeof OldOldlogisticsSiloAdjustmentsIndexRoute
'/_old/old/(ocme)/cyclecount/': typeof OldOldocmeCyclecountIndexRoute
'/_old/old/(logistics)/siloAdjustments/comment/$comment': typeof OldOldlogisticsSiloAdjustmentsCommentCommentRoute
'/_old/old/(logistics)/materialHelper/consumption/': typeof OldOldlogisticsMaterialHelperConsumptionIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/old'
| '/changelog'
| '/'
| '/login'
| '/old/'
@@ -268,13 +355,22 @@ export interface FileRouteTypes {
| '/m/relocate'
| '/user'
| '/m'
| '/old/ocp'
| '/old/rfid'
| '/admin/prodUsers'
| '/admin/users'
| '/old/siloAdjustments/$hist'
| '/old/barcodegen'
| '/old/dm'
| '/old/helperCommands'
| '/old/materialHelper'
| '/old/siloAdjustments'
| '/old/cyclecount'
| '/old/siloAdjustments/comment/$comment'
| '/old/materialHelper/consumption'
fileRoutesByTo: FileRoutesByTo
to:
| '/changelog'
| '/'
| '/login'
| '/old'
@@ -290,17 +386,26 @@ export interface FileRouteTypes {
| '/m/relocate'
| '/user'
| '/m'
| '/old/ocp'
| '/old/rfid'
| '/admin/prodUsers'
| '/admin/users'
| '/old/siloAdjustments/$hist'
| '/old/barcodegen'
| '/old/dm'
| '/old/helperCommands'
| '/old/materialHelper'
| '/old/siloAdjustments'
| '/old/cyclecount'
| '/old/siloAdjustments/comment/$comment'
| '/old/materialHelper/consumption'
id:
| '__root__'
| '/_app'
| '/_app/_adminLayout'
| '/_mobile/_mobileLayout'
| '/_old/old'
| '/_app/changelog'
| '/_app/'
| '/_app/(auth)/login'
| '/_old/old/'
@@ -317,11 +422,19 @@ export interface FileRouteTypes {
| '/_mobile/_mobileLayout/m/relocate'
| '/_app/(auth)/user/'
| '/_mobile/_mobileLayout/m/'
| '/_old/old/ocp/'
| '/_old/old/rfid/'
| '/_app/_adminLayout/admin/_users/prodUsers'
| '/_app/_adminLayout/admin/_users/users'
| '/_old/old/(logistics)/siloAdjustments/$hist'
| '/_old/old/(logistics)/barcodegen/'
| '/_old/old/(logistics)/dm/'
| '/_old/old/(logistics)/helperCommands/'
| '/_old/old/(logistics)/materialHelper/'
| '/_old/old/(logistics)/siloAdjustments/'
| '/_old/old/(ocme)/cyclecount/'
| '/_old/old/(logistics)/siloAdjustments/comment/$comment'
| '/_old/old/(logistics)/materialHelper/consumption/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
@@ -346,6 +459,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppIndexRouteImport
parentRoute: typeof AppRouteRoute
}
'/_app/changelog': {
id: '/_app/changelog'
path: '/changelog'
fullPath: '/changelog'
preLoaderRoute: typeof AppChangelogRouteImport
parentRoute: typeof AppRouteRoute
}
'/_old/old': {
id: '/_old/old'
path: '/old'
@@ -388,6 +508,20 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppauthLoginRouteImport
parentRoute: typeof AppRouteRoute
}
'/_old/old/rfid/': {
id: '/_old/old/rfid/'
path: '/rfid'
fullPath: '/old/rfid'
preLoaderRoute: typeof OldOldRfidIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/ocp/': {
id: '/_old/old/ocp/'
path: '/ocp'
fullPath: '/old/ocp'
preLoaderRoute: typeof OldOldOcpIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_mobile/_mobileLayout/m/': {
id: '/_mobile/_mobileLayout/m/'
path: '/m'
@@ -472,6 +606,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppAdminLayoutAdminUsersRouteRouteImport
parentRoute: typeof AppAdminLayoutAdminRoute
}
'/_old/old/(ocme)/cyclecount/': {
id: '/_old/old/(ocme)/cyclecount/'
path: '/cyclecount'
fullPath: '/old/cyclecount'
preLoaderRoute: typeof OldOldocmeCyclecountIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/siloAdjustments/': {
id: '/_old/old/(logistics)/siloAdjustments/'
path: '/siloAdjustments'
@@ -479,6 +620,34 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof OldOldlogisticsSiloAdjustmentsIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/materialHelper/': {
id: '/_old/old/(logistics)/materialHelper/'
path: '/materialHelper'
fullPath: '/old/materialHelper'
preLoaderRoute: typeof OldOldlogisticsMaterialHelperIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/helperCommands/': {
id: '/_old/old/(logistics)/helperCommands/'
path: '/helperCommands'
fullPath: '/old/helperCommands'
preLoaderRoute: typeof OldOldlogisticsHelperCommandsIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/dm/': {
id: '/_old/old/(logistics)/dm/'
path: '/dm'
fullPath: '/old/dm'
preLoaderRoute: typeof OldOldlogisticsDmIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/barcodegen/': {
id: '/_old/old/(logistics)/barcodegen/'
path: '/barcodegen'
fullPath: '/old/barcodegen'
preLoaderRoute: typeof OldOldlogisticsBarcodegenIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/siloAdjustments/$hist': {
id: '/_old/old/(logistics)/siloAdjustments/$hist'
path: '/siloAdjustments/$hist'
@@ -500,6 +669,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AppAdminLayoutAdminUsersProdUsersRouteImport
parentRoute: typeof AppAdminLayoutAdminUsersRouteRoute
}
'/_old/old/(logistics)/materialHelper/consumption/': {
id: '/_old/old/(logistics)/materialHelper/consumption/'
path: '/materialHelper/consumption'
fullPath: '/old/materialHelper/consumption'
preLoaderRoute: typeof OldOldlogisticsMaterialHelperConsumptionIndexRouteImport
parentRoute: typeof OldOldRouteRoute
}
'/_old/old/(logistics)/siloAdjustments/comment/$comment': {
id: '/_old/old/(logistics)/siloAdjustments/comment/$comment'
path: '/siloAdjustments/comment/$comment'
@@ -556,6 +732,7 @@ const AppAdminLayoutRouteRouteWithChildren =
interface AppRouteRouteChildren {
AppAdminLayoutRouteRoute: typeof AppAdminLayoutRouteRouteWithChildren
AppChangelogRoute: typeof AppChangelogRoute
AppIndexRoute: typeof AppIndexRoute
AppauthLoginRoute: typeof AppauthLoginRoute
AppauthUserProfileRoute: typeof AppauthUserProfileRoute
@@ -567,6 +744,7 @@ interface AppRouteRouteChildren {
const AppRouteRouteChildren: AppRouteRouteChildren = {
AppAdminLayoutRouteRoute: AppAdminLayoutRouteRouteWithChildren,
AppChangelogRoute: AppChangelogRoute,
AppIndexRoute: AppIndexRoute,
AppauthLoginRoute: AppauthLoginRoute,
AppauthUserProfileRoute: AppauthUserProfileRoute,
@@ -603,19 +781,38 @@ const MobileMobileLayoutRouteRouteWithChildren =
interface OldOldRouteRouteChildren {
OldOldIndexRoute: typeof OldOldIndexRoute
OldOldOcpIndexRoute: typeof OldOldOcpIndexRoute
OldOldRfidIndexRoute: typeof OldOldRfidIndexRoute
OldOldlogisticsSiloAdjustmentsHistRoute: typeof OldOldlogisticsSiloAdjustmentsHistRoute
OldOldlogisticsBarcodegenIndexRoute: typeof OldOldlogisticsBarcodegenIndexRoute
OldOldlogisticsDmIndexRoute: typeof OldOldlogisticsDmIndexRoute
OldOldlogisticsHelperCommandsIndexRoute: typeof OldOldlogisticsHelperCommandsIndexRoute
OldOldlogisticsMaterialHelperIndexRoute: typeof OldOldlogisticsMaterialHelperIndexRoute
OldOldlogisticsSiloAdjustmentsIndexRoute: typeof OldOldlogisticsSiloAdjustmentsIndexRoute
OldOldocmeCyclecountIndexRoute: typeof OldOldocmeCyclecountIndexRoute
OldOldlogisticsSiloAdjustmentsCommentCommentRoute: typeof OldOldlogisticsSiloAdjustmentsCommentCommentRoute
OldOldlogisticsMaterialHelperConsumptionIndexRoute: typeof OldOldlogisticsMaterialHelperConsumptionIndexRoute
}
const OldOldRouteRouteChildren: OldOldRouteRouteChildren = {
OldOldIndexRoute: OldOldIndexRoute,
OldOldOcpIndexRoute: OldOldOcpIndexRoute,
OldOldRfidIndexRoute: OldOldRfidIndexRoute,
OldOldlogisticsSiloAdjustmentsHistRoute:
OldOldlogisticsSiloAdjustmentsHistRoute,
OldOldlogisticsBarcodegenIndexRoute: OldOldlogisticsBarcodegenIndexRoute,
OldOldlogisticsDmIndexRoute: OldOldlogisticsDmIndexRoute,
OldOldlogisticsHelperCommandsIndexRoute:
OldOldlogisticsHelperCommandsIndexRoute,
OldOldlogisticsMaterialHelperIndexRoute:
OldOldlogisticsMaterialHelperIndexRoute,
OldOldlogisticsSiloAdjustmentsIndexRoute:
OldOldlogisticsSiloAdjustmentsIndexRoute,
OldOldocmeCyclecountIndexRoute: OldOldocmeCyclecountIndexRoute,
OldOldlogisticsSiloAdjustmentsCommentCommentRoute:
OldOldlogisticsSiloAdjustmentsCommentCommentRoute,
OldOldlogisticsMaterialHelperConsumptionIndexRoute:
OldOldlogisticsMaterialHelperConsumptionIndexRoute,
}
const OldOldRouteRouteWithChildren = OldOldRouteRoute._addFileChildren(

View File

@@ -17,6 +17,7 @@ const modules: string[] = [
"siloAdjustments",
"demandManagement",
"logistics",
"helperCommands",
"production",
"quality",
"eom",

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import Changelog from "@/components/changelog/ChangeLog";
export const Route = createFileRoute("/_app/changelog")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div className="m-2">
<Changelog />
</div>
);
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import BGPage from "../../-components/logistics/barcodeGenerator/BGPage";
export const Route = createFileRoute("/_old/old/(logistics)/barcodegen/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<BGPage />
</div>
);
}

View File

@@ -0,0 +1,33 @@
import { createFileRoute, redirect } from "@tanstack/react-router";
import { checkUserAccess } from "@/lib/authClient";
import DmPage from "../../-components/logistics/dm/dmPage";
export const Route = createFileRoute("/_old/old/(logistics)/dm/")({
component: RouteComponent,
beforeLoad: async () => {
const auth = await checkUserAccess({
allowedRoles: ["systemAdmin", "technician", "admin", "manager"],
moduleName: "siloAdjustments", // optional
});
if (!auth) {
throw redirect({
to: "/login",
search: {
// Use the current location to power a redirect after login
// (Do not use `router.state.resolvedLocation` as it can
// potentially lag behind the actual current location)
redirect: location.pathname + location.search,
},
});
}
},
});
function RouteComponent() {
return (
<div>
<DmPage />
</div>
);
}

View File

@@ -0,0 +1,28 @@
import { createFileRoute } from "@tanstack/react-router";
import HelperPage from "../../-components/logistics/helperCommands/helperPage";
export const Route = createFileRoute("/_old/old/(logistics)/helperCommands/")({
component: RouteComponent,
// beforeLoad: async () => {
// const auth = localStorage.getItem("auth_token");
// if (!auth) {
// throw redirect({
// to: "/login",
// search: {
// // Use the current location to power a redirect after login
// // (Do not use `router.state.resolvedLocation` as it can
// // potentially lag behind the actual current location)
// redirect: location.pathname + location.search,
// },
// });
// }
// },
});
function RouteComponent() {
return (
<div>
<HelperPage />
</div>
);
}

View File

@@ -0,0 +1,42 @@
import { createFileRoute } from "@tanstack/react-router";
import ConsumeMaterial from "../../../-components/logistics/materialHelper/consumption/ConsumeMaterial";
import PreformReturn from "../../../-components/logistics/materialHelper/consumption/MaterialReturn";
import TransferToNextLot from "../../../-components/logistics/materialHelper/consumption/TransferToNextLot";
export const Route = createFileRoute(
"/_old/old/(logistics)/materialHelper/consumption/",
)({
component: RouteComponent,
head: () => ({
meta: [
{
name: "description",
content: "My App is a web application",
},
{
title: "LST - Logistics",
},
],
}),
});
function RouteComponent() {
const url: string = window.location.host.split(":")[0];
const auth = localStorage.getItem("auth_token");
return (
<div className="flex flex-wrap">
{auth ? (
<>
<ConsumeMaterial />
{url === "localhost" && <PreformReturn />}
<TransferToNextLot />
</>
) : (
<>
<ConsumeMaterial />
<TransferToNextLot />
</>
)}
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { createFileRoute } from "@tanstack/react-router";
import MaterialHelperPage from "../../-components/logistics/materialHelper/materialHelperPage";
export const Route = createFileRoute("/_old/old/(logistics)/materialHelper/")({
component: RouteComponent,
head: () => ({
meta: [
{
name: "description",
content: "My App is a web application",
},
{
title: "LST - Logistics",
},
],
}),
});
function RouteComponent() {
return (
<div>
<MaterialHelperPage />
</div>
);
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import OcmeCycleCount from "../../-components/ocme/ocmeCycleCount";
export const Route = createFileRoute("/_old/old/(ocme)/cyclecount/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div className="m-2">
<OcmeCycleCount />
</div>
);
}

View File

@@ -17,7 +17,7 @@ export default function Cards(card: any) {
active: existing[0]?.active ?? false,
},
onSubmit: async ({ value }) => {
console.log(value);
//console.log(value);
const testCard: any = cards.filter((i: any) => i.name === value.name);
if (value.active) {

View File

@@ -1,7 +1,9 @@
import { Link } from "@tanstack/react-router";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarMenuItem,
SidebarTrigger,
} from "../../../../../components/ui/sidebar";
import {
@@ -48,6 +50,9 @@ export function AppSidebar() {
)}
</SidebarContent>
<SidebarFooter>
<SidebarMenuItem>
<Link to={"/changelog"}>Changelog</Link>
</SidebarMenuItem>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>

View File

@@ -0,0 +1,149 @@
import { CollapsibleTrigger } from "@radix-ui/react-collapsible";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import Barcode from "react-barcode";
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible";
import { getLanes } from "../../../-utils/querys/logistics/getWarehouseLanes";
import { LstCard } from "../../extendedUi/LstCard";
import { BarcodePDFExport } from "./BarcodeExport";
import { BulkBarcodePDFExport } from "./BulkExport";
import CommonCommands from "./CommonCommands";
export default function BGPage() {
const { data, isError, isLoading } = useQuery(getLanes());
const [checked, setChecked] = useState([]);
if (isLoading) return <div>Loading Data</div>;
if (isError)
return <div>There was an error getting the warehouse lane data.</div>;
/**
* get the warehouse names only
*/
const warhouses = new Map();
data?.forEach((item: any) => {
// if the warhouse is not already included add it to the map
if (!warhouses.has(item.warehouseId)) {
warhouses.set(item.warehouseId, item.warehouseDescription);
}
});
// convert the map to an array
const warehouseArray = Array.from(warhouses).map(([wid, wname]) => ({
warehouseId: wid,
warehouseDescription: wname,
}));
//console.log(warehouseArray);
// handle the onchange
const changeBox = (d: any) => {
setChecked((prev: any) => {
if (prev.includes(d)) {
return prev.filter((name: any) => name !== d);
} else {
return [...prev, d];
}
});
};
return (
<div className="flex flex-row m-2">
<div className="flex flex-row">
<div className="m-2">
<LstCard>
<CardHeader>Warehouse Barcodes</CardHeader>
<CardContent>
{warehouseArray.map((i: any) => {
const lanes = data?.filter(
(wid: any) => wid.warehouseId === i.warehouseId,
);
return (
<div className="m-2" key={i.warehouseId}>
<Collapsible>
<CollapsibleTrigger>
{i.warehouseDescription}
</CollapsibleTrigger>
<CollapsibleContent>
<div className="ml-2">
{lanes?.map((l: any) => {
return (
<div key={l.laneId}>
<Checkbox
id={l.laneId}
// checked={checked.includes(
// l
// )}
onCheckedChange={() => changeBox(l)}
/>
<label id={l.laneId} className="ml-2">
{l.laneDescription}
</label>
</div>
);
})}
</div>
</CollapsibleContent>
</Collapsible>
</div>
);
})}
</CardContent>
</LstCard>
</div>
{checked.length > 0 && (
<div className="m-2">
<LstCard>
<CardHeader>Current selected lanes</CardHeader>
<CardContent>
{checked.map((c: any) => {
return (
<div
className="flex justify-center"
key={`${c.warehouseId}-${c.laneId}`}
>
<div>
<Barcode
value={`loc#${c.warehouseId}#${c.laneId}`}
width={2}
height={50}
displayValue={false}
/>
<p className="flex justify-center">
Lane: {c.laneDescription}
</p>
</div>
<div className="ml-2 mt-4">
<BarcodePDFExport
barcodeValue={`loc#${c.warehouseId}#${c.laneId}`}
data={c}
/>
</div>
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex justify-end">
{checked.length > 1 && (
<div>
<BulkBarcodePDFExport data={checked} />
</div>
)}
</div>
</CardFooter>
</LstCard>
</div>
)}
</div>
<div className="m-2">
<CommonCommands />
</div>
</div>
);
}

View File

@@ -0,0 +1,125 @@
import {
Document,
Image,
Page,
pdf,
StyleSheet,
Text,
View,
} from "@react-pdf/renderer";
import JsBarcode from "jsbarcode";
import { Button } from "@/components/ui/button";
export const BulkBarcodePDFExport = ({ data }: { data: any }) => {
const createBarcode = (barcodeValue: any) => {
//const barcodeValue = data; // Barcode value
const canvas = document.createElement("canvas");
// Generate barcode on the canvas
JsBarcode(canvas, barcodeValue, {
format: "CODE128",
displayValue: false,
});
// Convert canvas to base64 image data
const barcodeImage = canvas.toDataURL("image/png");
return barcodeImage;
};
const generatePDF = () => {
// Define the document styles using @react-pdf/renderer
const styles = StyleSheet.create({
page: {
padding: 30,
},
centerContent: {
display: "flex",
justifyContent: "flex-start", // Center horizontally
alignItems: "center", // Center vertically
flexDirection: "row", // Stack items (barcode and description) vertically
//height: "5%", // Ensure the container takes full page height
textAlign: "center",
},
section: {
marginBottom: 10,
textAlign: "center",
},
barcode: {
width: 275, // Width of the barcode
height: 75, // Height of the barcode
marginBottom: 10,
},
description: {
fontSize: 14,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
},
headerText: {
fontSize: 28,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
display: "flex",
justifyContent: "center",
//height: "15%", // Ensure the container takes full page height
textAlign: "center",
},
horizontalLine: {
borderBottom: "#000000",
borderBottomWidth: 1,
},
});
// Create the document
const MyDocument = (
<Document>
<Page style={styles.page} orientation="portrait" size="A4">
<View style={styles.headerText}>
<Text>Multi Lane export.</Text>
</View>
<View style={styles.horizontalLine} />
{data.map((i: any, index: any) => {
return (
<View style={styles.centerContent} key={index}>
<View style={styles.section}>
<Image
src={createBarcode(`loc#${i.warehouseId}#${i.laneId}`)}
style={styles.barcode}
/>
</View>
<View style={styles.section}>
<Text style={styles.description}>
Lane: {i.laneDescription}
</Text>
</View>
</View>
);
})}
</Page>
</Document>
);
// Generate the PDF and trigger download
pdf(MyDocument)
.toBlob()
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `MultipleBarcodes.pdf`;
link.click();
});
};
return (
<div>
<Button onClick={() => generatePDF()} color="primary">
Export All Selected
</Button>
</div>
);
};

View File

@@ -0,0 +1,97 @@
import { useState } from "react";
import Barcode from "react-barcode";
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { LstCard } from "../../extendedUi/LstCard";
import { BarcodePDFExport } from "./BarcodeExport";
import { BulkBarcodePDFExport } from "./BulkExport";
const commoncmd = [
{ name: "Relocate", commandId: 33 },
//-{ name: "Stock in", commandId: 22 },
];
export default function CommonCommands() {
const [checked, setChecked] = useState([]);
// handle the onchange
const changeBox = (d: any) => {
setChecked((prev: any) => {
if (prev.includes(d)) {
return prev.filter((name: any) => name !== d);
} else {
return [...prev, d];
}
});
};
return (
<div>
<div>
<LstCard>
<CardHeader>Common Barcodes</CardHeader>
<CardContent>
{commoncmd.map((i: any) => {
return (
<div className="flex flex-row">
<div>
<Checkbox
id={i.commandId}
// checked={checked.includes(
// l
// )}
onCheckedChange={() => changeBox(i)}
/>
<label id={i.commandId} className="ml-2">
{i.name}
</label>
</div>
</div>
);
})}
</CardContent>
</LstCard>
</div>
<div>
{checked.length > 0 && (
<div className="m-2">
<LstCard>
<CardHeader>Current selected Barcodes</CardHeader>
<CardContent>
{checked.map((c: any) => {
return (
<div className="flex justify-center" key={`${c.name}`}>
<div>
<Barcode
value={`AlplaPRODcmd${c.commandId}`}
width={2}
height={50}
displayValue={false}
/>
<p className="flex justify-center">Bacrode: {c.name}</p>
</div>
<div className="ml-2 mt-4">
<BarcodePDFExport
barcodeValue={`AlplaPRODcmd${c.commandId}`}
data={c}
/>
</div>
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex justify-end">
{checked.length > 1 && (
<div>
<BulkBarcodePDFExport data={checked} />
</div>
)}
</div>
</CardFooter>
</LstCard>
</div>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,55 @@
import { useSettingStore } from "../../../-lib/store/useSettings";
import ForecastImport from "./ForecastImport";
import OrderImport from "./OrderImport";
export default function DMButtons() {
const { settings } = useSettingStore();
const testServers = ["test1", "test2", "test3"];
const plantToken = settings.filter((n) => n.name === "plantToken");
//console.log(plantToken);
return (
<div className="flex flex-row-reverse gap-1">
<OrderImport fileType={"macro"} name={"Macro Import"} />
{/* dev and testserver sees all */}
{testServers.includes(plantToken[0]?.value) && (
<div className="flex flex-row gap-2">
<OrderImport fileType={"abbott"} name={"Abbott truck list"} />
<OrderImport fileType={"energizer"} name={"Energizer Truck List"} />
<ForecastImport fileType={"loreal"} name={"VMI Import"} />
<ForecastImport fileType={"pg"} name={"P&G"} />
<ForecastImport fileType={"energizer"} name={"Energizer Forecast"} />
</div>
)}
{plantToken[0]?.value === "usday1" && (
<div className="flex flex-row gap-2">
<OrderImport fileType={"abbott"} name={"Abbott truck list"} />
<OrderImport fileType={"energizer"} name={"Energizer Truck List"} />
<ForecastImport fileType={"energizer"} name={"Energizer Forecast"} />
</div>
)}
{plantToken[0]?.value === "usflo1" && (
<div className="flex flex-row gap-2">
<ForecastImport fileType={"loreal"} name={"VMI Import"} />
</div>
)}
{plantToken[0]?.value === "usstp1" && (
<div className="flex flex-row gap-2"></div>
)}
{plantToken[0]?.value === "usiow1" && (
<div className="flex flex-row gap-2">
<ForecastImport fileType={"pg"} name={"P&G"} />
</div>
)}
{plantToken[0]?.value === "usiow2" && (
<div className="flex flex-row gap-2">
<ForecastImport fileType={"pg"} name={"P&G"} />
</div>
)}
{plantToken[0]?.value === "usksc1" && (
<div className="flex flex-row gap-2">
<ForecastImport fileType={"pg"} name={"P&G"} />
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,69 @@
import axios from "axios";
import { useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function ForecastImport(props: any) {
const fileInputRef: any = useRef(null);
const [posting, setPosting] = useState(false);
const token = localStorage.getItem("auth_token");
//const [fileType, setFileType] = useState("");
const importOrders = async (e: any) => {
const file = e.target.files[0];
if (!file) {
toast.error("Missing file please try again");
setPosting(false);
return;
}
// create the form data with the correct fileType
const formData = new FormData();
formData.append("postForecast", e.target.files[0]);
formData.append("fileType", props.fileType); // extra field
// console.log(formData);
toast.success("Import started.");
try {
const response = await axios.post(
"/lst/old/api/logistics/postforecastin",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
},
);
//console.log("Upload successful:", response.data);
toast.success(response?.data?.message);
fileInputRef.current.value = null;
setPosting(false);
// toast.success(
// "File Uploaded, please validate processing in alplaprod 2.0"
// );
setPosting(false);
} catch (error) {
console.log(error);
toast.error("Upload failed");
}
setPosting(false);
};
const handleButtonClick = () => {
setPosting(true);
fileInputRef.current.click();
};
return (
<div>
<Button onClick={handleButtonClick} disabled={posting}>
{props.name}
</Button>
<input
type="file"
accept=".xlsx, .xls, .xlsm"
ref={fileInputRef}
style={{ display: "none" }}
onChange={importOrders}
/>
</div>
);
}

View File

@@ -0,0 +1,64 @@
import axios from "axios";
import { useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function OrderImport(props: any) {
const fileInputRef: any = useRef(null);
const [posting, setPosting] = useState(false);
const token = localStorage.getItem("auth_token");
//const [fileType, setFileType] = useState("");
const importOrders = async (e: any) => {
const file = e.target.files[0];
if (!file) {
toast.error("Missing file please try again");
setPosting(false);
return;
}
// create the form data with the correct fileType
const formData = new FormData();
formData.append("postOrders", e.target.files[0]);
formData.append("fileType", props.fileType); // extra field
try {
const response = await axios.post(
"/lst/old/api/logistics/postbulkorders",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
},
);
//console.log("Upload successful:", response.data);
toast.success(response?.data?.message);
fileInputRef.current.value = null;
setPosting(false);
} catch (error) {
console.log(error);
toast.error("Upload failed");
}
setPosting(false);
};
const handleButtonClick = () => {
setPosting(true);
fileInputRef.current.click();
};
return (
<div>
<Button onClick={handleButtonClick} disabled={posting}>
{props.name}
</Button>
<input
type="file"
accept=".xlsx, .xls, .xlsm"
ref={fileInputRef}
style={{ display: "none" }}
onChange={importOrders}
/>
</div>
);
}

View File

@@ -0,0 +1,44 @@
import axios from "axios";
import { format } from "date-fns";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function StandardForecastTemplate() {
const [template, setTemplate] = useState(false);
const getTemplate = async () => {
setTemplate(true);
try {
const res = await axios.get(
`/lst/old/api/logistics/bulkforcasttemplate`,
{
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 = `ForecastTemplate-${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(`Forecast template`);
setTemplate(false);
} catch (error) {
setTemplate(false);
toast.error("There was an error getting the template");
}
};
return (
<Button onClick={getTemplate} disabled={template}>
Standard Forecast Template
</Button>
);
}

View File

@@ -0,0 +1,41 @@
import axios from "axios";
import { format } from "date-fns";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function StandardOrderTemplate() {
const [template, setTemplate] = useState(false);
const getTemplate = async () => {
setTemplate(true);
try {
const res = await axios.get(`/lst/old/api/logistics/bulkorderstemplate`, {
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 = `BulkOrderTemplate-${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(`Bulk Order template`);
setTemplate(false);
} catch (error) {
setTemplate(false);
toast.error("There was an error getting the tempalte");
}
};
return (
<Button onClick={getTemplate} disabled={template}>
Standard Order Template
</Button>
);
}

View File

@@ -0,0 +1,133 @@
import { Separator } from "@/components/ui/separator";
import { LstCard } from "../../extendedUi/LstCard";
import ForecastImport from "./ForecastImport";
import OrderImport from "./OrderImport";
import StandardForecastTemplate from "./StandardForecastTemplate";
import StandardOrderTemplate from "./StandardOrderTemplate";
export default function DmPage() {
return (
<div className="flex flex-row gap-2">
<LstCard className="w-1/2">
<div className="w-96">
<h4 className="text-center underline text-2xl">
Simple instructions for creating/updating orders
</h4>
<div className="flex flex-row gap-3 m-1">
<OrderImport fileType={"standard"} name={"Standard Order Import"} />
<StandardOrderTemplate />
</div>
<Separator />
</div>
<ul className="list-disc mr-2">
<li>
Download the standard template if you have not yet done so, Above
click Standard Order Template.
</li>
<li>Add in the orders like you see in the example below.</li>
<li>
When updating orders you are required to have the
customerOrderNumber, customerLineNumber, and customerReleaseNumber.
Quatity and dates can change.
</li>
<li>
Once you have all the orders entered, click Standard Order Import
</li>
</ul>
<Separator className="my-4" />
<div className="m-5">
<h4 className="text-center underline text-2xl">
Some notes to consider
</h4>
<ul className="list-disc mr-2">
<li>
No longer need to add in the invoice id, we take the default one.
</li>
<li>
You can have as many customers you want in the file and in any
order.
</li>
<li>
Orders created Manually, can not be updated with this process.
</li>
<li>
If you desire you can send up to 1000 orders at one time... or
more....
</li>
<li>
Customer mappings can be added, this means that you can upload
your customer file and it will parse onces mapped, you need to
request this.
</li>
<li>
Custom imports will be at the top right under custom, here you
will just upload the customer file once mapped.
</li>
</ul>
</div>
<Separator className="my-4" />
<p className="text-center underline text-2xl">Example order</p>
<div className="flex justify-center">
<img
src="/lst/app/imgs/ordersInExample.png"
alt="orders in example"
className="w-[680px] h-[280px]"
/>
</div>
</LstCard>
<LstCard className="w-1/2">
<div className="w-96">
<h4 className="text-center underline text-2xl">
Simple instructions for creating forecast
</h4>
<div className="flex flex-row gap-3 m-1">
<ForecastImport
fileType={"standard"}
name={"Standard Forecast Import"}
/>
<StandardForecastTemplate />
<Separator className="my-4" />
</div>
</div>
<div className="m-5">
<ul className="list-disc mr-2">
<li>Download the template if you have not yet done so.</li>
<li>Add in the forecast like you see in the example below.</li>
<li>
Once you have all the forecast enters click the upload button on
the top right
</li>
</ul>
</div>
<Separator className="my-4" />
<div className="m-5">
<h4 className="text-center underline text-2xl">
Some notes to consider.
</h4>
<ul className="list-disc mr-2">
<li>You can only use one customer at a time.</li>
<li>If you desire you can send up to 1000 orders at one time...</li>
<li>
The customer MUST be set as default address in order for the
system to validate the av.
</li>
</ul>
</div>
<Separator className="my-4" />
<p className="text-center underline text-2xl">Example forecast</p>
<div className="flex justify-center">
<img
src="/lst/app/imgs/exampleforecast.png"
alt="orders in example"
className="w-[480px] h-[280px]"
/>
</div>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,94 @@
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { LstCard } from "../../../extendedUi/LstCard";
export default function Bookin() {
const [bookingIn, setBookingIn] = useState(false);
const form = useForm({
defaultValues: { runningNr: " " },
onSubmit: async ({ value }) => {
// Do something with form data
setBookingIn(true);
try {
const res = await axios.post("/lst/old/api/ocp/bookin", {
runningNr: parseInt(value.runningNr),
});
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setBookingIn(false);
} else {
console.log(res.data.data.errors);
toast.error(res.data.data.errors[0]?.message);
form.reset();
setBookingIn(false);
}
} catch (error) {
console.log(error);
toast.error(
"There was an error booking in pallet please validate you entered the correct info and try again.",
);
setBookingIn(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Book in a pallet by running number</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button onClick={form.handleSubmit} disabled={bookingIn}>
Book in
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -0,0 +1,123 @@
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { LstCard } from "../../../extendedUi/LstCard";
export default function Relocate() {
const [bookingIn, setBookingIn] = useState(false);
const form = useForm({
defaultValues: { runningNr: " ", lane: "" },
onSubmit: async ({ value }) => {
// Do something with form data
setBookingIn(true);
try {
const res = await axios.post("/lst/old/api/ocp/bookin", {
runningNr: parseInt(value.runningNr),
});
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setBookingIn(false);
} else {
console.log(res.data.data.errors);
toast.error(res.data.data.errors[0]?.message);
form.reset();
setBookingIn(false);
}
} catch (error) {
console.log(error);
toast.error(
"There was an error booking in pallet please validate you entered the correct info and try again.",
);
setBookingIn(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Relocate a pallet to another lane</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<form.Field
name="lane"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Enter lane
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button onClick={form.handleSubmit} disabled={bookingIn}>
Relocate
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -0,0 +1,128 @@
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { LstCard } from "../../../extendedUi/LstCard";
export default function RemoveAsNonReusable() {
const [stockOut, setStockOut] = useState(false);
const form = useForm({
defaultValues: { runningNr: " ", reason: " " },
onSubmit: async ({ value }) => {
// Do something with form data
setStockOut(true);
//console.log(value);
try {
const res = await axios.post(
"/lst/old/api/logistics/removeasreusable",
value, // this is basically the data field
);
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setStockOut(false);
} else {
console.log(res.data);
toast.error(res.data?.message);
form.reset();
setStockOut(false);
}
} catch (error: any) {
console.log(error);
toast.error(error.message);
setStockOut(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Remove a pallet as non reusable</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="w-96">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
required
type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<form.Field
name="reason"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 10
? undefined
: "Please enter a valid reason on why you needed to remove this pallet",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="reason" className="mb-2">
Reason for removing
</Label>
<Textarea
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<div className="text-pretty max-w-96">
<em>{field.state.meta.errors.join(",")}</em>
</div>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button onClick={form.handleSubmit} disabled={stockOut}>
Remove
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -0,0 +1,107 @@
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { LstCard } from "../../../extendedUi/LstCard";
export default function ConsumeMaterial() {
const { register: register1, handleSubmit: handleSubmit1, reset } = useForm();
const [submitting, setSubmitting] = useState(false);
const handleConsume = async (data: any) => {
setSubmitting(true);
try {
// const result = await axios.post(`/api/logistics/consume`, data, {
// headers: {Authorization: `Bearer ${token}`},
// });
const result = await axios.post(`/lst/old/api/logistics/consume`, data);
if (result.data.success) {
toast.success(result.data.message);
setSubmitting(false);
reset();
}
if (!result.data.success) {
//console.log(result.data);
setSubmitting(false);
toast.error(result.data.message);
}
} catch (error: any) {
console.log(error);
setSubmitting(false);
if (error.status === 401) {
toast.error("Unauthorized to do this task.");
} else {
toast.error(
"Unexpected error if this continues please constact an admin.",
);
}
}
};
return (
<div className="m-2">
<LstCard>
<CardHeader>
<p className="text-center text-lg">Consuming Material.</p>
</CardHeader>
<div className="flex m-1">
<div className="w-96 m-1">
<LstCard>
<form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2">
<Label htmlFor="runningNr">Enter unit running number</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("runningNr")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">Enter lot number</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Consume materal
</Button>
</form>
</LstCard>
</div>
<div className="m-1 p-1">
<LstCard>
<div className="w-96 p-1">
<ol>
<li>
1. Enter the running number of the material you would like
to consume
</li>
<li>2. Enter the lot number you will be consuming to</li>
<li>3. Press consume material</li>
</ol>
<p className="text-pretty w-96">
*This process is only for barcoded material, if it is set to
auto consume you will encounter and error.
</p>
</div>
</LstCard>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,144 @@
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { LstCard } from "../../../extendedUi/LstCard";
export default function PreformReturn() {
const { register: register1, handleSubmit: handleSubmit1, reset } = useForm();
const [submitting, setSubmitting] = useState(false);
const handleConsume = async (data: any) => {
setSubmitting(true);
try {
const result = await axios.post(
`/lst/old/auth/api/logistics/consume`,
data,
);
if (result.data.success) {
toast.success(result.data.message);
setSubmitting(false);
reset();
}
if (!result.data.success) {
//console.log(result.data);
setSubmitting(false);
toast.error(result.data.message);
}
} catch (error: any) {
//console.log(error);
setSubmitting(false);
if (error.status === 401) {
toast.error("Unauthorized to do this task.");
} else {
toast.error(
"Unexpected error if this continues please constact an admin.",
);
}
}
};
return (
<div className="m-2">
<LstCard>
<CardHeader>
<p className="text-center text-lg">Preform Return.</p>
</CardHeader>
<div className="flex m-1">
<div className="w-96 m-1">
<LstCard>
<form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2">
<Label htmlFor="runningNr">Enter unit running number</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("runningNr")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Enter the new wight of the gaylord of preforms
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select the printer you would like to print to
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select the staging location to be returned to.
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select type of material coming back.
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Preform return
</Button>
</form>
</LstCard>
</div>
<div className="m-1 p-1">
<LstCard>
<div className="w-96 p-1">
<ol>
<li>
1. Enter the running number of the preform cage you would
like to return
</li>
<li>2. Enter the new weight of the gaylord</li>
<li>3. Select the printer you would like to print to</li>
</ol>
<p className="text-pretty w-96">
*As soon as you press preform return it will print a new label
and return to the staging location.
</p>
</div>
</LstCard>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,348 @@
import axios from "axios";
import { Info } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useAppForm } from "@/lib/formStuff";
import { useSettingStore } from "@/routes/_old/old/-lib/store/useSettings";
import { LstCard } from "../../../extendedUi/LstCard";
export default function TransferToNextLot() {
const [gaylordFilled, setGaylordFilled] = useState([0]);
const [actualAmount, setActualAmount] = useState(0);
const [tab, setTab] = useState("esitmate");
const [typeSwitch, setTypeSwitch] = useState(false);
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "plantToken");
const form = useAppForm({
defaultValues: {
runningNumber: "",
lotNumber: "",
originalAmount: "",
amount: "",
},
onSubmit: async ({ value }) => {
//console.log(transferData);
//toast.success("603468: qty: 361, was transfered to lot:24897");
try {
const res = await axios.post("/lst/old/api/ocp/materiallottransfer", {
runningNumber: Number(value.runningNumber),
lotNumber: Number(value.lotNumber),
originalAmount: Number(value.originalAmount),
level: Number(
gaylordFilled.length === 1
? 0.25
: gaylordFilled.length === 2
? 0.5
: gaylordFilled.length === 3
? 0.75
: gaylordFilled.length === 4 && 0.95,
),
amount: actualAmount,
type: typeSwitch ? "eom" : "lot",
});
if (res.data.success) {
toast.success(`${res.data.message}`);
form.reset();
setGaylordFilled([0]);
setActualAmount(0);
}
//console.log(res.data);
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
if (error) {
console.log(error);
//toast.error(error)
}
}
},
});
return (
<div>
<LstCard>
<CardHeader>
<p className="text-center text-lg">Material Transfer to Next lot</p>
</CardHeader>
<div>
<div className="flex flex-wrap m-2 gap-2">
<div className="flex gap-2">
<div>
<LstCard className="">
<Tabs defaultValue={tab} onValueChange={setTab}>
<TabsList>
<TabsTrigger value="esitmate">
Estimate Amount
</TabsTrigger>
<TabsTrigger value="actual">Actual Amount</TabsTrigger>
</TabsList>
<TabsContent value="esitmate">
<div className="grid columns-1">
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(4) ? " bg-green-500" : ""
}`}
onClick={() => setGaylordFilled([1, 2, 3, 4])}
>
<p className="text-center">Almost full - 95%</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(3) ? " bg-green-500" : ""
}`}
onClick={() => setGaylordFilled([1, 2, 3])}
>
<p className="text-center">About full - 75%</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(2) ? " bg-green-500" : ""
}`}
onClick={() => setGaylordFilled([1, 2])}
>
<p className="text-center">Half full - 50%</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(1) ? " bg-green-500" : ""
}`}
onClick={() => setGaylordFilled(() => [1])}
>
<p className="text-center">Almost empty - 25%</p>
</button>
</div>
<div className="flex justify-end pr-1">
<Button onClick={() => setGaylordFilled([0])}>
Reset Gaylord
</Button>
</div>
</TabsContent>
<TabsContent value="actual" className="w-96">
<CardHeader>
<p>Enter the total amount of the cage/gaylord</p>
</CardHeader>
<CardContent>
<Input
type="number"
//placeholder="35"
onChange={(e) =>
setActualAmount(Number(e.target.value))
}
/>
</CardContent>
</TabsContent>
</Tabs>
</LstCard>
</div>
<div>
<div className="w-96">
<LstCard>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="mt-3 p-2">
<form.AppField
name="runningNumber"
children={(field) => (
<field.InputField
label="Running Number"
inputType="number"
required={true}
/>
)}
/>
</div>
<div className="mt-3 p-2">
<form.AppField
name="lotNumber"
children={(field) => (
<field.InputField
label="Lot Number"
inputType="number"
required={true}
/>
)}
/>
{tab !== "actual" && (
<div className="mt-3 p-2">
<form.AppField
name="originalAmount"
children={(field) => (
<field.InputField
label="Orignal Quantity"
inputType="number"
required={true}
/>
)}
/>
</div>
)}
</div>
<div className="flex justify-between p-2">
<div className="flex items-center space-x-2">
<Switch
checked={typeSwitch}
onCheckedChange={setTypeSwitch}
/>
<span>
{typeSwitch ? (
<div className="flex items-center space-x-2">
<span>"EOM Transfer"</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click the toggle if you will be
transfering at EOM, NOTE: This will
trigger the delayed transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
) : (
<div className="flex items-center space-x-2">
<span>"Lot Transfer"</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click the toggle if you will be
transferring at EOM, NOTE: This will
trigger the delayed transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
)}
</span>
</div>
<form.AppForm>
<form.SubmitButton>Transfer To Lot</form.SubmitButton>
</form.AppForm>
</div>
</form>
</LstCard>
</div>
</div>
</div>
<div>
<LstCard className="p-2">
<CardHeader>
<p className="text-center text-lg">
Moving material to the next lot.
</p>
</CardHeader>
{tab !== "actual" ? (
<div>
<ol>
<li>
1. Grab the gaylord running number from the gaylord at
the line/next to the tschritter
</li>
<li>
2. Grab the next lot number you are going to be running
(or the one that state no Main material prepared)
</li>
<li>
3. Enter the total gaylord weight (this is how much the
gaylord weighed when it came in from the supplier.)
</li>
<li>
4. *Click the level of the gaylord (this is just an
estimate to move to the next lot.)
</li>
<li>5. type in running number on the gaylord.</li>
<li>6. Type in the new lot number.</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
* to reduce the time needed to get the lot going we will
use an estimate of how full the gaylord is.
</p>
<p>
NOTE: This is not the return process, this process will
just get the gaylord to the next lot.
</p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions please{" "}
<a
href={`https://${server[0].value}prod.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div>
) : (
<div>
<ol>
<li>
1. Grab the gaylord running number from the gaylord at
the line/next to the tschritter
</li>
<li>
2. Grab the next lot number you are going to be running
(or the one that state no Main material prepared)
</li>
<li>3. Take the gaylord to the scale and weight it</li>
<li>
4. Enter the weight of the gaylord minus the tar weight.
</li>
<li>5. type in running number on the gaylord.</li>
<li>6. Type in the new lot number.</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
NOTE: This is not the return process, this process will
just get the gaylord to the next lot.
</p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions please{" "}
<a
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div>
)}
</LstCard>
</div>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,101 @@
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function ManuallyEnterRn() {
const [sending, setSendingRn] = useState(false);
const form = useForm({
defaultValues: {
runningNr: "",
},
onSubmit: async ({ value }) => {
console.log(value);
setSendingRn(true);
try {
const res = await axios.post("/ocme/api/v1/postRunningNumber", {
runningNr: value.runningNr,
areaFrom: "wrapper_1",
completed: true,
});
if (res.data.success) {
form.reset();
toast.success(`${value.runningNr} was just created please login`);
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
if (!res.data.success) {
toast.error(res.data.message);
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
} catch (error) {
//console.log(error);
toast.error("There was an error registering");
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
},
});
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
//e.stopPropagation();
}}
>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 3
? undefined
: "pallet number must be greater than 4 numbers",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
<div>
<Label htmlFor="runningNr" className="mb-2">
Running Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
<div className="ml-1 mt-5">
<Button
className="ml-1"
type="submit"
onClick={form.handleSubmit}
disabled={sending}
>
Submit
</Button>
</div>
</div>
);
}}
/>
</form>
</div>
);
}

View File

@@ -0,0 +1,165 @@
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { format } from "date-fns";
import { Trash } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getOcmeInfo } from "../../-utils/querys/ocp/getOcmeInfo";
import { LstCard } from "../extendedUi/LstCard";
import ManualTrigger from "../rfid/ManualTrigger";
const currentPallets = [
{ key: "line", label: "Line" },
{ key: "runningNumber", label: "Running #" },
{ key: "upd_date", label: "Date Scanned" },
{ key: "waitingfor", label: "Waiting For" },
{ key: "clear", label: "Clear" },
];
// const currentTags = [
// { key: "line", label: "Line" },
// { key: "printerName", label: "Printer" },
// { key: "runningNr", label: "Running #" },
// { key: "upd_date", label: "Label date" },
// { key: "status", label: "Label Status" },
// ];
export default function WrapperManualTrigger() {
const { data, isError, isLoading } = useQuery(getOcmeInfo());
const cameraTrigger = async () => {
try {
const res = await axios.get("/ocme/api/v1/manualCameraTrigger");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
const clearLabel = async (d: any) => {
const data = {
runningNr: d.runningNr,
};
try {
const res = await axios.patch("/ocme/api/v1/pickedUp", data);
if (res.data.success) {
toast.success(`${d.runningNr} was just removed from being picked up.`);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
if (isError) {
return (
<div>
<p className="text-center text-pretty">
There was an error getting wrapper scans
</p>
</div>
);
}
const info = data?.filter((r: any) => r.areaFrom === "wrapper_1");
return (
<LstCard className="m-2 p-2 w-auto">
<ScrollArea className="max-h-[200px]">
<span>Wrapper Pallet Info</span>
<div>
<Table>
<TableHeader>
<TableRow>
{currentPallets.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<TableBody>
{Array(3)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
) : (
<TableBody>
{info.map((i: any) => (
<TableRow key={i.runningNr}>
<TableCell className="font-medium">{i.lineNum}</TableCell>
<TableCell>{i.runningNr}</TableCell>
<TableCell>
{format(i?.upd_date.replace("Z", ""), "M/d/yyyy hh:mm")}
</TableCell>
<TableCell>{i.waitingFor}</TableCell>
<TableCell>
<Button
variant="destructive"
size="icon"
onClick={() => clearLabel(i)}
>
<Trash />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
)}
</Table>
</div>
</ScrollArea>
<div>
<hr />
{/* <p className="text-center mb-3">Manual Trigger</p>
<ManuallyEnterRn />
<Separator className="m-1" /> */}
<div className="flex flex-row justify-between m-2">
<Button onClick={cameraTrigger}>Camera</Button>
<ManualTrigger />
</div>
</div>
</LstCard>
);
}

View File

@@ -0,0 +1,229 @@
import axios from "axios";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { LstCard } from "@/components/ui/lstCard";
//import CycleCountLog from "./CycleCountLog";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
export default function OcmeCycleCount() {
const token = localStorage.getItem("auth_token");
const [data, setData] = useState([]);
const [counting, setCounting] = useState(false);
const {
register,
handleSubmit,
//watch,
formState: { errors },
reset,
control,
} = useForm({
defaultValues: {
lane: "",
laneType: "name",
},
});
const onSubmit = async (data: any) => {
setData([]);
setCounting(true);
if (data.laneType === "") {
toast.error("Please select a type");
setCounting(false);
return;
}
toast.success(`Cycle count started`);
try {
const res = await axios.post("/lst/old/ocme/api/v1/cycleCount", data, {
headers: { Authorization: `Bearer ${token}` },
});
if (res.data.success) {
toast.success(res.data.message);
setData(res.data.data);
setCounting(false);
reset();
}
if (!res.data.success) {
toast.success(res.data.message);
setCounting(false);
}
} catch (error) {
toast.error("There was an error cycle counting");
setCounting(false);
reset();
}
};
return (
<div className="flex flex-row w-screen">
<div className="m-2 w-5/6">
<LstCard>
<p className="ml-2">
Please enter the name or laneID you want to cycle count.
</p>
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex justify-between">
<div className="m-2 flex flex-row">
<Input
placeholder="enter lane: L064"
className={errors.lane ? "border-red-500" : ""}
aria-invalid={!!errors.lane}
{...register("lane", {
required: true,
minLength: {
value: 3,
message: "The lane is too short!",
},
})}
/>
<div className="ml-2">
<Controller
control={control}
name="laneType"
render={({
field: { onChange },
fieldState: {},
//formState,
}) => (
<Select onValueChange={onChange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select name or id" />
</SelectTrigger>
<SelectContent>
<SelectItem value="name">Name</SelectItem>
<SelectItem value="laneID">Lane ID</SelectItem>
</SelectContent>
</Select>
)}
/>
</div>
</div>
<Button className="m-2" type="submit" disabled={counting}>
{counting ? (
<span>Counting...</span>
) : (
<span>CycleCount</span>
)}
</Button>
</div>
</form>
</div>
<div>
<Table>
<TableHeader>
<TableRow>
<TableHead>LaneID</TableHead>
<TableHead>Lane</TableHead>
<TableHead>AV</TableHead>
<TableHead>Description</TableHead>
<TableHead>Running Number</TableHead>
<TableHead>In Ocme</TableHead>
<TableHead>In Stock</TableHead>
<TableHead>Result</TableHead>
</TableRow>
</TableHeader>
{data?.length === 0 ? (
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
) : (
<>
{data.map((i: any) => {
let classname = ``;
if (i.info === "Validate pallet is ok.") {
classname = `bg-red-500`;
}
if (i.info === "Sent to Inv") {
classname = `bg-amber-700`;
}
return (
<TableRow key={i.runningNumber}>
<TableCell className={`font-medium ${classname}`}>
{i.alpla_laneID}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.alpla_laneDescription}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.Article}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.alpla_laneDescription}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.runningNumber}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.ocme}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.stock}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
{i.info}
</TableCell>
</TableRow>
);
})}
</>
)}
</Table>
</div>
</LstCard>
</div>
{/* <div className="m-2">
<CycleCountLog />
</div> */}
</div>
);
}

View File

@@ -0,0 +1,24 @@
// import {useSessionStore} from "@/lib/store/sessionStore";
// import {useSettingStore} from "@/lib/store/useSettings";
import { useQuery } from "@tanstack/react-query";
import { getlabels } from "../../-utils/querys/ocp/labels";
import { labelolumns } from "../../-utils/tableData/production/labels/labelColumns";
import { LabelTable } from "../../-utils/tableData/production/labels/labelData";
export default function LabelLog() {
const { data, isError, isLoading } = useQuery(getlabels("4"));
if (isError) return <div>Error</div>;
if (isLoading) return <div>Loading</div>;
const labelData = data ? data : [];
return (
<div className="m-2">
<LabelTable
columns={labelolumns}
data={labelData}
//style={style}
/>
</div>
);
}

View File

@@ -0,0 +1,27 @@
import { useQuery } from "@tanstack/react-query";
import { getlabelRatio } from "../../-utils/querys/ocp/labelRatio";
import { labelRatioColumns } from "../../-utils/tableData/production/labelRatio/labelRatioColumns";
import { LabelRatioTable } from "../../-utils/tableData/production/labelRatio/labelRatioData";
export default function LabelRatio() {
const { data, isError, isLoading } = useQuery(getlabelRatio());
const ratioData = data ? data : [];
if (isError) {
return <div>Error</div>;
}
if (isLoading) {
return <div>Loading</div>;
}
return (
<div className="m-2">
<LabelRatioTable
columns={labelRatioColumns}
data={ratioData}
//style={style}
/>
</div>
);
}

View File

@@ -1,5 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { LstCard } from "@/components/extendedUI/LstCard";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import {
@@ -10,12 +10,11 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useSessionStore } from "@/lib/store/sessionStore";
import { useGetUserRoles } from "@/lib/store/useGetRoles";
import { useModuleStore } from "@/lib/store/useModuleStore";
import { useSettingStore } from "@/lib/store/useSettings";
import { LotType } from "@/types/lots";
import { getlots } from "@/utils/querys/production/lots";
import { useAuth, userAccess } from "@/lib/authClient";
import { useSettingStore } from "../../-lib/store/useSettings";
import type { LotType } from "../../-types/lots";
import { getlots } from "../../-utils/querys/ocp/lots";
import { LstCard } from "../extendedUi/LstCard";
import ManualPrint from "./ManualPrinting/ManualPrint";
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
@@ -67,23 +66,20 @@ let lotColumns = [
];
export default function Lots() {
const { data, isError, isLoading } = useQuery(getlots());
const { user } = useSessionStore();
const { session } = useAuth();
const { settings } = useSettingStore();
const { userRoles } = useGetUserRoles();
const { modules } = useModuleStore();
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
const roles = ["systemAdmin", "technician", "admin", "manager", "operator"];
const server = settings.filter((n) => n.name === "dbServer")[0]?.value || "";
const lotdata = data ? data : [];
const module = modules.filter((n) => n.name === "logistics");
const accessRoles = userAccess("ocp", [
"systemAdmin",
"technician",
"admin",
"manager",
]);
const accessRoles = userRoles.filter(
(n: any) => n.module === module[0]?.name,
) as any;
if (user && roles.includes(accessRoles[0]?.role)) {
if (session?.user && accessRoles) {
//width = 1280;
const checkCol = lotColumns.some((l) => l.key === "printLabel");
if (!checkCol) {
@@ -230,7 +226,7 @@ export default function Lots() {
<TableCell className="font-medium">
{lot.overPrinting}
</TableCell>
{user && roles.includes(accessRoles[0]?.role) && (
{session?.user && accessRoles && (
<>
{server === "usday1vms006" || server === "localhost" ? (
<>

View File

@@ -0,0 +1,46 @@
import { Button } from "@/components/ui/button";
//import {useSettingStore} from "@/lib/store/useSettings";
import { Tag } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { useAuth } from "@/lib/authClient";
import type { LotType } from "../../../-types/lots";
import { manualPrintLabels } from "./ManualPrintLabel";
export default function ManualPrint({ lot }: { lot: LotType }) {
const { session } = useAuth();
const [printing, setPrinting] = useState(false);
//const {settings} = useSettingStore();
//const server = settings.filter((n) => n.name === "server")[0]?.value;
//const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
//const serverUrl = `http://${server}:${serverPort}`;
const handlePrintLabel = async (lot: LotType) => {
const labels: any = await manualPrintLabels(lot, session?.user);
if (labels.success) {
toast.success(labels.message);
setTimeout(() => {
setPrinting(false);
}, 5 * 1000);
setPrinting(true);
} else {
toast.error(labels.message);
setTimeout(() => {
setPrinting(false);
}, 5 * 1000);
}
};
return (
<Button
variant="outline"
size="icon"
onClick={() => handlePrintLabel(lot)}
disabled={printing}
>
<Tag className="h-[16px] w-[16px]" />
</Button>
);
}

View File

@@ -0,0 +1,256 @@
import axios from "axios";
import { Tag } from "lucide-react";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "sonner";
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 {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { useSettingStore } from "../../../-lib/store/useSettings";
const printReason = [
{ key: "printerIssue", label: "Printer Related" },
{ key: "missingRfidTag", label: "Missing or incorrect tag" },
{ key: "rfidMissScan", label: "Missed Scan from RFID reader" },
{ key: "strapper", label: "Strapper Error" },
{ key: "manualCheck", label: "20th pallet check" },
{ key: "outOfSync", label: "Labeler Out of Sync" },
];
export default function ManualPrintForm() {
const token = localStorage.getItem("auth_token");
const { settings } = useSettingStore();
const [open, setOpen] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const server = settings.filter((n) => n.name === "server")[0]?.value;
// const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
// const serverUrl = `http://${server}:${serverPort}`;
// what is the dyco set to? rfid or dyco
const dyco = settings.filter((n) => n.name === "dycoPrint");
const {
register,
handleSubmit,
//watch,
formState: { errors },
reset,
control,
} = useForm();
const handleManualPrintLog = async (logData: any) => {
// toast.success(`A new label was sent to printer: ${lot.PrinterName} for line ${lot.MachineDescription} `);
const logdataUrl = `/lst/old/api/ocp/manuallabellog`;
setIsSubmitting(true);
axios
.post(logdataUrl, logData, {
headers: { Authorization: `Bearer ${token}` },
})
.then((d) => {
console.log(d);
if (d.data.success) {
toast.success(d.data.message);
} else {
toast.error(d.data.message);
}
reset();
setOpen(false);
setIsSubmitting(false);
})
.catch((e) => {
if (e.response.status === 500) {
toast.error(`Internal Server error please try again.`);
setIsSubmitting(false);
return { sucess: false };
}
if (e.response.status === 401) {
//console.log(e.response);
toast.error(`You are not authorized to do this.`);
setIsSubmitting(false);
return { sucess: false };
}
});
};
const onSubmit = (data: any) => {
console.log(data);
handleManualPrintLog(data);
};
const closeForm = () => {
reset();
setOpen(false);
};
return (
<Dialog
open={open}
onOpenChange={(isOpen) => {
if (!open) {
reset();
}
setOpen(isOpen);
// toast.message("Model was something", {
// description: isOpen ? "Modal is open" : "Modal is closed",
// });
}}
>
<DialogTrigger asChild>
<Button variant="outline" size="icon">
<Tag className="h-[16px] w-[16px]" />
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Manual Print form</DialogTitle>
{/* <DialogDescription>
Make changes to your profile here. Click save when
you're done.
</DialogDescription> */}
</DialogHeader>
<form onSubmit={handleSubmit(onSubmit)}>
<p>
To manually print a label you must complete all the required fields
below.
<br />
If you clicked this in error just click close
</p>
<hr className="mt-2 mb-2" />
{server == "usday1vms006" ? (
<Controller
control={control}
name="printReason"
defaultValue={""}
render={({
field: { onChange },
fieldState: {},
//formState,
}) => (
<Select onValueChange={onChange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select Reason" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Print Reasons</SelectLabel>
{printReason.map((printReason: any) => (
<SelectItem value={printReason.key}>
{printReason.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
)}
/>
) : (
<div className="m-2">
<Label htmlFor="printRason" className="m-1">
Why are you manually printing?
</Label>
<Input
type="text"
className={errors.printReason ? "border-red-500" : ""}
aria-invalid={!!errors.printReason}
{...register("printReason", {
required: true,
minLength: {
value: 5,
message: "To short of a reason please try again!",
},
})}
/>
</div>
)}
<div className="m-2">
<Label htmlFor="line" className="m-1">
"What is the line number you are printing?"
</Label>
<Input
//variant="underlined"
type="number"
className={errors.line ? "border-red-500" : ""}
aria-invalid={!!errors.line}
{...register("line", { required: true })}
/>
</div>
<div className="m-2">
<Label htmlFor="initials" className="m-1">
Enter intials
</Label>
<Input
//variant="underlined"
//label="Enter intials"
{...register("initials", { required: true })}
/>
</div>
<hr />
{dyco[0].value === "0" && (
<div>
<p>Enter the missing tag number.</p>
<hr />
<Label htmlFor="rfidTag" className="m-1">
Enter the tag number only Example ALPLA000002541. only enter
2541
</Label>
<Input
type="text"
className={errors.printReason ? "border-red-500" : ""}
aria-invalid={!!errors.printReason}
{...register("rfidTag", {
required: true,
minLength: {
value: 1,
message: "Tag number is to short!",
},
})}
/>
</div>
)}
<div className="m-2">
<Textarea
//label="Comments"
placeholder="add more info as needed."
{
...register("additionalComments")
// { required: true, minLength: 10 }
}
/>
</div>
<DialogFooter>
<div className="mt-3">
<Button color="danger" variant="default" onClick={closeForm}>
Close
</Button>
<Button color="primary" type="submit" disabled={isSubmitting}>
Print
</Button>
</div>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}

View File

@@ -0,0 +1,44 @@
import axios from "axios";
import type { LotType } from "../../../-types/lots";
export const manualPrintLabels = async (lot: LotType, user: any) => {
//console.log(lot);
const labelUrl = `/lst/old/api/ocp/manualprintandfollow`;
try {
const res = await axios.post(
labelUrl,
{ line: lot.MachineLocation, printerName: lot.PrinterName },
{ headers: { Authorization: `Basic ${user?.prod}` } },
);
if (res.data.success) {
return {
success: true,
message: `A new label was printed for ${lot.MachineDescription} to printer: ${lot.PrinterName}`,
};
} else {
return {
success: false,
message: `Line ${lot.MachineDescription} encountered an error printing labels: ${res.data.message}`,
};
}
} catch (error: any) {
if (error.response.status === 500) {
//toast.error(`Internal Server error please try again.`);
return {
success: false,
message: `Internal Server error please try again.`,
};
}
if (error.response.status === 401) {
//console.log(e.response);
//toast.error(`You are not authorized to do this.`);
return {
success: false,
message: `You are not authorized to do this.`,
};
}
}
};

View File

@@ -0,0 +1,46 @@
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { useMemo } from "react";
import { toast } from "sonner";
import { getOcpLogs } from "../../-utils/querys/ocp/ocpLogs";
import { ocpColumns } from "../../-utils/tableData/production/ocpLogs/ocpLogColumns";
import { OcpLogTable } from "../../-utils/tableData/production/ocpLogs/ocpLogData";
export default function OcpLogs() {
const { data, isError, isLoading } = useQuery(getOcpLogs("4"));
const clearLog = async (log: any) => {
try {
const res = await axios.patch(`/lst/old/api/logger/logs/${log.log_id}`);
if (res.data.success) {
toast.success(`Log message: ${log.message}, was just cleared`);
} else {
console.log(res);
toast.error(`There was an error clearing the message.`);
}
} catch (error) {
toast.error(`There was an error trying to clearing the message.`);
}
};
const columns = useMemo(() => ocpColumns(clearLog), [clearLog]);
const logData = data ? data : [];
if (isError) {
return <div>Error</div>;
}
if (isLoading) {
return <div>Loading</div>;
}
return (
<div className="m-2">
<OcpLogTable
columns={columns}
data={logData}
//style={style}
/>
</div>
);
}

View File

@@ -0,0 +1,134 @@
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
import { useSettingStore } from "../../-lib/store/useSettings";
import WrapperManualTrigger from "../ocme/WrapperCard";
import LabelLog from "./LabelLog";
import LabelRatio from "./LabelRatio";
import Lots from "./Lots";
import OcpLogs from "./OcpLogs";
import PrinterStatus from "./PrinterStatus";
export default function OCPPage() {
const { settings } = useSettingStore();
if (settings.length === 0) return;
let token = settings.filter((n) => n.name === "plantToken");
return (
<div className="ml-5 w-11/12 h-9/10">
<ResizablePanelGroup
direction="horizontal"
//className="rounded-lg border"
autoSaveId="ocpPage"
>
<ResizablePanel>
<ResizablePanelGroup direction="vertical">
<ResizablePanel
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
>
<Lots />
</ResizablePanel>
<ResizableHandle />
<ResizablePanel>
<ResizablePanelGroup direction="horizontal" autoSaveId="ocpPage">
<ResizablePanel
//className="text-sm p-4 overflow-scroll"
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
>
<LabelLog />
</ResizablePanel>
<ResizableHandle />
<ResizablePanel
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
>
<OcpLogs />
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel className="min-h-[200px] min-w-[200px] max-w-[450px]">
<ResizablePanelGroup direction="vertical" autoSaveId="ocpPage_vert">
{token[0].value === "usday1vms006" ||
(location.pathname === "localhost" && (
<ResizablePanel
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
defaultSize={50}
className="min-h-[200px]"
>
<WrapperManualTrigger />
</ResizablePanel>
))}
<ResizableHandle />
<ResizablePanel>
<PrinterStatus />
<LabelRatio />
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>
</ResizablePanelGroup>
</div>
);
// return (
// <div className="h-screen w-full ">
// <div className="flex flex-row gap-2">
// <div className="flex flex-col w-4/5 h-dvh">
// <div className="">
// <Lots />
// </div>
// <div className="w-5/6 h-1/2">
// <Tabs defaultValue="ocplogs" className="w-full">
// <TabsList className="grid w-full grid-cols-2">
// <TabsTrigger value="ocplogs">
// OcpLogs
// </TabsTrigger>
// <TabsTrigger value="labels">Labels</TabsTrigger>
// </TabsList>
// <TabsContent value="ocplogs">
// <div className="w-full">
// <OcpLogs />
// </div>
// </TabsContent>
// <TabsContent value="labels">
// <LabelLog />
// </TabsContent>
// </Tabs>
// </div>
// </div>
// <div className="flex flex-col">
// {server[0].value === "usday1vms006" && (
// <div>
// <WrapperManualTrigger />
// </div>
// )}
// {server[0].value === "localhost" && (
// <div>
// <WrapperManualTrigger />
// </div>
// )}
// <div>
// <PrinterStatus />
// </div>
// </div>
// </div>
// </div>
// );
}

View File

@@ -0,0 +1,114 @@
import { useQuery } from "@tanstack/react-query";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getPrinters } from "../../-utils/querys/ocp/printers";
import { LstCard } from "../extendedUi/LstCard";
let printerCols = [
{
key: "printer",
label: "Printer",
},
{
key: "statusMessage",
label: "Status Message",
},
];
export default function PrinterStatus() {
const { data, isError, isLoading } = useQuery(getPrinters());
if (isError) {
return (
<ScrollArea className="h-[400px]">
<p className="text-center">Printer Staus error</p>
<Table>
<TableHeader>
<TableRow>
{printerCols.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(5)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
);
}
/**
* only show the assigned printers
*/
const assigned = data?.filter((a: any) => a.assigned) || [];
return (
<LstCard className="m-2 p-2">
<ScrollArea className="max-h-[800px]">
<p className="text-center">
{isLoading ? (
<span>Printers status loading...</span>
) : (
<span>Printer Status</span>
)}
</p>
<Table>
<TableHeader>
<TableRow>
{printerCols.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<TableBody>
{Array(5)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
) : (
<TableBody>
{assigned?.map((p: any) => (
<TableRow key={p.printer_id}>
<TableCell>{p.name}</TableCell>
<TableCell>{p.statusText}</TableCell>
</TableRow>
))}
</TableBody>
)}
</Table>
</ScrollArea>
</LstCard>
);
}

View File

@@ -0,0 +1,30 @@
import axios from "axios";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
export default function ManualTrigger() {
const rfidReaderTrigger = async () => {
try {
const res = await axios.post("/lst/old/api/rfid/manualtrigger/wrapper1");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
return (
<div>
<Button onClick={rfidReaderTrigger}>Wrapper 1 RFID</Button>
</div>
);
}

View File

@@ -0,0 +1,28 @@
import { useQuery } from "@tanstack/react-query";
import { getReaders } from "../../-utils/querys/rfid/getReaders";
import { readerColumns } from "../../-utils/tableData/rfid/readers/readerColumns";
import { ReaderTable } from "../../-utils/tableData/rfid/readers/readerData";
export default function RfidPage() {
const { data, isError, isLoading } = useQuery(getReaders());
if (isError) {
return <div>Error</div>;
}
if (isLoading) {
return <div>Loading</div>;
}
return (
<div className="m-2">
<ReaderTable
columns={readerColumns}
data={data.data.sort((a: any, b: any) =>
a.reader.localeCompare(b.reader),
)}
//style={style}
/>
</div>
);
}

View File

@@ -2,24 +2,24 @@ 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: 1000 * 60 * 15,
refetchOnWindowFocus: true,
});
return queryOptions({
queryKey: ["getInvCheck"],
queryFn: () => fetchStockSilo(data),
//enabled:
staleTime: 1000,
refetchInterval: 1000 * 60 * 15,
refetchOnWindowFocus: true,
});
}
const fetchStockSilo = async (info: any) => {
//console.log("What tpye of info:", info);
const { data } = await axios.post(`/api/logistics/cyclecountcheck`, {
age: info.age ? parseInt(info.age) : null,
type: "",
});
//console.log("What tpye of info:", info);
const { data } = await axios.post(`/lst/old/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 ?? [];
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -2,21 +2,21 @@ import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOpenOrders() {
return queryOptions({
queryKey: ["getOpenOrders"],
queryFn: () => fetchStockSilo(),
//enabled:
staleTime: 1000,
refetchInterval: 1000 * 60 * 15,
refetchOnWindowFocus: true,
});
return queryOptions({
queryKey: ["getOpenOrders"],
queryFn: () => fetchStockSilo(),
//enabled:
staleTime: 1000,
refetchInterval: 1000 * 60 * 15,
refetchOnWindowFocus: true,
});
}
const fetchStockSilo = async () => {
const { data } = await axios.get(
`/api/datamart/getopenorders?sDay=15&eDay=45`
);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
const { data } = await axios.get(
`/lst/old/api/datamart/getopenorders?sDay=15&eDay=45`,
);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -2,19 +2,19 @@ import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getLanes() {
return queryOptions({
queryKey: ["getLanes"],
queryFn: () => fetch(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
return queryOptions({
queryKey: ["getLanes"],
queryFn: () => fetch(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
}
const fetch = async () => {
const { data } = await axios.get(`/api/logistics/getactivelanes`);
// // if we are not localhost ignore the devDir setting.
// //const url: string = window.location.host.split(":")[0];
return data.data ?? [];
const { data } = await axios.get(`/lst/old/api/logistics/getactivelanes`);
// // if we are not localhost ignore the devDir setting.
// //const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,19 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOcmeInfo() {
return queryOptions({
queryKey: ["ocmeInfo"],
queryFn: () => fetchSettings(),
staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/lst/old/ocme/api/v1/getInfo`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabelRatio() {
return queryOptions({
queryKey: ["labelRatio"],
queryFn: () => fetchSettings(),
//staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/lst/old/api/ocp/labelratio`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabels(hours: string) {
return queryOptions({
queryKey: ["labels"],
queryFn: () => fetchSettings(hours),
//staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async (hours: string) => {
const { data } = await axios.get(`/lst/old/api/ocp/getlabels?hours=${hours}`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,21 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlots() {
return queryOptions({
queryKey: ["lots"],
queryFn: () => fetchSettings(),
staleTime: 10 * 1000,
refetchInterval: 1000 * 10,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get("/lst/old/api/ocp/getlots");
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
let lotData = data.data;
return lotData ?? [];
};

View File

@@ -0,0 +1,22 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOcpLogs(hours: string) {
return queryOptions({
queryKey: ["ocpLogs"],
queryFn: () => fetchSettings(hours),
staleTime: 1000,
refetchInterval: 2 * 1000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async (hours: string) => {
const { data } = await axios.get(
`/lst/old/api/logger/logs?service=ocp&service=rfid&service=dyco&level=error&level=warn&hours=${hours}`,
);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getPrinters() {
return queryOptions({
queryKey: ["printers"],
queryFn: () => fetchSettings(),
staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/lst/old/api/ocp/getprinters`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,19 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOcmeInfo() {
return queryOptions({
queryKey: ["ocmeInfo"],
queryFn: () => fetchSettings(),
staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/ocme/api/v1/getInfo`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,20 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabelRatio() {
return queryOptions({
queryKey: ["labelRatio"],
queryFn: () => fetchSettings(),
//staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/api/ocp/labelratio`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,20 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabels(hours: string) {
return queryOptions({
queryKey: ["labels"],
queryFn: () => fetchSettings(hours),
//staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async (hours: string) => {
const { data } = await axios.get(`/api/ocp/getlabels?hours=${hours}`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,21 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlots() {
return queryOptions({
queryKey: ["lots"],
queryFn: () => fetchSettings(),
staleTime: 10 * 1000,
refetchInterval: 1000 * 10,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get("/api/ocp/getlots");
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
let lotData = data.data;
return lotData ?? [];
};

View File

@@ -1,22 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getOcpLogs(hours: string) {
return queryOptions({
queryKey: ["ocpLogs"],
queryFn: () => fetchSettings(hours),
staleTime: 1000,
refetchInterval: 2 * 1000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async (hours: string) => {
const { data } = await axios.get(
`/api/logger/logs?service=ocp&service=rfid&service=dyco&level=error&level=warn&hours=${hours}`
);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,20 +0,0 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getPrinters() {
return queryOptions({
queryKey: ["printers"],
queryFn: () => fetchSettings(),
staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/api/ocp/getprinters`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -2,19 +2,19 @@ import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getReaders() {
return queryOptions({
queryKey: ["getReaders"],
queryFn: () => fetchReaders(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
return queryOptions({
queryKey: ["getReaders"],
queryFn: () => fetchReaders(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
}
const fetchReaders = async () => {
const { data } = await axios.get(`/api/rfid/getreaders`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
const { data } = await axios.get(`/lst/old/api/rfid/getreaders`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -1,9 +1,26 @@
import { createFileRoute } from "@tanstack/react-router";
import { AddCards } from "./-components/dashboard/AddCards";
import DashBoard from "./-components/dashboard/Dashboard";
import { useCardStore } from "./-lib/store/useCardStore";
export const Route = createFileRoute("/_old/old/")({
component: RouteComponent,
});
function RouteComponent() {
return <div>Missing DashBoard</div>;
const { cards } = useCardStore();
return (
<div>
{cards.length > 0 ? (
<DashBoard />
) : (
<div className="m-3">
<span>
Looks like you have no cards added try clicking adding some
</span>{" "}
<AddCards />
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import OCPPage from "../-components/ocp/OcpPage";
export const Route = createFileRoute("/_old/old/ocp/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div className="h-dvh w-dvw">
<OCPPage />
</div>
);
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import RfidPage from "../-components/rfid/RfidPage";
export const Route = createFileRoute("/_old/old/rfid/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<RfidPage />
</div>
);
}

View File

@@ -1,5 +1,6 @@
import { createFileRoute, Link, Outlet } from "@tanstack/react-router";
import Cookies from "js-cookie";
import { Button } from "@/components/ui/button";
import { ModeToggle } from "../../../components/mode-toggle";
import {
Avatar,
@@ -18,6 +19,7 @@ import { SidebarProvider } from "../../../components/ui/sidebar";
import { useAuth, useLogout } from "../../../lib/authClient";
import { AddCards } from "./-components/dashboard/AddCards";
import { AppSidebar } from "./-components/layout/lst-sidebar";
import DMButtons from "./-components/logistics/dm/DMButtons";
export const Route = createFileRoute("/_old/old")({
component: RouteComponent,
@@ -28,21 +30,23 @@ function RouteComponent() {
const { session } = useAuth();
const logout = useLogout();
//const { settings } = useSettingStore();
//console.log(location.pathname);
return (
<div>
<nav className="flex justify-end w-full shadow ">
<div className="m-2 flex flex-row">
{/* Inventory section */}
{location.pathname === "/" && (
<div className="m-auto pr-2 flex flex-row gap-2">
{/* <ExportInventoryData /> */}
<AddCards />
</div>
)}
{location.pathname === "/lst/app/old" ||
(location.pathname === "/lst/app/old/" && (
<div className="m-auto pr-2 flex flex-row gap-2">
{/* <ExportInventoryData /> */}
<AddCards />
</div>
))}
{/* Demand mgt section this should also include plant token stuff */}
{location.pathname === "/dm" && (
{location.pathname === "/lst/app/old/dm" && (
<div className="m-auto pr-2 flex flex-row gap-2">
{/* <DMButtons /> */}
<DMButtons />
</div>
)}
<div className="m-1">
@@ -58,7 +62,9 @@ function RouteComponent() {
</a>
)}
</div> */}
<Button className="m-1">
<Link to="/">New Version</Link>
</Button>
{session ? (
<div className="m-1">
<DropdownMenu>
@@ -79,9 +85,7 @@ function RouteComponent() {
<DropdownMenuItem>
{/* <Link to="/passwordChange">Password Change</Link> */}
</DropdownMenuItem>
<DropdownMenuItem>
<Link to="/">New Version</Link>
</DropdownMenuItem>
{/* <DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuItem>Subscription</DropdownMenuItem> */}
@@ -95,9 +99,9 @@ function RouteComponent() {
</DropdownMenu>
</div>
) : (
<div>
<Button className="m-1">
<Link to="/login">Login</Link>
</div>
</Button>
)}
</div>
</nav>

View File

@@ -5,7 +5,6 @@
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}

View File

@@ -62,6 +62,11 @@ export default defineConfig({
changeOrigin: true,
//rewrite: (path) => path.replace(/^\/lst\/d/, "/"),
},
"/ocme": {
target: `http://localhost:${Number(process.env.VITE_PORT || 4000)}`,
changeOrigin: true,
secure: false,
},
},
},
});

View File

@@ -1,33 +0,0 @@
// 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;

View File

@@ -1,47 +0,0 @@
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import Cards from "./Cards";
//import { toast } from "sonner";
export function AddCards() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Add Cards</Button>
</DialogTrigger>
<DialogContent className="min-w-fit ">
<DialogHeader>
<DialogTitle>Cards</DialogTitle>
<DialogDescription>
Manage Cards and there settings.
</DialogDescription>
</DialogHeader>
<div className="flex flex-row">
<div className="">
<Cards name={"ppoo"} inventory />
<Cards name={"inv-empty"} rowType={"empty"} />
<Cards name={"inv-fg"} rowType={"fg"} />
</div>
<div className="">
<Cards name={"inv-materials"} rowType={"materials"} />
<Cards name={"inv-packaging"} rowType={"packaging"} />
<Cards name={"inv-waste"} rowType={"waste"} />
<Cards name={"openOrder"} inventory />
</div>
</div>
{/* <DialogFooter>
<Button type="submit">Save changes</Button>
</DialogFooter> */}
</DialogContent>
</Dialog>
);
}

View File

@@ -1,108 +0,0 @@
import { useCardStore } from "@/lib/store/useCardStore";
import { Label } from "../ui/label";
import { Checkbox } from "../ui/checkbox";
import { Button } from "../ui/button";
import { useAppForm } from "@/utils/formStuff";
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 = useAppForm({
defaultValues: {
name: existing[0]?.name || card.name,
rowType: existing[0]?.type ?? card.rowType,
age: existing[0]?.age ?? 90,
active: existing[0]?.active ?? false,
},
onSubmit: async ({ value }) => {
console.log(value);
const testCard: any = cards.filter(
(i: any) => i.name === value.name
);
if (value.active) {
const newCard = {
name: `${value.name}`,
rowType: value.rowType,
age: value.age ?? 90,
active: value.active,
};
if (testCard.length > 0) {
removeCard(value.name);
addCard(newCard);
return;
}
// change the name for a type card
addCard(newCard);
} else {
removeCard(value.name);
}
},
});
return (
<div className="border-solid border-2 m-2">
<p>{card.name}</p>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
className="flex flex-row"
>
<form.AppField
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.AppField
name="age"
children={(field) => (
<field.InputField
label="Age"
inputType="number"
required={true}
/>
)}
/>
</>
)}
<div className="mt-7">
<Button type="submit" onClick={() => form.handleSubmit()}>
Save Card
</Button>
</div>
</form>
</div>
);
}

View File

@@ -1,84 +0,0 @@
import { useCardStore } from "@/lib/store/useCardStore";
import INVCheckCard from "../logistics/warehouse/InventoryCard";
import PPOO from "../logistics/warehouse/PPOOCard";
import OpenOrders from "../logistics/warehouse/openOrders";
const componentsMap: any = {
ppoo: PPOO,
inv: INVCheckCard,
openOrder: OpenOrders,
//QualityRequest,
};
export default function DashBoard() {
const { cards } = useCardStore();
//console.log(cards);
return (
<div className="ml-5 w-11/12 h-9/10 grid grid-cols-12 gap-1">
{cards.map((a: any) => {
const name = a.name; //.filter((c) => c.i === card.i)[0].i || "name";
const Component = componentsMap[name.split("-")[0]];
if (name === "openOrder") {
return (
<div key={a.name} className="col-span-6">
<Component age={a.age} type={a.rowType} />
</div>
);
} else {
//console.log(name.split("-")[0], a);
return (
<div key={a.name} className="col-span-3">
<Component data={a} />
</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>
*/

View File

@@ -1,165 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible";
import { getLanes } from "@/utils/querys/logistics/getWarehouseLanes";
import { CollapsibleTrigger } from "@radix-ui/react-collapsible";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
import Barcode from "react-barcode";
import { BarcodePDFExport } from "./BarcodeExport";
import { BulkBarcodePDFExport } from "./BulkExport";
import CommonCommands from "./CommonCommands";
export default function BGPage() {
const { data, isError, isLoading } = useQuery(getLanes());
const [checked, setChecked] = useState([]);
if (isLoading) return <div>Loading Data</div>;
if (isError)
return <div>There was an error getting the warehouse lane data.</div>;
/**
* get the warehouse names only
*/
const warhouses = new Map();
data?.forEach((item: any) => {
// if the warhouse is not already included add it to the map
if (!warhouses.has(item.warehouseId)) {
warhouses.set(item.warehouseId, item.warehouseDescription);
}
});
// convert the map to an array
const warehouseArray = Array.from(warhouses).map(([wid, wname]) => ({
warehouseId: wid,
warehouseDescription: wname,
}));
//console.log(warehouseArray);
// handle the onchange
const changeBox = (d: any) => {
setChecked((prev: any) => {
if (prev.includes(d)) {
return prev.filter((name: any) => name !== d);
} else {
return [...prev, d];
}
});
};
return (
<div className="flex flex-row m-2">
<div className="flex flex-row">
<div className="m-2">
<LstCard>
<CardHeader>Warehouse Barcodes</CardHeader>
<CardContent>
{warehouseArray.map((i: any) => {
const lanes = data?.filter(
(wid: any) =>
wid.warehouseId === i.warehouseId
);
return (
<div className="m-2" key={i.warehouseId}>
<Collapsible>
<CollapsibleTrigger>
{i.warehouseDescription}
</CollapsibleTrigger>
<CollapsibleContent>
<div className="ml-2">
{lanes?.map((l: any) => {
return (
<div key={l.laneId}>
<Checkbox
id={
l.laneId
}
// checked={checked.includes(
// l
// )}
onCheckedChange={() =>
changeBox(
l
)
}
/>
<label
id={
l.laneId
}
className="ml-2"
>
{
l.laneDescription
}
</label>
</div>
);
})}
</div>
</CollapsibleContent>
</Collapsible>
</div>
);
})}
</CardContent>
</LstCard>
</div>
{checked.length > 0 && (
<div className="m-2">
<LstCard>
<CardHeader>Current selected lanes</CardHeader>
<CardContent>
{checked.map((c: any) => {
return (
<div
className="flex justify-center"
key={`${c.warehouseId}-${c.laneId}`}
>
<div>
<Barcode
value={`loc#${c.warehouseId}#${c.laneId}`}
width={2}
height={50}
displayValue={false}
/>
<p className="flex justify-center">
Lane: {c.laneDescription}
</p>
</div>
<div className="ml-2 mt-4">
<BarcodePDFExport
barcodeValue={`loc#${c.warehouseId}#${c.laneId}`}
data={c}
/>
</div>
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex justify-end">
{checked.length > 1 && (
<div>
<BulkBarcodePDFExport
data={checked}
/>
</div>
)}
</div>
</CardFooter>
</LstCard>
</div>
)}
</div>
<div className="m-2">
<CommonCommands />
</div>
</div>
);
}

View File

@@ -1,127 +0,0 @@
import { Button } from "@/components/ui/button";
import {
pdf,
Page,
Text,
View,
Document,
StyleSheet,
Image,
} from "@react-pdf/renderer";
import JsBarcode from "jsbarcode";
export const BulkBarcodePDFExport = ({ data }: { data: any }) => {
const createBarcode = (barcodeValue: any) => {
//const barcodeValue = data; // Barcode value
const canvas = document.createElement("canvas");
// Generate barcode on the canvas
JsBarcode(canvas, barcodeValue, {
format: "CODE128",
displayValue: false,
});
// Convert canvas to base64 image data
const barcodeImage = canvas.toDataURL("image/png");
return barcodeImage;
};
const generatePDF = () => {
// Define the document styles using @react-pdf/renderer
const styles = StyleSheet.create({
page: {
padding: 30,
},
centerContent: {
display: "flex",
justifyContent: "flex-start", // Center horizontally
alignItems: "center", // Center vertically
flexDirection: "row", // Stack items (barcode and description) vertically
//height: "5%", // Ensure the container takes full page height
textAlign: "center",
},
section: {
marginBottom: 10,
textAlign: "center",
},
barcode: {
width: 275, // Width of the barcode
height: 75, // Height of the barcode
marginBottom: 10,
},
description: {
fontSize: 14,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
},
headerText: {
fontSize: 28,
fontWeight: "bold",
marginTop: 10,
marginBottom: 20, // Ensure there's space below the text
display: "flex",
justifyContent: "center",
//height: "15%", // Ensure the container takes full page height
textAlign: "center",
},
horizontalLine: {
borderBottom: "#000000",
borderBottomWidth: 1,
},
});
// Create the document
const MyDocument = (
<Document>
<Page style={styles.page} orientation="portrait" size="A4">
<View style={styles.headerText}>
<Text>Multi Lane export.</Text>
</View>
<View style={styles.horizontalLine} />
{data.map((i: any, index: any) => {
return (
<View style={styles.centerContent} key={index}>
<View style={styles.section}>
<Image
src={createBarcode(
`loc#${i.warehouseId}#${i.laneId}`
)}
style={styles.barcode}
/>
</View>
<View style={styles.section}>
<Text style={styles.description}>
Lane: {i.laneDescription}
</Text>
</View>
</View>
);
})}
</Page>
</Document>
);
// Generate the PDF and trigger download
pdf(MyDocument)
.toBlob()
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = `MultipleBarcodes.pdf`;
link.click();
});
};
return (
<div>
<Button onClick={() => generatePDF()} color="primary">
Export All Selected
</Button>
</div>
);
};

View File

@@ -1,107 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { useState } from "react";
import Barcode from "react-barcode";
import { BarcodePDFExport } from "./BarcodeExport";
import { BulkBarcodePDFExport } from "./BulkExport";
const commoncmd = [
{ name: "Relocate", commandId: 33 },
//-{ name: "Stock in", commandId: 22 },
];
export default function CommonCommands() {
const [checked, setChecked] = useState([]);
// handle the onchange
const changeBox = (d: any) => {
setChecked((prev: any) => {
if (prev.includes(d)) {
return prev.filter((name: any) => name !== d);
} else {
return [...prev, d];
}
});
};
return (
<div>
<div>
<LstCard>
<CardHeader>Common Barcodes</CardHeader>
<CardContent>
{commoncmd.map((i: any) => {
return (
<div className="flex flex-row">
<div>
<Checkbox
id={i.commandId}
// checked={checked.includes(
// l
// )}
onCheckedChange={() => changeBox(i)}
/>
<label
id={i.commandId}
className="ml-2"
>
{i.name}
</label>
</div>
</div>
);
})}
</CardContent>
</LstCard>
</div>
<div>
{checked.length > 0 && (
<div className="m-2">
<LstCard>
<CardHeader>Current selected Barcodes</CardHeader>
<CardContent>
{checked.map((c: any) => {
return (
<div
className="flex justify-center"
key={`${c.name}`}
>
<div>
<Barcode
value={`AlplaPRODcmd${c.commandId}`}
width={2}
height={50}
displayValue={false}
/>
<p className="flex justify-center">
Bacrode: {c.name}
</p>
</div>
<div className="ml-2 mt-4">
<BarcodePDFExport
barcodeValue={`AlplaPRODcmd${c.commandId}`}
data={c}
/>
</div>
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex justify-end">
{checked.length > 1 && (
<div>
<BulkBarcodePDFExport
data={checked}
/>
</div>
)}
</div>
</CardFooter>
</LstCard>
</div>
)}
</div>
</div>
);
}

View File

@@ -1,100 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
export default function Bookin() {
const [bookingIn, setBookingIn] = useState(false);
const form = useForm({
defaultValues: { runningNr: " " },
onSubmit: async ({ value }) => {
// Do something with form data
setBookingIn(true);
try {
const res = await axios.post("/api/ocp/bookin", {
runningNr: parseInt(value.runningNr),
});
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setBookingIn(false);
} else {
console.log(res.data.data.errors);
toast.error(res.data.data.errors[0]?.message);
form.reset();
setBookingIn(false);
}
} catch (error) {
console.log(error);
toast.error(
"There was an error booking in pallet please validate you entered the correct info and try again."
);
setBookingIn(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Book in a pallet by running number</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>
{field.state.meta.errors.join(",")}
</em>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button
onClick={form.handleSubmit}
disabled={bookingIn}
>
Book in
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -1,133 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
export default function Relocate() {
const [bookingIn, setBookingIn] = useState(false);
const form = useForm({
defaultValues: { runningNr: " ", lane: "" },
onSubmit: async ({ value }) => {
// Do something with form data
setBookingIn(true);
try {
const res = await axios.post("/api/ocp/bookin", {
runningNr: parseInt(value.runningNr),
});
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setBookingIn(false);
} else {
console.log(res.data.data.errors);
toast.error(res.data.data.errors[0]?.message);
form.reset();
setBookingIn(false);
}
} catch (error) {
console.log(error);
toast.error(
"There was an error booking in pallet please validate you entered the correct info and try again."
);
setBookingIn(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Relocate a pallet to another lane</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>
{field.state.meta.errors.join(",")}
</em>
) : null}
</div>
);
}}
/>
<form.Field
name="lane"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Enter lane
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>
{field.state.meta.errors.join(",")}
</em>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button
onClick={form.handleSubmit}
disabled={bookingIn}
>
Relocate
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -1,138 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { useForm } from "@tanstack/react-form";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
export default function RemoveAsNonReusable() {
const [stockOut, setStockOut] = useState(false);
const form = useForm({
defaultValues: { runningNr: " ", reason: " " },
onSubmit: async ({ value }) => {
// Do something with form data
setStockOut(true);
//console.log(value);
try {
const res = await axios.post(
"/api/logistics/removeasreusable",
value // this is basically the data field
);
if (res.data.success) {
toast.success(res.data.message);
form.reset();
setStockOut(false);
} else {
console.log(res.data);
toast.error(res.data?.message);
form.reset();
setStockOut(false);
}
} catch (error: any) {
console.log(error);
toast.error(error.message);
setStockOut(false);
}
},
});
return (
<LstCard>
<CardHeader>
<p>Remove a pallet as non reusable</p>
</CardHeader>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<CardContent>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
}}
children={(field) => {
return (
<div className="w-96">
<Label htmlFor="runningNr" className="mb-2">
Runnning Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
required
type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>
{field.state.meta.errors.join(",")}
</em>
) : null}
</div>
);
}}
/>
<form.Field
name="reason"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 10
? undefined
: "Please enter a valid reason on why you needed to remove this pallet",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="reason" className="mb-2">
Reason for removing
</Label>
<Textarea
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<div className="text-pretty max-w-96">
<em>
{field.state.meta.errors.join(
","
)}
</em>
</div>
) : null}
</div>
);
}}
/>
<div className="flex mt-2 justify-end">
<Button onClick={form.handleSubmit} disabled={stockOut}>
Remove
</Button>
</div>
</CardContent>
</form>
</LstCard>
);
}

View File

@@ -1,121 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
export default function ConsumeMaterial() {
const {
register: register1,
handleSubmit: handleSubmit1,
reset,
} = useForm();
const [submitting, setSubmitting] = useState(false);
const handleConsume = async (data: any) => {
setSubmitting(true);
try {
// const result = await axios.post(`/api/logistics/consume`, data, {
// headers: {Authorization: `Bearer ${token}`},
// });
const result = await axios.post(`/api/logistics/consume`, data);
if (result.data.success) {
toast.success(result.data.message);
setSubmitting(false);
reset();
}
if (!result.data.success) {
//console.log(result.data);
setSubmitting(false);
toast.error(result.data.message);
}
} catch (error: any) {
console.log(error);
setSubmitting(false);
if (error.status === 401) {
toast.error("Unauthorized to do this task.");
} else {
toast.error(
"Unexpected error if this continues please constact an admin."
);
}
}
};
return (
<div className="m-2">
<LstCard>
<CardHeader>
<p className="text-center text-lg">Consuming Material.</p>
</CardHeader>
<div className="flex m-1">
<div className="w-96 m-1">
<LstCard>
<form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2">
<Label htmlFor="runningNr">
Enter unit running number
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("runningNr")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Enter lot number
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Consume materal
</Button>
</form>
</LstCard>
</div>
<div className="m-1 p-1">
<LstCard>
<div className="w-96 p-1">
<ol>
<li>
1. Enter the running number of the
material you would like to consume
</li>
<li>
2. Enter the lot number you will be
consuming to
</li>
<li>3. Press consume material</li>
</ol>
<p className="text-pretty w-96">
*This process is only for barcoded material,
if it is set to auto consume you will
encounter and error.
</p>
</div>
</LstCard>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -1,160 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useSessionStore } from "@/lib/store/sessionStore";
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
export default function PreformReturn() {
const {
register: register1,
handleSubmit: handleSubmit1,
reset,
} = useForm();
const [submitting, setSubmitting] = useState(false);
const { token } = useSessionStore();
const handleConsume = async (data: any) => {
setSubmitting(true);
try {
const result = await axios.post(`/api/logistics/consume`, data, {
headers: { Authorization: `Bearer ${token}` },
});
if (result.data.success) {
toast.success(result.data.message);
setSubmitting(false);
reset();
}
if (!result.data.success) {
//console.log(result.data);
setSubmitting(false);
toast.error(result.data.message);
}
} catch (error: any) {
//console.log(error);
setSubmitting(false);
if (error.status === 401) {
toast.error("Unauthorized to do this task.");
} else {
toast.error(
"Unexpected error if this continues please constact an admin."
);
}
}
};
return (
<div className="m-2">
<LstCard>
<CardHeader>
<p className="text-center text-lg">Preform Return.</p>
</CardHeader>
<div className="flex m-1">
<div className="w-96 m-1">
<LstCard>
<form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2">
<Label htmlFor="runningNr">
Enter unit running number
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("runningNr")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Enter the new wight of the gaylord of
preforms
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select the printer you would like to
print to
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select the staging location to be
returned to.
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">
Select type of material coming back.
</Label>
<Input
className="mt-2"
//defaultValue="634"
type="number"
{...register1("lotNum")}
/>
</div>
<Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Preform return
</Button>
</form>
</LstCard>
</div>
<div className="m-1 p-1">
<LstCard>
<div className="w-96 p-1">
<ol>
<li>
1. Enter the running number of the
preform cage you would like to return
</li>
<li>
2. Enter the new weight of the gaylord
</li>
<li>
3. Select the printer you would like to
print to
</li>
</ol>
<p className="text-pretty w-96">
*As soon as you press preform return it will
print a new label and return to the staging
location.
</p>
</div>
</LstCard>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -1,478 +0,0 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useAppForm } from "@/utils/formStuff";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Info } from "lucide-react";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useSettingStore } from "@/lib/store/useSettings";
export default function TransferToNextLot() {
const [gaylordFilled, setGaylordFilled] = useState([0]);
const [actualAmount, setActualAmount] = useState(0);
const [tab, setTab] = useState("esitmate");
const [typeSwitch, setTypeSwitch] = useState(false);
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "plantToken");
const form = useAppForm({
defaultValues: {
runningNumber: "",
lotNumber: "",
originalAmount: "",
amount: "",
},
onSubmit: async ({ value }) => {
//console.log(transferData);
//toast.success("603468: qty: 361, was transfered to lot:24897");
try {
const res = await axios.post("/api/ocp/materiallottransfer", {
runningNumber: Number(value.runningNumber),
lotNumber: Number(value.lotNumber),
originalAmount: Number(value.originalAmount),
level: Number(
gaylordFilled.length === 1
? 0.25
: gaylordFilled.length === 2
? 0.5
: gaylordFilled.length === 3
? 0.75
: gaylordFilled.length === 4 && 0.95
),
amount: actualAmount,
type: typeSwitch ? "eom" : "lot",
});
if (res.data.success) {
toast.success(`${res.data.message}`);
form.reset();
setGaylordFilled([0]);
setActualAmount(0);
}
//console.log(res.data);
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
if (error) {
console.log(error);
//toast.error(error)
}
}
},
});
return (
<div>
<LstCard>
<CardHeader>
<p className="text-center text-lg">
Material Transfer to Next lot
</p>
</CardHeader>
<div>
<div className="flex flex-wrap m-2 gap-2">
<div className="flex gap-2">
<div>
<LstCard className="">
<Tabs
defaultValue={tab}
onValueChange={setTab}
>
<TabsList>
<TabsTrigger value="esitmate">
Estimate Amount
</TabsTrigger>
<TabsTrigger value="actual">
Actual Amount
</TabsTrigger>
</TabsList>
<TabsContent value="esitmate">
<div className="grid columns-1">
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
4
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([
1, 2, 3, 4,
])
}
>
<p className="text-center">
Almost full - 95%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
3
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([
1, 2, 3,
])
}
>
<p className="text-center">
About full - 75%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
2
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([1, 2])
}
>
<p className="text-center">
Half full - 50%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
1
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled(() => [
1,
])
}
>
<p className="text-center">
Almost empty - 25%
</p>
</button>
</div>
<div className="flex justify-end pr-1">
<Button
onClick={() =>
setGaylordFilled([0])
}
>
Reset Gaylord
</Button>
</div>
</TabsContent>
<TabsContent
value="actual"
className="w-96"
>
<CardHeader>
<p>
Enter the total amount of
the cage/gaylord
</p>
</CardHeader>
<CardContent>
<Input
type="number"
//placeholder="35"
onChange={(e) =>
setActualAmount(
Number(
e.target.value
)
)
}
/>
</CardContent>
</TabsContent>
</Tabs>
</LstCard>
</div>
<div>
<div className="w-96">
<LstCard>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="mt-3 p-2">
<form.AppField
name="runningNumber"
children={(field) => (
<field.InputField
label="Running Number"
inputType="number"
required={true}
/>
)}
/>
</div>
<div className="mt-3 p-2">
<form.AppField
name="lotNumber"
children={(field) => (
<field.InputField
label="Lot Number"
inputType="number"
required={true}
/>
)}
/>
{tab !== "actual" && (
<div className="mt-3 p-2">
<form.AppField
name="originalAmount"
children={(
field
) => (
<field.InputField
label="Orignal Quantity"
inputType="number"
required={
true
}
/>
)}
/>
</div>
)}
</div>
<div className="flex justify-between p-2">
<div className="flex items-center space-x-2">
<Switch
checked={typeSwitch}
onCheckedChange={
setTypeSwitch
}
/>
<span>
{typeSwitch ? (
<div className="flex items-center space-x-2">
<span>
"EOM
Transfer"
</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click
the
toggle
if
you
will
be
transfering
at
EOM,
NOTE:
This
will
trigger
the
delayed
transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
) : (
<div className="flex items-center space-x-2">
<span>
"Lot
Transfer"
</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click
the
toggle
if
you
will
be
transferring
at
EOM,
NOTE:
This
will
trigger
the
delayed
transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
)}
</span>
</div>
<form.AppForm>
<form.SubmitButton>
Transfer To Lot
</form.SubmitButton>
</form.AppForm>
</div>
</form>
</LstCard>
</div>
</div>
</div>
<div>
<LstCard className="p-2">
<CardHeader>
<p className="text-center text-lg">
Moving material to the next lot.
</p>
</CardHeader>
{tab !== "actual" ? (
<div>
<ol>
<li>
1. Grab the gaylord running
number from the gaylord at the
line/next to the tschritter
</li>
<li>
2. Grab the next lot number you
are going to be running (or the
one that state no Main material
prepared)
</li>
<li>
3. Enter the total gaylord
weight (this is how much the
gaylord weighed when it came in
from the supplier.)
</li>
<li>
4. *Click the level of the
gaylord (this is just an
estimate to move to the next
lot.)
</li>
<li>
5. type in running number on the
gaylord.
</li>
<li>
6. Type in the new lot number.
</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
* to reduce the time needed to get
the lot going we will use an
estimate of how full the gaylord is.
</p>
<p>
NOTE: This is not the return
process, this process will just get
the gaylord to the next lot.
</p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions
please{" "}
<a
href={`https://${server[0].value}prod.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div>
) : (
<div>
<ol>
<li>
1. Grab the gaylord running
number from the gaylord at the
line/next to the tschritter
</li>
<li>
2. Grab the next lot number you
are going to be running (or the
one that state no Main material
prepared)
</li>
<li>
3. Take the gaylord to the scale
and weight it
</li>
<li>
4. Enter the weight of the
gaylord minus the tar weight.
</li>
<li>
5. type in running number on the
gaylord.
</li>
<li>
6. Type in the new lot number.
</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
NOTE: This is not the return
process, this process will just get
the gaylord to the next lot.
</p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions
please{" "}
<a
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div>
)}
</LstCard>
</div>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -1,3 +0,0 @@
export default function MaterialHelperPage() {
return <div>materialHelperPage</div>;
}

View File

@@ -1,31 +0,0 @@
import { Button } from "@/components/ui/button";
import axios from "axios";
import { toast } from "sonner";
export default function ManualTrigger() {
const rfidReaderTrigger = async () => {
try {
const res = await axios.post("/api/rfid/manualtrigger/wrapper1");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
return (
<div>
<Button onClick={rfidReaderTrigger}>Wrapper 1 RFID</Button>
</div>
);
}

View File

@@ -1,106 +0,0 @@
import { useForm } from "@tanstack/react-form";
import { Input } from "../ui/input";
import { Label } from "../ui/label";
import axios from "axios";
import { toast } from "sonner";
import { Button } from "../ui/button";
import { useState } from "react";
export default function ManuallyEnterRn() {
const [sending, setSendingRn] = useState(false);
const form = useForm({
defaultValues: {
runningNr: "",
},
onSubmit: async ({ value }) => {
console.log(value);
setSendingRn(true);
try {
const res = await axios.post("/ocme/api/v1/postRunningNumber", {
runningNr: value.runningNr,
areaFrom: "wrapper_1",
completed: true,
});
if (res.data.success) {
form.reset();
toast.success(
`${value.runningNr} was just created please login`
);
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
if (!res.data.success) {
toast.error(res.data.message);
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
} catch (error) {
//console.log(error);
toast.error("There was an error registering");
setTimeout(() => {
setSendingRn(false);
}, 3 * 1000);
}
},
});
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
//e.stopPropagation();
}}
>
<form.Field
name="runningNr"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 3
? undefined
: "pallet number must be greater than 4 numbers",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
<div>
<Label htmlFor="runningNr" className="mb-2">
Running Number
</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>
{field.state.meta.errors.join(",")}
</em>
) : null}
</div>
<div className="ml-1 mt-5">
<Button
className="ml-1"
type="submit"
onClick={form.handleSubmit}
disabled={sending}
>
Submit
</Button>
</div>
</div>
);
}}
/>
</form>
</div>
);
}

Some files were not shown because too many files have changed in this diff Show More