import { useSelect, useTranslate } from "@refinedev/core"; import { useQueries } from "@tanstack/react-query"; import { Form, InputNumber, Modal, Radio } from "antd"; import { useForm } from "antd/es/form/Form"; import type { InputNumberRef } from "rc-input-number"; import { useCallback, useMemo, useRef, useState } from "react"; import { formatLength, formatWeight } from "../../utils/parsing"; import { SpoolType, useGetExternalDBFilaments } from "../../utils/queryExternalDB"; import { getAPIURL } from "../../utils/url"; import { IFilament } from "../filaments/model"; import { ISpool } from "./model"; export async function setSpoolArchived(spool: ISpool, archived: boolean) { const init: RequestInit = { method: "PATCH", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ archived: archived, }), }; const request = new Request(getAPIURL() + "/spool/" + spool.id); await fetch(request, init); } /** * Use some spool filament from this spool. Either specify length or weight. * @param spool The spool * @param length The length to add/subtract from the spool, in mm * @param weight The weight to add/subtract from the spool, in g */ export async function useSpoolFilament(spool: ISpool, length?: number, weight?: number) { const init: RequestInit = { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ use_length: length, use_weight: weight, }), }; const request = new Request(`${getAPIURL()}/spool/${spool.id}/use`); await fetch(request, init); } /** * Adjust usage based on the spool's current gross weight * @param spool The spool * @param weight The weight of the spool, in g */ export async function useSpoolFilamentMeasure(spool: ISpool, weight: number) { const init: RequestInit = { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ weight: weight, }), }; const request = new Request(`${getAPIURL()}/spool/${spool.id}/measure`); await fetch(request, init); } /** * Returns an array of queries using the useQueries hook from @tanstack/react-query. * Each query fetches a spool by its ID from the server. * * @param {number[]} ids - An array of spool IDs to fetch. * @return An array of query results, each containing the fetched spool data. */ export function useGetSpoolsByIds(ids: number[]) { return useQueries({ queries: ids.map((id) => { return { queryKey: ["spool", id], queryFn: async () => { const res = await fetch(getAPIURL() + "/spool/" + id); return (await res.json()) as ISpool; }, }; }), }); } /** * Formats a filament label with the given parameters. */ export function formatFilamentLabel( name: string, diameter: number, vendorName?: string, material?: string, weight?: number, spoolType?: SpoolType ): string { const portions = []; if (vendorName) { portions.push(vendorName); } portions.push(name); const extras = []; if (material) { extras.push(material); } extras.push(formatLength(diameter)); if (weight) { extras.push(formatWeight(weight)); } if (spoolType) { extras.push(spoolType.charAt(0).toUpperCase() + spoolType.slice(1) + " spool"); } return `${portions.join(" - ")} (${extras.join(", ")})`; } interface SelectOption { label: string; value: string | number; weight?: number; spool_weight?: number; is_internal: boolean; } export function useGetFilamentSelectOptions() { // Setup hooks const t = useTranslate(); const { query: internalFilaments } = useSelect({ resource: "filament", }); const externalFilaments = useGetExternalDBFilaments(); // Format and sort internal filament options const filamentSelectInternal: SelectOption[] = useMemo(() => { const data = internalFilaments.data?.data.map((item) => { return { label: formatFilamentLabel( item.name ?? `ID ${item.id}`, item.diameter, item.vendor?.name, item.material, item.weight ), value: item.id, weight: item.weight, spool_weight: item.spool_weight, is_internal: true, }; }) ?? []; data.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" })); return data; }, [internalFilaments.data?.data]); // Format and sort external filament options const filamentSelectExternal: SelectOption[] = useMemo(() => { const data = externalFilaments.data?.map((item) => { return { label: formatFilamentLabel( item.name, item.diameter, item.manufacturer, item.material, item.weight, item.spool_type ), value: item.id, weight: item.weight, spool_weight: item.spool_weight || undefined, is_internal: false, }; }) ?? []; data.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" })); return data; }, [externalFilaments.data]); return { options: [ { label: {t("spool.fields.filament_internal")}, options: filamentSelectInternal, }, { label: {t("spool.fields.filament_external")}, options: filamentSelectExternal, }, ], internalSelectOptions: filamentSelectInternal, externalSelectOptions: filamentSelectExternal, allExternalFilaments: externalFilaments.data, refetch: internalFilaments.refetch, }; } type MeasurementType = "length" | "weight" | "measured_weight"; export function useSpoolAdjustModal() { const t = useTranslate(); const [form] = useForm(); const [curSpool, setCurSpool] = useState(null); const [measurementType, setMeasurementType] = useState("length"); const inputNumberRef = useRef(null); const openSpoolAdjustModal = useCallback((spool: ISpool) => { setCurSpool(spool); setTimeout(() => { inputNumberRef.current?.focus(); }, 0); }, []); const spoolAdjustModal = useMemo(() => { if (curSpool === null) { return null; } const onSubmit = async () => { if (curSpool === null) { return; } const value = form.getFieldValue("filament_value"); if (value === undefined || value === null) { return; } if (measurementType === "length") { await useSpoolFilament(curSpool, value, undefined); } else if (measurementType === "weight") { await useSpoolFilament(curSpool, undefined, value); } else { await useSpoolFilamentMeasure(curSpool, value); } setCurSpool(null); }; return ( setCurSpool(null)} onOk={form.submit}>

{t("spool.form.adjust_filament_help")}

setMeasurementType(value as MeasurementType)} > {t("spool.form.measurement_type.length")} {t("spool.form.measurement_type.weight")} {t("spool.fields.measured_weight")}
); }, [curSpool, measurementType, t]); return { openSpoolAdjustModal, spoolAdjustModal, }; }