feat(frontend): migrated old > new silo adjustments
moved the apps around so we can use 1 url for cors bs
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
import { LstCard } from "../../../components/ui/lstCard";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../components/ui/card";
|
||||
import { useAppForm } from "../../../lib/formStuff";
|
||||
import { api } from "../../../lib/axiosAPI";
|
||||
import { toast } from "sonner";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
export default function RequestResetPassword() {
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
email: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await api.post("api/user/resetpassword", {
|
||||
email: value.email,
|
||||
});
|
||||
|
||||
console.log(res);
|
||||
|
||||
if (res.status === 200) {
|
||||
toast.success(
|
||||
res.data.message
|
||||
? res.data.message
|
||||
: "If this email exists in our system, check your email for the reset link"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Reset your password</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email address and we’ll send you a reset link
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<form.AppField
|
||||
name="email"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Email address"
|
||||
inputType="email"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>
|
||||
Send Reset Link
|
||||
</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Remembered your password?{" "}
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Back to login
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
import { useAppForm } from "../../../lib/formStuff";
|
||||
import { LstCard } from "../../../components/ui/lstCard";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../components/ui/card";
|
||||
import { api } from "../../../lib/axiosAPI";
|
||||
import { toast } from "sonner";
|
||||
import { Link, useNavigate } from "@tanstack/react-router";
|
||||
|
||||
export default function ResetPasswordForm({ token }: { token: string }) {
|
||||
const navigate = useNavigate();
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
if (value.password != value.confirmPassword) {
|
||||
toast.error("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.post("/api/auth/reset-password", {
|
||||
newPassword: value.password,
|
||||
token: token,
|
||||
});
|
||||
if (res.status === 200) {
|
||||
toast.success("Password has been reset");
|
||||
form.reset();
|
||||
navigate({ to: "/login" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// @ts-ignore
|
||||
toast.error(error?.response.data.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Set a new password</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your new password below and confirm it to continue
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<form.AppField
|
||||
name="password"
|
||||
children={(field) => (
|
||||
<field.InputPasswordField
|
||||
label="New Password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<form.AppField
|
||||
name="confirmPassword"
|
||||
// validators={{
|
||||
// onChangeListenTo: ["password"],
|
||||
// onChange: ({ value, fieldApi }) => {
|
||||
// if (
|
||||
// value !==
|
||||
// fieldApi.form.getFieldValue("password")
|
||||
// ) {
|
||||
// return "Passwords do not match";
|
||||
// }
|
||||
// return undefined;
|
||||
// },
|
||||
// }}
|
||||
children={(field) => (
|
||||
<field.InputPasswordField
|
||||
label="Confirm Password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>
|
||||
Reset Password
|
||||
</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Remembered your account?{" "}
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Back to login
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../components/ui/card";
|
||||
import { LstCard } from "../../../components/ui/lstCard";
|
||||
import { api } from "../../../lib/axiosAPI";
|
||||
import { useAppForm } from "../../../lib/formStuff";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
export default function SignupForm() {
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
username: "",
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
if (value.password != value.confirmPassword) {
|
||||
toast.error("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.post("/api/user/register", {
|
||||
username: value.username,
|
||||
name: value.username,
|
||||
email: value.email,
|
||||
password: value.password,
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
toast.success(`Welcome ${value.username}, to lst.`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// @ts-ignore
|
||||
toast.error(error?.response.data.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Create an account</CardTitle>
|
||||
<CardDescription>
|
||||
Fill in your details to get started
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
{/* Username */}
|
||||
<form.AppField
|
||||
name="username"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Username"
|
||||
inputType="text"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Email */}
|
||||
<form.AppField
|
||||
name="email"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Email address"
|
||||
inputType="email"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Password */}
|
||||
<form.AppField
|
||||
name="password"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Password"
|
||||
inputType="password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Confirm Password */}
|
||||
<form.AppField
|
||||
name="confirmPassword"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Confirm Password"
|
||||
inputType="password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Sign Up</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Already have an account?{" "}
|
||||
<Link
|
||||
to={"/login"}
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Log in
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { z } from "zod";
|
||||
import { authClient } from "../../lib/authClient";
|
||||
import LoginForm from "./-components/LoginForm";
|
||||
|
||||
export const Route = createFileRoute("/(auth)/login")({
|
||||
component: RouteComponent,
|
||||
validateSearch: z.object({
|
||||
redirect: z.string().optional(),
|
||||
}),
|
||||
beforeLoad: async () => {
|
||||
const result = await authClient.getSession({
|
||||
query: { disableCookieCache: true }, // force DB/Server lookup
|
||||
});
|
||||
|
||||
//console.log("session check:", result.data);
|
||||
|
||||
if (result.data) {
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div className="ml-[25%] mt-[0.5%]">
|
||||
<LoginForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,12 +6,8 @@ import {
|
||||
} from "@tanstack/react-router";
|
||||
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
||||
import mobile from "is-mobile";
|
||||
import Cookies from "js-cookie";
|
||||
import { useEffect } from "react";
|
||||
import { Toaster } from "sonner";
|
||||
import Nav from "../components/navBar/Nav";
|
||||
import SideBarNav from "../components/navBar/SideBarNav";
|
||||
import { SidebarProvider } from "../components/ui/sidebar";
|
||||
import { userAccess } from "../lib/authClient";
|
||||
import { SessionGuard } from "../lib/providers/SessionProvider";
|
||||
import { ThemeProvider } from "../lib/providers/theme-provider";
|
||||
@@ -26,7 +22,7 @@ interface RootRouteContext {
|
||||
|
||||
const RootLayout = () => {
|
||||
//const { logout, login } = Route.useRouteContext();
|
||||
const defaultOpen = Cookies.get("sidebar_state") === "true";
|
||||
|
||||
const router = useRouter();
|
||||
// console.log(mobile({ featureDetect: true, tablet: true }));
|
||||
|
||||
@@ -54,22 +50,13 @@ const RootLayout = () => {
|
||||
<div>
|
||||
<SessionGuard>
|
||||
<ThemeProvider>
|
||||
<div className="flex flex-col h-screen overflow-hidden">
|
||||
<Nav />
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
<SidebarProvider defaultOpen={defaultOpen}>
|
||||
<SideBarNav />
|
||||
|
||||
<div className="flex-2 overflow-y-auto">
|
||||
<Outlet />
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
</div>
|
||||
<Toaster expand richColors closeButton />
|
||||
{userAccess(null, ["systemAdmin"]) && (
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
)}
|
||||
<div className="flex-2 overflow-y-auto">
|
||||
<Outlet />
|
||||
</div>
|
||||
<Toaster expand richColors closeButton />
|
||||
{userAccess(null, ["systemAdmin"]) && (
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
)}
|
||||
</ThemeProvider>
|
||||
</SessionGuard>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
import { checkUserAccess } from "../../lib/authClient";
|
||||
|
||||
export const Route = createFileRoute("/_adminLayout")({
|
||||
beforeLoad: async () =>
|
||||
checkUserAccess({
|
||||
allowedRoles: ["admin", "systemAdmin"],
|
||||
moduleName: "admin", // optional
|
||||
}),
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,14 +6,14 @@ import {
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../components/ui/card";
|
||||
import { LstCard } from "../../../components/ui/lstCard";
|
||||
import { getSession, useAuth, useUserRoles } from "../../../lib/authClient";
|
||||
import { useAppForm } from "../../../lib/formStuff";
|
||||
} from "../../../../components/ui/card";
|
||||
import { LstCard } from "../../../../components/ui/lstCard";
|
||||
import { getSession, useAuth, useUserRoles } from "../../../../lib/authClient";
|
||||
import { useAppForm } from "../../../../lib/formStuff";
|
||||
|
||||
export default function LoginForm() {
|
||||
const router = useRouter();
|
||||
const search = useSearch({ from: "/(auth)/login" });
|
||||
const search = useSearch({ from: "/_app/(auth)/login" });
|
||||
const username = localStorage.getItem("username") || "";
|
||||
const rememberMe = localStorage.getItem("rememberMe") === "true";
|
||||
const { setSession } = useAuth();
|
||||
@@ -0,0 +1,86 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/lib/axiosAPI";
|
||||
import { useAppForm } from "@/lib/formStuff";
|
||||
import { LstCard } from "@/routes/_old/old/-components/extendedUi/LstCard";
|
||||
|
||||
export default function RequestResetPassword() {
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
email: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await api.post("api/user/resetpassword", {
|
||||
email: value.email,
|
||||
});
|
||||
|
||||
console.log(res);
|
||||
|
||||
if (res.status === 200) {
|
||||
toast.success(
|
||||
res.data.message
|
||||
? res.data.message
|
||||
: "If this email exists in our system, check your email for the reset link",
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Reset your password</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email address and we’ll send you a reset link
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<form.AppField
|
||||
name="email"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Email address"
|
||||
inputType="email"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Send Reset Link</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Remembered your password?{" "}
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Back to login
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { Link, useNavigate } from "@tanstack/react-router";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { LstCard } from "@/components/ui/lstCard";
|
||||
import { api } from "@/lib/axiosAPI";
|
||||
import { useAppForm } from "@/lib/formStuff";
|
||||
|
||||
export default function ResetPasswordForm({ token }: { token: string }) {
|
||||
const navigate = useNavigate();
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
if (value.password != value.confirmPassword) {
|
||||
toast.error("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.post("/api/auth/reset-password", {
|
||||
newPassword: value.password,
|
||||
token: token,
|
||||
});
|
||||
if (res.status === 200) {
|
||||
toast.success("Password has been reset");
|
||||
form.reset();
|
||||
navigate({ to: "/login" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// @ts-ignore
|
||||
toast.error(error?.response.data.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Set a new password</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your new password below and confirm it to continue
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<form.AppField
|
||||
name="password"
|
||||
children={(field) => (
|
||||
<field.InputPasswordField
|
||||
label="New Password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<form.AppField
|
||||
name="confirmPassword"
|
||||
// validators={{
|
||||
// onChangeListenTo: ["password"],
|
||||
// onChange: ({ value, fieldApi }) => {
|
||||
// if (
|
||||
// value !==
|
||||
// fieldApi.form.getFieldValue("password")
|
||||
// ) {
|
||||
// return "Passwords do not match";
|
||||
// }
|
||||
// return undefined;
|
||||
// },
|
||||
// }}
|
||||
children={(field) => (
|
||||
<field.InputPasswordField
|
||||
label="Confirm Password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Reset Password</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Remembered your account?{" "}
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Back to login
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
127
frontend/src/routes/_app/(auth)/-components/SignupForm.tsx
Normal file
127
frontend/src/routes/_app/(auth)/-components/SignupForm.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/lib/axiosAPI";
|
||||
import { useAppForm } from "@/lib/formStuff";
|
||||
import { LstCard } from "@/routes/_old/old/-components/extendedUi/LstCard";
|
||||
|
||||
export default function SignupForm() {
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
username: "",
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
if (value.password != value.confirmPassword) {
|
||||
toast.error("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.post("/api/user/register", {
|
||||
username: value.username,
|
||||
name: value.username,
|
||||
email: value.email,
|
||||
password: value.password,
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
toast.success(`Welcome ${value.username}, to lst.`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// @ts-ignore
|
||||
toast.error(error?.response.data.message);
|
||||
}
|
||||
},
|
||||
});
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard className="p-6 w-96">
|
||||
<CardHeader>
|
||||
<CardTitle>Create an account</CardTitle>
|
||||
<CardDescription>Fill in your details to get started</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
{/* Username */}
|
||||
<form.AppField
|
||||
name="username"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Username"
|
||||
inputType="text"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Email */}
|
||||
<form.AppField
|
||||
name="email"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Email address"
|
||||
inputType="email"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Password */}
|
||||
<form.AppField
|
||||
name="password"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Password"
|
||||
inputType="password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Confirm Password */}
|
||||
<form.AppField
|
||||
name="confirmPassword"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Confirm Password"
|
||||
inputType="password"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end mt-6">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Sign Up</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-600">
|
||||
Already have an account?{" "}
|
||||
<Link
|
||||
to={"/login"}
|
||||
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
||||
>
|
||||
Log in
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
30
frontend/src/routes/_app/(auth)/login.tsx
Normal file
30
frontend/src/routes/_app/(auth)/login.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { z } from "zod";
|
||||
import { authClient } from "../../../lib/authClient";
|
||||
import LoginForm from "./-components/LoginForm";
|
||||
|
||||
export const Route = createFileRoute("/_app/(auth)/login")({
|
||||
component: RouteComponent,
|
||||
validateSearch: z.object({
|
||||
redirect: z.string().optional(),
|
||||
}),
|
||||
beforeLoad: async () => {
|
||||
const result = await authClient.getSession({
|
||||
query: { disableCookieCache: true }, // force DB/Server lookup
|
||||
});
|
||||
|
||||
//console.log("session check:", result.data);
|
||||
|
||||
if (result.data) {
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div className="ml-[25%] mt-[0.5%]">
|
||||
<LoginForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(auth)/user/")({
|
||||
export const Route = createFileRoute("/_app/(auth)/user/")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -9,5 +9,5 @@ function RouteComponent() {
|
||||
<div>
|
||||
<span>Nothing here </span>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { authClient, useAuth } from "../../../lib/authClient";
|
||||
import { authClient, useAuth } from "../../../../lib/authClient";
|
||||
|
||||
export const Route = createFileRoute("/(auth)/user/profile")({
|
||||
export const Route = createFileRoute("/_app/(auth)/user/profile")({
|
||||
beforeLoad: async () => {
|
||||
const result = await authClient.getSession({
|
||||
query: { disableCookieCache: true }, // force DB/Server lookup
|
||||
@@ -3,7 +3,7 @@ import z from "zod";
|
||||
import RequestResetPassword from "../-components/RequestResetPassword";
|
||||
import ResetPasswordForm from "../-components/ResetPasswordForm";
|
||||
|
||||
export const Route = createFileRoute("/(auth)/user/resetpassword")({
|
||||
export const Route = createFileRoute("/_app/(auth)/user/resetpassword")({
|
||||
// beforeLoad: ({ search }) => {
|
||||
// return { token: search.token };
|
||||
// },
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import SignupForm from "../-components/SignupForm";
|
||||
|
||||
export const Route = createFileRoute("/(auth)/user/signup")({
|
||||
export const Route = createFileRoute("/_app/(auth)/user/signup")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/routes/traffic/Grid.tsx
|
||||
import { format } from "date-fns";
|
||||
import React from "react";
|
||||
import { ScrollArea, ScrollBar } from "../../../components/ui/scroll-area";
|
||||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
|
||||
|
||||
export const days = Array.from(
|
||||
{ length: 5 },
|
||||
@@ -1,19 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { coreSocket } from "../../../lib/socket.io/socket";
|
||||
import "../-components/style.css";
|
||||
import { coreSocket } from "../../../../lib/socket.io/socket";
|
||||
|
||||
export const Route = createFileRoute("/(logistics)/logistics/deliverySchedule")(
|
||||
{
|
||||
beforeLoad: async () => {
|
||||
coreSocket.emit("joinScheduler", "scheduler");
|
||||
// coreSocket.on("scheduler", (p) => {
|
||||
// console.log(`[scheduler] received:`, p);
|
||||
// });
|
||||
},
|
||||
component: RouteComponent,
|
||||
export const Route = createFileRoute(
|
||||
"/_app/(logistics)/logistics/deliverySchedule",
|
||||
)({
|
||||
beforeLoad: async () => {
|
||||
coreSocket.emit("joinScheduler", "scheduler");
|
||||
// coreSocket.on("scheduler", (p) => {
|
||||
// console.log(`[scheduler] received:`, p);
|
||||
// })
|
||||
},
|
||||
);
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
// connect to the channel
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../../../components/ui/select";
|
||||
import { api } from "../../../lib/axiosAPI";
|
||||
} from "../../../../components/ui/select";
|
||||
import { api } from "../../../../lib/axiosAPI";
|
||||
|
||||
const modules: string[] = [
|
||||
"users",
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/_adminLayout/admin/_users/prodUsers')({
|
||||
export const Route = createFileRoute('/_app/_adminLayout/admin/_users/prodUsers')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute, Link, Outlet } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/_adminLayout/admin/_users")({
|
||||
export const Route = createFileRoute("/_app/_adminLayout/admin/_users")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { Button } from "../../../../../components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
@@ -28,8 +28,8 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../../../components/ui/table";
|
||||
import { getUsers } from "../../../../lib/querys/admin/getUsers";
|
||||
} from "../../../../../components/ui/table";
|
||||
import { getUsers } from "../../../../../lib/querys/admin/getUsers";
|
||||
import ExpandedRow from "../../-components/ExpandedRow";
|
||||
|
||||
type User = {
|
||||
@@ -38,7 +38,7 @@ type User = {
|
||||
roles: string | null;
|
||||
};
|
||||
|
||||
export const Route = createFileRoute("/_adminLayout/admin/_users/users")({
|
||||
export const Route = createFileRoute("/_app/_adminLayout/admin/_users/users")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -147,7 +147,7 @@ function RouteComponent() {
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div>
|
||||
<div className="w-1/2">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
@@ -195,24 +195,24 @@ function RouteComponent() {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/_adminLayout/admin/servers')({
|
||||
export const Route = createFileRoute('/_app/_adminLayout/admin/servers')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/_adminLayout/admin/settings')({
|
||||
export const Route = createFileRoute('/_app/_adminLayout/admin/settings')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
19
frontend/src/routes/_app/_adminLayout/route.tsx
Normal file
19
frontend/src/routes/_app/_adminLayout/route.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
import { checkUserAccess } from "../../../lib/authClient";
|
||||
|
||||
export const Route = createFileRoute("/_app/_adminLayout")({
|
||||
beforeLoad: async () =>
|
||||
checkUserAccess({
|
||||
allowedRoles: ["admin", "systemAdmin"],
|
||||
moduleName: "admin", // optional
|
||||
}),
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<div>
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
frontend/src/routes/_app/index.tsx
Normal file
16
frontend/src/routes/_app/index.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
|
||||
export const Route = createFileRoute("/_app/")({
|
||||
component: Index,
|
||||
});
|
||||
|
||||
function Index() {
|
||||
return (
|
||||
<div>
|
||||
<div className="h-screen flex flex-col items-center justify-center">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
29
frontend/src/routes/_app/route.tsx
Normal file
29
frontend/src/routes/_app/route.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
import Cookies from "js-cookie";
|
||||
import Nav from "../../components/navBar/Nav";
|
||||
import SideBarNav from "../../components/navBar/SideBarNav";
|
||||
import { SidebarProvider } from "../../components/ui/sidebar";
|
||||
|
||||
export const Route = createFileRoute("/_app")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const defaultOpen = Cookies.get("sidebar_state") === "true";
|
||||
return (
|
||||
<div className="flex flex-col h-screen overflow-hidden">
|
||||
<div className="flex flex-col h-screen overflow-hidden">
|
||||
<Nav />
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
<SidebarProvider defaultOpen={defaultOpen}>
|
||||
<SideBarNav />
|
||||
|
||||
<div className="flex-2 overflow-y-auto">
|
||||
<Outlet />
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute(
|
||||
'/(mobileStuff)/_mobileLayout/m/cyclecounts',
|
||||
'/_mobile/_mobileLayout/m/cyclecounts',
|
||||
)({
|
||||
component: RouteComponent,
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/(mobileStuff)/_mobileLayout/m/delivery')(
|
||||
export const Route = createFileRoute('/_mobile/_mobileLayout/m/delivery')(
|
||||
{
|
||||
component: RouteComponent,
|
||||
},
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import { cn } from "../../../../lib/utils";
|
||||
|
||||
export const Route = createFileRoute("/(mobileStuff)/_mobileLayout/m/")({
|
||||
export const Route = createFileRoute("/_mobile/_mobileLayout/m/")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/(mobileStuff)/_mobileLayout/m/relocate')(
|
||||
export const Route = createFileRoute('/_mobile/_mobileLayout/m/relocate')(
|
||||
{
|
||||
component: RouteComponent,
|
||||
},
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createFileRoute, Outlet } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(mobileStuff)/_mobileLayout")({
|
||||
export const Route = createFileRoute("/_mobile/_mobileLayout")({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { checkUserAccess } from "@/lib/authClient";
|
||||
import HistoricalData from "../../-components/logistics/siloAdjustments/HistoricalData";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_old/old/(logistics)/siloAdjustments/$hist",
|
||||
)({
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// In a loader
|
||||
loader: ({ params }) => params.hist,
|
||||
// Or in a component
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { hist } = Route.useParams();
|
||||
return (
|
||||
<div>
|
||||
<HistoricalData laneId={hist} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { checkUserAccess } from "@/lib/authClient";
|
||||
import Comment from "../../../-components/logistics/siloAdjustments/Comment";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_old/old/(logistics)/siloAdjustments/comment/$comment",
|
||||
)({
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
// In a loader
|
||||
loader: ({ params }) => params.comment,
|
||||
// Or in a component
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { comment } = Route.useParams();
|
||||
return (
|
||||
<div className="ml-20 mt-20">
|
||||
<Comment id={comment} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
import { checkUserAccess } from "../../../../../lib/authClient";
|
||||
import SiloPage from "../../-components/logistics/siloAdjustments/SiloPage";
|
||||
|
||||
export const Route = createFileRoute("/_old/old/(logistics)/siloAdjustments/")({
|
||||
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>
|
||||
<SiloPage />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
104
frontend/src/routes/_old/old/-components/dashboard/Cards.tsx
Normal file
104
frontend/src/routes/_old/old/-components/dashboard/Cards.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { Button } from "../../../../../components/ui/button";
|
||||
import { Checkbox } from "../../../../../components/ui/checkbox";
|
||||
import { Label } from "../../../../../components/ui/label";
|
||||
import { useAppForm } from "../../../../../lib/formStuff";
|
||||
import { useCardStore } from "../../-lib/store/useCardStore";
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useCardStore } from "../../-lib/store/useCardStore";
|
||||
import INVCheckCard from "../logistics/warehouse/InventoryCard";
|
||||
import OpenOrders from "../logistics/warehouse/openOrders";
|
||||
import PPOO from "../logistics/warehouse/PPOOCard";
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
interface LstCardProps {
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export function LstCard({
|
||||
children,
|
||||
className = "",
|
||||
style = {},
|
||||
}: LstCardProps) {
|
||||
return (
|
||||
<Card
|
||||
className={`border-solid border-1 border-[#00659c] ${className}`}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarTrigger,
|
||||
} from "../../../../../components/ui/sidebar";
|
||||
import {
|
||||
useAuth,
|
||||
userAccess,
|
||||
useUserRoles,
|
||||
} from "../../../../../lib/authClient";
|
||||
import { useModuleStore } from "../../-lib/store/useModuleStore";
|
||||
import { AdminSideBar } from "./side-components/admin";
|
||||
import { EomSideBar } from "./side-components/eom";
|
||||
import { ForkliftSideBar } from "./side-components/forklift";
|
||||
import { Header } from "./side-components/header";
|
||||
import { LogisticsSideBar } from "./side-components/logistics";
|
||||
import { ProductionSideBar } from "./side-components/production";
|
||||
import { QualitySideBar } from "./side-components/quality";
|
||||
|
||||
export function AppSidebar() {
|
||||
const { session } = useAuth();
|
||||
const { userRoles } = useUserRoles();
|
||||
const { modules } = useModuleStore();
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarContent>
|
||||
<Header />
|
||||
|
||||
<ProductionSideBar
|
||||
user={session?.user as any}
|
||||
moduleID={
|
||||
modules.filter((n) => n.name === "production")[0]
|
||||
?.module_id as string
|
||||
}
|
||||
/>
|
||||
|
||||
{/* userAccess("logistics", ["systemAdmin", "admin","manager","viewer"]) */}
|
||||
<LogisticsSideBar user={session?.user as any} userRoles={userRoles} />
|
||||
{userAccess(null, ["systemAdmin"]) && (
|
||||
<>
|
||||
<ForkliftSideBar />
|
||||
<EomSideBar />
|
||||
<QualitySideBar />
|
||||
<AdminSideBar />
|
||||
</>
|
||||
)}
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarTrigger />
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
import {
|
||||
AlignJustify,
|
||||
Atom,
|
||||
Logs,
|
||||
Minus,
|
||||
Plus,
|
||||
Server,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Users,
|
||||
Webhook,
|
||||
} from "lucide-react";
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "../../../../../../components/ui/collapsible";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
import { useSettingStore } from "../../../-lib/store/useSettings";
|
||||
import { useSubModuleStore } from "../../../-lib/store/useSubModuleStore";
|
||||
|
||||
const iconMap: any = {
|
||||
ShieldCheck: ShieldCheck,
|
||||
AlignJustify: AlignJustify,
|
||||
Settings: Settings,
|
||||
Atom: Atom,
|
||||
Logs: Logs,
|
||||
Users: Users,
|
||||
Webhook: Webhook,
|
||||
Server: Server,
|
||||
};
|
||||
|
||||
export function AdminSideBar() {
|
||||
const { subModules } = useSubModuleStore();
|
||||
const { settings } = useSettingStore();
|
||||
|
||||
const plantToken = settings.filter((n) => n.name === "plantToken");
|
||||
|
||||
const items = subModules.filter((m) => m.moduleName === "admin");
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Admin section</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
{items.map((item: any, index) => {
|
||||
const Icon = iconMap[item.icon] || AlignJustify;
|
||||
// drop down menu setup
|
||||
return (
|
||||
<SidebarMenu key={item.name}>
|
||||
{item.link === "#" ? (
|
||||
<Collapsible
|
||||
key={item.name}
|
||||
defaultOpen={index === 1}
|
||||
className="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<Icon />
|
||||
{item.name}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.subSubModule?.length > 0 ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.subSubModule.map((i: any) => {
|
||||
const SubIcon = iconMap[i.icon] || AlignJustify;
|
||||
return (
|
||||
<SidebarMenuSubItem key={i.name}>
|
||||
{i.isActive && (
|
||||
<SidebarMenuSubButton asChild>
|
||||
<a
|
||||
href={
|
||||
i.name === "Swagger"
|
||||
? `https://${plantToken[0].value}prod.alpla.net/application/swagger/index.html`
|
||||
: i.link
|
||||
}
|
||||
target={i.newWindow ? "_blank" : "_self"}
|
||||
>
|
||||
<SubIcon />
|
||||
<span>{i.name}</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
)}
|
||||
</SidebarMenuSubItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
) : (
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
if (item.link === "#") return;
|
||||
return (
|
||||
<SidebarMenuItem key={item.name}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.link}>
|
||||
<Icon />
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
)}
|
||||
</SidebarMenu>
|
||||
);
|
||||
})}
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
/* <SidebarMenu>
|
||||
{data.navMain.map((item, index) => (
|
||||
<Collapsible
|
||||
key={item.title}
|
||||
defaultOpen={index === 1}
|
||||
className="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<item.icon />
|
||||
{item.title}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.items?.length ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((item) => (
|
||||
<SidebarMenuSubItem
|
||||
key={item.title}
|
||||
>
|
||||
{item.isActive && (
|
||||
<SidebarMenuSubButton
|
||||
asChild
|
||||
>
|
||||
<a
|
||||
href={item.url}
|
||||
target={
|
||||
item.newWindow
|
||||
? "_blank"
|
||||
: "_self"
|
||||
}
|
||||
>
|
||||
<item.icon />
|
||||
<span>
|
||||
{item.title}
|
||||
</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
)}
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu> */
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { FileText } from "lucide-react";
|
||||
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "End Of Month",
|
||||
url: "/eom",
|
||||
icon: FileText,
|
||||
},
|
||||
];
|
||||
|
||||
export function EomSideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>End of month</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import { Forklift, Hourglass, Minus, Plus, Signature } from "lucide-react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "../../../../../../components/ui/collapsible";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarMenuSub,
|
||||
SidebarMenuSubButton,
|
||||
SidebarMenuSubItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Gemone",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
isActive: false,
|
||||
},
|
||||
];
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
{
|
||||
title: "Forklift Management",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
items: [
|
||||
{
|
||||
title: "All Forklifts",
|
||||
url: "#",
|
||||
icon: Forklift,
|
||||
},
|
||||
{
|
||||
title: "Leasing data",
|
||||
url: "#",
|
||||
isActive: false,
|
||||
icon: Signature,
|
||||
},
|
||||
{
|
||||
title: "Forklift Hours",
|
||||
url: "#",
|
||||
isActive: false,
|
||||
icon: Hourglass,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function ForkliftSideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Forklift Section</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{data.navMain.map((item, index) => (
|
||||
<Collapsible
|
||||
key={item.title}
|
||||
defaultOpen={index === 1}
|
||||
className="group/collapsible"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton>
|
||||
<item.icon />
|
||||
{item.title}{" "}
|
||||
<Plus className="ml-auto group-data-[state=open]/collapsible:hidden" />
|
||||
<Minus className="ml-auto group-data-[state=closed]/collapsible:hidden" />
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
{item.items?.length ? (
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{item.items.map((item) => (
|
||||
<SidebarMenuSubItem key={item.title}>
|
||||
<SidebarMenuSubButton
|
||||
asChild
|
||||
isActive={item.isActive}
|
||||
>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuSubButton>
|
||||
</SidebarMenuSubItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
) : null}
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import {
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
|
||||
export function Header() {
|
||||
return (
|
||||
<SidebarHeader>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<Link to="/old">
|
||||
<SidebarMenuButton size="lg" asChild>
|
||||
<div className="flex flex-row">
|
||||
<img
|
||||
src={"/lst/app/imgs/dkLst.png"}
|
||||
alt="Description"
|
||||
className="size-8"
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-0.5 leading-none">
|
||||
<span className="font-semibold">Logistics Support Tool</span>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</Link>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Barcode, Command, Cylinder, Package, Truck } from "lucide-react";
|
||||
import type { UserRoles } from "@/lib/authClient";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
import { useSubModuleStore } from "../../../-lib/store/useSubModuleStore";
|
||||
import type { User } from "../../../-types/users";
|
||||
import { hasPageAccess } from "../../../-utils/userAccess";
|
||||
|
||||
const iconMap: any = {
|
||||
Package: Package,
|
||||
Truck: Truck,
|
||||
Cylinder: Cylinder,
|
||||
Barcode: Barcode,
|
||||
Command: Command,
|
||||
};
|
||||
|
||||
export function LogisticsSideBar({
|
||||
user,
|
||||
userRoles,
|
||||
}: {
|
||||
user: User | null;
|
||||
userRoles: UserRoles[] | null;
|
||||
}) {
|
||||
const { subModules } = useSubModuleStore();
|
||||
|
||||
const items = subModules?.filter((m) => m.moduleName === "logistics");
|
||||
const userUpdate = { ...user, roles: userRoles };
|
||||
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
const Icon = iconMap[item.icon];
|
||||
return (
|
||||
<SidebarMenuItem key={item.submodule_id}>
|
||||
{hasPageAccess(
|
||||
userUpdate as any,
|
||||
item.roles,
|
||||
item.moduleName,
|
||||
) && (
|
||||
<>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item?.link}>
|
||||
<Icon />
|
||||
<span>{item?.name}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</>
|
||||
)}
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { Printer, Tag } from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
import type { User } from "../../../-types/users";
|
||||
import { hasPageAccess } from "../../../-utils/userAccess";
|
||||
|
||||
export function ProductionSideBar({
|
||||
user,
|
||||
moduleID,
|
||||
}: {
|
||||
user: User | null;
|
||||
moduleID: string;
|
||||
}) {
|
||||
const url: string = window.location.host.split(":")[0];
|
||||
const items = [
|
||||
{
|
||||
title: "One Click Print",
|
||||
url: "/lst/app/old/ocp",
|
||||
icon: Printer,
|
||||
role: ["viewer"],
|
||||
module: "ocp",
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
title: "Rfid Readers",
|
||||
url: "/lst/app/old/rfid",
|
||||
icon: Tag,
|
||||
role: ["viewer"],
|
||||
module: "production",
|
||||
active: url === "usday1vms006" || url === "localhost" ? true : false,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Production</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<>
|
||||
{hasPageAccess(user, item.role, moduleID) && item.active && (
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
)}
|
||||
</>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Printer } from "lucide-react";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "../../../../../../components/ui/sidebar";
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: "Qaulity Request",
|
||||
url: "#",
|
||||
icon: Printer,
|
||||
},
|
||||
];
|
||||
|
||||
export function QualitySideBar() {
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Quality</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../../../../components/ui/dialog";
|
||||
import { useAppForm } from "../../../../../../lib/formStuff";
|
||||
import { getMachineConnected } from "../../../-utils/querys/logistics/machineConnected";
|
||||
import { getMachineNotConnected } from "../../../-utils/querys/logistics/notConnected";
|
||||
|
||||
export function AttachSilo(props: any) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, isError, isLoading, refetch } = useQuery(
|
||||
getMachineNotConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "detached",
|
||||
}),
|
||||
);
|
||||
const { refetch: attached } = useQuery(
|
||||
getMachineConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "connected",
|
||||
}),
|
||||
);
|
||||
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
laneId: props.silo.LocationID,
|
||||
productionLotId: "",
|
||||
machineId: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/lst/old/api/logistics/attachsilo",
|
||||
value,
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
attached();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
} else {
|
||||
console.log(res.data);
|
||||
toast.error(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(
|
||||
"There was an error attaching the silo please try again, if persist please enter a helpdesk ticket.",
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (isError)
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error loading data</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (isLoading)
|
||||
return (
|
||||
<div>
|
||||
<p>Loading....</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// convert the array that comes over to label and value
|
||||
const tranMachine = data.map((i: any) => ({
|
||||
value: i.machineId.toString(),
|
||||
label: i.name,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(!open)}>
|
||||
Attach Silo
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Attach silo for: {props.silo.Description}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Enter the new lotnumber, select the machine you would like to
|
||||
attach.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div>
|
||||
<p className="text-sm">
|
||||
NOTE: If the machine you are trying to attach is not showing in
|
||||
the drop down this means it is already attached to this silo.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<form.AppField
|
||||
name="productionLotId"
|
||||
children={(field) => (
|
||||
<field.InputField
|
||||
label="Lot Number"
|
||||
inputType="number"
|
||||
required={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<form.AppField
|
||||
name="machineId"
|
||||
children={(field) => (
|
||||
<field.SelectField
|
||||
label="Select Machine"
|
||||
options={tranMachine}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="mt-2">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(!open)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Attach</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { format } from "date-fns";
|
||||
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
|
||||
import { CardContent } from "../../../../../../components/ui/card";
|
||||
import {
|
||||
type ChartConfig,
|
||||
ChartContainer,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "../../../../../../components/ui/chart";
|
||||
import { LstCard } from "../../../../../../components/ui/lstCard";
|
||||
import { getAdjustments } from "../../../-utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
|
||||
export default function ChartData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
const chartConfig = {
|
||||
stock: {
|
||||
label: "Stock",
|
||||
color: "rgb(255, 99, 132)",
|
||||
},
|
||||
actual: {
|
||||
label: "Actual",
|
||||
color: "rgb(53, 162, 235)",
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
if (isLoading) return <div>Loading chart data</div>;
|
||||
if (isError) return <div>Error in loading chart data</div>;
|
||||
|
||||
let adjustments: any = data.filter((l: any) => l.locationID === props.laneId);
|
||||
adjustments = adjustments.splice(0, 10).map((s: any) => {
|
||||
return {
|
||||
date: format(s.dateAdjusted.replace("Z", ""), "M/d/yyyy hh:mm"),
|
||||
stock: s.currentStockLevel,
|
||||
actual: s.newLevel,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<LstCard className="w-[425px] h-[250px] m-1">
|
||||
<CardContent>
|
||||
{adjustments.length === 0 ? (
|
||||
<span>No silo data has been entered for this silo.</span>
|
||||
) : (
|
||||
<ChartContainer config={chartConfig}>
|
||||
<AreaChart
|
||||
accessibilityLayer
|
||||
data={adjustments}
|
||||
margin={{
|
||||
left: 35,
|
||||
right: 45,
|
||||
bottom: 50,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickMargin={14}
|
||||
angle={-45}
|
||||
textAnchor="end"
|
||||
dy={10}
|
||||
tickFormatter={(value) => format(value, "M/d/yyyy")}
|
||||
/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={<ChartTooltipContent indicator="dot" />}
|
||||
/>
|
||||
<Area
|
||||
dataKey="stock"
|
||||
type="natural"
|
||||
fill="rgba(53, 162, 235, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(53, 162, 235, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
<Area
|
||||
dataKey="actual"
|
||||
type="natural"
|
||||
fill="rgba(255, 99, 132, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(255, 99, 132, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)}
|
||||
</CardContent>
|
||||
{/* <CardFooter>
|
||||
<div className="flex w-full items-start gap-2 text-sm">
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center gap-2 font-medium leading-none">
|
||||
Trending up by 5.2% this month{" "}
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex items-center gap-2 leading-none text-muted-foreground">
|
||||
January - June 2024
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardFooter> */}
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useRouter } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CardContent, CardFooter, CardHeader } from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { LstCard } from "../../extendedUi/LstCard";
|
||||
|
||||
export default function Comment(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
comment: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
`/lst/old/api/logistics/postcomment/${data.id.split("&")[0]}`,
|
||||
{
|
||||
comment: value.comment,
|
||||
key: data.id.split("&")[1].replace("amp;", ""),
|
||||
},
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
form.reset();
|
||||
router.navigate({ to: "/old/siloAdjustments" });
|
||||
}
|
||||
|
||||
if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
form.reset();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(`There was an error posting your comment.`);
|
||||
}
|
||||
setIsSubmitting(false);
|
||||
},
|
||||
});
|
||||
return (
|
||||
<div className="">
|
||||
<LstCard>
|
||||
<CardHeader>Please enter your comment for the silo adjust</CardHeader>
|
||||
<CardContent>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="comment"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 10
|
||||
? undefined
|
||||
: "Comment must be longer than 10 characters.",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<Label htmlFor="comment" className="mb-2">
|
||||
Comment
|
||||
</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 ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<div className="flex justify-end">
|
||||
<Button onClick={form.handleSubmit} disabled={isSubmitting}>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "../../../../../../components/ui/dialog";
|
||||
import { useAppForm } from "../../../../../../lib/formStuff";
|
||||
import { getMachineConnected } from "../../../-utils/querys/logistics/machineConnected";
|
||||
import { getMachineNotConnected } from "../../../-utils/querys/logistics/notConnected";
|
||||
|
||||
export function DetachSilo(props: any) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, isError, isLoading, refetch } = useQuery(
|
||||
getMachineConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "connected",
|
||||
}),
|
||||
);
|
||||
|
||||
const { refetch: notConnected } = useQuery(
|
||||
getMachineNotConnected({
|
||||
siloID: props.silo.LocationID,
|
||||
connectionType: "detached",
|
||||
}),
|
||||
);
|
||||
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
laneId: props.silo.LocationID,
|
||||
machineId: 0,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/lst/old/api/logistics/detachsilo",
|
||||
value,
|
||||
);
|
||||
|
||||
if (res.status === 200) {
|
||||
console.log(res.data.data);
|
||||
toast.success(res.data.message);
|
||||
|
||||
refetch();
|
||||
notConnected();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
} else {
|
||||
console.log(res.data);
|
||||
toast.error(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
setOpen(!open);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.error(
|
||||
"There was an error detaching the silo please try again, if persist please enter a helpdesk ticket.",
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (isError)
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error loading data</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (isLoading)
|
||||
return (
|
||||
<div>
|
||||
<p>Loading....</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// convert the array that comes over to label and value
|
||||
const tranMachine = data.map((i: any) => ({
|
||||
value: i.machineId.toString(),
|
||||
label: i.name,
|
||||
}));
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(!open)}
|
||||
disabled={data.length === 0}
|
||||
>
|
||||
Detach Silo
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Attach silo for: {props.silo.Description}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Select the machine you would like to detach.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<div className="mt-2">
|
||||
<form.AppField
|
||||
name="machineId"
|
||||
children={(field) => (
|
||||
<field.SelectField
|
||||
label="Select Machine"
|
||||
options={tranMachine}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(!open)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Detach</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAdjustments } from "../../../-utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
import { columns } from "../../../-utils/tableData/siloAdjustmentHist/siloAdjHistColumns";
|
||||
import { SiloTable } from "../../../-utils/tableData/siloAdjustmentHist/siloData";
|
||||
|
||||
export default function HistoricalData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
|
||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the adjustments.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
//console.log(data[0].locationID, parseInt(props.laneId));
|
||||
const adjustments: any = data.filter(
|
||||
(l: any) => l.locationID === parseInt(props.laneId),
|
||||
);
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
<SiloTable columns={columns} data={adjustments} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { CircleAlert } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { 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 "../../../../../../components/ui/lstCard";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "../../../../../../components/ui/tooltip";
|
||||
import { useAuth, userAccess } from "../../../../../../lib/authClient";
|
||||
import { getStockSilo } from "../../../-utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { AttachSilo } from "./AttachSilo";
|
||||
import ChartData from "./ChartData";
|
||||
import { DetachSilo } from "./DetachSilo";
|
||||
|
||||
export default function SiloCard(data: any) {
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const { refetch } = useQuery(getStockSilo());
|
||||
const { session } = useAuth();
|
||||
|
||||
const silo = data.silo;
|
||||
|
||||
// roles that can do the silo adjustments
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
newLevel: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setSubmitting(true);
|
||||
const dataToSubmit = {
|
||||
quantity: parseFloat(value.newLevel),
|
||||
warehouseId: silo.WarehouseID,
|
||||
laneId: silo.LocationID,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"/lst/old/api/logistics/createsiloadjustment",
|
||||
dataToSubmit,
|
||||
{ withCredentials: true },
|
||||
);
|
||||
//console.log(res.data);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
form.reset();
|
||||
}
|
||||
if (!res.data.success && res.data.data?.status === 400) {
|
||||
if (res.data.data.status === 400) {
|
||||
toast.error(res.data.data.data.errors[0].message);
|
||||
}
|
||||
} else if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
}
|
||||
setSubmitting(false);
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
if (error.status === 401) {
|
||||
toast.error(error.response.statusText);
|
||||
setSubmitting(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<LstCard>
|
||||
<div className="flex flex-row">
|
||||
<LstCard className="grow m-1 max-w-[400px]">
|
||||
<CardHeader>{silo.Description}</CardHeader>
|
||||
<div className="m-1">
|
||||
<hr className="m-2" />
|
||||
<span>Current Stock: </span>
|
||||
{silo.Stock_Total}
|
||||
<hr className="m-2" />
|
||||
<span>Last date adjusted </span>
|
||||
{format(silo.LastAdjustment, "M/dd/yyyy")}
|
||||
<hr className="m-2" />
|
||||
</div>
|
||||
<div>
|
||||
{silo.Stock_Total === 0 ? (
|
||||
<div className="flex justify-center flex-col">
|
||||
<span>
|
||||
The silo is currently empty you will not be able to do an
|
||||
adjustment until you have received material in.
|
||||
</span>
|
||||
<hr />
|
||||
<ul>
|
||||
<li>
|
||||
-Someone click "Take inventory on a empty location" in
|
||||
stock.
|
||||
</li>
|
||||
<li>
|
||||
-Silo virtualy ran empty due to production over consumption.
|
||||
</li>
|
||||
<li>
|
||||
-Someone forgot to move a railcar compartment over to this
|
||||
location.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{session?.user &&
|
||||
userAccess("logistics", [
|
||||
"supervisor",
|
||||
"manager",
|
||||
"admin",
|
||||
"systemAdmin",
|
||||
]) && (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<form.Field
|
||||
name="newLevel"
|
||||
validators={{
|
||||
// We can choose between form-wide and field-specific validators
|
||||
onChange: ({ value }) =>
|
||||
value.length > 1
|
||||
? undefined
|
||||
: "You must enter a value greate than 1",
|
||||
}}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||
<div className="flex flex-row">
|
||||
<Label htmlFor="newLevel">New level</Label>
|
||||
<div>
|
||||
<Disclaimer />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
<Input
|
||||
name={field.name}
|
||||
value={field.state.value}
|
||||
onBlur={field.handleBlur}
|
||||
type="decimal"
|
||||
onChange={(e) =>
|
||||
field.handleChange(e.target.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
className="ml-1"
|
||||
variant="outline"
|
||||
type="submit"
|
||||
onClick={form.handleSubmit}
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? (
|
||||
<span className="w-24">Submitting...</span>
|
||||
) : (
|
||||
<span className="w-24">Submit</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{field.state.meta.errors.length ? (
|
||||
<em>{field.state.meta.errors.join(",")}</em>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</LstCard>
|
||||
<div className="grow max-w-[600px]">
|
||||
<ChartData laneId={silo.LocationID} />
|
||||
|
||||
<div className="flex justify-end m-1 gap-3">
|
||||
<AttachSilo silo={silo} />
|
||||
<DetachSilo silo={silo} />
|
||||
<Button variant="outline">
|
||||
<Link
|
||||
to={"/old/siloAdjustments/$hist"}
|
||||
params={{ hist: silo.LocationID }}
|
||||
>
|
||||
Historical Data
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
|
||||
const Disclaimer = () => {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<CircleAlert className="ml-1 w-[14px]" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-48">
|
||||
<p className="text-pretty">
|
||||
If you have had this page open for a period of time before
|
||||
submitting your data, there is a chance that the stock levels will
|
||||
be different from the ones you see above
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getStockSilo } from "../../../-utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import SiloCard from "./SiloCard";
|
||||
|
||||
export default function SiloPage() {
|
||||
const { data, isError, error, isLoading } = useQuery(getStockSilo());
|
||||
|
||||
if (isLoading) return;
|
||||
|
||||
if (isError) return;
|
||||
|
||||
if (error)
|
||||
return (
|
||||
<div>
|
||||
{" "}
|
||||
There was an error getting the silos please notify your admin if this
|
||||
continues to be an issue
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap">
|
||||
{data?.map((s: any) => (
|
||||
<div key={s.LocationID} className="grow m-2 max-w-[800px]">
|
||||
<SiloCard silo={s} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function ExportInventoryData() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
age: "",
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
setSaving(true);
|
||||
try {
|
||||
const res = await axios.get(
|
||||
`/api/logistics/getcyclecount?age=${value.age}`,
|
||||
{
|
||||
responseType: "blob",
|
||||
}
|
||||
);
|
||||
|
||||
const blob = new Blob([res.data], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = `CycleCount-${format(new Date(Date.now()), "M-d-yyyy")}.xlsx`; // You can make this dynamic
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
// Clean up
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
toast.success(`File Downloaded`);
|
||||
setSaving(false);
|
||||
setOpen(false);
|
||||
form.reset();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.log(`There was an error getting cycle counts.`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(isOpen) => {
|
||||
if (!open) {
|
||||
form.reset();
|
||||
}
|
||||
setOpen(isOpen);
|
||||
// toast.message("Model was something", {
|
||||
// description: isOpen ? "Modal is open" : "Modal is closed",
|
||||
// });
|
||||
}}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Export Inventory Check</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Export Inventory lane check</DialogTitle>
|
||||
<DialogDescription>
|
||||
Exports all lanes based on the age you enter, except
|
||||
empty lanes.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<>
|
||||
<form.Field
|
||||
name="age"
|
||||
// validators={{
|
||||
// // We can choose between form-wide and field-specific validators
|
||||
// onChange: ({ value }) =>
|
||||
// value.length > 3
|
||||
// ? undefined
|
||||
// : "Username must be longer than 3 letters",
|
||||
// }}
|
||||
children={(field) => {
|
||||
return (
|
||||
<div className="m-2 min-w-48 max-w-96 p-2 flex flex-row">
|
||||
<Label htmlFor="active">
|
||||
Age
|
||||
</Label>
|
||||
<Input
|
||||
className="ml-2"
|
||||
name={field.name}
|
||||
onBlur={field.handleBlur}
|
||||
type="number"
|
||||
onChange={(e) =>
|
||||
field.handleChange(
|
||||
e.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button onClick={() => setOpen(false)}>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={saving}
|
||||
onClick={form.handleSubmit}
|
||||
>
|
||||
{saving ? (
|
||||
<>
|
||||
<span>Saving....</span>
|
||||
</>
|
||||
) : (
|
||||
<span>Save setting</span>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getinventoryCheck } from "../../../-utils/querys/logistics/getInventoryCheck";
|
||||
import { invColumns } from "../../../-utils/tableData/InventoryCards/inventoryColumns";
|
||||
import { InvTable } from "../../../-utils/tableData/InventoryCards/inventoryData";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function INVCheckCard(props: any) {
|
||||
const { age, rowType } = props.data;
|
||||
|
||||
//console.log(props.data);
|
||||
const { data, isError, isLoading } = useQuery(
|
||||
getinventoryCheck({ age: age }),
|
||||
);
|
||||
|
||||
if (isLoading) return <div>Loading inventory data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the inv.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let laneData: any = data;
|
||||
if (props.type != "") {
|
||||
laneData = laneData.filter((l: any) => l.rowType === rowType.toUpperCase());
|
||||
|
||||
// age
|
||||
laneData = laneData.filter((l: any) => l.DaysSinceLast >= age);
|
||||
}
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return <InvTable columns={invColumns} data={laneData} info={props.data} />;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getPPOO } from "../../../-utils/querys/logistics/getPPOO";
|
||||
import { columns } from "../../../-utils/tableData/ppoo/ppooColumns";
|
||||
import { PPOOTable } from "../../../-utils/tableData/ppoo/ppooData";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function PPOO() {
|
||||
//{ style = {} }
|
||||
const { data, isError, isLoading } = useQuery(getPPOO());
|
||||
|
||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the adjustments.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return (
|
||||
<PPOOTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
//style={style}
|
||||
/>
|
||||
);
|
||||
// return (
|
||||
// <div style={style}>
|
||||
// <LstCard style={style}>
|
||||
// <Suspense fallback={<p>Loading PPOO...</p>}>
|
||||
// <div className={`flex justify-center`}>
|
||||
// <p
|
||||
// className={`drag-handle w-fit`}
|
||||
// style={{ cursor: "move", padding: "5px" }}
|
||||
// >
|
||||
// PPOO
|
||||
// </p>
|
||||
|
||||
// <button onClick={handleCloseCard}>
|
||||
// <CircleX />
|
||||
// </button>
|
||||
// </div>
|
||||
// <PPOOTable
|
||||
// columns={columns}
|
||||
// data={data}
|
||||
// //style={style}
|
||||
// />
|
||||
// </Suspense>
|
||||
// </LstCard>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getOpenOrders } from "../../../-utils/querys/logistics/getOpenOrders";
|
||||
import { openOrderColumns } from "../../../-utils/tableData/openorders/ooColumns";
|
||||
import { OpenOrderTable } from "../../../-utils/tableData/openorders/ooData";
|
||||
//import { CircleX } from "lucide-react";
|
||||
//import { Suspense } from "react";
|
||||
//import { toast } from "sonner";
|
||||
|
||||
export default function OpenOrders() {
|
||||
//{ style = {} }
|
||||
const { data, isError, isLoading } = useQuery(getOpenOrders());
|
||||
|
||||
if (isLoading) return <div>Loading openOrder data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the openorders.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let openOrders: any = data;
|
||||
|
||||
// const handleCloseCard = () => {
|
||||
// //removeCard("PPOO");
|
||||
|
||||
// toast.success("card removed");
|
||||
// };
|
||||
|
||||
return <OpenOrderTable columns={openOrderColumns} data={openOrders} />;
|
||||
}
|
||||
46
frontend/src/routes/_old/old/-lib/store/useCardStore.ts
Normal file
46
frontend/src/routes/_old/old/-lib/store/useCardStore.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { create } from "zustand";
|
||||
import { devtools, persist } from "zustand/middleware";
|
||||
|
||||
// interface CardSettings {
|
||||
// daysSinceLast?: number;
|
||||
// rowType?: string;
|
||||
// }
|
||||
|
||||
export interface Card {
|
||||
name: string;
|
||||
rowType: string;
|
||||
age: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
interface CardStore {
|
||||
cards: Card[]; // Array of card objects
|
||||
addCard: (card: Card) => void;
|
||||
updateCard: (name: string, updatedCard: Partial<Card>) => void;
|
||||
removeCard: (name: string) => void;
|
||||
}
|
||||
|
||||
export const useCardStore = create<CardStore>()(
|
||||
devtools(
|
||||
persist<CardStore>(
|
||||
(set) => ({
|
||||
cards: [],
|
||||
|
||||
addCard: (card) => set((state) => ({ cards: [...state.cards, card] })),
|
||||
|
||||
updateCard: (name, updatedCard) =>
|
||||
set((state) => ({
|
||||
cards: state.cards.map((card) =>
|
||||
card.name === name ? { ...card, ...updatedCard } : card,
|
||||
),
|
||||
})),
|
||||
|
||||
removeCard: (name) =>
|
||||
set((state) => ({
|
||||
cards: state.cards.filter((card) => card.name !== name),
|
||||
})),
|
||||
}),
|
||||
{ name: "cards" },
|
||||
),
|
||||
),
|
||||
);
|
||||
30
frontend/src/routes/_old/old/-lib/store/useModuleStore.ts
Normal file
30
frontend/src/routes/_old/old/-lib/store/useModuleStore.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
import type { Modules } from "../../-types/modules";
|
||||
|
||||
interface SettingState {
|
||||
modules: Modules[];
|
||||
|
||||
fetchModules: () => Promise<void>;
|
||||
setModules: (modules: Modules[]) => void;
|
||||
}
|
||||
interface FetchModulesResponse {
|
||||
data: Modules[];
|
||||
}
|
||||
|
||||
export const useModuleStore = create<SettingState>()((set) => ({
|
||||
modules: [],
|
||||
setModules: (modules) => set({ modules }),
|
||||
fetchModules: async () => {
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const response = await axios.get(`/lst/old/api/server/modules`, {});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({ modules: data.data });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch modules:", error);
|
||||
set({ modules: [] });
|
||||
}
|
||||
},
|
||||
}));
|
||||
28
frontend/src/routes/_old/old/-lib/store/useSettings.ts
Normal file
28
frontend/src/routes/_old/old/-lib/store/useSettings.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
|
||||
interface SettingState {
|
||||
settings: any[];
|
||||
fetchSettings: () => Promise<void>;
|
||||
setSettings: (settings: any[]) => void;
|
||||
}
|
||||
interface FetchModulesResponse {
|
||||
data: any[];
|
||||
}
|
||||
|
||||
export const useSettingStore = create<SettingState>()((set) => ({
|
||||
settings: [],
|
||||
setSettings: (settings) => set({ settings }),
|
||||
fetchSettings: async () => {
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const response = await axios.get(`/lst/api/system/settings`, {});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({ settings: data.data });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch settings:", error);
|
||||
set({ settings: [] });
|
||||
}
|
||||
},
|
||||
}));
|
||||
30
frontend/src/routes/_old/old/-lib/store/useSubModuleStore.ts
Normal file
30
frontend/src/routes/_old/old/-lib/store/useSubModuleStore.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import axios from "axios";
|
||||
import { create } from "zustand";
|
||||
import type { SubModules } from "../../-types/modules";
|
||||
|
||||
interface SettingState {
|
||||
subModules: SubModules[];
|
||||
|
||||
fetchSubModules: () => Promise<void>;
|
||||
setSubModules: (modules: SubModules[]) => void;
|
||||
}
|
||||
interface FetchModulesResponse {
|
||||
data: SubModules[];
|
||||
}
|
||||
|
||||
export const useSubModuleStore = create<SettingState>()((set) => ({
|
||||
subModules: [],
|
||||
setSubModules: (subModules) => set({ subModules }),
|
||||
fetchSubModules: async () => {
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const response = await axios.get(`/lst/old/api/server/submodules`, {});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({ subModules: data.data });
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch settings:", error);
|
||||
set({ subModules: [] });
|
||||
}
|
||||
},
|
||||
}));
|
||||
19
frontend/src/routes/_old/old/-types/lots.ts
Normal file
19
frontend/src/routes/_old/old/-types/lots.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export type LotType = {
|
||||
AV: number;
|
||||
Alias: string;
|
||||
lot: number;
|
||||
LabelOnlineID: number;
|
||||
MachineDescription: string;
|
||||
MachineID: number;
|
||||
MachineLocation: number;
|
||||
PlannedQTY: number;
|
||||
PrinterName: string;
|
||||
Produced: number;
|
||||
ProlinkLot: number;
|
||||
Remaining: number;
|
||||
machineID: number;
|
||||
overPrinting: string;
|
||||
pallerCopies: number;
|
||||
palletLabel: string;
|
||||
printerID: number;
|
||||
};
|
||||
20
frontend/src/routes/_old/old/-types/modules.ts
Normal file
20
frontend/src/routes/_old/old/-types/modules.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export interface Modules {
|
||||
module_id: string;
|
||||
name: string;
|
||||
active: boolean;
|
||||
roles: string;
|
||||
add_user: string;
|
||||
add_date: Date;
|
||||
upd_user: string;
|
||||
upd_date: Date;
|
||||
}
|
||||
|
||||
export interface SubModules {
|
||||
submodule_id: string;
|
||||
name: string;
|
||||
link: string;
|
||||
icon: string;
|
||||
moduleName: string;
|
||||
active: boolean;
|
||||
roles: string[];
|
||||
}
|
||||
4
frontend/src/routes/_old/old/-types/roles.ts
Normal file
4
frontend/src/routes/_old/old/-types/roles.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface Roles {
|
||||
role: string;
|
||||
module_id: string;
|
||||
}
|
||||
10
frontend/src/routes/_old/old/-types/users.ts
Normal file
10
frontend/src/routes/_old/old/-types/users.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { type Roles } from "./roles";
|
||||
|
||||
export type User = {
|
||||
user_id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
roles: Roles[];
|
||||
role: string;
|
||||
prod?: string;
|
||||
};
|
||||
25
frontend/src/routes/_old/old/-utils/moduleActive.ts
Normal file
25
frontend/src/routes/_old/old/-utils/moduleActive.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// type Feature = string;
|
||||
// interface Module {
|
||||
// id: number;
|
||||
// name: string;
|
||||
// features: Feature[];
|
||||
// active: boolean;
|
||||
// }
|
||||
|
||||
import { useModuleStore } from "../-lib/store/useModuleStore";
|
||||
|
||||
// const modules: Module[] = [
|
||||
// {id: 1, name: "production", active: true, features: ["view", "edit", "approve"]},
|
||||
// {id: 2, name: "logistics", active: true, features: ["view", "assign", "track"]},
|
||||
// {id: 3, name: "quality", active: false, features: ["view", "audit", "approve"]},
|
||||
// {id: 4, name: "forklift", active: true, features: ["view", "request", "operate"]},
|
||||
// {id: 5, name: "admin", active: true, features: ["view", "manage_users", "view_logs", "settings"]},
|
||||
// ];
|
||||
|
||||
export function moduleActive(moduleName: string): boolean {
|
||||
const { modules } = useModuleStore();
|
||||
const module = modules?.find(
|
||||
(m: any) => m.name === moduleName && m.active === true,
|
||||
);
|
||||
return module ? true : false;
|
||||
}
|
||||
14
frontend/src/routes/_old/old/-utils/oldAppUrl.tsx
Normal file
14
frontend/src/routes/_old/old/-utils/oldAppUrl.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import axios from "axios";
|
||||
|
||||
export const oldServerUrl = async () => {
|
||||
const res = await axios.get("/lst/api/system/settings");
|
||||
const settings = res.data.data;
|
||||
|
||||
console.log("Settings", settings);
|
||||
const server = settings.filter((n: any) => n.name === "v1Server");
|
||||
const port = settings.filter((n: any) => n.name === "v1Port");
|
||||
const url = `http://${server[0]?.value}:${port[0]?.value}`;
|
||||
|
||||
console.log(url);
|
||||
return url;
|
||||
};
|
||||
25
frontend/src/routes/_old/old/-utils/querys/admin/modules.tsx
Normal file
25
frontend/src/routes/_old/old/-utils/querys/admin/modules.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getModules(token: string) {
|
||||
return queryOptions({
|
||||
queryKey: ["modules"],
|
||||
queryFn: () => fetchSettings(token),
|
||||
enabled: !!token,
|
||||
//staleTime: 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchSettings = async (token: string) => {
|
||||
const { data } = await axios.get("/api/server/modules", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
const url: string = window.location.host.split(":")[0];
|
||||
let settingsData = data.data;
|
||||
if (url != "localhost") {
|
||||
settingsData.filter((n: any) => n.name === "devDir");
|
||||
}
|
||||
return settingsData;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getnotifications() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
return queryOptions({
|
||||
queryKey: ["getNotifications"],
|
||||
queryFn: () => fetchUsers(token),
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchUsers = async (token: string | null) => {
|
||||
const { data } = await axios.get(`/api/notify/notifications`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getSubModules(token: string) {
|
||||
return queryOptions({
|
||||
queryKey: ["submodules"],
|
||||
queryFn: () => fetchSettings(token),
|
||||
enabled: !!token,
|
||||
//staleTime: 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchSettings = async (token: string) => {
|
||||
const { data } = await axios.get("/api/server/submodules", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
const url: string = window.location.host.split(":")[0];
|
||||
let settingsData = data.data;
|
||||
if (url != "localhost") {
|
||||
settingsData.filter((n: any) => n.name === "devDir");
|
||||
}
|
||||
return settingsData;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getUserRoles() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
return queryOptions({
|
||||
queryKey: ["getUsers"],
|
||||
queryFn: () => fetchUsers(token),
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
//refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchUsers = async (token: string | null) => {
|
||||
const { data } = await axios.get(`/api/auth/allusersroles`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
26
frontend/src/routes/_old/old/-utils/querys/admin/users.tsx
Normal file
26
frontend/src/routes/_old/old/-utils/querys/admin/users.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getUsers() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
return queryOptions({
|
||||
queryKey: ["getUsers"],
|
||||
queryFn: () => fetchUsers(token),
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchUsers = async (token: string | null) => {
|
||||
const { data } = await axios.get(`/api/auth/allusers`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getinventoryCheck(data: any) {
|
||||
return queryOptions({
|
||||
queryKey: ["getInvCheck"],
|
||||
queryFn: () => fetchStockSilo(data),
|
||||
//enabled:
|
||||
staleTime: 1000,
|
||||
refetchInterval: 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: "",
|
||||
});
|
||||
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
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 ?? [];
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getPPOO() {
|
||||
return queryOptions({
|
||||
queryKey: ["getPPOO"],
|
||||
queryFn: () => fetchStockSilo(),
|
||||
//enabled:
|
||||
staleTime: 1000,
|
||||
refetchInterval: 60 * 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchStockSilo = async () => {
|
||||
const { data } = await axios.get(
|
||||
`/lst/old/api/logistics/getppoo`,
|
||||
);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
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 ?? [];
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getMachineConnected(siloCon: any) {
|
||||
return queryOptions({
|
||||
queryKey: [`siloConnectionAttached-${siloCon.siloID}`],
|
||||
queryFn: () => fetchStockSilo(siloCon),
|
||||
//enabled:
|
||||
//staleTime: 1000,
|
||||
//refetchInterval: 60 * 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchStockSilo = async (siloCon: any) => {
|
||||
const { data } = await axios.post(`/lst/old/api/logistics/siloconnection`, {
|
||||
siloID: siloCon.siloID,
|
||||
connectionType: siloCon.connectionType,
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getMachineNotConnected(siloCon: any) {
|
||||
return queryOptions({
|
||||
queryKey: [`siloConnectionNotConnected-${siloCon.siloID}`],
|
||||
queryFn: () => fetchStockSilo(siloCon),
|
||||
//enabled:
|
||||
//staleTime: 1000,
|
||||
//refetchInterval: 60 * 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchStockSilo = async (siloCon: any) => {
|
||||
const { data } = await axios.post(`/lst/old/api/logistics/siloconnection`, {
|
||||
siloID: siloCon.siloID,
|
||||
connectionType: siloCon.connectionType,
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getAdjustments() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
return queryOptions({
|
||||
queryKey: ["getAdjustments"],
|
||||
queryFn: () => fetchStockSilo(token),
|
||||
//enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchStockSilo = async (token: string | null) => {
|
||||
const { data } = await axios.get(`/lst/old/api/logistics/getsilosdjustment`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getStockSilo() {
|
||||
return queryOptions({
|
||||
queryKey: ["getSiloData"],
|
||||
queryFn: () => fetchStockSilo(),
|
||||
//enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
//refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchStockSilo = async () => {
|
||||
const { data } = await axios.get(`/lst/old/api/logistics/getstocksilo`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getProdPerms(token: string) {
|
||||
return queryOptions({
|
||||
queryKey: ["prodPerms"],
|
||||
queryFn: () => fetch(token),
|
||||
enabled: !!token,
|
||||
staleTime: 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetch = async (token: string) => {
|
||||
const { data } = await axios.get("/api/produser/prodrole", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
// const url: string = window.location.host.split(":")[0];
|
||||
// let settingsData = data.data;
|
||||
// if (url != "localhost") {
|
||||
// settingsData.filter((n: any) => n.name === "devDir");
|
||||
// }
|
||||
return data.data;
|
||||
};
|
||||
@@ -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(`/ocme/api/v1/getInfo`);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -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(`/api/ocp/labelratio`);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -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(`/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 ?? [];
|
||||
};
|
||||
@@ -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("/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 ?? [];
|
||||
};
|
||||
@@ -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(
|
||||
`/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 ?? [];
|
||||
};
|
||||
@@ -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(`/api/ocp/getprinters`);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
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 ?? [];
|
||||
};
|
||||
19
frontend/src/routes/_old/old/-utils/querys/servers.tsx
Normal file
19
frontend/src/routes/_old/old/-utils/querys/servers.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import {queryOptions} from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getServers(token: string) {
|
||||
return queryOptions({
|
||||
queryKey: ["servers"],
|
||||
queryFn: () => fetchSettings(token),
|
||||
enabled: !!token,
|
||||
staleTime: 1000,
|
||||
refetchInterval: 2500,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchSettings = async (token: string) => {
|
||||
const {data} = await axios.get("/api/server/servers", {headers: {Authorization: `Bearer ${token}`}});
|
||||
|
||||
return data.data;
|
||||
};
|
||||
25
frontend/src/routes/_old/old/-utils/querys/settings.tsx
Normal file
25
frontend/src/routes/_old/old/-utils/querys/settings.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getSettings(token: string) {
|
||||
return queryOptions({
|
||||
queryKey: ["settings"],
|
||||
queryFn: () => fetch(token),
|
||||
enabled: !!token,
|
||||
staleTime: 1000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetch = async (token: string) => {
|
||||
const { data } = await axios.get("/api/server/settings", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
// const url: string = window.location.host.split(":")[0];
|
||||
// let settingsData = data.data;
|
||||
// if (url != "localhost") {
|
||||
// settingsData.filter((n: any) => n.name === "devDir");
|
||||
// }
|
||||
return data.data;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
// This type is used to define the shape of our data.
|
||||
// You can use a Zod schema here if you want.
|
||||
export type Adjustmnets = {
|
||||
siloAdjust_id: string;
|
||||
currentStockLevel: string;
|
||||
newLevel: number;
|
||||
dateAdjusted: string;
|
||||
lastDateAdjusted: string;
|
||||
comment: string;
|
||||
commentAddedBy: string;
|
||||
commentDate: string;
|
||||
add_user: string;
|
||||
};
|
||||
|
||||
export const invColumns: ColumnDef<Adjustmnets>[] = [
|
||||
{
|
||||
accessorKey: "Description",
|
||||
header: () => <div className="text-left">Lane</div>,
|
||||
},
|
||||
{
|
||||
accessorKey: "DaysSinceLast",
|
||||
header: "Age",
|
||||
//enableSorting: true,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,164 @@
|
||||
import {
|
||||
type ColumnDef,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
//import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { LstCard } from "../../../-components/extendedUi/LstCard";
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
data: TData[];
|
||||
info: any;
|
||||
}
|
||||
|
||||
type ColumnSort = {
|
||||
id: string;
|
||||
desc: boolean;
|
||||
};
|
||||
type SortingState = ColumnSort[];
|
||||
|
||||
export function InvTable<TData, TValue>({
|
||||
columns,
|
||||
data,
|
||||
info,
|
||||
}: DataTableProps<TData, TValue>) {
|
||||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const [pagination, setPagination] = useState({
|
||||
pageIndex: 0, //initial page index
|
||||
pageSize: 500, //default page size
|
||||
});
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onPaginationChange: setPagination,
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
state: {
|
||||
//...
|
||||
pagination,
|
||||
sorting,
|
||||
},
|
||||
manualSorting: true,
|
||||
onSortingChange: setSorting,
|
||||
initialState: {
|
||||
sorting: [
|
||||
{
|
||||
id: "DaysSinceLast",
|
||||
desc: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
//console.log(table.getState().sorting);
|
||||
//console.log(parseInt(style.height.replace("px", "")) - 50);
|
||||
// console.log(info);
|
||||
return (
|
||||
<LstCard
|
||||
className="p-3"
|
||||
// style={{
|
||||
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
|
||||
// cursor: "move",
|
||||
// }}
|
||||
//style={{ overflow: "auto" }}
|
||||
>
|
||||
<div>
|
||||
<div className="flex flex-row justify-between">
|
||||
<p className="text-center text-pretty">
|
||||
{info.rowType} {data.length > 0 ? "lanes" : "lane"} older than:{" "}
|
||||
{info.age}, {data.length} needing to be completed
|
||||
</p>
|
||||
</div>
|
||||
<ScrollArea className="h-72 rounded-md border m-2">
|
||||
<Table
|
||||
// style={{
|
||||
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
|
||||
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
|
||||
// cursor: "move",
|
||||
// }}
|
||||
>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext(),
|
||||
)}
|
||||
</TableHead>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext(),
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={columns.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
{/* <div className="flex items-center justify-end space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div> */}
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import { format } from "date-fns";
|
||||
|
||||
// This type is used to define the shape of our data.
|
||||
// You can use a Zod schema here if you want.
|
||||
export type Adjustmnets = {
|
||||
siloAdjust_id: string;
|
||||
currentStockLevel: string;
|
||||
newLevel: number;
|
||||
dateAdjusted: string;
|
||||
lastDateAdjusted: string;
|
||||
comment: string;
|
||||
commentAddedBy: string;
|
||||
commentDate: string;
|
||||
add_user: string;
|
||||
};
|
||||
|
||||
export const notifyColumns: ColumnDef<Adjustmnets>[] = [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: () => <div className="text-left">Name</div>,
|
||||
},
|
||||
{
|
||||
accessorKey: "description",
|
||||
header: "Description",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<div className="text-left font-medium">
|
||||
<p className="max-w-48 text-pretty">{row.getValue("description")}</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "checkInterval",
|
||||
header: "Check Interval",
|
||||
},
|
||||
{
|
||||
accessorKey: "timeType",
|
||||
header: "Time tpye",
|
||||
},
|
||||
{
|
||||
accessorKey: "emails",
|
||||
header: "Emails",
|
||||
},
|
||||
{
|
||||
accessorKey: "active",
|
||||
header: "Active",
|
||||
},
|
||||
{
|
||||
accessorKey: "lastRan",
|
||||
header: "Last Ran",
|
||||
cell: ({ row }) => {
|
||||
if (row.getValue("lastRan")) {
|
||||
const correctDate = format(row.getValue("lastRan"), "M/d/yyyy hh:mm");
|
||||
return <div className="text-left font-medium">{correctDate}</div>;
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user