feat(opendock): added in new article link setup for fine tuning how od works
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
||||
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "../../../../components/ui/dialog";
|
||||
import { api } from "../../../../lib/apiHelper";
|
||||
import { useAppForm } from "../../../../lib/formSutff";
|
||||
import { getActiveArticle } from "../../../../lib/queries/getActiveArticles";
|
||||
import { getCustomerByAv } from "../../../../lib/queries/getCustomerByAv";
|
||||
|
||||
export default function NewArticleLink({ refetch }: { refetch: any }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selectedAv, setSelectedAv] = useState<string>("");
|
||||
const { data: articleData } = useSuspenseQuery(getActiveArticle());
|
||||
const {
|
||||
data: customerData,
|
||||
isPending,
|
||||
isLoading,
|
||||
} = useQuery(getCustomerByAv(selectedAv.split(" - ")[0]));
|
||||
|
||||
const form = useAppForm({
|
||||
defaultValues: {
|
||||
av: "",
|
||||
description: "",
|
||||
customer: "",
|
||||
customerDescription: "",
|
||||
loadType: "",
|
||||
dock: "",
|
||||
},
|
||||
|
||||
onSubmit: async ({ value }) => {
|
||||
const corrected = {
|
||||
av: parseInt(value.av.split(" - ")[0], 10),
|
||||
description: value.av.split(" - ")[1],
|
||||
customer: value.customer.split(" - ")[0],
|
||||
customerDescription: value.customer.split(" - ")[1],
|
||||
loadType: value.loadType,
|
||||
dock: value.dock,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await api.post("/opendock/articleCheck", corrected, {
|
||||
validateStatus: () => true,
|
||||
});
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(`The link for ${value.av} was just created :D`);
|
||||
refetch();
|
||||
form.reset();
|
||||
setSelectedAv("");
|
||||
setOpen(false);
|
||||
}
|
||||
|
||||
if (!res.data.success) {
|
||||
toast.error(
|
||||
"The article customer combo are not allowed to be created twice please select a different customer.",
|
||||
);
|
||||
|
||||
form.setFieldValue("customer", "");
|
||||
console.log(res.data);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const closeModel = (e: boolean) => {
|
||||
setOpen(e);
|
||||
|
||||
if (!e) {
|
||||
form.reset();
|
||||
setSelectedAv("");
|
||||
}
|
||||
};
|
||||
|
||||
const openForm = () => {
|
||||
setOpen(true);
|
||||
form.reset;
|
||||
setSelectedAv("");
|
||||
};
|
||||
|
||||
let n: any = [];
|
||||
if (articleData) {
|
||||
n = articleData.map((i: any) => ({
|
||||
label: `${i.article} - ${i.Bezeichnung}`,
|
||||
value: `${i.article} - ${i.Bezeichnung}`,
|
||||
}));
|
||||
}
|
||||
|
||||
let c: any = [];
|
||||
if ((selectedAv && !isPending) || !isLoading) {
|
||||
const cusData = customerData ?? [];
|
||||
c = cusData.map((i: any) => ({
|
||||
label: `${i.customer} - ${i.customerDescription}`,
|
||||
value: `${i.customer} - ${i.customerDescription}`,
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO: get this from lst as well once we get the actual docks in to link to.
|
||||
// this will be live || drop but also the actaul load types so we can have a little more refined times
|
||||
const loadType = [
|
||||
{
|
||||
label: "Live",
|
||||
value: "live",
|
||||
},
|
||||
{
|
||||
label: "Drop",
|
||||
value: "drop",
|
||||
},
|
||||
];
|
||||
|
||||
//TODO: get the docks from lst to help refine and actually link the dock correctly
|
||||
const dock = [
|
||||
{
|
||||
label: "Cermac",
|
||||
value: "cermac",
|
||||
},
|
||||
{
|
||||
label: "Gerber",
|
||||
value: "gerber",
|
||||
},
|
||||
{
|
||||
label: "Matrix",
|
||||
value: "matrix",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Dialog onOpenChange={(e) => closeModel(e)} open={open}>
|
||||
<Button onClick={openForm}>Create Article link</Button>
|
||||
|
||||
<DialogContent showCloseButton={false} className="min-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Article Link.</DialogTitle>
|
||||
<DialogDescription>
|
||||
Create the fine tuned per article setup, selecting an av will pull
|
||||
in only the sales prices for the av, After filling in the form all{" "}
|
||||
<p className="underline">NEW</p> release created will use this as
|
||||
the new default settings.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
form.handleSubmit();
|
||||
}}
|
||||
>
|
||||
<div className="w-fit">
|
||||
<div className="w-fill">
|
||||
<form.AppField
|
||||
name="av"
|
||||
listeners={{
|
||||
onChange: ({ value }) => {
|
||||
setSelectedAv(value);
|
||||
|
||||
if (form.getFieldValue("customer")) {
|
||||
form.setFieldValue("customer", "");
|
||||
}
|
||||
},
|
||||
}}
|
||||
>
|
||||
{(field) => (
|
||||
<field.SelectField
|
||||
label="Select Article"
|
||||
placeholder="Select av to link"
|
||||
options={n}
|
||||
/>
|
||||
)}
|
||||
</form.AppField>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-fit">
|
||||
<div className="w-fill">
|
||||
<form.AppField name="customer">
|
||||
{(field) => (
|
||||
<field.SelectField
|
||||
label="Select Customer"
|
||||
placeholder={
|
||||
!selectedAv
|
||||
? "Select AV first"
|
||||
: isLoading
|
||||
? "Loading customers..."
|
||||
: c.length === 0
|
||||
? "No customers to select"
|
||||
: "Select customer"
|
||||
}
|
||||
options={c}
|
||||
disabled={!selectedAv || (isLoading && c.length > 0)}
|
||||
/>
|
||||
)}
|
||||
</form.AppField>
|
||||
</div>
|
||||
</div>
|
||||
<div className=" flex flex-row w-fit mt-3">
|
||||
<div className="w-fill">
|
||||
<form.AppField name="loadType">
|
||||
{(field) => (
|
||||
<field.SelectField
|
||||
label="Select Load Type"
|
||||
placeholder={"Select LoadType"}
|
||||
options={loadType}
|
||||
disabled={!selectedAv}
|
||||
/>
|
||||
)}
|
||||
</form.AppField>
|
||||
</div>
|
||||
<div className="w-fill">
|
||||
<form.AppField name="dock">
|
||||
{(field) => (
|
||||
<field.SelectField
|
||||
label="Select Dock"
|
||||
placeholder={"Select dock"}
|
||||
options={dock}
|
||||
disabled={!selectedAv}
|
||||
/>
|
||||
)}
|
||||
</form.AppField>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2 ">
|
||||
<form.AppForm>
|
||||
<form.SubmitButton>Submit</form.SubmitButton>
|
||||
</form.AppForm>
|
||||
</div>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
122
frontend/src/routes/transportation/opendock/index.tsx
Normal file
122
frontend/src/routes/transportation/opendock/index.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { createColumnHelper } from "@tanstack/react-table";
|
||||
import { Suspense } from "react";
|
||||
import { authClient } from "../../../lib/auth-client";
|
||||
import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
|
||||
import LstTable from "../../../lib/tableStuff/LstTable";
|
||||
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
|
||||
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
|
||||
import NewArticleLink from "./-components/NewArticleLink";
|
||||
|
||||
export const Route = createFileRoute("/transportation/opendock/")({
|
||||
beforeLoad: async ({ location }) => {
|
||||
const { data: session } = await authClient.getSession();
|
||||
//const allowedRole = ["systemAdmin", "admin", "manager"];
|
||||
|
||||
const canAccess = await authClient.admin.hasPermission({
|
||||
permissions: {
|
||||
openDock: ["create"],
|
||||
},
|
||||
});
|
||||
|
||||
if (!session?.user) {
|
||||
throw redirect({
|
||||
to: "/",
|
||||
search: {
|
||||
redirect: location.href,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
//if (!allowedRole.includes(session.user.role as string)) {
|
||||
|
||||
if (!canAccess) {
|
||||
throw redirect({
|
||||
to: "/",
|
||||
});
|
||||
}
|
||||
|
||||
return { user: session.user };
|
||||
},
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
const ArticleLinkTable = () => {
|
||||
const { data, refetch } = useSuspenseQuery(getArticleLinks());
|
||||
|
||||
const columnHelper = createColumnHelper<any>();
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("av", {
|
||||
header: ({ column }) => (
|
||||
<SearchableHeader column={column} title="Article" searchable={true} />
|
||||
),
|
||||
filterFn: "includesString",
|
||||
cell: (i) => i.getValue(),
|
||||
}),
|
||||
columnHelper.accessor("description", {
|
||||
header: ({ column }) => (
|
||||
<SearchableHeader
|
||||
column={column}
|
||||
title="Description"
|
||||
searchable={true}
|
||||
/>
|
||||
),
|
||||
filterFn: "includesString",
|
||||
cell: (i) => i.getValue(),
|
||||
}),
|
||||
columnHelper.accessor("customer", {
|
||||
header: ({ column }) => (
|
||||
<SearchableHeader column={column} title="Customer" searchable={true} />
|
||||
),
|
||||
filterFn: "includesString",
|
||||
cell: (i) => (
|
||||
<span>
|
||||
{i.row.original.customer} - {i.row.original.customerDescription}
|
||||
</span>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor("loadType", {
|
||||
header: ({ column }) => (
|
||||
<SearchableHeader column={column} title="Load Type" searchable={true} />
|
||||
),
|
||||
filterFn: "includesString",
|
||||
cell: (i) => i.getValue(),
|
||||
}),
|
||||
columnHelper.accessor("dock", {
|
||||
header: ({ column }) => (
|
||||
<SearchableHeader column={column} title="Dock" searchable={true} />
|
||||
),
|
||||
filterFn: "includesString",
|
||||
cell: (i) => i.getValue(),
|
||||
}),
|
||||
];
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<div className="flex justify-end m-2">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div>
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<NewArticleLink refetch={refetch} />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div>
|
||||
<LstTable data={data} columns={columns} pageSize={50} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<Suspense fallback={<SkellyTable />}>
|
||||
<ArticleLinkTable />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user