From 59c58362baf57fb6a69d3bf2daf0df17117039c3 Mon Sep 17 00:00:00 2001 From: maziggy Date: Fri, 1 May 2026 08:21:37 +0200 Subject: [PATCH] fix(printers): copy buttons in Printer Info modal work on plain HTTP (#1174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PrinterInfoModal's CopyButton only tried navigator.clipboard.writeText(), which is gated by the secure-context requirement (HTTPS or localhost). On the typical Bambuddy deployment shape — bare-IP HTTP on the LAN — navigator.clipboard is undefined; the existing try/catch swallowed the TypeError, the icon never flipped to the tick, and nothing landed on the user's clipboard. Fixed by adding the same off-screen-textarea + document.execCommand('copy') fallback that CameraTokensPage's plaintext-token modal already uses for plain-HTTP LAN deployments. Gate on `navigator.clipboard && window.isSecureContext`, fall back to the legacy path otherwise, and surface the success-tick only when the copy actually landed (return early without flipping `copied` if execCommand returns false). The try/finally around the textarea guarantees DOM cleanup even when the browser throws on a restricted context. 3 new component tests in PrinterInfoModal.test.tsx cover the secure-context happy path (navigator.clipboard.writeText is called with the correct value), the plain-HTTP fallback path (execCommand is invoked, no leaked textarea left in the DOM), and the finally cleanup when execCommand throws synthetically. --- CHANGELOG.md | 2 + .../components/PrinterInfoModal.test.tsx | 136 ++++++++++++++++++ frontend/src/components/PrinterInfoModal.tsx | 26 +++- .../{index-D4GSGeyj.js => index-BM5VeuBp.js} | 2 +- static/index.html | 2 +- 5 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 frontend/src/__tests__/components/PrinterInfoModal.test.tsx rename static/assets/{index-D4GSGeyj.js => index-BM5VeuBp.js} (99%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c2c7ba67..b36f01955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ All notable changes to Bambuddy will be documented in this file. - **Filament Track Switch (FTS) support — print modal filament dropdown is no longer empty when an X2D / H2D has the FTS accessory installed** ([#1162](https://github.com/maziggy/bambuddy/issues/1162), reported by @mkavalecz) — When the FTS accessory is installed the printer's MQTT changes one nibble of the per-AMS `info` bitmask: bits 8-11 flip from a fixed extruder ID (0x0 / 0x1) to `0xE` ("uninitialized"), because the AMS is no longer wired to a single nozzle — the FTS dynamically routes any slot to either extruder. Bambuddy's MQTT parser already skipped 0xE entries when building `ams_extruder_map` (matching BambuStudio's reading for boot-time transient state), so with the FTS installed the map ended up empty and the print modal's filament dropdown — which filters by `extruderId === nozzle_id` to prevent cross-nozzle assignment ("position of left hotend is abnormal" failures) — filtered out *every* loaded slot. Net effect: empty Filament Mapping dropdown on every dual-nozzle print with the FTS, even when the AMS was fully loaded with the right material. Detection comes from a new MQTT field — `print.device.fila_switch` — which is non-null only when the accessory is installed; it carries the routing topology as two arrays: `in[track] = currently fed slot (-1 = empty)` and `out[track] = extruder this track terminates at`. The fix surfaces this through a new `FilaSwitchState` dataclass on `PrinterState` (`installed`, `in_slots`, `out_extruders`, `stat`, `info`) and the equivalent `FilaSwitchResponse` Pydantic schema on the `GET /printers/{id}/status` route. Frontend (`useFilamentMapping.ts` + `FilamentMapping.tsx`) skips the per-extruder filter when `printerStatus.fila_switch?.installed === true` so any compatible AMS slot can satisfy any nozzle's filament requirement, since the FTS handles the routing. Slots currently fed into a track also get a routing badge in the dropdown — `[L]` or `[R]` — so the user can tell at a glance which slot the FTS is currently routing where (idle slots get no badge: they can be routed to either extruder on demand). The hard "no cross-nozzle assignment" filter on real dual-nozzle printers without the FTS stays untouched (still trips the same way it always has — `fila_switch == null` keeps the existing behaviour). 4 backend tests in `test_bambu_mqtt.py::TestFilamentTrackSwitchDetection` (default-not-installed, detect-from-MQTT-using-the-reporter's-bundle, no-fila_switch-field-stays-not-installed, missing-in-out-arrays-don't-crash) and 2 frontend tests in `useFilamentMapping.test.ts` (FTS-active drops the nozzle filter; explicit `fila_switch: null` keeps the filter applied). Upstream fila_switch payloads with anything other than the documented shape are tolerated — `installed` flips on the *presence* of the field, the routing arrays default to empty lists if missing, and the dropdown skips the badge for slots not currently in `in_slots`. ### Fixed +- **Printer Info modal: serial-number and IP-address copy buttons silently did nothing on plain-HTTP LAN deployments** ([#1174](https://github.com/maziggy/bambuddy/issues/1174), reported by @BurntOutHylian) — `PrinterInfoModal`'s `CopyButton` only tried `navigator.clipboard.writeText()`, which is gated by the secure-context requirement (HTTPS or localhost). On the typical Bambuddy deployment shape — bare-IP HTTP on the LAN — `navigator.clipboard` is undefined; the existing `try/catch` swallowed the resulting `TypeError`, the icon never flipped to the tick, and nothing landed on the user's clipboard. Fixed by adding the same off-screen-textarea + `document.execCommand('copy')` fallback that `CameraTokensPage`'s plaintext-token modal already uses for plain-HTTP LAN deployments: gate on `navigator.clipboard && window.isSecureContext`, fall back to the legacy path otherwise, and surface the success-tick only when the copy actually landed (return early without flipping `copied` if `execCommand('copy')` returns false). The `try/finally` around the textarea guarantees DOM cleanup even when the browser throws on a restricted context. 3 new component tests in `PrinterInfoModal.test.tsx` cover (a) secure-context happy path uses `navigator.clipboard.writeText`, (b) plain-HTTP fallback path actually invokes `execCommand('copy')` and leaves no leaked textarea in the DOM, (c) `finally` cleanup removes the textarea even when `execCommand` throws synthetically. Thanks to @BurntOutHylian for the precise file/line pointer in the report. + - **Queue auto-dispatched the next print onto a fouled bed after an aborted or cancelled print** ([#1171](https://github.com/maziggy/bambuddy/issues/1171), reported by @tom5677) — When a print ended with status `aborted` (printer self-abort, or a user stopping the print on the printer's own touchscreen) or `cancelled` (user stopping the print via the Bambuddy queue UI), the plate-clear gate added in [#961](https://github.com/maziggy/bambuddy/issues/961) was *not* raised — only `completed` and `failed` triggered it (`backend/app/main.py:2660`). Result: the queue scheduler dispatched the next pending item ~2 seconds after the abort, with the previous print's material still on the bed. The reporter saw two prints (P1P + P1S) auto-start onto fouled beds within seconds of each other after touchscreen-aborts, and explicitly flagged the risk of damage to the printer; a third printer (his second P1S) behaved correctly because its previous print had ended `completed`. The original code's comment ("user-cancelled prints don't require a plate-clear ack — nothing printed on the bed") only holds if you cancel right at layer 1; cancelling a 12-hour print at hour 11 leaves a fouled bed too. Fix: the gate is now raised for every terminal status — `completed`, `failed`, `aborted`, `cancelled` — matching the safety contract that the user must acknowledge the bed is clear before any next queued print starts. The gate is user-clearable on the Printers page, so worst case for a layer-1 cancel the user clicks "Clear Plate" once. Touchscreen-aborts are particularly important to gate because Bambuddy's "user stopped via UI" override (`_user_stopped_printers` → `aborted` mapped to `cancelled`) only fires when the user stops via the Bambuddy queue; a touchscreen-stop reports `aborted` straight through. Regression coverage in `test_print_lifecycle.py::TestPlateClearGate`: parametrised across all four terminal statuses (asserts `set_awaiting_plate_clear(printer_id, True)` is called for each), plus a defence-in-depth test that an unrecognised future status string never silently raises the gate. - **Printer card always shows the first plate's thumbnail when printing a multi-plate 3MF** ([#1166](https://github.com/maziggy/bambuddy/issues/1166), reported by @smandon) — On printers running firmware that drops the plate path from `print.gcode_file` (the reporter's case: P1S 01.10.00.00, but the same shape appears on other firmware revisions), the printer reports `gcode_file: MyModel.3mf` instead of `gcode_file: /Metadata/plate_4.gcode`. The `/printers/{id}/cover` route's regex (`plate_(\d+)\.gcode`) found nothing in the bare `.3mf` filename, defaulted to plate 1, and the printer card showed `Metadata/plate_1.png` from the 3MF — even though the user dispatched plate 4. Same problem hit `current_plate_id` on the status response (printer card detail row showed plate 1). Two-pronged fix on a precedence ladder: **(1) Bambuddy now records the plate it dispatched** — `start_print()` writes `(dispatched_plate_id, dispatched_subtask)` onto `PrinterState` at publish time, and a new `resolve_plate_id(state)` helper prefers that record over the gcode_file regex when `dispatched_subtask == state.subtask_name` (the subtask check rejects stale entries from a prior Bambuddy-dispatched print bleeding into a Studio-direct dispatch). **(2) After the 3MF lands on disk, the cover route scans the zip for a unique `Metadata/plate_*.gcode` entry**: per-plate archives sliced separately in Bambu Studio bundle thumbnails for *every* plate but only the *active* plate's gcode, so a single match unambiguously identifies the plate even when no Bambuddy dispatch exists (Studio-direct flow). Final fallback is plate 1, unchanged. The cover-byte cache key was also simplified — `plate_num` was removed from the key now that resolution is late-bound; `clear_cover_cache()` already runs on every print start, so different plates of the same project always re-fetch a fresh thumbnail. Coverage: 5 unit tests in `test_printer_manager.py::TestResolvePlateId` (dispatch precedence, stale-subtask guard, gcode regex fallback, default-1 path, missing-subtask guard), 4 unit tests in `test_bambu_mqtt.py::TestStartPrintRecordsDispatchedPlate` (dispatch record set/cleared/overwritten/skipped on disconnect), 2 integration tests in `test_printers_api.py` (dispatch wins over plate-1 default; 3MF-scan fallback for per-plate archive without dispatch). Studio-direct multi-plate prints (no dispatch record AND multiple plate gcodes in the 3MF) still default to plate 1 — matches the firmware's own ambiguity, not regressed by this change. diff --git a/frontend/src/__tests__/components/PrinterInfoModal.test.tsx b/frontend/src/__tests__/components/PrinterInfoModal.test.tsx new file mode 100644 index 000000000..42a7eb278 --- /dev/null +++ b/frontend/src/__tests__/components/PrinterInfoModal.test.tsx @@ -0,0 +1,136 @@ +/** + * Tests for PrinterInfoModal — focused on the CopyButton clipboard fallback + * (#1174). Bambuddy is commonly deployed over plain HTTP on a LAN, where + * `navigator.clipboard` is gated by the secure-context requirement and the + * previous code (which only tried the modern API and silently swallowed the + * failure) left both copy buttons inert. + */ + +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { render } from '../utils'; +import { PrinterInfoModal } from '../../components/PrinterInfoModal'; +import type { Printer } from '../../api/client'; + +function mockPrinter(): Printer { + return { + id: 1, + name: 'Test P1S', + serial_number: '01S00A123456789', + ip_address: '192.168.1.42', + access_code: '12345678', + model: 'P1S', + location: null, + nozzle_count: 1, + is_active: true, + auto_archive: true, + external_camera_url: null, + external_camera_type: null, + external_camera_enabled: false, + camera_rotation: 0, + plate_detection_enabled: false, + created_at: '2026-01-01T00:00:00Z', + updated_at: '2026-01-01T00:00:00Z', + }; +} + +function getCopyButtons() { + // CopyButton renders as an icon button with title="Copy to clipboard". + return screen.getAllByRole('button').filter( + btn => /copy/i.test(btn.getAttribute('title') || ''), + ); +} + +describe('PrinterInfoModal — CopyButton clipboard fallback (#1174)', () => { + let originalIsSecureContext: PropertyDescriptor | undefined; + let originalClipboard: PropertyDescriptor | undefined; + let originalExecCommand: typeof document.execCommand; + + beforeEach(() => { + originalIsSecureContext = Object.getOwnPropertyDescriptor(window, 'isSecureContext'); + originalClipboard = Object.getOwnPropertyDescriptor(navigator, 'clipboard'); + originalExecCommand = document.execCommand; + }); + + afterEach(() => { + if (originalIsSecureContext) { + Object.defineProperty(window, 'isSecureContext', originalIsSecureContext); + } + if (originalClipboard) { + Object.defineProperty(navigator, 'clipboard', originalClipboard); + } + document.execCommand = originalExecCommand; + vi.clearAllMocks(); + }); + + it('uses navigator.clipboard.writeText in a secure context (HTTPS / localhost)', async () => { + const user = userEvent.setup(); + const writeTextMock = vi.fn().mockResolvedValue(undefined); + Object.defineProperty(window, 'isSecureContext', { value: true, configurable: true }); + Object.defineProperty(navigator, 'clipboard', { + value: { writeText: writeTextMock }, + configurable: true, + }); + + render( {}} />); + + const buttons = getCopyButtons(); + expect(buttons.length).toBeGreaterThanOrEqual(2); // serial + ip at minimum + + // Click the first copy button (IP address row appears first). + await user.click(buttons[0]); + await waitFor(() => { + expect(writeTextMock).toHaveBeenCalled(); + }); + // The value passed must be a real string from the printer fixture, not "". + expect(writeTextMock.mock.calls[0][0]).toMatch(/^(192\.168\.1\.42|01S00A123456789)$/); + }); + + it('falls back to execCommand("copy") on plain-HTTP LAN deployments — pre-fix #1174 path', async () => { + // Repro of the reporter's exact environment: plain-HTTP, no clipboard API. + // Pre-fix the catch-block silently swallowed the TypeError on + // navigator.clipboard.writeText and the icon never flipped to the tick. + const user = userEvent.setup(); + Object.defineProperty(window, 'isSecureContext', { value: false, configurable: true }); + Object.defineProperty(navigator, 'clipboard', { value: undefined, configurable: true }); + + const execCommandMock = vi.fn().mockReturnValue(true); + document.execCommand = execCommandMock; + + render( {}} />); + + const buttons = getCopyButtons(); + await user.click(buttons[0]); + + await waitFor(() => { + expect(execCommandMock).toHaveBeenCalledWith('copy'); + }); + // Off-screen textarea must be cleaned up on the success path; otherwise + // every click would leak a hidden DOM node. + expect(document.querySelectorAll('textarea').length).toBe(0); + }); + + it('cleans up the off-screen textarea even when execCommand throws', async () => { + // The fallback path uses a try/finally around execCommand. The finally + // block must remove the textarea even if the browser rejects the copy + // (e.g. permission denied), so a hostile / restricted environment doesn't + // leak DOM nodes per click. + const user = userEvent.setup(); + Object.defineProperty(window, 'isSecureContext', { value: false, configurable: true }); + Object.defineProperty(navigator, 'clipboard', { value: undefined, configurable: true }); + + document.execCommand = vi.fn().mockImplementation(() => { + throw new Error('synthetic execCommand failure'); + }); + + render( {}} />); + + const buttons = getCopyButtons(); + await user.click(buttons[0]); + + await waitFor(() => { + expect(document.querySelectorAll('textarea').length).toBe(0); + }); + }); +}); diff --git a/frontend/src/components/PrinterInfoModal.tsx b/frontend/src/components/PrinterInfoModal.tsx index 965af6c6d..fd866ad94 100644 --- a/frontend/src/components/PrinterInfoModal.tsx +++ b/frontend/src/components/PrinterInfoModal.tsx @@ -18,12 +18,34 @@ function CopyButton({ value }: { value: string }) { const [copied, setCopied] = useState(false); const handleCopy = async () => { + // navigator.clipboard is gated by the secure-context requirement, so on + // plain-HTTP LAN deployments (#1174) the API is undefined and the previous + // code silently swallowed the failure — the icon never flipped to the tick + // and nothing landed on the user's clipboard. Fall back to the legacy + // execCommand path via an off-screen textarea, matching the pattern used + // by CameraTokensPage's plaintext-token modal. try { - await navigator.clipboard.writeText(value); + if (navigator.clipboard && window.isSecureContext) { + await navigator.clipboard.writeText(value); + } else { + const ta = document.createElement('textarea'); + ta.value = value; + ta.style.position = 'fixed'; + ta.style.opacity = '0'; + document.body.appendChild(ta); + try { + ta.select(); + const ok = document.execCommand('copy'); + if (!ok) return; + } finally { + document.body.removeChild(ta); + } + } setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { - // Clipboard may not be available in non-secure contexts + // Both paths failed (no clipboard API, no execCommand). Leave the icon + // unchanged so the user knows nothing was copied. } }; diff --git a/static/assets/index-D4GSGeyj.js b/static/assets/index-BM5VeuBp.js similarity index 99% rename from static/assets/index-D4GSGeyj.js rename to static/assets/index-BM5VeuBp.js index d6ae4399f..c120f5be5 100644 --- a/static/assets/index-D4GSGeyj.js +++ b/static/assets/index-BM5VeuBp.js @@ -8511,7 +8511,7 @@ void main() { ${o("inventory.assignProfileMismatchMessage",{spoolProfile:N.spoolProfile||o("common.unknown"),trayProfile:N.trayProfile||o("common.unknown"),location:s.location})}`:N.type==="partial_profile"?ie=`${o("inventory.assignPartialMismatchMessage",{spoolMaterial:N.spoolMaterial,trayMaterial:N.trayMaterial,location:s.location})} ${o("inventory.assignProfileMismatchMessage",{spoolProfile:N.spoolProfile||o("common.unknown"),trayProfile:N.trayProfile||o("common.unknown"),location:s.location})}`:N.type==="profile"&&(ie=o("inventory.assignProfileMismatchMessage",{spoolProfile:N.spoolProfile||o("common.unknown"),trayProfile:N.trayProfile||o("common.unknown"),location:s.location})),a.jsx(yn,{title:o("inventory.assignMismatchTitle"),message:ie,confirmText:o("inventory.assignMismatchConfirm"),variant:"warning",isLoading:k.isPending,onConfirm:ue,onCancel:()=>{k.isPending||(S(!1),b(null),P(null))}})})()]})}function pK(t,e){if(t===255)return"External";let n,r=!1;t>=128&&t<=135?(n=t-128,r=!0):t>=0&&t<=3?(n=t,r=e===1):n=0,n=Math.max(0,Math.min(n,7));const i=String.fromCharCode(65+n);return r?`HT-${i}`:`AMS-${i}`}function BD(t){const e=t.includes("_")?t.split("_")[0]:t;return e.startsWith("GFS")?"GF"+e.slice(3):(e.startsWith("PFUS")||e.startsWith("PFSP"),e)}const U0=["PLA","PETG","PCTG","ABS","ASA","TPU","PC","PA","NYLON","PVA","HIPS","PP","PET"];function fK(t){const e=t.replace(/@.+$/,"").trim(),n=e.toUpperCase(),r=n.match(/\bSUPPORT\s+FOR\s+/);if(r){const s=n.slice(r.index+r[0].length);for(const o of U0)if(new RegExp(`\\b${o}\\b`).test(s)){const c=e.slice(0,r.index).trim();return{material:o,brand:c,variant:"Support"}}}for(const s of U0){const o=new RegExp(`\\b${s}\\b`,"i");if(o.test(n)){const l=e.split(o),c=l[0]?.trim()||"",d=l[1]?.trim()||"";return{material:s,brand:c,variant:d}}}const i=e.split(/\s+/);return i.length>=2?{material:i[1],brand:i[0],variant:i.slice(2).join(" ")}:{material:e,brand:"",variant:""}}function F7e(t){return!t.startsWith("GF")&&!t.startsWith("P1")}const R7e={white:"FFFFFF",black:"000000",red:"FF0000",green:"00FF00",blue:"0000FF",yellow:"FFFF00",cyan:"00FFFF",magenta:"FF00FF",orange:"FFA500",purple:"800080",pink:"FFC0CB",brown:"8B4513",gray:"808080",grey:"808080","jade white":"FFFEF2",ivory:"FFFFF0",beige:"F5F5DC",cream:"FFFDD0",silver:"C0C0C0",gold:"FFD700",bronze:"CD7F32",copper:"B87333",navy:"000080",teal:"008080",olive:"808000",maroon:"800000",coral:"FF7F50",salmon:"FA8072",lime:"32CD32",mint:"98FF98","forest green":"228B22","sky blue":"87CEEB","royal blue":"4169E1",turquoise:"40E0D0",lavender:"E6E6FA",violet:"EE82EE",plum:"DDA0DD",tan:"D2B48C",chocolate:"D2691E",charcoal:"36454F",slate:"708090",transparent:"000000",natural:"F5F5DC",wood:"DEB887"},gK=[{name:"White",hex:"FFFFFF"},{name:"Black",hex:"000000"},{name:"Red",hex:"FF0000"},{name:"Blue",hex:"0000FF"},{name:"Green",hex:"00AA00"},{name:"Yellow",hex:"FFFF00"},{name:"Orange",hex:"FFA500"},{name:"Gray",hex:"808080"}],bK=[{name:"Cyan",hex:"00FFFF"},{name:"Magenta",hex:"FF00FF"},{name:"Purple",hex:"800080"},{name:"Pink",hex:"FFC0CB"},{name:"Brown",hex:"8B4513"},{name:"Beige",hex:"F5F5DC"},{name:"Navy",hex:"000080"},{name:"Teal",hex:"008080"},{name:"Lime",hex:"32CD32"},{name:"Gold",hex:"FFD700"},{name:"Silver",hex:"C0C0C0"},{name:"Maroon",hex:"800000"},{name:"Olive",hex:"808000"},{name:"Coral",hex:"FF7F50"},{name:"Salmon",hex:"FA8072"},{name:"Turquoise",hex:"40E0D0"},{name:"Violet",hex:"EE82EE"},{name:"Indigo",hex:"4B0082"},{name:"Chocolate",hex:"D2691E"},{name:"Tan",hex:"D2B48C"},{name:"Slate",hex:"708090"},{name:"Charcoal",hex:"36454F"},{name:"Ivory",hex:"FFFFF0"},{name:"Cream",hex:"FFFDD0"}];function xK(t){const e=t.toLowerCase().trim();return R7e[e]||null}function L7e(t){const e=t.indexOf("@");if(e<0)return null;const r=t.slice(e+1).trim().match(/^BBL\s+(.+?)(?:\s+[\d.]+\s*nozzle)?$/i);return r?r[1].trim():null}function xie({isOpen:t,onClose:e,printerId:n,slotInfo:r,nozzleDiameter:i="0.4",printerModel:s,onSuccess:o,fullScreen:l}){const{t:c}=_t(),[d,u]=w.useState(""),[m,p]=w.useState(null),[f,x]=w.useState(""),[v,b]=w.useState(""),[g,S]=w.useState(""),[N,P]=w.useState(!1),[C,A]=w.useState(!1),T=w.useRef(""),{data:F,isLoading:k,isError:E}=Qe({queryKey:["cloudSettings"],queryFn:()=>oe.getCloudSettings(),enabled:t,retry:!1}),{data:$,isLoading:z}=Qe({queryKey:["localPresets"],queryFn:()=>oe.getLocalPresets(),enabled:t}),{data:X,isLoading:R}=Qe({queryKey:["builtinFilaments"],queryFn:()=>oe.getBuiltinFilaments(),enabled:t,staleTime:1/0}),{data:ne,isLoading:re}=Qe({queryKey:["kprofiles",n,i],queryFn:()=>oe.getKProfiles(n,i),enabled:t&&!!n}),{data:J}=Qe({queryKey:["colorCatalog"],queryFn:()=>oe.getColorCatalog(),enabled:t,staleTime:1/0}),ue=ot({mutationFn:async()=>{if(!d)throw new Error("No filament preset selected");const M=d.startsWith("local_"),U=d.startsWith("builtin_"),Q=M?parseInt(d.replace("local_",""),10):null,O=U?d.replace("builtin_",""):null,ce=M?$?.filament.find(Fe=>Fe.id===Q):null,I=U?X?.find(Fe=>Fe.filament_id===O):null,G=!M&&!U?F?.filament.find(Fe=>Fe.setting_id===d):null;if(!M&&!U&&!G)throw new Error("Selected preset not found");if(M&&!ce)throw new Error("Selected local preset not found");if(U&&!I)throw new Error("Selected builtin preset not found");const q=M?ce.name:U?I.name:G.name,W=fK(q),te=m?.slot_id??-1,le=f||r.trayColor?.slice(0,6)||"FFFFFF",ye=q.replace(/@.+$/,"").trim();let he,me;const H=W.material.toUpperCase();if(M){const Fe=(U0.includes(H)?H:ce?.filament_type||W.material||"").toUpperCase(),Be={PLA:"GFL99","PLA-CF":"GFL98","PLA SILK":"GFL96","PLA HIGH SPEED":"GFL95",PETG:"GFG99","PETG HF":"GFG96","PETG-CF":"GFG98",PCTG:"GFG97",ABS:"GFB99",ASA:"GFB98",PC:"GFC99",PA:"GFN99","PA-CF":"GFN98",NYLON:"GFN99",TPU:"GFU99",PVA:"GFS99",HIPS:"GFS98",PE:"GFP99",PP:"GFP97"};he=Be[Fe]||Be[Fe.replace(/[-\s]?CF$/,"")]||Be[Fe.replace(/\+$/,"")]||Be[Fe.split(/[-\s]/)[0]]||"",me=""}else if(U)he=O,me="";else if(he=BD(d),me=d,!d.startsWith("GFS"))try{const Fe=await oe.getCloudSettingDetail(d);Fe.filament_id&&(he=Fe.filament_id)}catch(Fe){console.warn("Failed to fetch preset detail for filament_id:",Fe)}let L=M&&ce?.nozzle_temp_min?ce.nozzle_temp_min:190,ee=M&&ce?.nozzle_temp_max?ce.nozzle_temp_max:230;if(!M||U||!ce?.nozzle_temp_min&&!ce?.nozzle_temp_max){const Fe=(M?U0.includes(H)?H:ce?.filament_type||W.material||"":W.material).toUpperCase();Fe.includes("PLA")?(L=190,ee=230):Fe.includes("PETG")?(L=220,ee=260):Fe.includes("ABS")||Fe.includes("ASA")?(L=240,ee=280):Fe.includes("TPU")?(L=200,ee=240):Fe==="PCTG"?(L=220,ee=260):Fe.includes("PC")?(L=260,ee=300):(Fe.includes("PA")||Fe.includes("NYLON"))&&(L=250,ee=290)}const ge=m?.k_value?parseFloat(m.k_value):0,ke=M?U0.includes(H)?H:ce?.filament_type||W.material||"PLA":W.material||"PLA",je=await oe.configureAmsSlot(n,r.amsId,r.trayId,{tray_info_idx:he,tray_type:ke,tray_sub_brands:ye,tray_color:le+"FF",nozzle_temp_min:L,nozzle_temp_max:ee,cali_idx:te,nozzle_diameter:i,setting_id:me,kprofile_filament_id:m?.filament_id,kprofile_setting_id:m?.setting_id||void 0,k_value:ge}),Te=M?`local_${Q}`:U?`builtin_${O}`:d,xe=M?"local":U?"builtin":"cloud";try{await oe.saveSlotPreset(n,r.amsId,r.trayId,Te,ye,xe)}catch(Fe){console.warn("Failed to save slot preset mapping:",Fe)}return je},onSuccess:()=>{P(!0),o?.(),setTimeout(()=>{P(!1),e()},1500)}}),ie=ot({mutationFn:async()=>oe.resetAmsSlot(n,r.amsId,r.trayId),onSuccess:()=>{P(!0),o?.(),setTimeout(()=>{P(!1),e()},1500)}}),se=w.useMemo(()=>{const M=g.toLowerCase(),U=[],Q=new Set,O=r.savedPresetId,ce=r.trayInfoIdx;if(F?.filament)for(const I of F.filament){Q.add(I.setting_id);const q=O===I.setting_id||ce&&(I.setting_id===ce||BD(I.setting_id)===ce);if(!(M&&!I.name.toLowerCase().includes(M))){if(!q&&s){const W=L7e(I.name);if(W&&W.toUpperCase()!==s.toUpperCase())continue}U.push({id:I.setting_id,name:I.name,source:"cloud",isUser:F7e(I.setting_id)})}}if($?.filament)for(const I of $.filament){const G=`local_${I.id}`;M&&!I.name.toLowerCase().includes(M)||U.push({id:G,name:I.name,source:"local",isUser:!1})}if(X)for(const I of X){if(Q.has(I.filament_id))continue;const G=I.filament_id.startsWith("GF")?"GFS"+I.filament_id.slice(2):I.filament_id;Q.has(G)||(!M||I.name.toLowerCase().includes(M))&&U.push({id:`builtin_${I.filament_id}`,name:I.name,source:"builtin",isUser:!1})}return U.sort((I,G)=>{const q={cloud:0,local:1,builtin:2};return I.source!==G.source?q[I.source]-q[G.source]:I.isUser&&!G.isUser?-1:!I.isUser&&G.isUser?1:I.name.localeCompare(G.name)})},[F?.filament,$?.filament,X,g,s,r.savedPresetId,r.trayInfoIdx]),K=w.useMemo(()=>{if(!d)return null;let M=null;if(d.startsWith("local_")){const O=parseInt(d.replace("local_",""),10);M=$?.filament.find(I=>I.id===O)?.name||null}else if(d.startsWith("builtin_")){const O=d.replace("builtin_","");M=X?.find(I=>I.filament_id===O)?.name||null}else F?.filament&&(M=F.filament.find(ce=>ce.setting_id===d)?.name||null);if(!M)return null;let U=M.replace(/@.+$/,"").trim();U.startsWith("# ")&&(U=U.slice(2).trim());const Q=fK(U);return{fullName:U,material:Q.material,brand:Q.brand}},[d,F?.filament,$?.filament,X]),ae=K?.fullName||"",pe=w.useMemo(()=>{if(!J||!K)return[];const{fullName:M,brand:U}=K,Q=M.replace(/^(Bambu\s*(Lab)?|eSUN|Polymaker|Overture|Sunlu|Hatchbox)\s*/i,"").trim();return J.filter(O=>{const ce=(O.material||"").toUpperCase(),I=O.manufacturer.toUpperCase();if(!(ce===Q.toUpperCase()||ce.includes(Q.toUpperCase())||Q.toUpperCase().includes(ce)))return!1;if(U){const q=U.toUpperCase();if(!I.includes(q)&&!q.includes(I))return!1}return!0})},[J,K]),be=w.useMemo(()=>{if(!ne?.profiles||!K)return[];const{fullName:M,material:U,brand:Q}=K,O=M.toUpperCase(),ce=U.toUpperCase(),I=Q.toUpperCase();if(!ce||ce.length<2)return[];const G=ne.profiles.filter(W=>{const te=W.name.toUpperCase();if(I)return!(!te.includes(I)||!te.includes(ce));if(te.includes(O)||te.includes(ce))return!0;const ye={NYLON:["PA","PA-CF","PA6"],PA:["NYLON"]}[ce]||[];for(const he of ye)if(te.includes(he))return!0;return!1}),q=new Map;for(const W of G){const te=`${W.name}|${W.k_value}`,le=q.get(te);le?r.extruderId!==void 0&&W.extruder_id===r.extruderId&&le.extruder_id!==r.extruderId&&q.set(te,W):q.set(te,W)}return Array.from(q.values())},[ne?.profiles,K,r.extruderId]);w.useEffect(()=>{if(t){if(r.savedPresetId)u(r.savedPresetId);else if(r.trayInfoIdx&&F?.filament){let M=F.filament.find(U=>U.setting_id===r.trayInfoIdx);M||(M=F.filament.find(U=>BD(U.setting_id)===r.trayInfoIdx)),M&&u(M.setting_id)}else if(r.trayInfoIdx&&X?.length){const M=r.trayInfoIdx,U=X.find(Q=>Q.filament_id===M);U&&u(`builtin_${U.filament_id}`)}if(r.trayColor){const M=r.trayColor.slice(0,6);M&&x(M)}}else u(""),p(null),x(""),b(""),S(""),P(!1),T.current=""},[t,r.savedPresetId,r.trayInfoIdx,r.trayColor,F?.filament,X]),w.useEffect(()=>{if(be.length>0){if(r.caliIdx!=null&&r.caliIdx>0){const M=be.find(U=>U.slot_id===r.caliIdx);if(M){p(M);return}}p(be[0])}else p(null)},[d,be,r.caliIdx]);const fe=w.useCallback(M=>{M.key==="Escape"&&e()},[e]);w.useEffect(()=>{if(t)return document.addEventListener("keydown",fe),()=>document.removeEventListener("keydown",fe)},[t,fe]);const B=k&&!E||z||R||re;if(w.useEffect(()=>{if(!B&&d&&d!==T.current){const M=requestAnimationFrame(()=>{const Q=document.querySelector('[class*="fixed inset-0 z-50"]')?.querySelector(`[data-preset-id="${CSS.escape(d)}"]`);Q&&(T.current=d,Q.scrollIntoView({block:"nearest"}))});return()=>cancelAnimationFrame(M)}},[d,B]),!t)return null;const Y=d&&!ue.isPending,D=f||r.trayColor?.slice(0,6)||"FFFFFF";return a.jsxs("div",{className:`fixed inset-0 z-50 flex ${l?"":"items-center justify-center"}`,children:[!l&&a.jsx("div",{className:"absolute inset-0 bg-black/60 backdrop-blur-sm",onClick:e}),a.jsxs("div",{className:l?"relative w-full h-full bg-bambu-dark-secondary flex flex-col":"relative w-full max-w-lg mx-4 bg-bambu-dark-secondary border border-bambu-dark-tertiary rounded-xl shadow-2xl",children:[a.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-bambu-dark-tertiary shrink-0",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx(Hd,{className:"w-5 h-5 text-bambu-blue"}),a.jsx("h2",{className:"text-lg font-semibold text-white",children:c("configureAmsSlot.title")}),l&&a.jsxs("div",{className:"flex items-center gap-2 ml-4 text-sm text-bambu-gray",children:[a.jsx("span",{className:"text-white/30",children:"|"}),r.trayColor&&a.jsx("span",{className:"w-4 h-4 rounded-full border border-black/20",style:{backgroundColor:`#${r.trayColor.slice(0,6)}`}}),a.jsx("span",{className:"text-white/70",children:c("configureAmsSlot.slotLabel",{ams:pK(r.amsId,r.trayCount),slot:r.trayId+1})}),r.traySubBrands&&a.jsxs("span",{children:["(",r.traySubBrands,")"]})]})]}),a.jsx("button",{onClick:e,className:"p-1 text-bambu-gray hover:text-white rounded transition-colors",children:a.jsx(Bt,{className:"w-5 h-5"})})]}),a.jsxs("div",{className:`p-4 overflow-y-auto ${l?"flex-1 min-h-0":"space-y-4 max-h-[60vh]"}`,children:[N&&a.jsx("div",{className:"absolute inset-0 bg-bambu-dark-secondary/95 z-10 flex items-center justify-center rounded-xl",children:a.jsxs("div",{className:"text-center space-y-3",children:[a.jsx(Bc,{className:"w-16 h-16 text-bambu-green mx-auto"}),a.jsx("p",{className:"text-lg font-semibold text-white",children:c("configureAmsSlot.slotConfigured")}),a.jsx("p",{className:"text-sm text-bambu-gray",children:c("configureAmsSlot.settingsSentToPrinter")})]})}),!l&&a.jsxs("div",{className:"p-3 bg-bambu-dark rounded-lg border border-bambu-dark-tertiary",children:[a.jsx("p",{className:"text-xs text-bambu-gray mb-1",children:c("configureAmsSlot.configuringSlot")}),a.jsxs("div",{className:"flex items-center gap-2",children:[r.trayColor&&a.jsx("span",{className:"w-4 h-4 rounded-full border border-black/20",style:{backgroundColor:`#${r.trayColor.slice(0,6)}`}}),a.jsx("span",{className:"text-white font-medium",children:c("configureAmsSlot.slotLabel",{ams:pK(r.amsId,r.trayCount),slot:r.trayId+1})}),r.traySubBrands&&a.jsxs("span",{className:"text-bambu-gray",children:["(",r.traySubBrands,")"]})]})]}),B?a.jsx("div",{className:"flex justify-center py-8",children:a.jsx(mt,{className:"w-6 h-6 text-bambu-green animate-spin"})}):l?a.jsxs("div",{className:"flex gap-4 h-full",children:[a.jsxs("div",{className:"w-1/2 flex flex-col min-h-0",children:[a.jsxs("label",{className:"block text-sm text-bambu-gray mb-2",children:[c("configureAmsSlot.filamentProfile")," ",a.jsx("span",{className:"text-red-400",children:"*"})]}),a.jsx("input",{type:"text",placeholder:c("configureAmsSlot.searchPresets"),value:g,onChange:M=>S(M.target.value),className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder:text-bambu-gray focus:border-bambu-green focus:outline-none mb-2 shrink-0"}),a.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto space-y-1",children:se.length===0?a.jsx("p",{className:"text-center py-4 text-bambu-gray",children:F?.filament?.length===0&&!$?.filament?.length?c("configureAmsSlot.noPresetsAvailable"):c("configureAmsSlot.noMatchingPresets")}):se.map(M=>a.jsx("button",{"data-preset-id":M.id,onClick:()=>u(M.id),className:`w-full p-2 rounded-lg border text-left transition-colors ${d===M.id?"bg-bambu-green/20 border-bambu-green":"bg-bambu-dark border-bambu-dark-tertiary hover:border-bambu-gray"}`,children:a.jsxs("div",{className:"flex items-center justify-between",children:[a.jsx("span",{className:"text-white text-sm truncate",children:M.name}),a.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[M.source==="local"&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-green-500/20 text-green-400",children:c("profiles.localProfiles.badge")}),M.source==="builtin"&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-amber-500/20 text-amber-400",children:c("configureAmsSlot.builtin")}),M.isUser&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-bambu-blue/20 text-bambu-blue",children:c("configureAmsSlot.custom")})]})]})},M.id))})]}),a.jsxs("div",{className:"w-1/2 flex flex-col gap-4 min-h-0 overflow-y-auto",children:[a.jsxs("div",{children:[a.jsxs("label",{className:"block text-sm text-bambu-gray mb-2",children:[c("configureAmsSlot.kProfileLabel"),ae&&a.jsx("span",{className:"ml-2 text-xs text-bambu-blue",children:c("configureAmsSlot.filteringFor",{material:ae})})]}),be.length>0?a.jsxs("div",{className:"relative",children:[a.jsxs("select",{value:m?.name||"",onChange:M=>{const U=be.find(Q=>Q.name===M.target.value);p(U||null)},className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none appearance-none pr-10",children:[a.jsx("option",{value:"",children:c("configureAmsSlot.noKProfile")}),be.map(M=>a.jsxs("option",{value:M.name,children:[M.name," (K=",M.k_value,")"]},`${M.name}-${M.extruder_id}`))]}),a.jsx(zn,{className:"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none"})]}):d?a.jsx("p",{className:"text-sm text-bambu-gray italic py-2",children:c("configureAmsSlot.noMatchingKProfiles")}):a.jsx("span",{className:"inline-block text-xs px-2 py-1 rounded bg-amber-500/20 text-amber-400 border border-amber-500/30",children:c("configureAmsSlot.selectFilamentFirst")}),m&&a.jsx("p",{className:"text-xs text-bambu-green mt-1",children:c("configureAmsSlot.kFromCalibration",{value:m.k_value})})]}),a.jsxs("div",{children:[a.jsx("label",{className:"block text-sm text-bambu-gray mb-2",children:c("configureAmsSlot.customColorLabel")}),pe.length>0&&a.jsxs("div",{className:"mb-3",children:[a.jsx("p",{className:"text-xs text-bambu-gray mb-1.5",children:c("configureAmsSlot.presetColors",{name:K?.fullName})}),a.jsx("div",{className:"flex flex-wrap gap-1.5",children:pe.map(M=>a.jsxs("button",{onClick:()=>{const U=M.hex_color.replace("#","").toUpperCase();x(U),b(M.color_name)},className:`h-7 px-2 rounded-md border-2 transition-all flex items-center gap-1.5 ${f===M.hex_color.replace("#","").toUpperCase()?"border-bambu-green scale-105":"border-white/20 hover:border-white/40"}`,title:M.color_name,children:[a.jsx("span",{className:"w-4 h-4 rounded-full border border-black/20 flex-shrink-0",style:{backgroundColor:M.hex_color}}),a.jsx("span",{className:"text-xs text-white/80 whitespace-nowrap",children:M.color_name})]},M.id))})]}),a.jsxs("div",{className:"flex flex-wrap gap-1.5 mb-2",children:[gK.map(M=>a.jsx("button",{onClick:()=>{x(M.hex),b(M.name)},className:`w-7 h-7 rounded-md border-2 transition-all ${f===M.hex?"border-bambu-green scale-110":"border-white/20 hover:border-white/40"}`,style:{backgroundColor:`#${M.hex}`},title:M.name},M.hex)),a.jsx("button",{onClick:()=>A(!C),className:"w-7 h-7 rounded-md border-2 border-white/20 hover:border-white/40 flex items-center justify-center text-white/60 hover:text-white/80 transition-all text-xs",title:c(C?"configureAmsSlot.showLessColors":"configureAmsSlot.showMoreColors"),children:C?"−":"+"})]}),C&&a.jsx("div",{className:"flex flex-wrap gap-1.5 mb-2",children:bK.map(M=>a.jsx("button",{onClick:()=>{x(M.hex),b(M.name)},className:`w-7 h-7 rounded-md border-2 transition-all ${f===M.hex?"border-bambu-green scale-110":"border-white/20 hover:border-white/40"}`,style:{backgroundColor:`#${M.hex}`},title:M.name},M.hex))}),a.jsxs("div",{className:"flex gap-2 items-center",children:[a.jsx("div",{className:"w-10 h-10 rounded-lg border-2 border-white/20 flex-shrink-0",style:{backgroundColor:`#${D}`}}),a.jsx("input",{type:"text",placeholder:c("configureAmsSlot.colorPlaceholder"),value:v,onChange:M=>{const U=M.target.value;b(U);const Q=xK(U);if(Q)x(Q);else{const O=U.replace(/[^0-9A-Fa-f]/g,"").toUpperCase();O.length===6?x(O):O.length===3&&x(O.split("").map(ce=>ce+ce).join(""))}},className:"flex-1 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder:text-bambu-gray focus:border-bambu-green focus:outline-none text-sm"}),f&&a.jsx("button",{onClick:()=>{x(""),b("")},className:"px-2 py-1 text-xs text-bambu-gray hover:text-white bg-bambu-dark-tertiary rounded",title:c("configureAmsSlot.clearCustomColor"),children:c("configureAmsSlot.clear")})]}),f&&a.jsx("p",{className:"text-xs text-bambu-gray mt-1.5",children:c("configureAmsSlot.hexLabel",{hex:f})})]})]})]}):a.jsxs(a.Fragment,{children:[a.jsxs("div",{children:[a.jsxs("label",{className:"block text-sm text-bambu-gray mb-2",children:[c("configureAmsSlot.filamentProfile")," ",a.jsx("span",{className:"text-red-400",children:"*"})]}),a.jsxs("div",{className:"relative",children:[a.jsx("input",{type:"text",placeholder:c("configureAmsSlot.searchPresets"),value:g,onChange:M=>S(M.target.value),className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder:text-bambu-gray focus:border-bambu-green focus:outline-none mb-2"}),a.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1",children:se.length===0?a.jsx("p",{className:"text-center py-4 text-bambu-gray",children:F?.filament?.length===0&&!$?.filament?.length?c("configureAmsSlot.noPresetsAvailable"):c("configureAmsSlot.noMatchingPresets")}):se.map(M=>a.jsx("button",{"data-preset-id":M.id,onClick:()=>u(M.id),className:`w-full p-2 rounded-lg border text-left transition-colors ${d===M.id?"bg-bambu-green/20 border-bambu-green":"bg-bambu-dark border-bambu-dark-tertiary hover:border-bambu-gray"}`,children:a.jsxs("div",{className:"flex items-center justify-between",children:[a.jsx("span",{className:"text-white text-sm truncate",children:M.name}),a.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[M.source==="local"&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-green-500/20 text-green-400",children:c("profiles.localProfiles.badge")}),M.source==="builtin"&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-amber-500/20 text-amber-400",children:c("configureAmsSlot.builtin")}),M.isUser&&a.jsx("span",{className:"text-xs px-1.5 py-0.5 rounded bg-bambu-blue/20 text-bambu-blue",children:c("configureAmsSlot.custom")})]})]})},M.id))})]})]}),a.jsxs("div",{children:[a.jsxs("label",{className:"block text-sm text-bambu-gray mb-2",children:[c("configureAmsSlot.kProfileLabel"),ae&&a.jsx("span",{className:"ml-2 text-xs text-bambu-blue",children:c("configureAmsSlot.filteringFor",{material:ae})})]}),be.length>0?a.jsxs("div",{className:"relative",children:[a.jsxs("select",{value:m?.name||"",onChange:M=>{const U=be.find(Q=>Q.name===M.target.value);p(U||null)},className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none appearance-none pr-10",children:[a.jsx("option",{value:"",children:c("configureAmsSlot.noKProfile")}),be.map(M=>a.jsxs("option",{value:M.name,children:[M.name," (K=",M.k_value,")"]},`${M.name}-${M.extruder_id}`))]}),a.jsx(zn,{className:"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-bambu-gray pointer-events-none"})]}):d?a.jsx("p",{className:"text-sm text-bambu-gray italic py-2",children:c("configureAmsSlot.noMatchingKProfiles")}):a.jsx("span",{className:"inline-block text-xs px-2 py-1 rounded bg-amber-500/20 text-amber-400 border border-amber-500/30",children:c("configureAmsSlot.selectFilamentFirst")}),m&&a.jsx("p",{className:"text-xs text-bambu-green mt-1",children:c("configureAmsSlot.kFromCalibration",{value:m.k_value})})]}),a.jsxs("div",{children:[a.jsx("label",{className:"block text-sm text-bambu-gray mb-2",children:c("configureAmsSlot.customColorLabel")}),pe.length>0&&a.jsxs("div",{className:"mb-3",children:[a.jsx("p",{className:"text-xs text-bambu-gray mb-1.5",children:c("configureAmsSlot.presetColors",{name:K?.fullName})}),a.jsx("div",{className:"flex flex-wrap gap-1.5",children:pe.map(M=>a.jsxs("button",{onClick:()=>{const U=M.hex_color.replace("#","").toUpperCase();x(U),b(M.color_name)},className:`h-7 px-2 rounded-md border-2 transition-all flex items-center gap-1.5 ${f===M.hex_color.replace("#","").toUpperCase()?"border-bambu-green scale-105":"border-white/20 hover:border-white/40"}`,title:M.color_name,children:[a.jsx("span",{className:"w-4 h-4 rounded-full border border-black/20 flex-shrink-0",style:{backgroundColor:M.hex_color}}),a.jsx("span",{className:"text-xs text-white/80 whitespace-nowrap",children:M.color_name})]},M.id))})]}),a.jsxs("div",{className:"flex flex-wrap gap-1.5 mb-2",children:[gK.map(M=>a.jsx("button",{onClick:()=>{x(M.hex),b(M.name)},className:`w-7 h-7 rounded-md border-2 transition-all ${f===M.hex?"border-bambu-green scale-110":"border-white/20 hover:border-white/40"}`,style:{backgroundColor:`#${M.hex}`},title:M.name},M.hex)),a.jsx("button",{onClick:()=>A(!C),className:"w-7 h-7 rounded-md border-2 border-white/20 hover:border-white/40 flex items-center justify-center text-white/60 hover:text-white/80 transition-all text-xs",title:c(C?"configureAmsSlot.showLessColors":"configureAmsSlot.showMoreColors"),children:C?"−":"+"})]}),C&&a.jsx("div",{className:"flex flex-wrap gap-1.5 mb-2",children:bK.map(M=>a.jsx("button",{onClick:()=>{x(M.hex),b(M.name)},className:`w-7 h-7 rounded-md border-2 transition-all ${f===M.hex?"border-bambu-green scale-110":"border-white/20 hover:border-white/40"}`,style:{backgroundColor:`#${M.hex}`},title:M.name},M.hex))}),a.jsxs("div",{className:"flex gap-2 items-center",children:[a.jsx("div",{className:"w-10 h-10 rounded-lg border-2 border-white/20 flex-shrink-0",style:{backgroundColor:`#${D}`}}),a.jsx("input",{type:"text",placeholder:c("configureAmsSlot.colorPlaceholder"),value:v,onChange:M=>{const U=M.target.value;b(U);const Q=xK(U);if(Q)x(Q);else{const O=U.replace(/[^0-9A-Fa-f]/g,"").toUpperCase();O.length===6?x(O):O.length===3&&x(O.split("").map(ce=>ce+ce).join(""))}},className:"flex-1 px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white placeholder:text-bambu-gray focus:border-bambu-green focus:outline-none text-sm"}),f&&a.jsx("button",{onClick:()=>{x(""),b("")},className:"px-2 py-1 text-xs text-bambu-gray hover:text-white bg-bambu-dark-tertiary rounded",title:c("configureAmsSlot.clearCustomColor"),children:c("configureAmsSlot.clear")})]}),f&&a.jsx("p",{className:"text-xs text-bambu-gray mt-1.5",children:c("configureAmsSlot.hexLabel",{hex:f})})]})]})]}),a.jsxs("div",{className:"flex justify-between p-4 border-t border-bambu-dark-tertiary shrink-0",children:[a.jsx(De,{variant:"secondary",onClick:()=>ie.mutate(),disabled:ie.isPending||ue.isPending,className:"text-red-400 hover:text-red-300 hover:bg-red-500/10",children:ie.isPending?a.jsxs(a.Fragment,{children:[a.jsx(mt,{className:"w-4 h-4 animate-spin"}),c("configureAmsSlot.resetting")]}):a.jsxs(a.Fragment,{children:[a.jsx(Ts,{className:"w-4 h-4"}),c("configureAmsSlot.resetSlot")]})}),a.jsxs("div",{className:"flex gap-2",children:[a.jsx(De,{variant:"secondary",onClick:e,children:c("configureAmsSlot.cancel")}),a.jsx(De,{onClick:()=>ue.mutate(),disabled:!Y,children:ue.isPending?a.jsxs(a.Fragment,{children:[a.jsx(mt,{className:"w-4 h-4 animate-spin"}),c("configureAmsSlot.configuring")]}):a.jsxs(a.Fragment,{children:[a.jsx(Hd,{className:"w-4 h-4"}),c("configureAmsSlot.configureSlot")]})})]})]}),(ue.isError||ie.isError)&&a.jsx("div",{className:"mx-4 mb-4 p-2 bg-red-500/20 border border-red-500/50 rounded text-sm text-red-400",children:ue.error?.message||ie.error?.message})]})]})}function yK({className:t="w-4 h-4"}){return a.jsx("svg",{viewBox:"0 0 1945 1370",fill:"none",className:t,"aria-hidden":"true",children:a.jsxs("g",{transform:"translate(-754.293 -471.685)",children:[a.jsxs("g",{transform:"translate(0.18191 255.976)",children:[a.jsx("g",{transform:"matrix(1.05469 0 0 0.241063 -153.484 1120.2)",children:a.jsx("rect",{x:"922.048",y:"1195.15",width:"1721.5",height:"470.135",stroke:"currentColor",strokeOpacity:"0.99",strokeWidth:"168.84",strokeLinecap:"round",strokeLinejoin:"round"})}),a.jsx("g",{transform:"matrix(0.983656 0 0 1.0767 -62.2035 141.539)",children:a.jsx("path",{d:"M2741.42,1175.93L895.832,1175.93L1125.16,621.902L2512.09,621.902L2741.42,1175.93Z",fill:"currentColor",fillOpacity:"0.05",stroke:"currentColor",strokeOpacity:"0.99",strokeWidth:"125.26",strokeLinecap:"round",strokeLinejoin:"round"})})]}),a.jsx("g",{transform:"translate(21.1916 0.684817)",children:a.jsx("path",{d:"M1981.31,567.518C1954.86,567.518 1933.39,546.047 1933.39,519.601C1933.39,493.156 1954.86,471.685 1981.31,471.685L2146.61,471.685C2173.07,471.685 2194.53,493.138 2194.53,519.601L2194.53,688.741C2194.53,715.187 2173.05,736.658 2146.61,736.658C2120.16,736.658 2098.69,715.187 2098.69,688.741L2098.69,567.518L1981.31,567.518ZM2098.69,1252.54C2098.69,1226.1 2120.16,1204.62 2146.61,1204.62C2173.05,1204.62 2194.53,1226.1 2194.53,1252.54L2194.53,1421.68C2194.53,1448.14 2173.07,1469.6 2146.61,1469.6L1981.31,1469.6C1954.86,1469.6 1933.39,1448.13 1933.39,1421.68C1933.39,1395.24 1954.86,1373.76 1981.31,1373.76L2098.69,1373.76L2098.69,1252.54ZM1430.29,1373.76C1456.74,1373.76 1478.21,1395.24 1478.21,1421.68C1478.21,1448.13 1456.74,1469.6 1430.29,1469.6L1264.99,1469.6C1238.53,1469.6 1217.07,1448.14 1217.07,1421.68L1217.07,1252.54C1217.07,1226.1 1238.55,1204.62 1264.99,1204.62C1291.44,1204.62 1312.91,1226.1 1312.91,1252.54L1312.91,1373.76L1430.29,1373.76ZM1312.91,688.741C1312.91,715.187 1291.44,736.658 1264.99,736.658C1238.55,736.658 1217.07,715.187 1217.07,688.741L1217.07,519.601C1217.07,493.138 1238.53,471.685 1264.99,471.685L1430.29,471.685C1456.74,471.685 1478.21,493.156 1478.21,519.601C1478.21,546.047 1456.74,567.518 1430.29,567.518L1312.91,567.518L1312.91,688.741Z",fill:"currentColor",fillOpacity:"0.99"})})]})})}function yie({folderId:t,onClose:e,onUploadComplete:n,onFileUploaded:r,autoUpload:i,validateFile:s,accept:o}){const{t:l}=_t(),[c,d]=w.useState([]),[u,m]=w.useState(!1),[p,f]=w.useState(!1),[x,v]=w.useState(!0),[b,g]=w.useState(!1),[S,N]=w.useState(!0),[P,C]=w.useState(null),A=w.useRef(null),T=se=>{se.preventDefault(),m(!0)},F=se=>{se.preventDefault(),m(!1)},k=se=>{se.preventDefault(),m(!1),X(Array.from(se.dataTransfer.files))},E=se=>{se.target.files&&X(Array.from(se.target.files))},$=(se,K)=>{d(ae=>ae.map(pe=>pe.file===se?{...pe,...K}:pe))},z=async se=>{f(!0);for(const K of se)if(K.status==="pending"){$(K.file,{status:"uploading"});try{if(K.isZip){const ae=await oe.extractZipFile(K.file,t,x,b,S);$(K.file,{status:ae.errors.length>0&&ae.extracted===0?"error":"success",extractedCount:ae.extracted,error:ae.errors.length>0?l("fileManager.zipFilesFailed","{{count}} files failed",{count:ae.errors.length}):void 0})}else{const ae=await oe.uploadLibraryFile(K.file,t,S);$(K.file,{status:"success"});const pe=r?.(ae);if(pe){C(pe),d([]),f(!1);return}}}catch(ae){$(K.file,{status:"error",error:ae instanceof Error?ae.message:l("fileManager.uploadFailed","Upload failed")})}}f(!1),n(),e()},X=se=>{if(C(null),s)for(const ae of se){const pe=s(ae);if(pe){C(pe);return}}const K=se.map(ae=>({file:ae,status:"pending",isZip:ae.name.toLowerCase().endsWith(".zip"),is3mf:ae.name.toLowerCase().endsWith(".3mf")}));d(ae=>[...ae,...K]),i&&se.length>0&&z(K)},R=se=>{d(K=>K.filter((ae,pe)=>pe!==se))},ne=c.some(se=>se.isZip&&se.status==="pending"),re=c.some(se=>se.file.name.toLowerCase().endsWith(".stl")&&se.status==="pending"),J=c.some(se=>se.is3mf&&se.status==="pending"),ue=c.filter(se=>se.status==="pending").length,ie=c.length>0&&ue===0&&!p;return a.jsx("div",{className:"fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4",children:a.jsxs("div",{className:"bg-bambu-dark-secondary rounded-lg w-full max-w-lg border border-bambu-dark-tertiary",children:[a.jsxs("div",{className:"p-4 border-b border-bambu-dark-tertiary flex items-center justify-between",children:[a.jsx("h2",{className:"text-lg font-semibold text-white",children:l("fileManager.uploadFiles")}),a.jsx("button",{onClick:e,className:"p-1 hover:bg-bambu-dark rounded",children:a.jsx(Bt,{className:"w-5 h-5 text-bambu-gray"})})]}),a.jsxs("div",{className:"p-4 space-y-4",children:[a.jsxs("div",{onDragOver:T,onDragLeave:F,onDrop:k,onClick:()=>A.current?.click(),className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${u?"border-bambu-green bg-bambu-green/10":"border-bambu-dark-tertiary hover:border-bambu-green/50"}`,children:[a.jsx(_a,{className:`w-10 h-10 mx-auto mb-3 ${u?"text-bambu-green":"text-bambu-gray"}`}),a.jsx("p",{className:"text-white font-medium",children:l(u?"fileManager.dropFilesHere":"fileManager.dragDropFiles")}),a.jsx("p",{className:"text-sm text-bambu-gray mt-1",children:l("fileManager.orClickToBrowse")}),a.jsx("p",{className:"text-xs text-bambu-gray/70 mt-2",children:l("fileManager.allFileTypesSupported")})]}),a.jsx("input",{ref:A,type:"file",multiple:!0,accept:o,className:"hidden",onChange:E}),ne&&a.jsx("div",{className:"p-3 bg-blue-500/10 border border-blue-500/30 rounded-lg",children:a.jsxs("div",{className:"flex items-start gap-3",children:[a.jsx(lo,{className:"w-5 h-5 text-blue-400 mt-0.5 flex-shrink-0"}),a.jsxs("div",{className:"flex-1",children:[a.jsx("p",{className:"text-sm text-blue-300 font-medium",children:l("fileManager.zipFilesDetected")}),a.jsx("p",{className:"text-xs text-blue-300/70 mt-1",children:l("fileManager.zipExtractOptions")}),a.jsxs("label",{className:"flex items-center gap-2 mt-2 cursor-pointer",children:[a.jsx("input",{type:"checkbox",checked:x,onChange:se=>v(se.target.checked),className:"w-4 h-4 rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsx("span",{className:"text-sm text-white",children:l("fileManager.preserveZipStructure")})]}),a.jsxs("label",{className:"flex items-center gap-2 mt-2 cursor-pointer",children:[a.jsx("input",{type:"checkbox",checked:b,onChange:se=>g(se.target.checked),className:"w-4 h-4 rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsx("span",{className:"text-sm text-white",children:l("fileManager.createFolderFromZip")})]})]})]})}),J&&a.jsx("div",{className:"p-3 bg-purple-500/10 border border-purple-500/30 rounded-lg",children:a.jsxs("div",{className:"flex items-start gap-3",children:[a.jsx(Mr,{className:"w-5 h-5 text-purple-400 mt-0.5 flex-shrink-0"}),a.jsxs("div",{className:"flex-1",children:[a.jsx("p",{className:"text-sm text-purple-300 font-medium",children:l("fileManager.threemfDetected")}),a.jsx("p",{className:"text-xs text-purple-300/70 mt-1",children:l("fileManager.threemfExtractionInfo")})]})]})}),(re||ne)&&a.jsx("div",{className:"p-3 bg-bambu-green/10 border border-bambu-green/30 rounded-lg",children:a.jsxs("div",{className:"flex items-start gap-3",children:[a.jsx(Bd,{className:"w-5 h-5 text-bambu-green mt-0.5 flex-shrink-0"}),a.jsxs("div",{className:"flex-1",children:[a.jsx("p",{className:"text-sm text-bambu-green font-medium",children:l("fileManager.stlThumbnailGeneration")}),a.jsx("p",{className:"text-xs text-bambu-green/70 mt-1",children:l(ne&&!re?"fileManager.zipMayContainStl":"fileManager.thumbnailsCanBeGenerated")}),a.jsxs("label",{className:"flex items-center gap-2 mt-2 cursor-pointer",children:[a.jsx("input",{type:"checkbox",checked:S,onChange:se=>N(se.target.checked),className:"w-4 h-4 rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsx("span",{className:"text-sm text-white",children:l("fileManager.generateThumbnailsForStl")})]})]})]})}),c.length>0&&a.jsx("div",{className:"max-h-48 overflow-y-auto space-y-2",children:c.map((se,K)=>a.jsxs("div",{className:"flex items-center gap-3 p-2 bg-bambu-dark rounded-lg",children:[se.isZip?a.jsx(lo,{className:"w-4 h-4 text-blue-400 flex-shrink-0"}):a.jsx(JP,{className:"w-4 h-4 text-bambu-gray flex-shrink-0"}),a.jsxs("div",{className:"flex-1 min-w-0",children:[a.jsx("p",{className:"text-sm text-white truncate",children:se.file.name}),a.jsxs("p",{className:"text-xs text-bambu-gray",children:[(se.file.size/1024/1024).toFixed(2)," MB",se.isZip&&se.status==="pending"&&a.jsxs("span",{className:"text-blue-400 ml-2",children:["• ",l("fileManager.willBeExtracted")]}),se.extractedCount!==void 0&&a.jsxs("span",{className:"text-green-400 ml-2",children:["• ",l("fileManager.filesExtracted",{count:se.extractedCount})]})]})]}),se.status==="pending"&&a.jsx("button",{onClick:()=>R(K),className:"p-1 hover:bg-bambu-dark-tertiary rounded",children:a.jsx(Bt,{className:"w-4 h-4 text-bambu-gray"})}),se.status==="uploading"&&a.jsx(mt,{className:"w-4 h-4 text-bambu-green animate-spin"}),se.status==="success"&&a.jsx(wr,{className:"w-4 h-4 text-green-500"}),se.status==="error"&&a.jsx("span",{title:se.error,children:a.jsx(Da,{className:"w-4 h-4 text-red-500"})})]},K))}),P&&a.jsx("div",{className:"p-3 bg-red-500/10 border border-red-500/30 rounded-lg",children:a.jsxs("div",{className:"flex items-start gap-3",children:[a.jsx(Da,{className:"w-5 h-5 text-red-400 mt-0.5 flex-shrink-0"}),a.jsx("p",{className:"text-sm text-red-300",children:P})]})})]}),a.jsxs("div",{className:"p-4 border-t border-bambu-dark-tertiary flex justify-end gap-2",children:[a.jsx(De,{variant:"secondary",onClick:e,children:l("common.cancel")}),!ie&&a.jsx(De,{onClick:()=>z(c),disabled:ue===0||p,children:p?a.jsxs(a.Fragment,{children:[a.jsx(mt,{className:"w-4 h-4 mr-2 animate-spin"}),l("fileManager.uploading")]}):a.jsxs(a.Fragment,{children:[a.jsx(_a,{className:"w-4 h-4 mr-2"}),l("common.upload")," ",ue>0?`(${ue})`:""]})})]})]})})}function vK(t){return t?`#${t.replace("#","").substring(0,6)}`:"#808080"}function ja(t){return t?t.replace("#","").toLowerCase().substring(0,6):""}const I7e=[["PA-CF","PA12-CF","PAHT-CF"]],vie={};for(const t of I7e){const e=t[0];for(const n of t)vie[n.toUpperCase()]=e.toUpperCase()}function XC(t){if(!t)return"";const e=t.toUpperCase();return vie[e]??e}function HD(t,e){return XC(t)===XC(e)}function Gc(t,e,n=40){const r=ja(t),i=ja(e);if(!r||!i||r.length<6||i.length<6)return!1;const s=parseInt(r.substring(0,2),16),o=parseInt(r.substring(2,4),16),l=parseInt(r.substring(4,6),16),c=parseInt(i.substring(0,2),16),d=parseInt(i.substring(2,4),16),u=parseInt(i.substring(4,6),16);return Math.abs(s-c)<=n&&Math.abs(o-d)<=n&&Math.abs(l-u)<=n}function BS(t,e,n,r){if(r)return"Ext";const i=String.fromCharCode(65+(t>=128?t-128:t));return n?`HT-${i}`:`${i}${e+1}`}function Rg(t,e,n){return n?254+e:t>=128?t:t*4+e}function Gx(t){return t>50?"#00ae42":t>=15?"#f59e0b":"#ef4444"}function lN(t){return!t?.remaining_weight||!t?.filament_weight||t.filament_weight<=0?null:Math.min(100,Math.round(t.remaining_weight/t.filament_weight*100))}function wK(t,e){return(Number.isFinite(t)?Math.max(0,Math.trunc(t)):0).toString(16).toUpperCase().padStart(e,"0").slice(-e)}function O7e(t){const e=(t||"").trim().toUpperCase();let n=2166136261;for(let r=0;r>>0).toString(16).toUpperCase().padStart(8,"0")}function Gu(t,e,n){return`${O7e(t)}${wK(e,4)}${wK(n,4)}`}function SK(t){if(!t)return!1;const e=Date.now()+4320*60*60*1e3;return(Kn(t)?.getTime()??0)>e}function z7e(t,e,n,r){let i=wie(e,t.nozzle_id);r&&(i=[...i].sort((c,d)=>{const u=(c.remain??-1)>=0?c.remain??-1:101,m=(d.remain??-1)>=0?d.remain??-1:101;return u-m}));const s=i.find(c=>!n.has(c.globalTrayId)&&HD(c.type,t.type)&&ja(c.color)===ja(t.color)),o=s?void 0:i.find(c=>!n.has(c.globalTrayId)&&HD(c.type,t.type)&&Gc(c.color,t.color)),l=s||o?void 0:i.find(c=>!n.has(c.globalTrayId)&&HD(c.type,t.type));return s??o??l}function wie(t,e){return t.filter(n=>e==null||n.extruderId===e)}function HS(t){const e=[],n=t?.ams_extruder_map,r=n&&Object.keys(n).length>0;t?.ams?.forEach(i=>{const s=i.tray.length===1;i.tray.forEach(o=>{if(o.tray_type){const l=vK(o.tray_color);e.push({type:o.tray_type,color:l,colorName:nc(l),amsId:i.id,trayId:o.id,isHt:s,isExternal:!1,label:BS(i.id,o.id,s,!1),globalTrayId:Rg(i.id,o.id,!1),trayInfoIdx:o.tray_info_idx||"",traySubBrands:o.tray_sub_brands||"",extruderId:n?.[String(i.id)],remain:o.remain??-1})}})});for(const i of t?.vt_tray??[])if(i.tray_type){const s=vK(i.tray_color),o=i.id??254,l=(t?.vt_tray?.length??0)>1;e.push({type:i.tray_type,color:s,colorName:nc(s),amsId:-1,trayId:o-254,isHt:!1,isExternal:!0,label:l?o===254?"Ext-L":"Ext-R":"External",globalTrayId:o,trayInfoIdx:i.tray_info_idx||"",traySubBrands:i.tray_sub_brands||"",extruderId:r?255-o:void 0,remain:i.remain??-1})}return e}function _K(t,e,n){if(!t?.filaments||t.filaments.length===0)return;const r=HS(e);if(r.length===0)return;const i=e?.fila_switch?.installed===!0,s=new Set,o=t.filaments.map(d=>{const u=d.tray_info_idx||"";let m=r.filter(g=>!s.has(g.globalTrayId));d.nozzle_id!=null&&!i&&(m=m.filter(g=>g.extruderId===d.nozzle_id)),n&&(m=[...m].sort((g,S)=>{const N=g.remain>=0?g.remain:101,P=S.remain>=0?S.remain:101;return N-P}));let p,f,x,v;if(u){const g=m.filter(S=>S.trayInfoIdx===u);g.length===1?p=g[0]:g.length>1&&(n&&g.sort((S,N)=>{const P=S.remain>=0?S.remain:101,C=N.remain>=0?N.remain:101;return P-C}),f=g.find(S=>S.type?.toUpperCase()===d.type?.toUpperCase()&&ja(S.color)===ja(d.color)),f||(x=g.find(S=>S.type?.toUpperCase()===d.type?.toUpperCase()&&Gc(S.color,d.color))),!f&&!x&&(v=g.find(S=>S.type?.toUpperCase()===d.type?.toUpperCase())))}!p&&!f&&!x&&!v&&(f=m.find(g=>g.type?.toUpperCase()===d.type?.toUpperCase()&&ja(g.color)===ja(d.color)),f||(x=m.find(g=>g.type?.toUpperCase()===d.type?.toUpperCase()&&Gc(g.color,d.color))),!f&&!x&&(v=m.find(g=>g.type?.toUpperCase()===d.type?.toUpperCase())));const b=p||f||x||v||void 0;return b&&s.add(b.globalTrayId),{slot_id:d.slot_id,globalTrayId:b?.globalTrayId??-1}}),l=Math.max(...o.map(d=>d.slot_id||0));if(l<=0)return;const c=new Array(l).fill(-1);return o.forEach(d=>{d.slot_id&&d.slot_id>0&&(c[d.slot_id-1]=d.globalTrayId)}),c}function U7e(t){return w.useMemo(()=>HS(t),[t])}function Sie(t,e,n,r){const i=U7e(e),s=e?.fila_switch?.installed===!0,o=w.useMemo(()=>{if(!t?.filaments||t.filaments.length===0)return[];const u=new Set(Object.values(n));return t.filaments.map(m=>{const p=m.slot_id||0;if(p>0&&n[p]!==void 0){const F=n[p],k=i.find(E=>E.globalTrayId===F);if(k){const E=k.type?.toUpperCase()===m.type?.toUpperCase(),$=ja(k.color)===ja(m.color)||Gc(k.color,m.color);let z;return E&&$?z="match":E?z="type_only":z="mismatch",{...m,loaded:k,hasFilament:!0,typeMatch:E,colorMatch:$,status:z,isManual:!0}}}const f=m.tray_info_idx||"";let x=i.filter(F=>!u.has(F.globalTrayId));m.nozzle_id!=null&&!s&&(x=x.filter(F=>F.extruderId===m.nozzle_id)),r&&(x=[...x].sort((F,k)=>{const E=F.remain>=0?F.remain:101,$=k.remain>=0?k.remain:101;return E-$}));let v,b,g,S;if(f){const F=x.filter(k=>k.trayInfoIdx===f);F.length===1?v=F[0]:F.length>1&&(r&&F.sort((k,E)=>{const $=k.remain>=0?k.remain:101,z=E.remain>=0?E.remain:101;return $-z}),b=F.find(k=>k.type?.toUpperCase()===m.type?.toUpperCase()&&ja(k.color)===ja(m.color)),b||(g=F.find(k=>k.type?.toUpperCase()===m.type?.toUpperCase()&&Gc(k.color,m.color))),!b&&!g&&(S=F.find(k=>k.type?.toUpperCase()===m.type?.toUpperCase())))}!v&&!b&&!g&&!S&&(b=x.find(F=>F.type?.toUpperCase()===m.type?.toUpperCase()&&ja(F.color)===ja(m.color)),b||(g=x.find(F=>F.type?.toUpperCase()===m.type?.toUpperCase()&&Gc(F.color,m.color))),!b&&!g&&(S=x.find(F=>F.type?.toUpperCase()===m.type?.toUpperCase())));const N=v||b||g||S||void 0;N&&u.add(N.globalTrayId);const P=!!N,C=P,A=!!v||!!b||!!g;let T;return v||b||g?T="match":S?T="type_only":T="mismatch",{...m,loaded:N,hasFilament:P,typeMatch:C,colorMatch:A,status:T,isManual:!1}})},[t,i,n,r,s]),l=w.useMemo(()=>{if(o.length===0)return;const u=Math.max(...o.map(p=>p.slot_id||0));if(u<=0)return;const m=new Array(u).fill(-1);return o.forEach(p=>{p.slot_id&&p.slot_id>0&&(m[p.slot_id-1]=p.loaded?.globalTrayId??-1)}),m},[o]),c=o.some(u=>u.status==="mismatch"),d=o.some(u=>u.status==="type_only");return{loadedFilaments:i,filamentComparison:o,amsMapping:l,hasTypeMismatch:c,hasColorMismatch:d}}function B7e(t,e,n,r){if(!t||t.length===0)return{exactMatches:0,typeOnlyMatches:0,missingTypes:0,totalSlots:0,status:"full"};let i=0,s=0,o=0;const l=new Set(Object.values(n));for(const u of t){const m=u.slot_id||0;if(m>0&&n[m]!==void 0){const g=n[m],S=e.find(N=>N.globalTrayId===g);if(S){const N=S.type?.toUpperCase()===u.type?.toUpperCase(),P=ja(S.color)===ja(u.color)||Gc(S.color,u.color);N&&P?i++:N?s++:o++;continue}}let p=e.filter(g=>!l.has(g.globalTrayId));if(u.nozzle_id!=null){const g=p.filter(S=>S.extruderId===u.nozzle_id);g.length>0&&(p=g)}r&&(p=[...p].sort((g,S)=>{const N=g.remain>=0?g.remain:101,P=S.remain>=0?S.remain:101;return N-P}));const f=p.find(g=>g.type?.toUpperCase()===u.type?.toUpperCase()&&ja(g.color)===ja(u.color)),x=f?void 0:p.find(g=>g.type?.toUpperCase()===u.type?.toUpperCase()&&Gc(g.color,u.color)),v=f||x?void 0:p.find(g=>g.type?.toUpperCase()===u.type?.toUpperCase()),b=f??x??v;b&&l.add(b.globalTrayId),f||x?i++:v?s++:o++}const c=t.length;let d="full";return o>0?d="missing":s>0&&(d="partial"),{exactMatches:i,typeOnlyMatches:s,missingTypes:o,totalSlots:c,status:d}}function H7e(t,e,n,r){if(!t?.filaments||t.filaments.length===0)return;const i=HS(e);if(i.length===0)return;const s=new Set(Object.values(n)),o=[];for(const d of t.filaments){const u=d.slot_id||0;if(u>0&&n[u]!==void 0){o.push({slot_id:u,globalTrayId:n[u]});continue}let m=i.filter(b=>!s.has(b.globalTrayId));if(d.nozzle_id!=null){const b=m.filter(g=>g.extruderId===d.nozzle_id);b.length>0&&(m=b)}r&&(m=[...m].sort((b,g)=>{const S=b.remain>=0?b.remain:101,N=g.remain>=0?g.remain:101;return S-N}));const p=m.find(b=>b.type?.toUpperCase()===d.type?.toUpperCase()&&ja(b.color)===ja(d.color)),f=p?void 0:m.find(b=>b.type?.toUpperCase()===d.type?.toUpperCase()&&Gc(b.color,d.color)),x=p||f?void 0:m.find(b=>b.type?.toUpperCase()===d.type?.toUpperCase()),v=p??f??x;v&&s.add(v.globalTrayId),o.push({slot_id:u,globalTrayId:v?.globalTrayId??-1})}const l=Math.max(...o.map(d=>d.slot_id||0));if(l<=0)return;const c=new Array(l).fill(-1);return o.forEach(d=>{d.slot_id&&d.slot_id>0&&(c[d.slot_id-1]=d.globalTrayId)}),c}const kK={useDefault:!0,manualMappings:{},autoConfigured:!1};function q7e(t,e,n,r,i,s,o){const l=Dp({queries:t.map(v=>({queryKey:["printer-status",v],queryFn:()=>oe.getPrinterStatus(v),enabled:t.length>0,staleTime:5e3}))}),c=w.useMemo(()=>t.map((v,b)=>{const g=l[b],S=g?.data,P=e?.find($=>$.id===v)?.name||`Printer ${v}`,C=HS(S),A=i[v]||kK,T=_K(n,S,o),F=A.useDefault?r:A.manualMappings,k=H7e(n,S,F,o),E=B7e(n?.filaments,C,F,o);return{printerId:v,printerName:P,status:S,isLoading:g?.isLoading??!1,loadedFilaments:C,autoMapping:T,finalMapping:k,matchStatus:E.status,exactMatches:E.exactMatches,typeOnlyMatches:E.typeOnlyMatches,missingTypes:E.missingTypes,totalSlots:E.totalSlots,config:A}}),[t,l,e,n,i,r,o]),d=l.some(v=>v.isLoading),u=(v,b)=>{s(g=>({...g,[v]:{...g[v]||kK,...b}}))},m=v=>{const b=c.find(N=>N.printerId===v);if(!b||!b.status||!n?.filaments)return;const g=_K(n,b.status,o);if(!g)return;const S={};g.forEach((N,P)=>{N!==-1&&(S[P+1]=N)}),u(v,{useDefault:!1,manualMappings:S,autoConfigured:!0})},p=()=>{for(const v of t)m(v)},f=v=>c.find(g=>g.printerId===v)?.finalMapping,x=c.every(v=>v.matchStatus!=="missing");return{printerResults:c,isLoading:d,perPrinterConfigs:i,updatePrinterConfig:u,autoConfigureAll:p,autoConfigurePrinter:m,getFinalMapping:f,allPrintersReady:x}}const _ie={USD:"$",EUR:"€",GBP:"£",CHF:"Fr.",JPY:"¥",CNY:"¥",CAD:"$",AUD:"$",INR:"₹",HKD:"HK$",KRW:"₩",SEK:"kr",NOK:"kr",DKK:"kr",PLN:"zł",BRL:"R$",TWD:"NT$",SGD:"S$",NZD:"NZ$",MXN:"MX$",MYR:"RM",CZK:"Kč",THB:"฿",ZAR:"R",TRY:"₺",RUB:"₽",HUF:"Ft",ILS:"₪",UAH:"₴"};function Mo(t){return _ie[t.toUpperCase()]||t}const $7e=Object.entries(_ie).map(([t,e])=>({code:t,label:`${t} (${e})`}));function V7e({printerId:t,filamentReqs:e,manualMappings:n,onManualMappingChange:r,currencySymbol:i,defaultCostPerKg:s,defaultExpanded:o=!1}){const{t:l}=_t(),c=tn(),[d,u]=w.useState(!1),[m,p]=w.useState(o),{data:f}=Qe({queryKey:["printer-status",t],queryFn:()=>oe.getPrinterStatus(t),enabled:!!t}),{data:x}=Qe({queryKey:["spool-assignments",t],queryFn:()=>oe.getAssignments(t),enabled:!!t}),{loadedFilaments:v,filamentComparison:b,hasTypeMismatch:g,hasColorMismatch:S}=Sie(e,f,n),N=w.useMemo(()=>{const R=new Map;for(const ne of x||[]){const re=ne.ams_id===255,J=Rg(ne.ams_id,ne.tray_id,re);R.set(J,ne.spool?.cost_per_kg??null)}return R},[x]),P=w.useMemo(()=>{const R=new Map;for(const ne of x||[]){const re=ne.ams_id===255,J=Rg(ne.ams_id,ne.tray_id,re),ue=ne.spool;if(!ue){R.set(J,null);continue}R.set(J,Math.max(0,Math.round((ue.label_weight??0)-(ue.weight_used??0))))}return R},[x]),C=w.useMemo(()=>{let R=0;for(const ne of b){const re=ne.loaded?.globalTrayId;if(re==null)continue;const ue=N.get(re)??null??s;ue>0&&(R+=ne.used_grams/1e3*ue)}return R},[b,N,s]),A=w.useMemo(()=>Array.from(N.values()).some(R=>R!=null&&R>0),[N]),T=e?.filaments&&e.filaments.length>0,F=e?.filaments?.some(R=>R.nozzle_id!=null)??!1,k=f?.fila_switch?.installed===!0,E=R=>{const ne=f?.fila_switch;if(!ne?.installed)return null;const re=ne.in_slots.indexOf(R);return re<0?null:ne.out_extruders[re]??null};if(!T||!f)return null;const $=g?"#f97316":S?"#facc15":"#00ae42",z=(R,ne)=>{if(R>0)if(ne===""){const re={...n};delete re[R],r(re)}else r({...n,[R]:parseInt(ne,10)})},X=async()=>{u(!0);try{await oe.refreshPrinterStatus(t),await new Promise(R=>setTimeout(R,500)),await c.refetchQueries({queryKey:["printer-status",t]})}finally{u(!1)}};return a.jsxs("div",{className:"mb-4",children:[a.jsxs("button",{type:"button",onClick:()=>p(!m),className:"flex items-center gap-2 text-sm text-bambu-gray hover:text-white transition-colors w-full",children:[a.jsx(cw,{className:"w-4 h-4",fill:$,stroke:"none"}),a.jsx("span",{children:l("printModal.filamentMapping")}),g?a.jsx("span",{className:"text-xs text-orange-400",children:"(Type not found)"}):S?a.jsx("span",{className:"text-xs text-yellow-400",children:"(Color mismatch)"}):a.jsx("span",{className:"text-xs text-bambu-green",children:"(Ready)"}),m?a.jsx(lc,{className:"w-4 h-4 ml-auto"}):a.jsx(zn,{className:"w-4 h-4 ml-auto"})]}),m&&a.jsxs("div",{className:"mt-2 bg-bambu-dark rounded-lg p-3 space-y-2",children:[a.jsxs("div",{className:"flex items-center justify-between mb-2",children:[a.jsx("span",{className:"text-xs text-bambu-gray",children:"Click to change slot assignment"}),a.jsxs("button",{type:"button",onClick:X,className:"flex items-center gap-1 px-2 py-0.5 text-xs rounded border border-bambu-gray/30 hover:border-bambu-gray hover:bg-bambu-dark-tertiary transition-colors text-bambu-gray hover:text-white",disabled:d,children:[a.jsx(sr,{className:`w-3 h-3 ${d?"animate-spin":""}`}),a.jsx("span",{children:"Re-read"})]})]}),b.map((R,ne)=>a.jsxs("div",{className:"grid items-center gap-2 text-xs",style:{gridTemplateColumns:"16px minmax(70px, 1fr) auto 2fr 16px"},children:[a.jsx("span",{title:`Required: ${R.type} - ${nc(R.color)}`,children:a.jsx(cw,{className:"w-3 h-3",fill:R.color,stroke:R.color})}),a.jsxs("span",{className:"text-white truncate flex items-center gap-1",children:[F&&R.nozzle_id!=null&&a.jsx("span",{className:"inline-flex items-center justify-center w-3.5 h-3.5 rounded text-[9px] font-bold leading-none bg-bambu-gray/20 text-bambu-gray shrink-0",title:R.nozzle_id===1?l("printModal.leftNozzleTooltip"):l("printModal.rightNozzleTooltip"),children:R.nozzle_id===1?l("printModal.leftNozzle"):l("printModal.rightNozzle")}),R.type," ",a.jsxs("span",{className:"text-bambu-gray",children:["(",R.used_grams,"g)"]})]}),a.jsx("span",{className:"text-bambu-gray",children:"→"}),a.jsxs("select",{value:R.loaded?.globalTrayId??"",onChange:re=>z(R.slot_id||0,re.target.value),className:`flex-1 px-2 py-1 rounded border text-xs bg-bambu-dark-secondary focus:outline-none focus:ring-1 focus:ring-bambu-green ${R.status==="match"?"border-bambu-green/50 text-bambu-green":R.status==="type_only"?"border-yellow-400/50 text-yellow-400":"border-orange-400/50 text-orange-400"} ${R.isManual?"ring-1 ring-blue-400/50":""}`,title:R.isManual?"Manually selected":"Auto-matched",children:[a.jsx("option",{value:"",className:"bg-bambu-dark text-bambu-gray",children:"-- Select slot --"}),v.filter(re=>R.nozzle_id==null||k||re.extruderId===R.nozzle_id).map(re=>{const J=P.get(re.globalTrayId),ue=J!=null?l("printModal.slotRemainingShort",{grams:J,defaultValue:` - ${J}g left`}):"",ie=k?E(re.globalTrayId):null,se=ie==null?"":` [${l(ie===1?"printModal.leftNozzle":"printModal.rightNozzle")}]`;return a.jsxs("option",{value:re.globalTrayId,className:"bg-bambu-dark text-white",children:[re.label,": ",re.traySubBrands||re.type," (",re.colorName,")",ue,se]},re.globalTrayId)})]}),R.status==="match"?a.jsx(jr,{className:"w-3 h-3 text-bambu-green"}):R.status==="type_only"?a.jsx("span",{title:"Same type, different color",children:a.jsx(Cn,{className:"w-3 h-3 text-yellow-400"})}):a.jsx("span",{title:"Filament type not loaded",children:a.jsx(Cn,{className:"w-3 h-3 text-orange-400"})})]},ne)),a.jsxs("div",{className:"text-xs text-bambu-gray",children:[l("printModal.totalCost")," ",a.jsx("span",{className:"text-white",children:C>0||A?`${i}${C.toFixed(2)}`:"N/A"})]}),g&&a.jsx("p",{className:"text-xs text-orange-400 mt-2",children:"Required filament type not found in printer."})]})]})}function G7e({filamentReqs:t,availableFilaments:e,overrides:n,onChange:r,forceColorMatch:i,onForceColorMatchChange:s}){const{t:o}=_t(),l=w.useMemo(()=>{const u={};for(const m of e){const p=XC(m.type);u[p]||(u[p]=[]),u[p].push(m)}return u},[e]),c=t?.filaments;if(!c||c.length===0||e.length===0)return null;const d=(u,m)=>{if(m===""){const p={...n};delete p[u],r(p)}else{const[p,f]=m.split("|");r({...n,[u]:{type:p,color:f}})}};return a.jsxs("div",{className:"mb-4",children:[a.jsx("div",{className:"flex items-center gap-2 text-sm text-bambu-gray mb-2",children:a.jsx("span",{children:o("printModal.filamentOverride")})}),a.jsx("p",{className:"text-xs text-bambu-gray mb-2",children:o("printModal.filamentOverrideHint")}),a.jsx("div",{className:"bg-bambu-dark rounded-lg p-3 space-y-2",children:c.map(u=>{const m=n[u.slot_id],p=!!m,f=l[XC(u.type)]||[],x=u.nozzle_id!=null?f.filter(v=>v.extruder_id==null||v.extruder_id===u.nozzle_id):f;return a.jsxs("div",{className:"space-y-1",children:[a.jsxs("div",{className:"grid items-center gap-2 text-xs",style:{gridTemplateColumns:"16px minmax(70px, 1fr) auto 2fr 20px"},children:[a.jsx("span",{title:`${o("printModal.originalFilament")}: ${u.type} - ${nc(u.color)}`,children:a.jsx(cw,{className:"w-3 h-3",fill:u.color,stroke:u.color})}),a.jsxs("span",{className:"text-white truncate",children:[u.type," ",a.jsxs("span",{className:"text-bambu-gray",children:["(",u.used_grams,"g)"]})]}),a.jsx("span",{className:"text-bambu-gray",children:"→"}),a.jsxs("select",{value:p?`${m.type}|${m.color}`:"",onChange:v=>d(u.slot_id,v.target.value),disabled:x.length===0,className:`flex-1 px-2 py-1 rounded border text-xs bg-bambu-dark-secondary focus:outline-none focus:ring-1 focus:ring-bambu-green ${p?"border-blue-400/50 text-blue-400":"border-bambu-gray/30 text-bambu-gray"}`,children:[a.jsxs("option",{value:"",className:"bg-bambu-dark text-bambu-gray",children:[o("printModal.originalFilament"),": ",u.type," (",nc(u.color),")"]}),x.map((v,b)=>a.jsxs("option",{value:`${v.type}|${v.color}`,className:"bg-bambu-dark text-white",children:[v.tray_sub_brands||v.type," (",nc(v.color),")"]},`${v.type}-${v.color}-${v.tray_sub_brands}-${b}`))]}),p?a.jsx("button",{type:"button",onClick:()=>d(u.slot_id,""),className:"text-bambu-gray hover:text-white transition-colors",title:o("printModal.resetToOriginal"),children:a.jsx(Ts,{className:"w-3 h-3"})}):a.jsx("span",{className:"w-3"})]}),a.jsxs("label",{className:"inline-flex items-center gap-1.5 text-xs text-bambu-gray cursor-pointer select-none pl-5",children:[a.jsx("input",{type:"checkbox",checked:i?.[u.slot_id]??!1,onChange:v=>s?.(u.slot_id,v.target.checked),className:"accent-bambu-green w-3 h-3"}),a.jsx(lS,{className:"w-3 h-3"}),o("printModal.forceColorMatch")]})]},u.slot_id)})})]})}function W7e({plates:t,isMultiPlate:e,selectedPlates:n,onToggle:r,onSelectAll:i,onDeselectAll:s,multiSelect:o}){const{t:l}=_t();if(!e||t.length<=1)return null;const c=n.size===t.length;return a.jsxs("div",{className:"mb-4",children:[a.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[a.jsx(ia,{className:"w-4 h-4 text-bambu-gray"}),a.jsxs("span",{className:"text-sm text-bambu-gray",children:["Select Plate",o?"s":""," to Print"]}),n.size===0&&a.jsxs("span",{className:"text-xs text-orange-400 flex items-center gap-1",children:[a.jsx(Cn,{className:"w-3 h-3"}),"Selection required"]}),o&&i&&s&&a.jsx("button",{type:"button",onClick:c?s:i,className:`ml-auto text-xs px-2 py-0.5 rounded-full border transition-colors ${c?"border-bambu-green bg-bambu-green/10 text-bambu-green":"border-bambu-dark-tertiary text-bambu-gray hover:border-bambu-gray"}`,children:c?l("queue.deselectAll"):l("queue.selectAllPlates",{count:t.length})})]}),a.jsx("div",{className:"grid grid-cols-2 gap-2",children:t.map(d=>{const u=n.has(d.index);return a.jsxs("button",{type:"button",onClick:()=>r(d.index),className:`flex items-center gap-2 p-2 rounded-lg border transition-colors text-left ${u?"border-bambu-green bg-bambu-green/10":"border-bambu-dark-tertiary bg-bambu-dark hover:border-bambu-gray"}`,children:[o&&(u?a.jsx(As,{className:"w-4 h-4 text-bambu-green flex-shrink-0"}):a.jsx(mo,{className:"w-4 h-4 text-bambu-gray flex-shrink-0"})),d.has_thumbnail&&d.thumbnail_url!=null?a.jsx("img",{src:Ta(d.thumbnail_url),alt:`Plate ${d.index}`,className:"w-10 h-10 rounded object-cover bg-bambu-dark-tertiary"}):a.jsx("div",{className:"w-10 h-10 rounded bg-bambu-dark-tertiary flex items-center justify-center",children:a.jsx(ia,{className:"w-5 h-5 text-bambu-gray"})}),a.jsxs("div",{className:"min-w-0 flex-1",children:[a.jsx("p",{className:"text-sm text-white font-medium truncate",children:d.name||`Plate ${d.index}`}),a.jsxs("p",{className:"text-xs text-bambu-gray truncate",children:[d.objects.length>0?d.objects.slice(0,3).join(", ")+(d.objects.length>3?"...":""):`${d.filaments.length} filament${d.filaments.length!==1?"s":""}`,d.print_time_seconds!=null?` • ${Qi(d.print_time_seconds)}`:""]})]}),!o&&u&&a.jsx(jr,{className:"w-4 h-4 text-bambu-green flex-shrink-0"})]},d.index)})})]})}const K7e=new Set(["IDLE","FINISH","FAILED"]);function X7e({printerResult:t,filamentReqs:e,onUpdateConfig:n}){const r=tn(),[i,s]=w.useState(!1),o=(d,u)=>{if(d<=0)return;const m={...t.config.manualMappings};u===""?delete m[d]:m[d]=parseInt(u,10),n({useDefault:!1,manualMappings:m,autoConfigured:!1})},l=async()=>{s(!0);try{await oe.refreshPrinterStatus(t.printerId),await new Promise(d=>setTimeout(d,500)),await r.refetchQueries({queryKey:["printer-status",t.printerId]})}finally{s(!1)}},c=e.map(d=>{const u=d.slot_id||0,m=t.config.manualMappings[u];let p,f=!1;if(m!==void 0)p=t.loadedFilaments.find(v=>v.globalTrayId===m),f=!0;else{const v=new Set(Object.values(t.config.manualMappings)),b=r.getQueryData(["settings"]);p=z7e(d,t.loadedFilaments,v,b?.prefer_lowest_filament)}let x="mismatch";if(p){const v=p.type?.toUpperCase()===d.type?.toUpperCase(),b=ja(p.color)===ja(d.color)||Gc(p.color,d.color);v&&b?x="match":v&&(x="type_only")}return{req:d,loaded:p,status:x,isManual:f}});return a.jsxs("div",{className:"mt-2 bg-bambu-dark rounded-lg p-3 space-y-2",children:[a.jsxs("div",{className:"flex items-center justify-between mb-2",children:[a.jsx("span",{className:"text-xs text-bambu-gray",children:"Custom slot mapping"}),a.jsxs("button",{type:"button",onClick:l,className:"flex items-center gap-1 px-2 py-0.5 text-xs rounded border border-bambu-gray/30 hover:border-bambu-gray hover:bg-bambu-dark-tertiary transition-colors text-bambu-gray hover:text-white",disabled:i,children:[a.jsx(sr,{className:`w-3 h-3 ${i?"animate-spin":""}`}),a.jsx("span",{children:"Re-read"})]})]}),c.map(({req:d,loaded:u,status:m,isManual:p},f)=>a.jsxs("div",{className:"grid items-center gap-2 text-xs",style:{gridTemplateColumns:"16px minmax(70px, 1fr) auto 2fr 16px"},children:[a.jsx("span",{title:`Required: ${d.type} - ${nc(d.color)}`,children:a.jsx(cw,{className:"w-3 h-3",fill:d.color,stroke:d.color})}),a.jsxs("span",{className:"text-white truncate",children:[d.type," ",a.jsxs("span",{className:"text-bambu-gray",children:["(",d.used_grams,"g)"]})]}),a.jsx("span",{className:"text-bambu-gray",children:"→"}),a.jsxs("select",{value:u?.globalTrayId??"",onChange:x=>o(d.slot_id||0,x.target.value),className:`flex-1 px-2 py-1 rounded border text-xs bg-bambu-dark-secondary focus:outline-none focus:ring-1 focus:ring-bambu-green ${m==="match"?"border-bambu-green/50 text-bambu-green":m==="type_only"?"border-yellow-400/50 text-yellow-400":"border-orange-400/50 text-orange-400"} ${p?"ring-1 ring-blue-400/50":""}`,title:p?"Manually selected":"Auto-matched",children:[a.jsx("option",{value:"",className:"bg-bambu-dark text-bambu-gray",children:"-- Select slot --"}),wie(t.loadedFilaments,d.nozzle_id).map(x=>a.jsxs("option",{value:x.globalTrayId,className:"bg-bambu-dark text-white",children:[x.label,": ",x.traySubBrands||x.type," (",x.colorName,")"]},x.globalTrayId))]}),m==="match"?a.jsx(jr,{className:"w-3 h-3 text-bambu-green"}):m==="type_only"?a.jsx("span",{title:"Same type, different color",children:a.jsx(Cn,{className:"w-3 h-3 text-yellow-400"})}):a.jsx("span",{title:"Filament type not loaded",children:a.jsx(Cn,{className:"w-3 h-3 text-orange-400"})})]},f))]})}function Y7e({printers:t,selectedPrinterIds:e,onMultiSelect:n,isLoading:r=!1,allowMultiple:i=!1,showInactive:s=!1,disableBusy:o=!1,printerMappingResults:l,filamentReqs:c,onAutoConfigurePrinter:d,onUpdatePrinterConfig:u,assignmentMode:m="printer",onAssignmentModeChange:p,targetModel:f,onTargetModelChange:x,targetLocation:v,onTargetLocationChange:b,slicedForModel:g}){const[S,N]=w.useState(!1),P=s?t:t.filter(ae=>ae.is_active),C=Dp({queries:P.map(ae=>({queryKey:["printerStatus",ae.id],queryFn:()=>oe.getPrinterStatus(ae.id),staleTime:5e3}))}),A=w.useMemo(()=>{const ae=new Map;return P.forEach((pe,be)=>{const fe=C[be];fe?.data&&ae.set(pe.id,fe.data)}),ae},[P,C]),T=ae=>{const pe=A.get(ae);return pe?pe.connected?!K7e.has(pe.state??""):!0:!1},F=ae=>{const pe=A.get(ae);if(!pe)return null;if(!pe.connected)return"Offline";const be=pe.state;return be?be==="RUNNING"?pe.stg_cur_name||"Printing":be==="PREPARE"?"Preparing":be==="PAUSE"?"Paused":be==="IDLE"?"Idle":be==="FINISH"?"Finished":be==="FAILED"?"Failed":be:null},k=w.useMemo(()=>{if(m!=="printer"||!g||S)return P;const ae=P.filter(pe=>pe.model===g);return ae.length>0?ae:P},[P,m,g,S]),E=P.length-k.length,$=w.useMemo(()=>{const ae=P.map(pe=>pe.model).filter(pe=>!!pe);return[...new Set(ae)].sort()},[P]),z=w.useMemo(()=>{if(!f)return[];const ae=P.filter(pe=>pe.model===f&&pe.location).map(pe=>pe.location).filter(pe=>!!pe);return[...new Set(ae)].sort()},[P,f]),X=p&&x&&$.length>0,R=i&&e.length>1&&l&&c?.filaments&&c.filaments.length>0&&d&&u;if(r)return a.jsx("div",{className:"flex justify-center py-8",children:a.jsx(mt,{className:"w-6 h-6 text-bambu-green animate-spin"})});if(k.length===0)return a.jsxs("div",{className:"flex items-center gap-2 text-red-400 text-sm mb-4",children:[a.jsx(Oa,{className:"w-4 h-4"}),"No ",s?"":"active ","printers available"]});const ne=ae=>{o&&T(ae)||(i?e.includes(ae)?n(e.filter(pe=>pe!==ae)):n([...e,ae]):n([ae]))},re=()=>{const ae=o?k.filter(pe=>!T(pe.id)):k;n(ae.map(pe=>pe.id))},J=()=>{n([])},ue=(ae,pe,be)=>{be.stopPropagation(),!(!d||!u)&&(pe?d(ae):u(ae,{useDefault:!0,manualMappings:{},autoConfigured:!1}))},ie=ae=>e.includes(ae),se=e.length,K=ae=>l?.find(pe=>pe.printerId===ae);return a.jsxs("div",{className:"space-y-2 mb-6",children:[X&&a.jsxs("div",{className:"flex gap-2 mb-4",children:[a.jsxs("button",{type:"button",onClick:()=>{p("printer"),x(null)},className:`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded-lg border transition-colors ${m==="printer"?"border-bambu-green bg-bambu-green/10 text-white":"border-bambu-dark-tertiary bg-bambu-dark text-bambu-gray hover:border-bambu-gray"}`,children:[a.jsx(Mr,{className:"w-4 h-4"}),a.jsx("span",{className:"text-sm",children:"Specific Printer"})]}),a.jsxs("button",{type:"button",onClick:()=>{p("model"),n([]);const ae=g&&$.includes(g)?g:$[0];x(ae)},className:`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded-lg border transition-colors ${m==="model"?"border-bambu-green bg-bambu-green/10 text-white":"border-bambu-dark-tertiary bg-bambu-dark text-bambu-gray hover:border-bambu-gray"}`,children:[a.jsx(Ku,{className:"w-4 h-4"}),a.jsxs("span",{className:"text-sm",children:["Any ",g||"Model"]})]})]}),m==="model"&&X&&a.jsxs("div",{className:"space-y-3 mb-4",children:[!g&&a.jsxs("div",{children:[a.jsx("label",{className:"block text-xs text-bambu-gray mb-1",children:"Target Model"}),a.jsxs("select",{value:f||"",onChange:ae=>{x(ae.target.value||null),b&&b(null)},className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm",children:[a.jsx("option",{value:"",children:"Select a model..."}),$.map(ae=>a.jsx("option",{value:ae,children:ae},ae))]})]}),f&&z.length>0&&b&&a.jsxs("div",{children:[a.jsx("label",{className:"block text-xs text-bambu-gray mb-1",children:"Location Filter (optional)"}),a.jsxs("select",{value:v||"",onChange:ae=>b(ae.target.value||null),className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white focus:border-bambu-green focus:outline-none text-sm",children:[a.jsx("option",{value:"",children:"Any location"}),z.map(ae=>a.jsx("option",{value:ae,children:ae},ae))]})]}),f&&a.jsxs("p",{className:"text-xs text-bambu-gray",children:["Scheduler will assign to first available idle ",f," printer",v?` in ${v}`:""]})]}),m==="printer"&&i&&k.length>1&&a.jsxs("div",{className:"flex items-center justify-between text-xs text-bambu-gray mb-2",children:[a.jsx("span",{children:se===0?"Select printers":`${se} printer${se!==1?"s":""} selected`}),a.jsxs("div",{className:"flex gap-2",children:[se0&&a.jsx("button",{type:"button",onClick:J,className:"text-bambu-gray hover:text-white transition-colors",children:"Clear"})]})]}),m==="printer"&&k.map(ae=>{const pe=ie(ae.id),be=K(ae.id),fe=be&&!be.config.useDefault,B=T(ae.id),Y=o&&B,D=F(ae.id);return a.jsxs("div",{children:[a.jsxs("button",{type:"button",onClick:()=>ne(ae.id),disabled:Y,className:`w-full flex items-center gap-3 p-3 rounded-lg border transition-colors ${Y?"border-bambu-dark-tertiary bg-bambu-dark opacity-50 cursor-not-allowed":pe?"border-bambu-green bg-bambu-green/10":"border-bambu-dark-tertiary bg-bambu-dark hover:border-bambu-gray"} ${ae.is_active?"":"opacity-60"}`,children:[a.jsx("div",{className:`p-2 rounded-lg ${Y?"bg-bambu-dark-tertiary":pe?"bg-bambu-green/20":"bg-bambu-dark-tertiary"}`,children:a.jsx(Mr,{className:`w-5 h-5 ${Y?"text-bambu-gray/50":pe?"text-bambu-green":"text-bambu-gray"}`})}),a.jsxs("div",{className:"text-left flex-1",children:[a.jsxs("p",{className:`font-medium ${Y?"text-bambu-gray":"text-white"}`,children:[ae.name,!ae.is_active&&a.jsx("span",{className:"text-bambu-gray text-xs ml-2",children:"(inactive)"})]}),a.jsxs("p",{className:"text-xs text-bambu-gray",children:[ae.model||"Unknown model"," • ",ae.ip_address]})]}),D&&a.jsx("span",{className:`text-xs px-2 py-0.5 rounded-full ${B?"bg-yellow-500/20 text-yellow-400":"bg-bambu-green/20 text-bambu-green"}`,children:D}),i&&a.jsx("div",{className:`w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${Y?"border-bambu-gray/30":pe?"bg-bambu-green border-bambu-green":"border-bambu-gray/50"}`,children:pe&&a.jsx(jr,{className:"w-3 h-3 text-white"})})]}),pe&&R&&be&&a.jsxs("div",{className:"ml-4 mt-2 mb-3",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",onClick:M=>M.stopPropagation(),children:[a.jsx("input",{type:"checkbox",checked:fe,onChange:M=>ue(ae.id,M.target.checked,M),className:"w-3.5 h-3.5 rounded border-bambu-gray/30 bg-bambu-dark-secondary text-bambu-green focus:ring-bambu-green focus:ring-offset-0"}),a.jsx("span",{className:"text-xs text-bambu-gray",children:"Custom mapping"})]}),a.jsxs("span",{className:`text-xs ml-2 ${be.matchStatus==="full"?"text-bambu-green":be.matchStatus==="partial"?"text-yellow-400":"text-orange-400"}`,children:["(",be.exactMatches,"/",be.totalSlots," matched)"]}),be.isLoading&&a.jsx(sr,{className:"w-3 h-3 text-bambu-gray animate-spin"}),fe&&a.jsxs("button",{type:"button",onClick:M=>{M.stopPropagation(),d(ae.id)},className:"ml-auto flex items-center gap-1 px-2 py-0.5 text-xs rounded border border-bambu-gray/30 hover:border-bambu-gray hover:bg-bambu-dark-tertiary transition-colors text-bambu-gray hover:text-white",children:[a.jsx(bJ,{className:"w-3 h-3"}),"Auto"]})]}),fe&&a.jsx(X7e,{printerResult:be,filamentReqs:c.filaments,onUpdateConfig:M=>u(ae.id,M)})]})]},ae.id)}),m==="printer"&&E>0&&!S&&a.jsxs("button",{type:"button",onClick:()=>N(!0),className:"text-xs text-bambu-gray hover:text-white transition-colors mt-2 flex items-center gap-1",children:[a.jsx(Cn,{className:"w-3 h-3 text-yellow-400"}),E," other printer",E>1?"s":""," hidden (different model) —",a.jsx("span",{className:"underline",children:"show all"})]}),m==="printer"&&S&&g&&a.jsx("button",{type:"button",onClick:()=>N(!1),className:"text-xs text-bambu-gray hover:text-white transition-colors mt-2",children:a.jsxs("span",{className:"underline",children:["Show only ",g," printers"]})}),m==="printer"&&se===0&&a.jsxs("p",{className:"text-xs text-orange-400 mt-1 flex items-center gap-1",children:[a.jsx(Oa,{className:"w-3 h-3"}),"Select at least one printer"]}),m==="model"&&!f&&a.jsxs("p",{className:"text-xs text-orange-400 mt-1 flex items-center gap-1",children:[a.jsx(Oa,{className:"w-3 h-3"}),"Select a target printer model"]})]})}const Q7e=[{key:"bed_levelling",label:"Bed Levelling",desc:"Auto-level bed before print"},{key:"flow_cali",label:"Flow Calibration",desc:"Calibrate extrusion flow"},{key:"vibration_cali",label:"Vibration Calibration",desc:"Reduce ringing artifacts"},{key:"layer_inspect",label:"First Layer Inspection",desc:"AI inspection of first layer"},{key:"timelapse",label:"Timelapse",desc:"Record timelapse video"}];function J7e({options:t,onChange:e,defaultExpanded:n=!1}){const[r,i]=w.useState(n),s=o=>{e({...t,[o]:!t[o]})};return a.jsxs("div",{className:"mb-4",children:[a.jsxs("button",{type:"button",onClick:()=>i(!r),className:"flex items-center gap-2 text-sm text-bambu-gray hover:text-white transition-colors w-full",children:[a.jsx(mS,{className:"w-4 h-4"}),a.jsx("span",{children:"Print Options"}),r?a.jsx(lc,{className:"w-4 h-4 ml-auto"}):a.jsx(zn,{className:"w-4 h-4 ml-auto"})]}),r&&a.jsx("div",{className:"mt-2 bg-bambu-dark rounded-lg p-3 space-y-2",children:Q7e.map(({key:o,label:l,desc:c})=>a.jsxs("label",{className:"flex items-center justify-between cursor-pointer group",children:[a.jsxs("div",{children:[a.jsx("span",{className:"text-sm text-white",children:l}),a.jsx("p",{className:"text-xs text-bambu-gray",children:c})]}),a.jsx("div",{className:`relative w-10 h-5 rounded-full transition-colors ${t[o]?"bg-bambu-green":"bg-bambu-dark-tertiary"}`,onClick:()=>s(o),children:a.jsx("div",{className:`absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform ${t[o]?"translate-x-5":"translate-x-0.5"}`})})]},o))})]})}function Z7e({options:t,onChange:e,dateFormat:n="system",timeFormat:r="system",canControlPrinter:i=!0,showStagger:s=!1,printerCount:o=0,hasGcodeSnippets:l=!1}){const{t:c}=_t(),[d,u]=w.useState(""),[m,p]=w.useState(""),[f,x]=w.useState(!0),[v,b]=w.useState(!0),g=w.useRef(null),S=w.useRef(!1);w.useEffect(()=>{if(t.scheduleType!=="scheduled"){S.current=!1;return}if(!S.current){S.current=!0;let k;t.scheduledTime?(k=new Date(t.scheduledTime),isNaN(k.getTime())&&(k=new Date,k.setHours(k.getHours()+1,0,0,0))):(k=new Date,k.setHours(k.getHours()+1,0,0,0),e({...t,scheduledTime:AF(k)})),u(TF(k,n)),p(r6(k,r)),x(!0),b(!0)}},[t.scheduleType,t.scheduledTime,n,r,e,t]);const N=k=>{e({...t,scheduleType:k})},P=(k,E)=>{const $=ive(k,n),z=sve(E);x(!!$),b(!!z),$&&z&&($.setHours(z.hours,z.minutes,0,0),$>new Date&&e({...t,scheduledTime:AF($)}))},C=k=>{u(k),P(k,m)},A=k=>{p(k),P(d,k)},T=k=>{const E=k.target.value;if(E){const $=new Date(E);isNaN($.getTime())||(u(TF($,n)),p(r6($,r)),x(!0),b(!0),e({...t,scheduledTime:E}))}},F=()=>{g.current?.showPicker()};return a.jsxs("div",{className:"space-y-4",children:[a.jsxs("div",{children:[a.jsx("label",{className:"block text-sm text-bambu-gray mb-2",children:"When to print"}),a.jsxs("div",{className:"flex gap-2",children:[a.jsxs("button",{type:"button",className:`flex-1 px-2 py-2 rounded-lg border text-sm flex items-center justify-center gap-1.5 transition-colors ${t.scheduleType==="asap"?"bg-bambu-green border-bambu-green text-white":"bg-bambu-dark border-bambu-dark-tertiary text-bambu-gray hover:text-white"}`,onClick:()=>N("asap"),children:[a.jsx(Yn,{className:"w-4 h-4"}),"ASAP"]}),a.jsxs("button",{type:"button",className:`flex-1 px-2 py-2 rounded-lg border text-sm flex items-center justify-center gap-1.5 transition-colors ${t.scheduleType==="scheduled"?"bg-bambu-green border-bambu-green text-white":"bg-bambu-dark border-bambu-dark-tertiary text-bambu-gray hover:text-white"}`,onClick:()=>N("scheduled"),children:[a.jsx(da,{className:"w-4 h-4"}),"Scheduled"]}),a.jsxs("button",{type:"button",className:`flex-1 px-2 py-2 rounded-lg border text-sm flex items-center justify-center gap-1.5 transition-colors ${t.scheduleType==="manual"?"bg-bambu-green border-bambu-green text-white":"bg-bambu-dark border-bambu-dark-tertiary text-bambu-gray hover:text-white"}`,onClick:()=>N("manual"),children:[a.jsx(oJ,{className:"w-4 h-4"}),"Queue Only"]})]})]}),t.scheduleType==="scheduled"&&a.jsxs("div",{children:[a.jsx("label",{className:"block text-sm text-bambu-gray mb-1",children:"Date & Time"}),a.jsxs("div",{className:"flex gap-2",children:[a.jsxs("div",{className:"flex-1 relative",children:[a.jsx("input",{type:"text",className:`w-full px-3 py-2 pr-10 bg-bambu-dark border rounded-lg text-white focus:outline-none ${f?"border-bambu-dark-tertiary focus:border-bambu-green":"border-red-500"}`,value:d,onChange:k=>C(k.target.value),placeholder:nve(n)}),a.jsx("button",{type:"button",onClick:F,className:"absolute right-2 top-1/2 -translate-y-1/2 text-bambu-gray hover:text-white",title:"Open calendar",children:a.jsx(da,{className:"w-4 h-4"})}),a.jsx("input",{ref:g,type:"datetime-local",className:"absolute top-0 left-0 w-0 h-0 opacity-0 pointer-events-none",value:t.scheduledTime,onChange:T,tabIndex:-1})]}),a.jsx("div",{className:"w-32",children:a.jsx("input",{type:"text",className:`w-full px-3 py-2 bg-bambu-dark border rounded-lg text-white focus:outline-none ${v?"border-bambu-dark-tertiary focus:border-bambu-green":"border-red-500"}`,value:m,onChange:k=>A(k.target.value),placeholder:rve(r)})})]}),(!f||!v)&&a.jsx("p",{className:"mt-1 text-xs text-red-400",children:"Please enter a valid date and time"})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"requirePrevious",checked:t.requirePreviousSuccess,onChange:k=>e({...t,requirePreviousSuccess:k.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsx("label",{htmlFor:"requirePrevious",className:"text-sm text-bambu-gray",children:"Only start if previous print succeeded"})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"autoOffAfter",checked:t.autoOffAfter,onChange:k=>e({...t,autoOffAfter:k.target.checked}),disabled:!i,className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green disabled:opacity-50"}),a.jsxs("label",{htmlFor:"autoOffAfter",className:`text-sm flex items-center gap-1 ${i?"text-bambu-gray":"text-bambu-gray/50"}`,children:[a.jsx(Jd,{className:"w-3.5 h-3.5"}),"Power off printer when done"]})]}),l&&a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"gcodeInjection",checked:t.gcodeInjection,onChange:k=>e({...t,gcodeInjection:k.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"gcodeInjection",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(Py,{className:"w-3.5 h-3.5"}),c("printModal.gcodeInjection","Inject auto-print G-code")]})]}),s&&t.scheduleType!=="manual"&&a.jsxs("div",{className:"space-y-3",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"staggerEnabled",checked:t.staggerEnabled,onChange:k=>e({...t,staggerEnabled:k.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"staggerEnabled",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(ia,{className:"w-3.5 h-3.5"}),c("printModal.staggerPrinterStarts","Stagger printer starts")]})]}),t.staggerEnabled&&a.jsxs("div",{className:"ml-6 space-y-3",children:[a.jsxs("div",{className:"flex gap-3",children:[a.jsxs("div",{className:"flex-1",children:[a.jsx("label",{className:"block text-xs text-bambu-gray mb-1",children:c("printModal.staggerGroupSize","Group size")}),a.jsx("input",{type:"number",min:1,max:o,value:t.staggerGroupSize,onChange:k=>e({...t,staggerGroupSize:Math.max(1,parseInt(k.target.value)||1)}),className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm focus:outline-none focus:border-bambu-green"})]}),a.jsxs("div",{className:"flex-1",children:[a.jsx("label",{className:"block text-xs text-bambu-gray mb-1",children:c("printModal.staggerInterval","Interval (min)")}),a.jsx("input",{type:"number",min:1,max:60,value:t.staggerIntervalMinutes,onChange:k=>e({...t,staggerIntervalMinutes:Math.max(1,parseInt(k.target.value)||1)}),className:"w-full px-3 py-2 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg text-white text-sm focus:outline-none focus:border-bambu-green"})]})]}),o>0&&(()=>{const k=Math.ceil(o/t.staggerGroupSize),E=o%t.staggerGroupSize,$=(k-1)*t.staggerIntervalMinutes;return a.jsxs("p",{className:"text-xs text-bambu-gray",children:[c("printModal.staggerPreview","{{printers}} printers → {{groups}} groups of {{size}}, starting every {{interval}} min",{printers:o,groups:k,size:t.staggerGroupSize,interval:t.staggerIntervalMinutes}),E!==0&&t.staggerGroupSize1?` (${c("printModal.staggerTotal","total: {{minutes}} min",{minutes:$})})`:""]})})()]})]}),a.jsx("p",{className:"text-xs text-bambu-gray",children:t.scheduleType==="asap"?"Print will start as soon as the printer is idle.":t.scheduleType==="scheduled"?"Print will start at the scheduled time if the printer is idle. If busy, it will wait until the printer becomes available.":"Print will be staged but won't start automatically. Use the Start button to release it to the queue."})]})}const Dc={bed_levelling:!0,flow_cali:!1,vibration_cali:!0,layer_inspect:!1,timelapse:!1},qD={scheduleType:"asap",scheduledTime:"",requirePreviousSuccess:!1,autoOffAfter:!1,gcodeInjection:!1,staggerEnabled:!1,staggerGroupSize:2,staggerIntervalMinutes:5};function ac({mode:t,archiveId:e,libraryFileId:n,archiveName:r,queueItem:i,initialSelectedPrinterIds:s,onClose:o,onSuccess:l,projectId:c,cleanupLibraryAfterDispatch:d}){const{t:u}=_t(),m=tn(),{showToast:p}=rn(),{hasPermission:f}=gr(),x=!!n&&!e,[v,b]=w.useState(()=>t==="edit-queue-item"&&i?.printer_id?[i.printer_id]:s?.length?s:[]),[g,S]=w.useState(()=>t==="edit-queue-item"&&i?.plate_id!=null?new Set([i.plate_id]):new Set),N=g.size===1?[...g][0]:null,[P,C]=w.useState(1),[A,T]=w.useState(()=>t==="edit-queue-item"&&i?{bed_levelling:i.bed_levelling??Dc.bed_levelling,flow_cali:i.flow_cali??Dc.flow_cali,vibration_cali:i.vibration_cali??Dc.vibration_cali,layer_inspect:i.layer_inspect??Dc.layer_inspect,timelapse:i.timelapse??Dc.timelapse}:Dc),[F,k]=w.useState(()=>{if(t==="edit-queue-item"&&i){let zt="asap";i.manual_start?zt="manual":i.scheduled_time&&!SK(i.scheduled_time)&&(zt="scheduled");let Tt="";if(i.scheduled_time&&!SK(i.scheduled_time)){const Ie=Kn(i.scheduled_time)??new Date;Tt=AF(Ie)}return{scheduleType:zt,scheduledTime:Tt,requirePreviousSuccess:i.require_previous_success,autoOffAfter:i.auto_off_after,gcodeInjection:i.gcode_injection??!1,staggerEnabled:!1,staggerGroupSize:qD.staggerGroupSize,staggerIntervalMinutes:qD.staggerIntervalMinutes}}return qD}),[E,$]=w.useState(()=>{if(t==="edit-queue-item"&&i?.ams_mapping&&Array.isArray(i.ams_mapping)){const zt={};return i.ams_mapping.forEach((Tt,Ie)=>{Tt!==-1&&(zt[Ie+1]=Tt)}),zt}return{}}),[z,X]=w.useState({}),[R,ne]=w.useState(()=>t==="edit-queue-item"&&i?.target_model?"model":"printer"),[re,J]=w.useState(()=>t==="edit-queue-item"&&i?.target_model?i.target_model:null),[ue,ie]=w.useState(()=>t==="edit-queue-item"&&i?.target_location?i.target_location:null),[se,K]=w.useState(()=>{if(t==="edit-queue-item"&&i?.filament_overrides){const zt={};for(const Tt of i.filament_overrides)zt[Tt.slot_id]={type:Tt.type,color:Tt.color};return zt}return{}}),[ae,pe]=w.useState(()=>{if(t==="edit-queue-item"&&i?.filament_overrides){const zt={};for(const Tt of i.filament_overrides)zt[Tt.slot_id]=Tt.force_color_match===!0;return zt}return{}}),[be]=w.useState(()=>t==="edit-queue-item"&&i?.printer_id?[i.printer_id]:[]),[fe]=w.useState(()=>t==="edit-queue-item"&&i?i.plate_id:null),[B,Y]=w.useState(!1),[D,M]=w.useState({current:0,total:0}),[U,Q]=w.useState(null),[O,ce]=w.useState(new Set),I=v.length,G=v.length>0?v[0]:null,{data:q}=Qe({queryKey:["settings"],queryFn:oe.getSettings}),W=w.useRef(!1);w.useEffect(()=>{!q||W.current||t==="edit-queue-item"||(W.current=!0,T({bed_levelling:q.default_bed_levelling??Dc.bed_levelling,flow_cali:q.default_flow_cali??Dc.flow_cali,vibration_cali:q.default_vibration_cali??Dc.vibration_cali,layer_inspect:q.default_layer_inspect??Dc.layer_inspect,timelapse:q.default_timelapse??Dc.timelapse}))},[q,t]);const te=w.useRef(!1);w.useEffect(()=>{!q||te.current||t==="edit-queue-item"||(te.current=!0,k(zt=>({...zt,staggerGroupSize:q.stagger_group_size??zt.staggerGroupSize,staggerIntervalMinutes:q.stagger_interval_minutes??zt.staggerIntervalMinutes})))},[q,t]);const le=Mo(q?.currency||"USD"),ye=q?.default_filament_cost??0,{data:he,isLoading:me}=Qe({queryKey:["printers"],queryFn:oe.getPrinters}),{data:H}=Qe({queryKey:["spool-assignments"],queryFn:()=>oe.getAssignments(),staleTime:30*1e3,enabled:(t==="reprint"||t==="add-to-queue")&&R==="printer"||x&&t==="reprint"}),{data:L}=Qe({queryKey:["archive",e],queryFn:()=>oe.getArchive(e),enabled:!!e&&!x}),{data:ee}=Qe({queryKey:["library-file",n],queryFn:()=>oe.getLibraryFile(n),enabled:x&&!!n}),ge=L?.sliced_for_model||ee?.sliced_for_model||null,{data:ke,isError:je}=Qe({queryKey:["archive-plates",e],queryFn:()=>oe.getArchivePlates(e),enabled:!!e&&!x,retry:!1}),{data:Te}=Qe({queryKey:["library-file-plates",n],queryFn:()=>oe.getLibraryFilePlates(n),enabled:x&&!!n}),xe=x?Te:ke,{data:Fe,isError:Be}=Qe({queryKey:["archive-filaments",e,N],queryFn:()=>oe.getArchiveFilamentRequirements(e,N??void 0),enabled:!!e&&!x&&(N!==null||!xe?.is_multi_plate),retry:!1}),{data:Ce}=Qe({queryKey:["library-file-filaments",n,N],queryFn:()=>oe.getLibraryFileFilamentRequirements(n,N??void 0),enabled:x&&!!n&&(N!==null||!xe?.is_multi_plate)}),ze=!x&&(je||Be),Me=x?Ce:Fe,Oe=w.useMemo(()=>{if(!(N===null||!xe?.plates?.length))return xe.plates.find(zt=>zt.index===N)?.name||void 0},[xe,N]),{data:Ge}=Qe({queryKey:["available-filaments",re,ue],queryFn:()=>oe.getAvailableFilaments(re,ue??void 0),enabled:R==="model"&&!!re}),{data:et}=Qe({queryKey:["printer-status",G],queryFn:()=>oe.getPrinterStatus(G),enabled:!!G}),{amsMapping:ve}=Sie(Me,et,E,q?.prefer_lowest_filament),Xe=q7e(v,he,Me,E,z,X,q?.prefer_lowest_filament);w.useEffect(()=>{xe?.plates&&xe.plates.length>=1&&g.size===0&&S(new Set([xe.plates[0].index]))},[xe,g.size]),w.useEffect(()=>{if(t==="edit-queue-item")return;const zt=he?.filter(Tt=>Tt.is_active)||[];zt.length===1&&v.length===0&&b([zt[0].id])},[t,he,v.length]),w.useEffect(()=>{t==="edit-queue-item"?(JSON.stringify(v.sort())!==JSON.stringify(be.sort())||N!==fe)&&($({}),X({}),ce(new Set)):($({}),X({}),ce(new Set))},[t,v,N,be,fe]);const[Pe,Ve]=w.useState(re),[we,de]=w.useState(N);w.useEffect(()=>{(re!==Pe||N!==we)&&(Ve(re),de(N),(t!=="edit-queue-item"||Pe!==null)&&(K({}),pe({})))},[re,N,Pe,we,t]),w.useEffect(()=>{if(!q?.per_printer_mapping_expanded||v.length<=1)return;const zt=v.filter(Tt=>{if(O.has(Tt))return!1;const Ie=Xe.printerResults.find(Re=>Re.printerId===Tt);return Ie&&Ie.status&&!Ie.isLoading});zt.length>0&&(ce(Tt=>{const Ie=new Set(Tt);return zt.forEach(Re=>Ie.add(Re)),Ie}),zt.forEach(Tt=>{Xe.autoConfigurePrinter(Tt)}))},[q?.per_printer_mapping_expanded,v,O,Xe]),w.useEffect(()=>{const zt=Tt=>{Tt.key==="Escape"&&!B&&o()};return window.addEventListener("keydown",zt),()=>window.removeEventListener("keydown",zt)},[o,B]);const Se=xe?.is_multi_plate??!1,$e=xe?.plates??[],st=w.useMemo(()=>{const zt=new Map;return H&&H.forEach(Tt=>{const Ie=Tt.ams_id===255,Re=Rg(Tt.ams_id,Tt.tray_id,Ie),Ye=zt.get(Tt.printer_id)??new Map;Ye.set(Re,Tt),zt.set(Tt.printer_id,Ye)}),zt},[H]),He=w.useMemo(()=>{if(!U||U.length===0)return"";const zt=U.map(Tt=>u("printModal.insufficientFilamentLine",{printer:Tt.printerName,slot:Tt.slotLabel,required:Math.round(Tt.requiredGrams),remaining:Math.round(Tt.remainingGrams)}));return[u("printModal.insufficientFilamentMessage"),...zt].join(` -`)},[U,u]),at=ot({mutationFn:zt=>oe.addToQueue(zt)}),ht=ot({mutationFn:zt=>oe.updateQueueItem(i.id,zt),onSuccess:()=>{m.invalidateQueries({queryKey:["queue"]}),p("Queue item updated"),l?.(),o()},onError:zt=>{p(zt.message||"Failed to update queue item","error")}}),Mt=F.staggerEnabled&&v.length>1,qt=async(zt,Tt)=>{if(zt?.preventDefault(),!Tt?.skipFilamentCheck&&!q?.disable_filament_warnings&&(t==="reprint"||t==="add-to-queue")&&R==="printer"){const We=[],tt=Me?.filaments??[];if(tt.length>0&&st.size>0){const nt=(Je,Ue)=>!Number.isFinite(Je)||Je<=0||!Number.isFinite(Ue)||Ue<0?null:Math.max(0,Je-Ue);for(const Je of v){const Ue=v.length>1?Xe.getFinalMapping(Je):ve;if(!Ue)continue;const rt=v.length>1?Xe.printerResults.find(Ft=>Ft.printerId===Je)?.status:et,Ct=HS(rt),bt=new Map(Ct.map(Ft=>[Ft.globalTrayId,Ft.label])),Ot=st.get(Je),Lt=he?.find(Ft=>Ft.id===Je)?.name??`Printer ${Je}`;Ot&&tt.forEach(Ft=>{if(!Ft.slot_id||Ft.slot_id<=0)return;const Ke=Ue[Ft.slot_id-1];if(!Number.isFinite(Ke)||Ke<0)return;const Yt=Ot.get(Ke)?.spool;if(!Yt)return;const on=nt(Yt.label_weight,Yt.weight_used);on!==null&&(on>=Ft.used_grams||We.push({printerName:Lt,slotLabel:bt.get(Ke)??`Slot ${Ft.slot_id}`,requiredGrams:Ft.used_grams,remainingGrams:on}))})}}if(We.length>0){Q(We);return}}if(R==="printer"&&v.length===0){p("Please select at least one printer","error");return}if(R==="model"&&!re){p("Please select a target printer model","error");return}Y(!0);const Ie=g.size>1?$e.filter(We=>g.has(We.index)):[null],Re=R==="model"?Ie.length:v.length*Ie.length;M({current:0,total:Re});const Ye={success:0,failed:0,errors:[]},Ze=We=>{if(v.length>1){const tt=z[We];if(tt&&!tt.useDefault)return Xe.getFinalMapping(We)}return ve},dt=(()=>{const We=[];if(Me?.filaments)for(const tt of Me.filaments){const nt=se[tt.slot_id],Je=ae[tt.slot_id]??!1,Ue=nt?.type??tt.type,rt=nt?.color??tt.color;(nt||Je)&&We.push({slot_id:tt.slot_id,type:Ue,color:rt,color_name:nc(rt),force_color_match:Je})}else for(const[tt,{type:nt,color:Je}]of Object.entries(se)){const Ue=parseInt(tt,10),rt=ae[Ue]??!1;We.push({slot_id:Ue,type:nt,color:Je,color_name:nc(Je),force_color_match:rt})}return We.length>0?We:void 0})(),Ae=(We,tt)=>({printer_id:R==="printer"?We:null,target_model:R==="model"?re:null,target_location:R==="model"?ue:null,filament_overrides:R==="model"?dt:void 0,archive_id:x?void 0:e,library_file_id:x?n:void 0,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:We?Ze(We):void 0,plate_id:tt!==void 0?tt:N,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():void 0,...A,project_id:c??void 0});if(R==="model"){if(t==="reprint"){p("Model-based assignment only works with queue mode","error"),Y(!1);return}let We=0;for(const tt of Ie){We++,M({current:We,total:Re});const nt=tt?tt.index:N;try{if(t==="edit-queue-item"&&!tt){const Je={printer_id:null,target_model:re,target_location:ue,filament_overrides:dt||null,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:void 0,plate_id:nt,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():null,...A};await ht.mutateAsync(Je)}else{const Je=Ae(null,nt);Qt>1&&(Je.quantity=Qt),await at.mutateAsync(Je)}Ye.success++}catch(Je){Ye.failed++;const Ue=tt?tt.name||`Plate ${tt.index}`:"";Ye.errors.push(Ue?`${Ue}: ${Je.message}`:Je.message)}}}else{const We=F.staggerEnabled&&(t==="add-to-queue"||t==="reprint")&&v.length>1,tt=We?F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).getTime():Date.now():0;let nt=0;for(const Je of Ie){const Ue=Je?Je.index:N;for(let rt=0;rt1){const Ot=Ae(Ct,Ue);Ot.quantity=Qt-1,await at.mutateAsync(Ot)}}else if(t==="edit-queue-item"&&nt===1){const bt=Ze(Ct),Ot={printer_id:Ct,target_model:null,target_location:null,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:bt,plate_id:Ue,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():null,...A};await ht.mutateAsync(Ot)}else{const bt=Ae(Ct,Ue);if(Qt>1&&(bt.quantity=Qt),We){const Ot=Math.floor(rt/F.staggerGroupSize);if(Ot>0){const Lt=Ot*F.staggerIntervalMinutes*6e4;bt.scheduled_time=new Date(tt+Lt).toISOString()}}await at.mutateAsync(bt)}Ye.success++}catch(bt){Ye.failed++;const Ot=he?.find(Ke=>Ke.id===Ct)?.name||`Printer ${Ct}`,Lt=Je?Je.name||`Plate ${Je.index}`:"",Ft=Lt?`${Ot} (${Lt})`:Ot;Ye.errors.push(`${Ft}: ${bt.message}`)}}}}Y(!1),Ye.failed===0?(t==="reprint"&&Mt?p(u("queue.itemsQueued",{count:Ye.success})):t!=="reprint"&&(t==="edit-queue-item"?p("Queue item updated"):Ye.success===1?p(R==="model"?`Queued for any ${re}`:u("queue.printQueued")):p(u("queue.itemsQueued",{count:Ye.success}))),m.invalidateQueries({queryKey:["queue"]}),l?.(),o()):Ye.success===0?p(`Failed: ${Ye.errors[0]}`,"error"):(p(`${Ye.success} succeeded, ${Ye.failed} failed`,"error"),m.invalidateQueries({queryKey:["queue"]}))},Vt=B||ht.isPending,Gt=w.useMemo(()=>!(Vt||R==="printer"&&v.length===0||R==="model"&&!re||R==="model"&&t==="reprint"||Se&&g.size===0),[v.length,R,re,t,Se,g.size,Vt]),Qt=R==="printer"&&v.length>1?1:P,mn=(()=>{const zt=v.length;if(t==="reprint"){const Tt=Mt&&zt>1;let Ie=Tt?u("printModal.staggerToPrinters",{count:zt,defaultValue:"Stagger to {{count}} printers"}):zt>1?u("queue.printToPrinters",{count:zt}):u("queue.print");return Qt>1&&(Ie=`${Ie} ×${Qt}`),{title:u(x?"queue.print":"queue.reprint"),icon:Mr,submitText:Ie,submitIcon:Tt?da:Mr,loadingText:D.total>1?u("queue.sendingProgress",{current:D.current,total:D.total}):u("queue.sending")}}if(t==="add-to-queue"){let Tt=u("queue.addToQueue");return g.size>1?Tt=u("queue.queueSelectedPlates",{count:g.size}):zt>1&&(Tt=u("queue.queueToPrinters",{count:zt})),Qt>1&&(Tt=`${Tt} ×${Qt}`),{title:u("queue.schedulePrint"),icon:da,submitText:Tt,submitIcon:da,loadingText:D.total>1?u("queue.addingProgress",{current:D.current,total:D.total}):u("queue.adding")}}return{title:u("queue.editQueueItem"),icon:li,submitText:u("common.save"),submitIcon:li,loadingText:D.total>1?u("queue.savingProgress",{current:D.current,total:D.total}):u("common.saving")}})(),dn=mn.icon,jt=mn.submitIcon,Jt=G&&g.size<=1&&(x||(Se?N!==null:!0));return a.jsxs("div",{className:"fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4",onClick:B?void 0:o,children:[a.jsx(wt,{className:"w-full max-w-2xl max-h-[90vh] overflow-y-auto",onClick:zt=>zt.stopPropagation(),children:a.jsxs(St,{className:t==="reprint"?"":"p-0",children:[a.jsxs("div",{className:`flex items-center justify-between ${t==="reprint"?"mb-4":"p-4 border-b border-bambu-dark-tertiary"}`,children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx(dn,{className:"w-5 h-5 text-bambu-green"}),a.jsx("h2",{className:"text-lg font-semibold text-white",children:mn.title})]}),a.jsx(De,{variant:"ghost",size:"sm",onClick:o,disabled:B,children:a.jsx(Bt,{className:"w-5 h-5"})})]}),a.jsxs("form",{onSubmit:qt,className:t==="reprint"?"":"p-4 space-y-4",children:[a.jsx("p",{className:`text-sm text-bambu-gray ${t==="reprint"?"mb-4":""}`,children:t==="reprint"?a.jsxs(a.Fragment,{children:["Send ",a.jsx("span",{className:"text-white",children:r})," to"," ",s?.length===1&&he?a.jsx("span",{className:"text-white",children:he.find(zt=>zt.id===s[0])?.name??"printer(s)"}):"printer(s)"]}):a.jsxs(a.Fragment,{children:[a.jsx("span",{className:"block text-bambu-gray mb-1",children:"Print Job"}),a.jsx("span",{className:"text-white font-medium truncate block",children:r})]})}),a.jsx(W7e,{plates:$e,isMultiPlate:Se,selectedPlates:g,onToggle:zt=>{S(Tt=>{const Ie=new Set(Tt);return t==="add-to-queue"?Ie.has(zt)?Ie.delete(zt):Ie.add(zt):(Ie.clear(),Ie.add(zt)),Ie})},onSelectAll:t==="add-to-queue"?()=>S(new Set($e.map(zt=>zt.index))):void 0,onDeselectAll:t==="add-to-queue"?()=>S(new Set):void 0,multiSelect:t==="add-to-queue"}),!s?.length&&a.jsx(Y7e,{printers:he||[],selectedPrinterIds:v,onMultiSelect:b,isLoading:me,allowMultiple:!0,showInactive:t==="edit-queue-item",disableBusy:t==="reprint",printerMappingResults:Xe.printerResults,filamentReqs:Me,onAutoConfigurePrinter:Xe.autoConfigurePrinter,onUpdatePrinterConfig:Xe.updatePrinterConfig,assignmentMode:t==="reprint"?"printer":R,onAssignmentModeChange:t!=="reprint"?ne:void 0,targetModel:re,onTargetModelChange:t!=="reprint"?J:void 0,targetLocation:ue,onTargetLocationChange:t!=="reprint"?ie:void 0,slicedForModel:ge}),R==="model"&&re&&Me&&Ge&&Ge.length>0&&a.jsx(G7e,{filamentReqs:Me,availableFilaments:Ge,overrides:se,onChange:K,forceColorMatch:ae,onForceColorMatchChange:(zt,Tt)=>pe(Ie=>({...Ie,[zt]:Tt}))}),ge&&R==="printer"&&v.length===1&&(()=>{const zt=he?.find(Tt=>Tt.id===v[0]);return zt&&zt.model&&ge!==zt.model?a.jsxs("div",{className:"p-3 mb-2 bg-yellow-500/10 border border-yellow-500/30 rounded-lg flex items-center gap-2",children:[a.jsx(Cn,{className:"w-4 h-4 text-yellow-400 flex-shrink-0"}),a.jsxs("span",{className:"text-sm text-yellow-400",children:["File was sliced for ",ge,", but printing on ",zt.model]})]}):null})(),ze&&a.jsxs("div",{className:"flex items-start gap-2 p-3 mb-2 bg-orange-500/10 border border-orange-500/30 rounded-lg text-sm",children:[a.jsx(Oa,{className:"w-4 h-4 text-orange-400 mt-0.5 flex-shrink-0"}),a.jsx("p",{className:"text-orange-400",children:"Archive data unavailable. The source file may have been deleted. Filament mapping is disabled."})]}),Jt&&!ze&&v.length===1&&a.jsx(V7e,{printerId:G,filamentReqs:Me,manualMappings:E,onManualMappingChange:$,defaultExpanded:!!s?.length||(q?.per_printer_mapping_expanded??!1),currencySymbol:le,defaultCostPerKg:ye}),(t==="reprint"||I>0||R==="model"&&re)&&a.jsx(J7e,{options:A,onChange:T,defaultExpanded:!!s?.length}),t!=="edit-queue-item"&&(R==="model"||v.length<=1)&&a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx("label",{htmlFor:"printQuantity",className:"text-sm text-bambu-gray whitespace-nowrap",children:u("queue.quantity","Quantity")}),a.jsx("input",{id:"printQuantity",type:"number",min:1,max:999,value:P,onChange:zt=>C(Math.max(1,Math.min(999,parseInt(zt.target.value)||1))),className:"w-20 px-2 py-1 text-sm bg-bambu-dark border border-bambu-dark-tertiary rounded text-white focus:outline-none focus:ring-1 focus:ring-bambu-green"}),P>1&&a.jsx("span",{className:"text-xs text-bambu-gray",children:u("queue.quantityHint","Creates {{count}} queue items",{count:P})})]}),t==="reprint"&&R==="printer"&&v.length>1&&a.jsxs("div",{className:"space-y-2 pb-2",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"staggerEnabledReprint",checked:F.staggerEnabled,onChange:zt=>k({...F,staggerEnabled:zt.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"staggerEnabledReprint",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(ia,{className:"w-3.5 h-3.5"}),u("printModal.staggerPrinterStarts","Stagger printer starts")]})]}),F.staggerEnabled&&(()=>{const zt=F.staggerGroupSize,Tt=F.staggerIntervalMinutes,Ie=Math.ceil(v.length/zt),Re=(Ie-1)*Tt;return a.jsxs("p",{className:"ml-6 text-xs text-bambu-gray",children:[u("printModal.staggerPreview","{{printers}} printers → {{groups}} groups of {{size}}, starting every {{interval}} min",{printers:v.length,groups:Ie,size:zt,interval:Tt}),Ie>1?` (${u("printModal.staggerTotal","total: {{minutes}} min",{minutes:Re})})`:""]})})()]}),t!=="reprint"&&a.jsx(Z7e,{options:F,onChange:k,dateFormat:q?.date_format||"system",timeFormat:q?.time_format||"system",canControlPrinter:f("printers:control"),showStagger:t==="add-to-queue"&&R==="printer"&&v.length>1,printerCount:v.length,hasGcodeSnippets:!!q?.gcode_snippets}),t==="reprint"&&!!q?.gcode_snippets&&Qt>1&&a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"gcodeInjectionReprint",checked:F.gcodeInjection,onChange:zt=>k({...F,gcodeInjection:zt.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"gcodeInjectionReprint",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(Py,{className:"w-3.5 h-3.5"}),u("printModal.gcodeInjection","Inject auto-print G-code")]})]}),ht.isError&&a.jsx("div",{className:"mb-4 p-3 bg-red-500/20 border border-red-500/50 rounded-lg text-sm text-red-400",children:ht.error?.message||"Failed to complete operation"}),a.jsxs("div",{className:`flex gap-3 ${t==="reprint"?"":"pt-2"}`,children:[a.jsx(De,{type:"button",variant:"secondary",onClick:o,className:"flex-1",disabled:B,children:"Cancel"}),a.jsx(De,{type:"submit",disabled:!Gt,className:"flex-1",children:Vt?a.jsxs(a.Fragment,{children:[a.jsx(mt,{className:"w-4 h-4 animate-spin"}),mn.loadingText]}):a.jsxs(a.Fragment,{children:[a.jsx(jt,{className:"w-4 h-4"}),mn.submitText]})})]})]})]})}),U&&U.length>0&&a.jsx(yn,{title:u("printModal.insufficientFilamentTitle"),message:He,confirmText:u("printModal.printAnyway"),cancelText:u("common.cancel"),variant:"warning",onConfirm:()=>{Q(null),qt(void 0,{skipFilamentCheck:!0})},onCancel:()=>Q(null)})]})}function NK({value:t}){const{t:e}=_t(),[n,r]=w.useState(!1),i=async()=>{try{await navigator.clipboard.writeText(t),r(!0),setTimeout(()=>r(!1),2e3)}catch{}};return a.jsx("button",{onClick:i,className:"ml-2 p-1 rounded hover:bg-bambu-dark-tertiary text-bambu-gray hover:text-white transition-colors",title:e(n?"printers.copied":"printers.copyToClipboard"),children:n?a.jsx(jr,{className:"w-3.5 h-3.5 text-bambu-green"}):a.jsx(ns,{className:"w-3.5 h-3.5"})})}function eGe({printer:t,status:e,totalPrintHours:n,onClose:r}){const{t:i}=_t();w.useEffect(()=>{const o=l=>{l.key==="Escape"&&r()};return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[r]);const s=[];if(s.push({label:i("printers.model"),value:t.model??"—"}),s.push({label:i("common.status"),value:a.jsxs("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium ${e?.connected?"bg-bambu-green/20 text-bambu-green":"bg-red-500/20 text-red-400"}`,children:[a.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${e?.connected?"bg-bambu-green":"bg-red-400"}`}),e?.connected?i("printers.status.available"):i("printers.status.offline")]})}),e?.state){const o={IDLE:"printers.status.idle",RUNNING:"printers.status.printing",PAUSE:"printers.status.paused",FINISH:"printers.status.finished",FAILED:"printers.status.error"};s.push({label:i("printers.state"),value:i(o[e.state]??"printers.status.unknown")})}if(s.push({label:i("printers.ipAddress"),value:a.jsxs("span",{className:"flex items-center",children:[a.jsx("span",{className:"font-mono",children:t.ip_address}),a.jsx(NK,{value:t.ip_address})]})}),s.push({label:i("printers.serialNumber"),value:a.jsxs("span",{className:"flex items-center",children:[a.jsx("span",{className:"font-mono truncate",children:t.serial_number}),a.jsx(NK,{value:t.serial_number})]})}),e?.wired_network)s.push({label:i("printers.networkLabel","Network"),value:a.jsxs("span",{className:"flex items-center gap-2",children:[a.jsx(KI,{className:"w-4 h-4 text-bambu-green"}),a.jsx("span",{className:"text-bambu-green",children:i("printers.connection.ethernet","Ethernet")})]})});else if(e?.wifi_signal!=null){const o=tee(e.wifi_signal);s.push({label:i("printers.wifiSignalLabel"),value:a.jsxs("span",{className:"flex items-center gap-2",children:[a.jsx(hJ,{className:`w-4 h-4 ${o.color}`}),a.jsx("span",{className:o.color,children:i(o.labelKey)}),a.jsxs("span",{className:"text-bambu-gray text-xs",children:["(",e.wifi_signal," dBm)"]})]})})}return s.push({label:i("printers.firmware"),value:e?.firmware_version??"—"}),e?.developer_mode!=null&&s.push({label:i("printers.developerMode"),value:a.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${e.developer_mode?"bg-bambu-green/20 text-bambu-green":"bg-bambu-dark-tertiary text-bambu-gray"}`,children:e.developer_mode?i("printers.enabled"):i("printers.disabled")})}),s.push({label:i("printers.nozzleCount"),value:t.nozzle_count}),s.push({label:i("printers.autoArchive"),value:a.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${t.auto_archive?"bg-bambu-green/20 text-bambu-green":"bg-bambu-dark-tertiary text-bambu-gray"}`,children:t.auto_archive?i("printers.enabled"):i("printers.disabled")})}),n!=null&&n>0&&s.push({label:i("printers.totalPrintHours"),value:`${Math.round(n)}h`}),t.location&&s.push({label:i("printers.sort.location"),value:t.location}),s.push({label:i("printers.addedOn"),value:yg(t.created_at)}),a.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",role:"dialog","aria-modal":"true",onClick:r,children:a.jsx(wt,{className:"w-full max-w-md",onClick:o=>o.stopPropagation(),children:a.jsxs(St,{children:[a.jsxs("div",{className:"flex items-center justify-between mb-4",children:[a.jsx("h2",{className:"text-lg font-semibold text-white",children:t.name}),a.jsx("button",{onClick:r,className:"p-1 hover:bg-bambu-dark rounded flex-shrink-0",children:a.jsx(Bt,{className:"w-5 h-5 text-bambu-gray"})})]}),a.jsx("div",{className:"flex justify-center mb-4",children:a.jsx("img",{src:eee(t.model),alt:t.model??t.name,className:"h-24 object-contain"})}),a.jsx("div",{className:"space-y-0",children:s.map((o,l)=>a.jsxs("div",{className:"flex items-center justify-between gap-4 py-2.5 border-b border-bambu-dark-tertiary last:border-0",children:[a.jsx("span",{className:"text-sm text-bambu-gray whitespace-nowrap",children:o.label}),a.jsx("span",{className:"text-sm text-white text-right",children:o.value})]},l))})]})})})}function tGe(t){if(!t||t.length<6)return!1;const e=parseInt(t.slice(0,2),16),n=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16);return(.299*e+.587*n+.114*r)/255>.6}function $D({trayColor:t,trayType:e,isEmpty:n,slotNumber:r}){return a.jsx("div",{className:"w-3.5 h-3.5 rounded-full mx-auto mb-0.5 border-2 flex items-center justify-center",style:{backgroundColor:t?`#${t}`:e?"#333":"transparent",borderColor:n?"#666":"rgba(255,255,255,0.1)",borderStyle:n?"dashed":"solid"},children:a.jsx("span",{className:"text-[6px] font-bold leading-none select-none",style:{color:t&&tGe(t)?"#000":"#fff"},children:r})})}function Uz({summary:t,children:e,defaultOpen:n=!1,className:r="",summaryClassName:i="",open:s,onToggle:o}){const[l,c]=w.useState(n),d=s!==void 0,u=d?s:l,m=()=>{const p=!u;d||c(p),o?.(p)};return a.jsxs("div",{className:r,children:[a.jsxs("div",{role:"button",tabIndex:0,onClick:m,onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),m())},className:`w-full flex items-center justify-between gap-2 text-left cursor-pointer ${i}`,"aria-expanded":u,children:[a.jsx("div",{className:"flex-1 min-w-0",children:t}),a.jsx(zn,{className:`w-4 h-4 text-bambu-gray flex-shrink-0 transition-transform ${u?"rotate-180":""}`})]}),u&&a.jsx("div",{className:"mt-3",children:e})]})}function VD(t){return(t??.02).toFixed(3)}function CK({side:t}){const{mode:e}=Gg(),n=e==="dark"?"#1a4d2e":"#e7f5e9";return a.jsx("span",{className:"inline-flex items-center justify-center w-4 h-4 text-[10px] font-bold rounded",style:{backgroundColor:n,color:"#00ae42"},children:t})}function kie(t,e){if(!t)return"";if(t.includes("hardened"))return e("printers.nozzleHardenedSteel");if(t.includes("stainless"))return e("printers.nozzleStainlessSteel");if(t.includes("tungsten"))return e("printers.nozzleTungstenCarbide");if(t.length>=4){const n=t.slice(2,4);if(n==="00")return e("printers.nozzleStainlessSteel");if(n==="01")return e("printers.nozzleHardenedSteel");if(n==="05")return e("printers.nozzleTungstenCarbide")}return t==="00"?e("printers.nozzleStainlessSteel"):t==="01"?e("printers.nozzleHardenedSteel"):t==="05"?e("printers.nozzleTungstenCarbide"):t.startsWith("H")?e("printers.nozzleHardenedSteel"):t}function Nie(t,e){return t?t.startsWith("HH")?e("printers.nozzleHighFlow"):t.startsWith("HS")?e("printers.nozzleStandardFlow"):"":""}function Cie({slot:t,index:e,activeStatus:n,filamentName:r,children:i}){const{t:s}=_t(),[o,l]=w.useState(!1),[c,d]=w.useState("top"),u=w.useRef(null),m=w.useRef(null),p=w.useRef(null),f=!t.nozzle_diameter&&!t.nozzle_type,x=t.stat===1;w.useEffect(()=>{if(o&&u.current&&m.current){const P=u.current.getBoundingClientRect(),C=m.current.offsetHeight,T=P.top-56,F=window.innerHeight-P.bottom;TT?d("bottom"):d("top")}},[o]);const v=()=>{p.current&&clearTimeout(p.current),p.current=setTimeout(()=>l(!0),80)},b=()=>{p.current&&clearTimeout(p.current),p.current=setTimeout(()=>l(!1),100)};w.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const g=sO(t.filament_color),S=kie(t.nozzle_type,s),N=Nie(t.nozzle_type,s);return a.jsxs("div",{ref:u,className:"relative",onMouseEnter:v,onMouseLeave:b,children:[i,o&&a.jsxs("div",{ref:m,className:` +`)},[U,u]),at=ot({mutationFn:zt=>oe.addToQueue(zt)}),ht=ot({mutationFn:zt=>oe.updateQueueItem(i.id,zt),onSuccess:()=>{m.invalidateQueries({queryKey:["queue"]}),p("Queue item updated"),l?.(),o()},onError:zt=>{p(zt.message||"Failed to update queue item","error")}}),Mt=F.staggerEnabled&&v.length>1,qt=async(zt,Tt)=>{if(zt?.preventDefault(),!Tt?.skipFilamentCheck&&!q?.disable_filament_warnings&&(t==="reprint"||t==="add-to-queue")&&R==="printer"){const We=[],tt=Me?.filaments??[];if(tt.length>0&&st.size>0){const nt=(Je,Ue)=>!Number.isFinite(Je)||Je<=0||!Number.isFinite(Ue)||Ue<0?null:Math.max(0,Je-Ue);for(const Je of v){const Ue=v.length>1?Xe.getFinalMapping(Je):ve;if(!Ue)continue;const rt=v.length>1?Xe.printerResults.find(Ft=>Ft.printerId===Je)?.status:et,Ct=HS(rt),bt=new Map(Ct.map(Ft=>[Ft.globalTrayId,Ft.label])),Ot=st.get(Je),Lt=he?.find(Ft=>Ft.id===Je)?.name??`Printer ${Je}`;Ot&&tt.forEach(Ft=>{if(!Ft.slot_id||Ft.slot_id<=0)return;const Ke=Ue[Ft.slot_id-1];if(!Number.isFinite(Ke)||Ke<0)return;const Yt=Ot.get(Ke)?.spool;if(!Yt)return;const on=nt(Yt.label_weight,Yt.weight_used);on!==null&&(on>=Ft.used_grams||We.push({printerName:Lt,slotLabel:bt.get(Ke)??`Slot ${Ft.slot_id}`,requiredGrams:Ft.used_grams,remainingGrams:on}))})}}if(We.length>0){Q(We);return}}if(R==="printer"&&v.length===0){p("Please select at least one printer","error");return}if(R==="model"&&!re){p("Please select a target printer model","error");return}Y(!0);const Ie=g.size>1?$e.filter(We=>g.has(We.index)):[null],Re=R==="model"?Ie.length:v.length*Ie.length;M({current:0,total:Re});const Ye={success:0,failed:0,errors:[]},Ze=We=>{if(v.length>1){const tt=z[We];if(tt&&!tt.useDefault)return Xe.getFinalMapping(We)}return ve},dt=(()=>{const We=[];if(Me?.filaments)for(const tt of Me.filaments){const nt=se[tt.slot_id],Je=ae[tt.slot_id]??!1,Ue=nt?.type??tt.type,rt=nt?.color??tt.color;(nt||Je)&&We.push({slot_id:tt.slot_id,type:Ue,color:rt,color_name:nc(rt),force_color_match:Je})}else for(const[tt,{type:nt,color:Je}]of Object.entries(se)){const Ue=parseInt(tt,10),rt=ae[Ue]??!1;We.push({slot_id:Ue,type:nt,color:Je,color_name:nc(Je),force_color_match:rt})}return We.length>0?We:void 0})(),Ae=(We,tt)=>({printer_id:R==="printer"?We:null,target_model:R==="model"?re:null,target_location:R==="model"?ue:null,filament_overrides:R==="model"?dt:void 0,archive_id:x?void 0:e,library_file_id:x?n:void 0,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:We?Ze(We):void 0,plate_id:tt!==void 0?tt:N,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():void 0,...A,project_id:c??void 0});if(R==="model"){if(t==="reprint"){p("Model-based assignment only works with queue mode","error"),Y(!1);return}let We=0;for(const tt of Ie){We++,M({current:We,total:Re});const nt=tt?tt.index:N;try{if(t==="edit-queue-item"&&!tt){const Je={printer_id:null,target_model:re,target_location:ue,filament_overrides:dt||null,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:void 0,plate_id:nt,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():null,...A};await ht.mutateAsync(Je)}else{const Je=Ae(null,nt);Qt>1&&(Je.quantity=Qt),await at.mutateAsync(Je)}Ye.success++}catch(Je){Ye.failed++;const Ue=tt?tt.name||`Plate ${tt.index}`:"";Ye.errors.push(Ue?`${Ue}: ${Je.message}`:Je.message)}}}else{const We=F.staggerEnabled&&(t==="add-to-queue"||t==="reprint")&&v.length>1,tt=We?F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).getTime():Date.now():0;let nt=0;for(const Je of Ie){const Ue=Je?Je.index:N;for(let rt=0;rt1){const Ot=Ae(Ct,Ue);Ot.quantity=Qt-1,await at.mutateAsync(Ot)}}else if(t==="edit-queue-item"&&nt===1){const bt=Ze(Ct),Ot={printer_id:Ct,target_model:null,target_location:null,require_previous_success:F.requirePreviousSuccess,auto_off_after:F.autoOffAfter,gcode_injection:F.gcodeInjection,manual_start:F.scheduleType==="manual",ams_mapping:bt,plate_id:Ue,scheduled_time:F.scheduleType==="scheduled"&&F.scheduledTime?new Date(F.scheduledTime).toISOString():null,...A};await ht.mutateAsync(Ot)}else{const bt=Ae(Ct,Ue);if(Qt>1&&(bt.quantity=Qt),We){const Ot=Math.floor(rt/F.staggerGroupSize);if(Ot>0){const Lt=Ot*F.staggerIntervalMinutes*6e4;bt.scheduled_time=new Date(tt+Lt).toISOString()}}await at.mutateAsync(bt)}Ye.success++}catch(bt){Ye.failed++;const Ot=he?.find(Ke=>Ke.id===Ct)?.name||`Printer ${Ct}`,Lt=Je?Je.name||`Plate ${Je.index}`:"",Ft=Lt?`${Ot} (${Lt})`:Ot;Ye.errors.push(`${Ft}: ${bt.message}`)}}}}Y(!1),Ye.failed===0?(t==="reprint"&&Mt?p(u("queue.itemsQueued",{count:Ye.success})):t!=="reprint"&&(t==="edit-queue-item"?p("Queue item updated"):Ye.success===1?p(R==="model"?`Queued for any ${re}`:u("queue.printQueued")):p(u("queue.itemsQueued",{count:Ye.success}))),m.invalidateQueries({queryKey:["queue"]}),l?.(),o()):Ye.success===0?p(`Failed: ${Ye.errors[0]}`,"error"):(p(`${Ye.success} succeeded, ${Ye.failed} failed`,"error"),m.invalidateQueries({queryKey:["queue"]}))},Vt=B||ht.isPending,Gt=w.useMemo(()=>!(Vt||R==="printer"&&v.length===0||R==="model"&&!re||R==="model"&&t==="reprint"||Se&&g.size===0),[v.length,R,re,t,Se,g.size,Vt]),Qt=R==="printer"&&v.length>1?1:P,mn=(()=>{const zt=v.length;if(t==="reprint"){const Tt=Mt&&zt>1;let Ie=Tt?u("printModal.staggerToPrinters",{count:zt,defaultValue:"Stagger to {{count}} printers"}):zt>1?u("queue.printToPrinters",{count:zt}):u("queue.print");return Qt>1&&(Ie=`${Ie} ×${Qt}`),{title:u(x?"queue.print":"queue.reprint"),icon:Mr,submitText:Ie,submitIcon:Tt?da:Mr,loadingText:D.total>1?u("queue.sendingProgress",{current:D.current,total:D.total}):u("queue.sending")}}if(t==="add-to-queue"){let Tt=u("queue.addToQueue");return g.size>1?Tt=u("queue.queueSelectedPlates",{count:g.size}):zt>1&&(Tt=u("queue.queueToPrinters",{count:zt})),Qt>1&&(Tt=`${Tt} ×${Qt}`),{title:u("queue.schedulePrint"),icon:da,submitText:Tt,submitIcon:da,loadingText:D.total>1?u("queue.addingProgress",{current:D.current,total:D.total}):u("queue.adding")}}return{title:u("queue.editQueueItem"),icon:li,submitText:u("common.save"),submitIcon:li,loadingText:D.total>1?u("queue.savingProgress",{current:D.current,total:D.total}):u("common.saving")}})(),dn=mn.icon,jt=mn.submitIcon,Jt=G&&g.size<=1&&(x||(Se?N!==null:!0));return a.jsxs("div",{className:"fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4",onClick:B?void 0:o,children:[a.jsx(wt,{className:"w-full max-w-2xl max-h-[90vh] overflow-y-auto",onClick:zt=>zt.stopPropagation(),children:a.jsxs(St,{className:t==="reprint"?"":"p-0",children:[a.jsxs("div",{className:`flex items-center justify-between ${t==="reprint"?"mb-4":"p-4 border-b border-bambu-dark-tertiary"}`,children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx(dn,{className:"w-5 h-5 text-bambu-green"}),a.jsx("h2",{className:"text-lg font-semibold text-white",children:mn.title})]}),a.jsx(De,{variant:"ghost",size:"sm",onClick:o,disabled:B,children:a.jsx(Bt,{className:"w-5 h-5"})})]}),a.jsxs("form",{onSubmit:qt,className:t==="reprint"?"":"p-4 space-y-4",children:[a.jsx("p",{className:`text-sm text-bambu-gray ${t==="reprint"?"mb-4":""}`,children:t==="reprint"?a.jsxs(a.Fragment,{children:["Send ",a.jsx("span",{className:"text-white",children:r})," to"," ",s?.length===1&&he?a.jsx("span",{className:"text-white",children:he.find(zt=>zt.id===s[0])?.name??"printer(s)"}):"printer(s)"]}):a.jsxs(a.Fragment,{children:[a.jsx("span",{className:"block text-bambu-gray mb-1",children:"Print Job"}),a.jsx("span",{className:"text-white font-medium truncate block",children:r})]})}),a.jsx(W7e,{plates:$e,isMultiPlate:Se,selectedPlates:g,onToggle:zt=>{S(Tt=>{const Ie=new Set(Tt);return t==="add-to-queue"?Ie.has(zt)?Ie.delete(zt):Ie.add(zt):(Ie.clear(),Ie.add(zt)),Ie})},onSelectAll:t==="add-to-queue"?()=>S(new Set($e.map(zt=>zt.index))):void 0,onDeselectAll:t==="add-to-queue"?()=>S(new Set):void 0,multiSelect:t==="add-to-queue"}),!s?.length&&a.jsx(Y7e,{printers:he||[],selectedPrinterIds:v,onMultiSelect:b,isLoading:me,allowMultiple:!0,showInactive:t==="edit-queue-item",disableBusy:t==="reprint",printerMappingResults:Xe.printerResults,filamentReqs:Me,onAutoConfigurePrinter:Xe.autoConfigurePrinter,onUpdatePrinterConfig:Xe.updatePrinterConfig,assignmentMode:t==="reprint"?"printer":R,onAssignmentModeChange:t!=="reprint"?ne:void 0,targetModel:re,onTargetModelChange:t!=="reprint"?J:void 0,targetLocation:ue,onTargetLocationChange:t!=="reprint"?ie:void 0,slicedForModel:ge}),R==="model"&&re&&Me&&Ge&&Ge.length>0&&a.jsx(G7e,{filamentReqs:Me,availableFilaments:Ge,overrides:se,onChange:K,forceColorMatch:ae,onForceColorMatchChange:(zt,Tt)=>pe(Ie=>({...Ie,[zt]:Tt}))}),ge&&R==="printer"&&v.length===1&&(()=>{const zt=he?.find(Tt=>Tt.id===v[0]);return zt&&zt.model&&ge!==zt.model?a.jsxs("div",{className:"p-3 mb-2 bg-yellow-500/10 border border-yellow-500/30 rounded-lg flex items-center gap-2",children:[a.jsx(Cn,{className:"w-4 h-4 text-yellow-400 flex-shrink-0"}),a.jsxs("span",{className:"text-sm text-yellow-400",children:["File was sliced for ",ge,", but printing on ",zt.model]})]}):null})(),ze&&a.jsxs("div",{className:"flex items-start gap-2 p-3 mb-2 bg-orange-500/10 border border-orange-500/30 rounded-lg text-sm",children:[a.jsx(Oa,{className:"w-4 h-4 text-orange-400 mt-0.5 flex-shrink-0"}),a.jsx("p",{className:"text-orange-400",children:"Archive data unavailable. The source file may have been deleted. Filament mapping is disabled."})]}),Jt&&!ze&&v.length===1&&a.jsx(V7e,{printerId:G,filamentReqs:Me,manualMappings:E,onManualMappingChange:$,defaultExpanded:!!s?.length||(q?.per_printer_mapping_expanded??!1),currencySymbol:le,defaultCostPerKg:ye}),(t==="reprint"||I>0||R==="model"&&re)&&a.jsx(J7e,{options:A,onChange:T,defaultExpanded:!!s?.length}),t!=="edit-queue-item"&&(R==="model"||v.length<=1)&&a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx("label",{htmlFor:"printQuantity",className:"text-sm text-bambu-gray whitespace-nowrap",children:u("queue.quantity","Quantity")}),a.jsx("input",{id:"printQuantity",type:"number",min:1,max:999,value:P,onChange:zt=>C(Math.max(1,Math.min(999,parseInt(zt.target.value)||1))),className:"w-20 px-2 py-1 text-sm bg-bambu-dark border border-bambu-dark-tertiary rounded text-white focus:outline-none focus:ring-1 focus:ring-bambu-green"}),P>1&&a.jsx("span",{className:"text-xs text-bambu-gray",children:u("queue.quantityHint","Creates {{count}} queue items",{count:P})})]}),t==="reprint"&&R==="printer"&&v.length>1&&a.jsxs("div",{className:"space-y-2 pb-2",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"staggerEnabledReprint",checked:F.staggerEnabled,onChange:zt=>k({...F,staggerEnabled:zt.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"staggerEnabledReprint",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(ia,{className:"w-3.5 h-3.5"}),u("printModal.staggerPrinterStarts","Stagger printer starts")]})]}),F.staggerEnabled&&(()=>{const zt=F.staggerGroupSize,Tt=F.staggerIntervalMinutes,Ie=Math.ceil(v.length/zt),Re=(Ie-1)*Tt;return a.jsxs("p",{className:"ml-6 text-xs text-bambu-gray",children:[u("printModal.staggerPreview","{{printers}} printers → {{groups}} groups of {{size}}, starting every {{interval}} min",{printers:v.length,groups:Ie,size:zt,interval:Tt}),Ie>1?` (${u("printModal.staggerTotal","total: {{minutes}} min",{minutes:Re})})`:""]})})()]}),t!=="reprint"&&a.jsx(Z7e,{options:F,onChange:k,dateFormat:q?.date_format||"system",timeFormat:q?.time_format||"system",canControlPrinter:f("printers:control"),showStagger:t==="add-to-queue"&&R==="printer"&&v.length>1,printerCount:v.length,hasGcodeSnippets:!!q?.gcode_snippets}),t==="reprint"&&!!q?.gcode_snippets&&Qt>1&&a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("input",{type:"checkbox",id:"gcodeInjectionReprint",checked:F.gcodeInjection,onChange:zt=>k({...F,gcodeInjection:zt.target.checked}),className:"rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"}),a.jsxs("label",{htmlFor:"gcodeInjectionReprint",className:"text-sm flex items-center gap-1 text-bambu-gray",children:[a.jsx(Py,{className:"w-3.5 h-3.5"}),u("printModal.gcodeInjection","Inject auto-print G-code")]})]}),ht.isError&&a.jsx("div",{className:"mb-4 p-3 bg-red-500/20 border border-red-500/50 rounded-lg text-sm text-red-400",children:ht.error?.message||"Failed to complete operation"}),a.jsxs("div",{className:`flex gap-3 ${t==="reprint"?"":"pt-2"}`,children:[a.jsx(De,{type:"button",variant:"secondary",onClick:o,className:"flex-1",disabled:B,children:"Cancel"}),a.jsx(De,{type:"submit",disabled:!Gt,className:"flex-1",children:Vt?a.jsxs(a.Fragment,{children:[a.jsx(mt,{className:"w-4 h-4 animate-spin"}),mn.loadingText]}):a.jsxs(a.Fragment,{children:[a.jsx(jt,{className:"w-4 h-4"}),mn.submitText]})})]})]})]})}),U&&U.length>0&&a.jsx(yn,{title:u("printModal.insufficientFilamentTitle"),message:He,confirmText:u("printModal.printAnyway"),cancelText:u("common.cancel"),variant:"warning",onConfirm:()=>{Q(null),qt(void 0,{skipFilamentCheck:!0})},onCancel:()=>Q(null)})]})}function NK({value:t}){const{t:e}=_t(),[n,r]=w.useState(!1),i=async()=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(t);else{const s=document.createElement("textarea");s.value=t,s.style.position="fixed",s.style.opacity="0",document.body.appendChild(s);try{if(s.select(),!document.execCommand("copy"))return}finally{document.body.removeChild(s)}}r(!0),setTimeout(()=>r(!1),2e3)}catch{}};return a.jsx("button",{onClick:i,className:"ml-2 p-1 rounded hover:bg-bambu-dark-tertiary text-bambu-gray hover:text-white transition-colors",title:e(n?"printers.copied":"printers.copyToClipboard"),children:n?a.jsx(jr,{className:"w-3.5 h-3.5 text-bambu-green"}):a.jsx(ns,{className:"w-3.5 h-3.5"})})}function eGe({printer:t,status:e,totalPrintHours:n,onClose:r}){const{t:i}=_t();w.useEffect(()=>{const o=l=>{l.key==="Escape"&&r()};return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[r]);const s=[];if(s.push({label:i("printers.model"),value:t.model??"—"}),s.push({label:i("common.status"),value:a.jsxs("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium ${e?.connected?"bg-bambu-green/20 text-bambu-green":"bg-red-500/20 text-red-400"}`,children:[a.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${e?.connected?"bg-bambu-green":"bg-red-400"}`}),e?.connected?i("printers.status.available"):i("printers.status.offline")]})}),e?.state){const o={IDLE:"printers.status.idle",RUNNING:"printers.status.printing",PAUSE:"printers.status.paused",FINISH:"printers.status.finished",FAILED:"printers.status.error"};s.push({label:i("printers.state"),value:i(o[e.state]??"printers.status.unknown")})}if(s.push({label:i("printers.ipAddress"),value:a.jsxs("span",{className:"flex items-center",children:[a.jsx("span",{className:"font-mono",children:t.ip_address}),a.jsx(NK,{value:t.ip_address})]})}),s.push({label:i("printers.serialNumber"),value:a.jsxs("span",{className:"flex items-center",children:[a.jsx("span",{className:"font-mono truncate",children:t.serial_number}),a.jsx(NK,{value:t.serial_number})]})}),e?.wired_network)s.push({label:i("printers.networkLabel","Network"),value:a.jsxs("span",{className:"flex items-center gap-2",children:[a.jsx(KI,{className:"w-4 h-4 text-bambu-green"}),a.jsx("span",{className:"text-bambu-green",children:i("printers.connection.ethernet","Ethernet")})]})});else if(e?.wifi_signal!=null){const o=tee(e.wifi_signal);s.push({label:i("printers.wifiSignalLabel"),value:a.jsxs("span",{className:"flex items-center gap-2",children:[a.jsx(hJ,{className:`w-4 h-4 ${o.color}`}),a.jsx("span",{className:o.color,children:i(o.labelKey)}),a.jsxs("span",{className:"text-bambu-gray text-xs",children:["(",e.wifi_signal," dBm)"]})]})})}return s.push({label:i("printers.firmware"),value:e?.firmware_version??"—"}),e?.developer_mode!=null&&s.push({label:i("printers.developerMode"),value:a.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${e.developer_mode?"bg-bambu-green/20 text-bambu-green":"bg-bambu-dark-tertiary text-bambu-gray"}`,children:e.developer_mode?i("printers.enabled"):i("printers.disabled")})}),s.push({label:i("printers.nozzleCount"),value:t.nozzle_count}),s.push({label:i("printers.autoArchive"),value:a.jsx("span",{className:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${t.auto_archive?"bg-bambu-green/20 text-bambu-green":"bg-bambu-dark-tertiary text-bambu-gray"}`,children:t.auto_archive?i("printers.enabled"):i("printers.disabled")})}),n!=null&&n>0&&s.push({label:i("printers.totalPrintHours"),value:`${Math.round(n)}h`}),t.location&&s.push({label:i("printers.sort.location"),value:t.location}),s.push({label:i("printers.addedOn"),value:yg(t.created_at)}),a.jsx("div",{className:"fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4",role:"dialog","aria-modal":"true",onClick:r,children:a.jsx(wt,{className:"w-full max-w-md",onClick:o=>o.stopPropagation(),children:a.jsxs(St,{children:[a.jsxs("div",{className:"flex items-center justify-between mb-4",children:[a.jsx("h2",{className:"text-lg font-semibold text-white",children:t.name}),a.jsx("button",{onClick:r,className:"p-1 hover:bg-bambu-dark rounded flex-shrink-0",children:a.jsx(Bt,{className:"w-5 h-5 text-bambu-gray"})})]}),a.jsx("div",{className:"flex justify-center mb-4",children:a.jsx("img",{src:eee(t.model),alt:t.model??t.name,className:"h-24 object-contain"})}),a.jsx("div",{className:"space-y-0",children:s.map((o,l)=>a.jsxs("div",{className:"flex items-center justify-between gap-4 py-2.5 border-b border-bambu-dark-tertiary last:border-0",children:[a.jsx("span",{className:"text-sm text-bambu-gray whitespace-nowrap",children:o.label}),a.jsx("span",{className:"text-sm text-white text-right",children:o.value})]},l))})]})})})}function tGe(t){if(!t||t.length<6)return!1;const e=parseInt(t.slice(0,2),16),n=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16);return(.299*e+.587*n+.114*r)/255>.6}function $D({trayColor:t,trayType:e,isEmpty:n,slotNumber:r}){return a.jsx("div",{className:"w-3.5 h-3.5 rounded-full mx-auto mb-0.5 border-2 flex items-center justify-center",style:{backgroundColor:t?`#${t}`:e?"#333":"transparent",borderColor:n?"#666":"rgba(255,255,255,0.1)",borderStyle:n?"dashed":"solid"},children:a.jsx("span",{className:"text-[6px] font-bold leading-none select-none",style:{color:t&&tGe(t)?"#000":"#fff"},children:r})})}function Uz({summary:t,children:e,defaultOpen:n=!1,className:r="",summaryClassName:i="",open:s,onToggle:o}){const[l,c]=w.useState(n),d=s!==void 0,u=d?s:l,m=()=>{const p=!u;d||c(p),o?.(p)};return a.jsxs("div",{className:r,children:[a.jsxs("div",{role:"button",tabIndex:0,onClick:m,onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),m())},className:`w-full flex items-center justify-between gap-2 text-left cursor-pointer ${i}`,"aria-expanded":u,children:[a.jsx("div",{className:"flex-1 min-w-0",children:t}),a.jsx(zn,{className:`w-4 h-4 text-bambu-gray flex-shrink-0 transition-transform ${u?"rotate-180":""}`})]}),u&&a.jsx("div",{className:"mt-3",children:e})]})}function VD(t){return(t??.02).toFixed(3)}function CK({side:t}){const{mode:e}=Gg(),n=e==="dark"?"#1a4d2e":"#e7f5e9";return a.jsx("span",{className:"inline-flex items-center justify-center w-4 h-4 text-[10px] font-bold rounded",style:{backgroundColor:n,color:"#00ae42"},children:t})}function kie(t,e){if(!t)return"";if(t.includes("hardened"))return e("printers.nozzleHardenedSteel");if(t.includes("stainless"))return e("printers.nozzleStainlessSteel");if(t.includes("tungsten"))return e("printers.nozzleTungstenCarbide");if(t.length>=4){const n=t.slice(2,4);if(n==="00")return e("printers.nozzleStainlessSteel");if(n==="01")return e("printers.nozzleHardenedSteel");if(n==="05")return e("printers.nozzleTungstenCarbide")}return t==="00"?e("printers.nozzleStainlessSteel"):t==="01"?e("printers.nozzleHardenedSteel"):t==="05"?e("printers.nozzleTungstenCarbide"):t.startsWith("H")?e("printers.nozzleHardenedSteel"):t}function Nie(t,e){return t?t.startsWith("HH")?e("printers.nozzleHighFlow"):t.startsWith("HS")?e("printers.nozzleStandardFlow"):"":""}function Cie({slot:t,index:e,activeStatus:n,filamentName:r,children:i}){const{t:s}=_t(),[o,l]=w.useState(!1),[c,d]=w.useState("top"),u=w.useRef(null),m=w.useRef(null),p=w.useRef(null),f=!t.nozzle_diameter&&!t.nozzle_type,x=t.stat===1;w.useEffect(()=>{if(o&&u.current&&m.current){const P=u.current.getBoundingClientRect(),C=m.current.offsetHeight,T=P.top-56,F=window.innerHeight-P.bottom;TT?d("bottom"):d("top")}},[o]);const v=()=>{p.current&&clearTimeout(p.current),p.current=setTimeout(()=>l(!0),80)},b=()=>{p.current&&clearTimeout(p.current),p.current=setTimeout(()=>l(!1),100)};w.useEffect(()=>()=>{p.current&&clearTimeout(p.current)},[]);const g=sO(t.filament_color),S=kie(t.nozzle_type,s),N=Nie(t.nozzle_type,s);return a.jsxs("div",{ref:u,className:"relative",onMouseEnter:v,onMouseLeave:b,children:[i,o&&a.jsxs("div",{ref:m,className:` absolute left-1/2 -translate-x-1/2 z-50 ${c==="top"?"bottom-full mb-2":"top-full mt-2"} animate-in fade-in-0 zoom-in-95 duration-150 diff --git a/static/index.html b/static/index.html index c46f54659..e77b875fe 100644 --- a/static/index.html +++ b/static/index.html @@ -26,7 +26,7 @@ - +