test(ocp): more work on the dashboard
This commit is contained in:
@@ -1,5 +1,92 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {CardHeader} from "@/components/ui/card";
|
||||||
|
import {Skeleton} from "@/components/ui/skeleton";
|
||||||
|
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||||
|
// import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
// import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
|
import {useQuery} from "@tanstack/react-query";
|
||||||
|
import {getlabels} from "@/utils/querys/production/labels";
|
||||||
|
import {format} from "date-fns";
|
||||||
|
|
||||||
|
const labelLogs = [
|
||||||
|
{key: "line", label: "Line"},
|
||||||
|
{key: "printerName", label: "Printer"},
|
||||||
|
{key: "runningNr", label: "Running #"},
|
||||||
|
{key: "upd_date", label: "Label date"},
|
||||||
|
{key: "status", label: "Label Status"},
|
||||||
|
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
|
||||||
|
];
|
||||||
export default function LabelLog() {
|
export default function LabelLog() {
|
||||||
return <LstCard className="m-2 p-2"> label logs here</LstCard>;
|
const {data, isError, error, isLoading} = useQuery(getlabels("4"));
|
||||||
|
//const {user} = useSessionStore();
|
||||||
|
//const {settings} = useSettingStore();
|
||||||
|
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||||
|
|
||||||
|
//const roles = ["admin", "manager", "operator"];
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>There was an error loading the lots</CardHeader>
|
||||||
|
{JSON.stringify(error)}
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LstCard className="m-2 p-2 min-h-2/5">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
{labelLogs.map((l) => (
|
||||||
|
<TableHead key={l.key}>{l.label}</TableHead>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<TableBody>
|
||||||
|
{Array(7)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TableBody>
|
||||||
|
{data?.map((label: any) => (
|
||||||
|
<TableRow key={label.runningNr}>
|
||||||
|
<TableCell className="font-medium">{label.line}</TableCell>
|
||||||
|
<TableCell className="font-medium">{label.printerName}</TableCell>
|
||||||
|
<TableCell className="font-medium">{label.runningNr}</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
{format(label.upd_date, "M/d/yyyy hh:mm")}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">{label.status}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,177 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import {LstCard} from "@/components/extendedUI/LstCard";
|
||||||
|
import {CardHeader} from "@/components/ui/card";
|
||||||
|
import {Skeleton} from "@/components/ui/skeleton";
|
||||||
|
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import {getlots} from "@/utils/querys/production/lots";
|
||||||
|
import {useQuery} from "@tanstack/react-query";
|
||||||
|
import ManualPrint from "./ManualPrinting/ManualPrint";
|
||||||
|
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
|
||||||
|
|
||||||
|
let lotColumns = [
|
||||||
|
{
|
||||||
|
key: "MachineDescription",
|
||||||
|
label: "Machine",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "AV",
|
||||||
|
label: "AV",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Alias",
|
||||||
|
label: "AvDescription",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "LOT",
|
||||||
|
label: "LotNumber",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ProlinkLot",
|
||||||
|
label: "ProlinkLot",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "PlannedQTY",
|
||||||
|
label: "PlannedQTY",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Produced",
|
||||||
|
label: "Produced",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "Remaining",
|
||||||
|
label: "Remaining",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "overPrinting",
|
||||||
|
label: "Overprinting",
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// key: "lastProlinkUpdate",
|
||||||
|
// label: "Last ProlinkCheck",
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: "printLabel",
|
||||||
|
// label: "Print Label",
|
||||||
|
// },
|
||||||
|
];
|
||||||
export default function Lots() {
|
export default function Lots() {
|
||||||
|
const {data, isError, error, isLoading} = useQuery(getlots());
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
const {settings} = useSettingStore();
|
||||||
|
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||||
|
|
||||||
|
console.log(server);
|
||||||
|
|
||||||
|
const roles = ["admin", "manager", "operator"];
|
||||||
|
|
||||||
|
if (user && roles.includes(user.role)) {
|
||||||
|
//width = 1280;
|
||||||
|
const checkCol = lotColumns.some((l) => l.key === "printLabel");
|
||||||
|
if (!checkCol) {
|
||||||
|
lotColumns = [
|
||||||
|
...lotColumns,
|
||||||
|
{
|
||||||
|
key: "printLabel",
|
||||||
|
label: "Print Label",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>There was an error loading the lots</CardHeader>
|
||||||
|
{JSON.stringify(error)}
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LstCard className="m-2 p-2 min-h-2/5">
|
<LstCard className="m-2 p-2 min-h-2/5">
|
||||||
<h1>Lots</h1>
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
{lotColumns.map((l) => (
|
||||||
|
<TableHead key={l.key}>{l.label}</TableHead>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<TableBody>
|
||||||
|
{Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TableBody>
|
||||||
|
{data?.map((lot: LotType) => (
|
||||||
|
<TableRow key={lot.LabelOnlineID}>
|
||||||
|
<TableCell className="font-medium">{lot.MachineLocation}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.AV}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.Alias}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.LOT}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.ProlinkLot}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.PlannedQTY}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.Produced}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.Remaining}</TableCell>
|
||||||
|
<TableCell className="font-medium">{lot.overPrinting}</TableCell>
|
||||||
|
{user && roles.includes(user.role) && (
|
||||||
|
<>
|
||||||
|
{server === "usday1vms006" || server === "localhost" ? (
|
||||||
|
<>
|
||||||
|
<TableCell className="flex justify-center">
|
||||||
|
<ManualPrintForm lot={lot} />
|
||||||
|
</TableCell>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<TableCell className="flex justify-center">
|
||||||
|
<ManualPrint lot={lot} />
|
||||||
|
</TableCell>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
//import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import {Tag} from "lucide-react";
|
||||||
|
import {toast} from "sonner";
|
||||||
|
import {manualPrintLabels} from "./ManualPrintLabel";
|
||||||
|
|
||||||
|
export default function ManualPrint({lot}: {lot: LotType}) {
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
//const {settings} = useSettingStore();
|
||||||
|
//const server = settings.filter((n) => n.name === "server")[0]?.value;
|
||||||
|
//const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
|
||||||
|
//const serverUrl = `http://${server}:${serverPort}`;
|
||||||
|
|
||||||
|
const handlePrintLabel = async (lot: LotType) => {
|
||||||
|
//console.log(lot);
|
||||||
|
|
||||||
|
const labels: any = await manualPrintLabels(lot, user);
|
||||||
|
|
||||||
|
if (labels.success) {
|
||||||
|
toast.success(labels.message);
|
||||||
|
} else {
|
||||||
|
toast.error(labels.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Button variant="outline" size="icon" onClick={() => handlePrintLabel(lot)}>
|
||||||
|
<Tag className="h-[16px] w-[16px]" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
import {Button} from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import {Input} from "@/components/ui/input";
|
||||||
|
import {Label} from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import {Textarea} from "@/components/ui/textarea";
|
||||||
|
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||||
|
import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import axios from "axios";
|
||||||
|
import {Tag} from "lucide-react";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {Controller, useForm} from "react-hook-form";
|
||||||
|
import {toast} from "sonner";
|
||||||
|
import {manualPrintLabels} from "./ManualPrintLabel";
|
||||||
|
|
||||||
|
const printReason = [
|
||||||
|
{key: "printerIssue", label: "Printer Related"},
|
||||||
|
{key: "strapper", label: "Strapper Error"},
|
||||||
|
{key: "manualCheck", label: "20th pallet check"},
|
||||||
|
{key: "outOfSync", label: "Labeler Out of Sync"},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ManualPrintForm({lot}: {lot: LotType}) {
|
||||||
|
const {user} = useSessionStore();
|
||||||
|
const token = localStorage.getItem("auth_token");
|
||||||
|
const {settings} = useSettingStore();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const server = settings.filter((n) => n.name === "server")[0]?.value;
|
||||||
|
// const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
|
||||||
|
// const serverUrl = `http://${server}:${serverPort}`;
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
//watch,
|
||||||
|
formState: {errors},
|
||||||
|
reset,
|
||||||
|
control,
|
||||||
|
} = useForm();
|
||||||
|
|
||||||
|
const handlePrintLabel = async (lot: LotType) => {
|
||||||
|
//console.log(lot);
|
||||||
|
const labels: any = await manualPrintLabels(lot, user);
|
||||||
|
|
||||||
|
if (labels.success) {
|
||||||
|
toast.success(labels.message);
|
||||||
|
} else {
|
||||||
|
toast.error(labels.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleManualPrintLog = async (logData: any, lot: LotType) => {
|
||||||
|
// toast.success(`A new label was sent to printer: ${lot.PrinterName} for line ${lot.MachineDescription} `);
|
||||||
|
const logdataUrl = `/api/ocp/manualLabelLog`;
|
||||||
|
axios
|
||||||
|
.post(logdataUrl, logData, {headers: {Authorization: `Bearer ${token}`}})
|
||||||
|
.then((d) => {
|
||||||
|
//console.log(d);
|
||||||
|
toast.success(d.data.message);
|
||||||
|
handlePrintLabel(lot);
|
||||||
|
reset();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
if (e.response.status === 500) {
|
||||||
|
toast.error(`Internal Server error please try again.`);
|
||||||
|
return {sucess: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.response.status === 401) {
|
||||||
|
//console.log(e.response);
|
||||||
|
toast.error(`You are not authorized to do this.`);
|
||||||
|
return {sucess: false};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (data: any) => {
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
handleManualPrintLog(data, lot);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
if (!open) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
setOpen(isOpen);
|
||||||
|
// toast.message("Model was something", {
|
||||||
|
// description: isOpen ? "Modal is open" : "Modal is closed",
|
||||||
|
// });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<Tag className="h-[16px] w-[16px]" />
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Edit profile</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Make changes to your profile here. Click save when you're done.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<p>
|
||||||
|
To manually print a label you must complete all the required fields below.
|
||||||
|
<br />
|
||||||
|
If you clicked this in error just click close
|
||||||
|
</p>
|
||||||
|
<hr className="mt-2 mb-2" />
|
||||||
|
{server == "usday1vms006" ? (
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="printReason"
|
||||||
|
defaultValue={""}
|
||||||
|
render={({
|
||||||
|
field: {onChange},
|
||||||
|
fieldState: {},
|
||||||
|
//formState,
|
||||||
|
}) => (
|
||||||
|
<Select onValueChange={onChange}>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue placeholder="Select Reason" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>Print Reasons</SelectLabel>
|
||||||
|
{printReason.map((printReason: any) => (
|
||||||
|
<SelectItem value={printReason.key}>{printReason.label}</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="printRason" className="m-1">
|
||||||
|
Why are you manually printing?
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
className={errors.printReason ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.printReason}
|
||||||
|
{...register("printReason", {
|
||||||
|
required: true,
|
||||||
|
minLength: {
|
||||||
|
value: 5,
|
||||||
|
message: "To short of a reason please try again!",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="line" className="m-1">
|
||||||
|
"What is the line number you are printing?"
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
//variant="underlined"
|
||||||
|
type="number"
|
||||||
|
className={errors.line ? "border-red-500" : ""}
|
||||||
|
aria-invalid={!!errors.line}
|
||||||
|
{...register("line", {required: true})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label htmlFor="initials" className="m-1">
|
||||||
|
Enter intials
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
//variant="underlined"
|
||||||
|
//label="Enter intials"
|
||||||
|
|
||||||
|
{...register("initials", {required: true})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Textarea
|
||||||
|
//label="Comments"
|
||||||
|
placeholder="add more info as needed."
|
||||||
|
{...register("additionalComments")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button color="danger" variant="default" onClick={() => setOpen(!open)}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
<Button color="primary" type="submit">
|
||||||
|
Print
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {LotType} from "@/types/lots";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export const manualPrintLabels = async (lot: LotType, user: any) => {
|
||||||
|
//console.log(lot);
|
||||||
|
const labelUrl = `/ocp/manualPrintAndFollow`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.post(
|
||||||
|
labelUrl,
|
||||||
|
{line: lot.MachineLocation, printerName: lot.PrinterName},
|
||||||
|
{headers: {Authorization: `Basic ${user?.prod}`}}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `A new label was printed for ${lot.MachineDescription} to printer: ${lot.PrinterName}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Line ${lot.MachineDescription} encountered an error printing labels: ${res.data.message}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.response.status === 500) {
|
||||||
|
//toast.error(`Internal Server error please try again.`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Internal Server error please try again.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
//console.log(e.response);
|
||||||
|
//toast.error(`You are not authorized to do this.`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `You are not authorized to do this.`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
||||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
import {useModuleStore} from "../../lib/store/useModuleStore";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
|
import {useSettingStore} from "@/lib/store/useSettings";
|
||||||
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
||||||
const {fetchModules} = useModuleStore();
|
const {fetchModules} = useModuleStore();
|
||||||
|
const {fetchSettings} = useSettingStore();
|
||||||
//const {fetchUserRoles} = useGetUserRoles();
|
//const {fetchUserRoles} = useGetUserRoles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchModules();
|
fetchModules();
|
||||||
|
fetchSettings();
|
||||||
//fetchUserRoles();
|
//fetchUserRoles();
|
||||||
}, []);
|
}, []);
|
||||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
||||||
|
|||||||
183
frontend/src/components/ui/select.tsx
Normal file
183
frontend/src/components/ui/select.tsx
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as SelectPrimitive from "@radix-ui/react-select"
|
||||||
|
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Select({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||||
|
return <SelectPrimitive.Root data-slot="select" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectGroup({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||||
|
return <SelectPrimitive.Group data-slot="select-group" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectValue({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||||
|
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectTrigger({
|
||||||
|
className,
|
||||||
|
size = "default",
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||||
|
size?: "sm" | "default"
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Trigger
|
||||||
|
data-slot="select-trigger"
|
||||||
|
data-size={size}
|
||||||
|
className={cn(
|
||||||
|
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<SelectPrimitive.Icon asChild>
|
||||||
|
<ChevronDownIcon className="size-4 opacity-50" />
|
||||||
|
</SelectPrimitive.Icon>
|
||||||
|
</SelectPrimitive.Trigger>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectContent({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
position = "popper",
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Portal>
|
||||||
|
<SelectPrimitive.Content
|
||||||
|
data-slot="select-content"
|
||||||
|
className={cn(
|
||||||
|
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
||||||
|
position === "popper" &&
|
||||||
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
position={position}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SelectScrollUpButton />
|
||||||
|
<SelectPrimitive.Viewport
|
||||||
|
className={cn(
|
||||||
|
"p-1",
|
||||||
|
position === "popper" &&
|
||||||
|
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SelectPrimitive.Viewport>
|
||||||
|
<SelectScrollDownButton />
|
||||||
|
</SelectPrimitive.Content>
|
||||||
|
</SelectPrimitive.Portal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectLabel({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Label
|
||||||
|
data-slot="select-label"
|
||||||
|
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectItem({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Item
|
||||||
|
data-slot="select-item"
|
||||||
|
className={cn(
|
||||||
|
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
||||||
|
<SelectPrimitive.ItemIndicator>
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ItemIndicator>
|
||||||
|
</span>
|
||||||
|
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||||
|
</SelectPrimitive.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectSeparator({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.Separator
|
||||||
|
data-slot="select-separator"
|
||||||
|
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectScrollUpButton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.ScrollUpButton
|
||||||
|
data-slot="select-scroll-up-button"
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default items-center justify-center py-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronUpIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ScrollUpButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectScrollDownButton({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
||||||
|
return (
|
||||||
|
<SelectPrimitive.ScrollDownButton
|
||||||
|
data-slot="select-scroll-down-button"
|
||||||
|
className={cn(
|
||||||
|
"flex cursor-default items-center justify-center py-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronDownIcon className="size-4" />
|
||||||
|
</SelectPrimitive.ScrollDownButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
|
SelectScrollDownButton,
|
||||||
|
SelectScrollUpButton,
|
||||||
|
SelectSeparator,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
}
|
||||||
18
frontend/src/components/ui/textarea.tsx
Normal file
18
frontend/src/components/ui/textarea.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
data-slot="textarea"
|
||||||
|
className={cn(
|
||||||
|
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Textarea }
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/ocp/lots')({
|
|
||||||
component: RouteComponent,
|
|
||||||
})
|
|
||||||
|
|
||||||
function RouteComponent() {
|
|
||||||
return <div>Hello "/ocp/lots"!</div>
|
|
||||||
}
|
|
||||||
19
frontend/src/types/lots.ts
Normal file
19
frontend/src/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/utils/querys/production/labels.tsx
Normal file
20
frontend/src/utils/querys/production/labels.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {queryOptions} from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getlabels(hours: string) {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["labels"],
|
||||||
|
queryFn: () => fetchSettings(hours),
|
||||||
|
|
||||||
|
staleTime: 1000,
|
||||||
|
refetchInterval: 2500,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSettings = async (hours: string) => {
|
||||||
|
const {data} = await axios.get(`/api/v1/ocp/labels?hours=${hours}`);
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
21
frontend/src/utils/querys/production/lots.tsx
Normal file
21
frontend/src/utils/querys/production/lots.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {queryOptions} from "@tanstack/react-query";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export function getlots() {
|
||||||
|
return queryOptions({
|
||||||
|
queryKey: ["lots"],
|
||||||
|
queryFn: () => fetchSettings(),
|
||||||
|
|
||||||
|
staleTime: 10 * 1000,
|
||||||
|
refetchInterval: 10 * 1000,
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSettings = async () => {
|
||||||
|
const {data} = await axios.get("/api/v1/ocp/lots");
|
||||||
|
// if we are not localhost ignore the devDir setting.
|
||||||
|
//const url: string = window.location.host.split(":")[0];
|
||||||
|
let lotData = data.data;
|
||||||
|
return lotData;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user