diff --git a/package-lock.json b/package-lock.json index d25ee989..829f0680 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@hookform/resolvers": "^5.4.0", "@mui/icons-material": "^9.2.0", "@mui/material": "^9.2.0", + "@tanstack/query-broadcast-client-experimental": "^5.101.2", "@tanstack/react-query": "^5.101.2", "@tanstack/react-query-devtools": "^5.101.2", "@testing-library/dom": "^10.4.1", @@ -2332,6 +2333,20 @@ "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, + "node_modules/@tanstack/query-broadcast-client-experimental": { + "version": "5.101.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-broadcast-client-experimental/-/query-broadcast-client-experimental-5.101.2.tgz", + "integrity": "sha512-BFJp1HqDjUY3x51zzgfB2scGhg1nw2V8Y6+aoSA8TEWYh0oI5kYx1z+37fzlws2uaT7ObjCz1PXzzftE6xpmhw==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.101.2", + "broadcast-channel": "^7.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/query-core": { "version": "5.101.2", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.2.tgz", @@ -3214,6 +3229,30 @@ "node": ">=8" } }, + "node_modules/broadcast-channel": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-7.3.0.tgz", + "integrity": "sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.28.6", + "oblivious-set": "2.0.0", + "p-queue": "6.6.2", + "unload": "2.4.1" + }, + "funding": { + "url": "https://github.com/sponsors/pubkey" + } + }, + "node_modules/broadcast-channel/node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/browserslist": { "version": "4.28.6", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", @@ -5345,6 +5384,15 @@ "node": ">=0.10.0" } }, + "node_modules/oblivious-set": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-2.0.0.tgz", + "integrity": "sha512-QOUH5Xrsced9fKXaQTjWoDGKeS/Or7E2jB0FN63N4mkAO4qJdB7WR7e6qWAOHM5nk25FJ8TGjhP7DH4l6vFVLg==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/obug": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", @@ -5393,6 +5441,15 @@ "node": ">= 0.8.0" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5425,6 +5482,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6401,6 +6492,15 @@ "devOptional": true, "license": "MIT" }, + "node_modules/unload": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.4.1.tgz", + "integrity": "sha512-IViSAm8Z3sRBYA+9wc0fLQmU9Nrxb16rcDmIiR6Y9LJSZzI7QY5QsDhqPpKOjAn0O9/kfK1TfNEMMAGPTIraPw==", + "license": "Apache-2.0", + "funding": { + "url": "https://github.com/sponsors/pubkey" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", diff --git a/src/api/api-error.ts b/src/api/api-error.ts index 6746359a..59870e65 100644 --- a/src/api/api-error.ts +++ b/src/api/api-error.ts @@ -1,5 +1,14 @@ import { isHTTPError, isNetworkError, isTimeoutError } from "ky"; +export class ApiError extends Error { + readonly status: number; + + constructor(message: string, status: number) { + super(message); + this.name = "ApiError"; + this.status = status; + } +} export function mapHttpStatusToMessage(status: number, data?: unknown): string { if (status === 401) { return "You are not authorized to access this page."; diff --git a/src/app/(protected)/workorders/_components/work-order-form.tsx b/src/app/(protected)/workorders/_components/work-order-form.tsx index bdb9bdff..1ced7ef1 100644 --- a/src/app/(protected)/workorders/_components/work-order-form.tsx +++ b/src/app/(protected)/workorders/_components/work-order-form.tsx @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { Controller, useForm, useWatch } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Link as RouterLink, useNavigate, useParams } from "react-router-dom"; +import { Link as RouterLink, useNavigate, useParams } from "react-router"; import { Autocomplete, Box, diff --git a/src/test/domain/work-orders/utils/list-week-utils.test.ts b/src/test/domain/work-orders/utils/list-week-utils.test.ts index 3c221b9b..46cf2cf6 100644 --- a/src/test/domain/work-orders/utils/list-week-utils.test.ts +++ b/src/test/domain/work-orders/utils/list-week-utils.test.ts @@ -7,7 +7,7 @@ import { nextWeekMonday, weekRange, } from "@/domain/work-orders/utils/list-week-utils"; -import { addDaysIso, mondayOf } from "@/domain/work-orders/utils/wizard-date-utils"; +import { mondayOf } from "@/domain/work-orders/utils/wizard-date-utils"; describe("list-week-utils", () => { it("currentWeekMonday returns a Monday ISO date", () => {