feat(silo attached detach): added in silo attach detach setup in the silo card

This commit is contained in:
2025-06-23 12:00:28 -05:00
parent d6d19f8e5b
commit 2ac48138cb
22 changed files with 1362 additions and 598 deletions

View File

@@ -0,0 +1,14 @@
import { createFormHook, createFormHookContexts } from "@tanstack/react-form";
import { InputField } from "./options/InputField";
import { SubmitButton } from "./options/submitButton";
import { SelectField } from "./options/selectorField";
export const { fieldContext, useFieldContext, formContext, useFormContext } =
createFormHookContexts();
export const { useAppForm } = createFormHook({
fieldComponents: { InputField, SelectField },
formComponents: { SubmitButton },
fieldContext,
formContext,
});

View File

@@ -0,0 +1,16 @@
import { AnyFieldMeta } from "@tanstack/react-form";
import { ZodError } from "zod";
type FieldErrorsProps = {
meta: AnyFieldMeta;
};
export const FieldErrors = ({ meta }: FieldErrorsProps) => {
if (!meta.isTouched) return null;
return meta.errors.map(({ message }: ZodError, index) => (
<p key={index} className="text-sm font-medium text-destructive">
{message}
</p>
));
};

View File

@@ -1,32 +1,28 @@
//import { Input } from "@/components/ui/input";
//import { Label } from "@radix-ui/react-dropdown-menu";
import { Label } from "@/components/ui/label";
import { useFieldContext } from "..";
import { Input } from "@/components/ui/input";
import { FieldErrors } from "./FieldErrors";
// export const FormInput = (form: any, label: string) => {
// // <form.Field
// // name="username"
// // 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">
// // <Label htmlFor="username">{label}</Label>
// // <Input
// // name={field.name}
// // value={field.state.value}
// // onBlur={field.handleBlur}
// // //type="number"
// // onChange={(e) => field.handleChange(e.target.value)}
// // />
// // {field.state.meta.errors.length ? (
// // <em>{field.state.meta.errors.join(",")}</em>
// // ) : null}
// // </div>
// // );
// // }}
// // />;
// };
type InputFieldProps = {
label: string;
inputType: string;
required: boolean;
};
export const InputField = ({ label, inputType, required }: InputFieldProps) => {
const field = useFieldContext<any>();
return (
<div className="grid gap-3">
<Label htmlFor={field.name}>{label}</Label>
<Input
id={field.name}
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
onBlur={field.handleBlur}
type={inputType}
required={required}
/>
<FieldErrors meta={field.state.meta} />
</div>
);
};

View File

@@ -0,0 +1,57 @@
import { Label } from "@/components/ui/label";
import { useFieldContext } from "..";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { FieldErrors } from "./FieldErrors";
type SelectOption = {
value: string;
label: string;
};
type SelectFieldProps = {
label: string;
options: SelectOption[];
placeholder?: string;
};
export const SelectField = ({
label,
options,
placeholder,
}: SelectFieldProps) => {
const field = useFieldContext<string>();
return (
<div className="grid gap-3">
<div className="grid gap-3">
<Label htmlFor={field.name}>{label}</Label>
<Select
value={field.state.value}
onValueChange={(value) => field.handleChange(value)}
>
<SelectTrigger
id={field.name}
onBlur={field.handleBlur}
className="w-[380px]"
>
<SelectValue placeholder={placeholder} />
</SelectTrigger>
<SelectContent>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<FieldErrors meta={field.state.meta} />
</div>
);
};

View File

@@ -0,0 +1,24 @@
import { useStore } from "@tanstack/react-form";
import { useFormContext } from "..";
import { Button } from "@/components/ui/button";
type SubmitButtonProps = {
children: React.ReactNode;
};
export const SubmitButton = ({ children }: SubmitButtonProps) => {
const form = useFormContext();
const [isSubmitting] = useStore(form.store, (state) => [
state.isSubmitting,
state.canSubmit,
]);
return (
<div className="">
<Button type="submit" disabled={isSubmitting}>
{children}
</Button>
</div>
);
};

View File

@@ -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(`/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 ?? [];
};

View File

@@ -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(`/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 ?? [];
};