diff --git a/package-lock.json b/package-lock.json index d7ffd3eb..a20c8c4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,26 +9,38 @@ "version": "0.1.0", "dependencies": { "@react-pdf/renderer": "^4.3.1", + "@supabase/supabase-js": "^2.89.0", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-table": "^8.21.3", "axios": "^1.12.2", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "embla-carousel-react": "^8.6.0", "formik": "^2.4.6", + "input-otp": "^1.4.2", "jspdf": "^3.0.4", "jspdf-autotable": "^5.0.2", + "lucide-react": "^0.562.0", "moment": "^2.30.1", "next": "15.5.9", - "react": "19.1.0", + "next-themes": "^0.4.6", + "radix-ui": "^1.4.3", + "react": "^19.1.2", "react-day-picker": "^9.11.1", - "react-dom": "19.1.0", + "react-dom": "^19.1.2", "react-dropzone": "^14.3.8", + "react-hook-form": "^7.70.0", "react-hot-toast": "^2.6.0", "react-number-format": "^5.4.4", + "react-resizable-panels": "2.1.7", "react-select": "^5.10.2", "recharts": "^3.6.0", + "sonner": "^2.0.7", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", "use-debounce": "^10.0.6", + "vaul": "^1.1.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "yup": "^1.7.0", "zustand": "^5.0.8" @@ -517,6 +529,19 @@ "@floating-ui/utils": "^0.2.10" } }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@floating-ui/utils": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", @@ -1277,6 +1302,2419 @@ "node": ">=12.4.0" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accessible-icon": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.7.tgz", + "integrity": "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-aspect-ratio": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", + "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-aspect-ratio/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-form": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.8.tgz", + "integrity": "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-form/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-hover-card": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-navigation-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-one-time-password-field": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.1.8.tgz", + "integrity": "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-one-time-password-field/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-password-toggle-field": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.1.3.tgz", + "integrity": "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-password-toggle-field/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toast": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", + "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle-group/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toolbar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.11.tgz", + "integrity": "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-toggle-group": "1.1.11" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toolbar/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, "node_modules/@react-pdf/fns": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz", @@ -1513,6 +3951,86 @@ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, + "node_modules/@supabase/auth-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.89.0.tgz", + "integrity": "sha512-wiWZdz8WMad8LQdJMWYDZ2SJtZP5MwMqzQq3ehtW2ngiI3UTgbKiFrvMUUS3KADiVlk4LiGfODB2mrYx7w2f8w==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.89.0.tgz", + "integrity": "sha512-XEueaC5gMe5NufNYfBh9kPwJlP5M2f+Ogr8rvhmRDAZNHgY6mI35RCkYDijd92pMcNM7g8pUUJov93UGUnqfyw==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.89.0.tgz", + "integrity": "sha512-/b0fKrxV9i7RNOEXMno/I1862RsYhuUo+Q6m6z3ar1f4ulTMXnDfv0y4YYxK2POcgrOXQOgKYQx1eArybyNvtg==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.89.0.tgz", + "integrity": "sha512-aMOvfDb2a52u6PX6jrrjvACHXGV3zsOlWRzZsTIOAJa0hOVvRp01AwC1+nLTGUzxzezejrYeCX+KnnM1xHdl+w==", + "license": "MIT", + "dependencies": { + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.89.0.tgz", + "integrity": "sha512-6zKcXofk/M/4Eato7iqpRh+B+vnxeiTumCIP+Tz26xEqIiywzD9JxHq+udRrDuv6hXE+pmetvJd8n5wcf4MFRQ==", + "license": "MIT", + "dependencies": { + "iceberg-js": "^0.8.1", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.89.0.tgz", + "integrity": "sha512-KlaRwSfFA0fD73PYVMHj5/iXFtQGCcX7PSx0FdQwYEEw9b2wqM7GxadY+5YwcmuEhalmjFB/YvqaoNVF+sWUlg==", + "license": "MIT", + "dependencies": { + "@supabase/auth-js": "2.89.0", + "@supabase/functions-js": "2.89.0", + "@supabase/postgrest-js": "2.89.0", + "@supabase/realtime-js": "2.89.0", + "@supabase/storage-js": "2.89.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -1953,7 +4471,6 @@ "version": "20.19.23", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz", "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1971,6 +4488,12 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, + "node_modules/@types/phoenix": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", + "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", + "license": "MIT" + }, "node_modules/@types/raf": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", @@ -1983,6 +4506,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1991,8 +4515,9 @@ "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", - "dev": true, + "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2019,6 +4544,15 @@ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.46.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", @@ -2065,6 +4599,7 @@ "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", @@ -2588,6 +5123,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2645,6 +5181,18 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -3112,6 +5660,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -3136,6 +5696,22 @@ "node": ">=6" } }, + "node_modules/cmdk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3253,7 +5829,8 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/d3-array": { "version": "3.2.4", @@ -3566,6 +6143,12 @@ "node": ">=8" } }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, "node_modules/dfa": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", @@ -3619,6 +6202,35 @@ "node": ">= 0.4" } }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT", + "peer": true + }, + "node_modules/embla-carousel-react": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", + "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", + "license": "MIT", + "dependencies": { + "embla-carousel": "8.6.0", + "embla-carousel-reactive-utils": "8.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -3856,6 +6468,7 @@ "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4029,6 +6642,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -4623,6 +7237,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -4896,6 +7519,15 @@ "integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==", "license": "ISC" }, + "node_modules/iceberg-js": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", + "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4948,6 +7580,16 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/input-otp": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", + "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -5518,6 +8160,7 @@ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.4.tgz", "integrity": "sha512-dc6oQ8y37rRcHn316s4ngz/nOjayLF/FFxBF4V9zamQKRqXxyiH1zagkCdktdWhtoQId5K20xt1lB90XzkB+hQ==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4", "fast-png": "^6.2.0", @@ -5531,12 +8174,12 @@ } }, "node_modules/jspdf-autotable": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-5.0.2.tgz", - "integrity": "sha512-YNKeB7qmx3pxOLcNeoqAv3qTS7KuvVwkFe5AduCawpop3NOkBUtqDToxNc225MlNecxT4kP2Zy3z/y/yvGdXUQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-5.0.7.tgz", + "integrity": "sha512-2wr7H6liNDBYNwt25hMQwXkEWFOEopgKIvR1Eukuw6Zmprm/ZcnmLTQEjW7Xx3FCbD3v7pflLcnMAv/h1jFDQw==", "license": "MIT", "peerDependencies": { - "jspdf": "^2 || ^3" + "jspdf": "^2 || ^3 || ^4" } }, "node_modules/jsx-ast-utils": { @@ -5932,6 +8575,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lucide-react": { + "version": "0.562.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz", + "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -6139,6 +8791,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -6603,6 +9265,106 @@ ], "license": "MIT" }, + "node_modules/radix-ui": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz", + "integrity": "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-accessible-icon": "1.1.7", + "@radix-ui/react-accordion": "1.2.12", + "@radix-ui/react-alert-dialog": "1.1.15", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-aspect-ratio": "1.1.7", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-checkbox": "1.3.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-context-menu": "2.2.16", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-form": "0.1.8", + "@radix-ui/react-hover-card": "1.1.15", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-menubar": "1.1.16", + "@radix-ui/react-navigation-menu": "1.2.14", + "@radix-ui/react-one-time-password-field": "0.1.8", + "@radix-ui/react-password-toggle-field": "0.1.3", + "@radix-ui/react-popover": "1.1.15", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-progress": "1.1.7", + "@radix-ui/react-radio-group": "1.3.8", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-scroll-area": "1.2.10", + "@radix-ui/react-select": "2.2.6", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-slider": "1.3.6", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-switch": "1.2.6", + "@radix-ui/react-tabs": "1.1.13", + "@radix-ui/react-toast": "1.2.15", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-toggle-group": "1.1.11", + "@radix-ui/react-toolbar": "1.1.11", + "@radix-ui/react-tooltip": "1.2.8", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-escape-keydown": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/radix-ui/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -6614,10 +9376,11 @@ } }, "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6644,15 +9407,16 @@ } }, "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", + "peer": true, "dependencies": { - "scheduler": "^0.26.0" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.1.0" + "react": "^19.2.3" } }, "node_modules/react-dropzone": { @@ -6678,6 +9442,22 @@ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", "license": "MIT" }, + "node_modules/react-hook-form": { + "version": "7.70.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.70.0.tgz", + "integrity": "sha512-COOMajS4FI3Wuwrs3GPpi/Jeef/5W1DRR84Yl5/ShlT3dKVFUfoGiEZ/QE6Uw8P4T2/CLJdcTVYKvWBMQTEpvw==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-hot-toast": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", @@ -6699,7 +9479,8 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-number-format": { "version": "5.4.4", @@ -6716,6 +9497,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -6734,6 +9516,63 @@ } } }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-resizable-panels": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.7.tgz", + "integrity": "sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/react-select": { "version": "5.10.2", "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", @@ -6755,6 +9594,28 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -6805,7 +9666,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -7054,9 +9916,9 @@ } }, "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/semver": { @@ -7278,6 +10140,16 @@ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7661,6 +10533,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7828,6 +10701,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7859,7 +10733,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, "node_modules/unicode-properties": { @@ -7933,6 +10806,27 @@ "punycode": "^2.1.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-debounce": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.6.tgz", @@ -7959,6 +10853,28 @@ } } }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -7984,6 +10900,19 @@ "base64-arraybuffer": "^1.0.2" } }, + "node_modules/vaul": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", + "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/victory-vendor": { "version": "37.3.6", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", @@ -8135,6 +11064,27 @@ "node": ">=0.10.0" } }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xlsx": { "version": "0.20.3", "resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", diff --git a/package.json b/package.json index 319f0e3d..aa90e44a 100644 --- a/package.json +++ b/package.json @@ -12,26 +12,38 @@ }, "dependencies": { "@react-pdf/renderer": "^4.3.1", + "@supabase/supabase-js": "^2.89.0", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-table": "^8.21.3", "axios": "^1.12.2", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "embla-carousel-react": "^8.6.0", "formik": "^2.4.6", + "input-otp": "^1.4.2", "jspdf": "^3.0.4", "jspdf-autotable": "^5.0.2", + "lucide-react": "^0.562.0", "moment": "^2.30.1", "next": "15.5.9", - "react": "19.1.0", + "next-themes": "^0.4.6", + "radix-ui": "^1.4.3", + "react": "^19.1.2", "react-day-picker": "^9.11.1", - "react-dom": "19.1.0", + "react-dom": "^19.1.2", "react-dropzone": "^14.3.8", + "react-hook-form": "^7.70.0", "react-hot-toast": "^2.6.0", "react-number-format": "^5.4.4", + "react-resizable-panels": "2.1.7", "react-select": "^5.10.2", "recharts": "^3.6.0", + "sonner": "^2.0.7", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", "use-debounce": "^10.0.6", + "vaul": "^1.1.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "yup": "^1.7.0", "zustand": "^5.0.8" diff --git a/src/app/closing/detail/page.tsx b/src/app/closing/detail/page.tsx index 62f3fa20..f3a78d9d 100644 --- a/src/app/closing/detail/page.tsx +++ b/src/app/closing/detail/page.tsx @@ -19,10 +19,10 @@ const ClosingDetailPage = () => { (id: number) => ClosingApi.getGeneralInfo(id) ); - const { data: salesData, isLoading: isLoadingSales } = useSWR( - closingId ? `sales-${closingId}` : null, - () => ClosingApi.getPenjualan(Number(closingId)) - ); + // const { data: salesData, isLoading: isLoadingSales } = useSWR( + // closingId ? `sales-${closingId}` : null, + // () => ClosingApi.getPenjualan(Number(closingId)) + // ); const { data: hppEkspedisiData, isLoading: isLoadingHppEkspedisi } = useSWR( closingId ? `hpp-ekspedisi-${closingId}` : null, @@ -44,7 +44,8 @@ const ClosingDetailPage = () => { return; } - const isLoading = isLoadingClosing || isLoadingSales || isLoadingHppEkspedisi; + const isLoading = isLoadingClosing || isLoadingHppEkspedisi; + // const isLoading = isLoadingClosing || isLoadingSales || isLoadingHppEkspedisi; return (
@@ -54,7 +55,7 @@ const ClosingDetailPage = () => { { + return ( +
+ +
+ ); +}; + +export default DailyChecklistPage; diff --git a/src/app/daily-checklist/dashboard/page.tsx b/src/app/daily-checklist/dashboard/page.tsx new file mode 100644 index 00000000..bc935d2d --- /dev/null +++ b/src/app/daily-checklist/dashboard/page.tsx @@ -0,0 +1,11 @@ +import { Dashboard as DashboardDailyChecklist } from '@/figma-make/components/pages/dashboard/Dashboard'; + +const DailyChecklistDashboardPage = () => { + return ( +
+ +
+ ); +}; + +export default DailyChecklistDashboardPage; diff --git a/src/app/daily-checklist/list-daily-checklist/detail/layout.tsx b/src/app/daily-checklist/list-daily-checklist/detail/layout.tsx new file mode 100644 index 00000000..7220dfa1 --- /dev/null +++ b/src/app/daily-checklist/list-daily-checklist/detail/layout.tsx @@ -0,0 +1,11 @@ +import SuspenseHelper from '@/components/helper/SuspenseHelper'; + +const Layout = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + return {children}; +}; + +export default Layout; diff --git a/src/app/daily-checklist/list-daily-checklist/detail/page.tsx b/src/app/daily-checklist/list-daily-checklist/detail/page.tsx new file mode 100644 index 00000000..d816d560 --- /dev/null +++ b/src/app/daily-checklist/list-daily-checklist/detail/page.tsx @@ -0,0 +1,11 @@ +import { DetailDailyChecklistContent } from '@/figma-make/components/pages/list-daily-checklist/detail/DetailDailyChecklistContent'; + +const ListDailyChecklistDetailPage = () => { + return ( +
+ +
+ ); +}; + +export default ListDailyChecklistDetailPage; diff --git a/src/app/daily-checklist/list-daily-checklist/page.tsx b/src/app/daily-checklist/list-daily-checklist/page.tsx new file mode 100644 index 00000000..ad62a0be --- /dev/null +++ b/src/app/daily-checklist/list-daily-checklist/page.tsx @@ -0,0 +1,11 @@ +import { ListDailyChecklistContent } from '@/figma-make/components/pages/list-daily-checklist/ListDailyChecklistContent'; + +const ListDailyChecklistPage = () => { + return ( +
+ +
+ ); +}; + +export default ListDailyChecklistPage; diff --git a/src/app/daily-checklist/master-data/activity/page.tsx b/src/app/daily-checklist/master-data/activity/page.tsx new file mode 100644 index 00000000..aadead88 --- /dev/null +++ b/src/app/daily-checklist/master-data/activity/page.tsx @@ -0,0 +1,11 @@ +import { MasterAktivitasContent } from '@/figma-make/components/pages/master-data/activity/MasterAktivitasContent'; + +const MasterAktivitasPage = () => { + return ( +
+ +
+ ); +}; + +export default MasterAktivitasPage; diff --git a/src/app/daily-checklist/master-data/employee/page.tsx b/src/app/daily-checklist/master-data/employee/page.tsx new file mode 100644 index 00000000..bd235e26 --- /dev/null +++ b/src/app/daily-checklist/master-data/employee/page.tsx @@ -0,0 +1,11 @@ +import { MasterEmployeeContent } from '@/figma-make/components/pages/master-data/employee/MasterEmployeeContent'; + +const MasterEmployeePage = () => { + return ( +
+ +
+ ); +}; + +export default MasterEmployeePage; diff --git a/src/app/daily-checklist/reports/page.tsx b/src/app/daily-checklist/reports/page.tsx new file mode 100644 index 00000000..fb9cd5b0 --- /dev/null +++ b/src/app/daily-checklist/reports/page.tsx @@ -0,0 +1,11 @@ +import { DailyChecklistReportsContent } from '@/figma-make/components/pages/reports/DailyChecklistReportsContent'; + +const DailyChecklistReportsPage = () => { + return ( +
+ +
+ ); +}; + +export default DailyChecklistReportsPage; diff --git a/src/app/globals.css b/src/app/globals.css index 10b48ad5..0e3d1e43 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,6 +1,7 @@ @import 'tailwindcss'; @plugin "daisyui"; @import '../styles/daisyui.css'; +@import '../figma-make/styles/theme.css'; @plugin "daisyui/theme" { name: 'lti'; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c19b8a77..91e9d624 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,7 @@ import { Inter } from 'next/font/google'; import '@/app/globals.css'; import { Toaster } from 'react-hot-toast'; +import { Toaster as SonnerToaster } from '@/figma-make/components/base/sonner'; import MainDrawer from '@/components/MainDrawer'; import RequireAuth from '@/components/helper/RequireAuth'; @@ -35,6 +36,7 @@ export default function RootLayout({ + ); diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx index fc8cbb18..eaf1e2c1 100644 --- a/src/components/MainDrawer.tsx +++ b/src/components/MainDrawer.tsx @@ -67,7 +67,9 @@ const MainDrawer = ({ const pathname = usePathname(); const { permissionCheck } = useAuth(); - const isPermitted = ROUTE_PERMISSIONS[pathname]?.some((permission) => + const formattedPathname = pathname.endsWith('/') ? pathname : `${pathname}/`; + + const isPermitted = ROUTE_PERMISSIONS[formattedPathname]?.some((permission) => permissionCheck(permission) ); diff --git a/src/components/helper/form/FormErrors.tsx b/src/components/helper/form/FormErrors.tsx new file mode 100644 index 00000000..a351227f --- /dev/null +++ b/src/components/helper/form/FormErrors.tsx @@ -0,0 +1,46 @@ +import Alert from '@/components/Alert'; +import Button from '@/components/Button'; +import { Icon } from '@iconify/react'; + +/** + * Alert Unique Error List + * @param formErrorList - Array of error messages + * @param onClose - Function to close the alert + */ +const AlertErrorList = ({ + formErrorList, + onClose, +}: { + formErrorList: string[]; + onClose: () => void; +}) => { + return ( + +
+
+ + + Terdapat {formErrorList.length} error pada form: + +
+ +
+
    + {formErrorList.map((error, index) => ( +
  • + {error} +
  • + ))} +
+
+ ); +}; + +export default AlertErrorList; diff --git a/src/components/input/FileInput.tsx b/src/components/input/FileInput.tsx index aee7cb78..5f3a8610 100644 --- a/src/components/input/FileInput.tsx +++ b/src/components/input/FileInput.tsx @@ -33,6 +33,7 @@ const FileInput = ({ isError, errorMessage, disabled = false, + required = false, onChange, onBlur, readOnly = false, @@ -56,6 +57,13 @@ const FileInput = ({ )} > {label} + {required && ( + <> + + * + + + )} )} diff --git a/src/components/pages/ApprovalSteps.tsx b/src/components/pages/ApprovalSteps.tsx index 6ae7c13a..27d03da3 100644 --- a/src/components/pages/ApprovalSteps.tsx +++ b/src/components/pages/ApprovalSteps.tsx @@ -309,7 +309,7 @@ const useApprovalSteps = ({ moduleId: string; params?: { page?: number; - limit: number; + limit: number | string; search?: string; group_step_number?: boolean; }; diff --git a/src/components/pages/closing/ClosingDetail.tsx b/src/components/pages/closing/ClosingDetail.tsx index 94647f87..778124be 100644 --- a/src/components/pages/closing/ClosingDetail.tsx +++ b/src/components/pages/closing/ClosingDetail.tsx @@ -45,13 +45,18 @@ const ClosingDetail: React.FC = ({ { id: 'perhitunganSapronak', label: 'Perhitungan Sapronak', - content: , - }, - { - id: 'penjualan', - label: 'Penjualan', - content: , + content: ( + + ), }, + // { + // id: 'penjualan', + // label: 'Penjualan', + // content: , + // }, { id: 'overhead', label: 'Overhead', diff --git a/src/components/pages/closing/ClosingFinanceTable.tsx b/src/components/pages/closing/ClosingFinanceTable.tsx index 9d0c92d6..8c39b3fb 100644 --- a/src/components/pages/closing/ClosingFinanceTable.tsx +++ b/src/components/pages/closing/ClosingFinanceTable.tsx @@ -23,6 +23,14 @@ type HppTableRow = type?: never; budgeting?: never; realization?: never; + } + | { + type: string; + group_name: string; + group_index: number; + isGroupHeader: false; + budgeting?: { rp_per_bird: number; rp_per_kg: number; amount: number }; + realization?: { rp_per_bird: number; rp_per_kg: number; amount: number }; }; type ProfitLossTableRow = @@ -52,25 +60,117 @@ const ClosingFinanceTable = ({ () => ClosingApi.getFinance(projectFlockId) ); - const hppTableData: HppTableRow[] = isResponseSuccess(finance) - ? finance.data.hpp_purchases.hpp.flatMap((hpp, groupIndex) => [ - // Group header row - { - group_name: hpp.group_name, - group_index: groupIndex, - isGroupHeader: true as const, - }, - // Data rows - ...hpp.data.map((item) => ({ - group_name: hpp.group_name, - group_index: groupIndex, - type: item.type, - budgeting: item.budgeting, - realization: item.realization, + const staticHppRows: Array<{ + group_name: string; + type: string; + group_index: number; + }> = [ + { + group_name: 'HPP dan Pengeluaran', + type: 'Pembelian PAKAN', + group_index: 0, + }, + { + group_name: 'HPP dan Pengeluaran', + type: 'Pembelian STARTER', + group_index: 0, + }, + { + group_name: 'HPP dan Pengeluaran', + type: 'Pembelian DOC', + group_index: 0, + }, + { + group_name: 'HPP dan Pengeluaran', + type: 'Pembelian PULLET', + group_index: 0, + }, + { + group_name: 'HPP dan Pengeluaran', + type: 'Pembelian LAYER', + group_index: 0, + }, + { + group_name: 'HPP dan Bahan Baku', + type: 'Pengeluaran Overhead', + group_index: 1, + }, + { + group_name: 'HPP dan Bahan Baku', + type: 'Beban Ekspedisi', + group_index: 1, + }, + ]; + + const hppTableData: HppTableRow[] = [ + { + group_name: 'HPP dan Pengeluaran', + group_index: 0, + isGroupHeader: true as const, + }, + ...staticHppRows + .filter((row) => row.group_index === 0) + .map((staticRow) => { + const apiData = isResponseSuccess(finance) + ? finance.data.hpp_purchases.hpp + .find((g) => g.group_name === staticRow.group_name) + ?.data.find((d) => d.type === staticRow.type) + : null; + + return { + group_name: staticRow.group_name, + group_index: staticRow.group_index, + type: staticRow.type, + budgeting: apiData?.budgeting || { + rp_per_bird: 0, + rp_per_kg: 0, + amount: 0, + }, + realization: apiData?.realization || { + rp_per_bird: 0, + rp_per_kg: 0, + amount: 0, + }, isGroupHeader: false as const, - })), - ]) - : []; + }; + }), + { + group_name: 'HPP dan Bahan Baku', + group_index: 1, + isGroupHeader: true as const, + }, + ...staticHppRows + .filter((row) => row.group_index === 1) + .map((staticRow) => { + const apiData = isResponseSuccess(finance) + ? finance.data.hpp_purchases.hpp + .find((g) => g.group_name === staticRow.group_name) + ?.data.find((d) => d.type === staticRow.type) + : null; + + return { + group_name: staticRow.group_name, + group_index: staticRow.group_index, + type: staticRow.type, + budgeting: apiData?.budgeting || { + rp_per_bird: 0, + rp_per_kg: 0, + amount: 0, + }, + realization: apiData?.realization || { + rp_per_bird: 0, + rp_per_kg: 0, + amount: 0, + }, + isGroupHeader: false as const, + }; + }), + { + group_name: 'HPP', + group_index: 2, + isGroupHeader: true as const, + }, + ]; const profitLossTableData: ProfitLossTableRow[] = isResponseSuccess(finance) ? [ @@ -217,8 +317,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'budgeting_rp_per_bird' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.budgeting - .rp_per_bird || 0 + finance.data.hpp_purchases.summary_hpp?.budgeting + ?.rp_per_bird || 0 ) : '-'; }, @@ -233,8 +333,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'budgeting_rp_per_kg' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.budgeting - .rp_per_kg || 0 + finance.data.hpp_purchases.summary_hpp?.budgeting + ?.rp_per_kg || 0 ) : '-'; }, @@ -249,8 +349,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'budgeting_amount' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.budgeting - .amount || 0 + finance.data.hpp_purchases.summary_hpp?.budgeting + ?.amount || 0 ) : '-'; }, @@ -271,8 +371,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'realization_rp_per_bird' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.realization - .rp_per_bird || 0 + finance.data.hpp_purchases.summary_hpp + ?.realization?.rp_per_bird || 0 ) : '-'; }, @@ -287,8 +387,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'realization_rp_per_kg' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.realization - .rp_per_kg || 0 + finance.data.hpp_purchases.summary_hpp + ?.realization?.rp_per_kg || 0 ) : '-'; }, @@ -303,8 +403,8 @@ const ClosingFinanceTable = ({ return props.column.id === 'realization_amount' && isResponseSuccess(finance) ? formatCurrency( - finance.data.hpp_purchases.summary_hpp.realization - .amount || 0 + finance.data.hpp_purchases.summary_hpp + ?.realization?.amount || 0 ) : '-'; }, diff --git a/src/components/pages/closing/ClosingSapronakCalculationTabContent.tsx b/src/components/pages/closing/ClosingSapronakCalculationTabContent.tsx index 15e43bbc..b8add15b 100644 --- a/src/components/pages/closing/ClosingSapronakCalculationTabContent.tsx +++ b/src/components/pages/closing/ClosingSapronakCalculationTabContent.tsx @@ -1,21 +1,25 @@ 'use client'; -import ClosingIncomingSapronaksTable from '@/components/pages/closing/ClosingIncomingSapronaksTable'; -import ClosingOutgoingSapronaksTable from '@/components/pages/closing/ClosingOutgoingSapronaksTable'; import ClosingSapronakCalculationTable from '@/components/pages/closing/ClosingSapronakCalculationTable'; +import { ClosingGeneralInformation } from '@/types/api/closing'; interface ClosingSapronakCalculationTabContentProps { projectFlockId?: number; + closingGeneralInformation?: ClosingGeneralInformation; } const ClosingSapronakCalculationTabContent = ({ projectFlockId, + closingGeneralInformation, }: ClosingSapronakCalculationTabContentProps) => { return (
{projectFlockId && ( <> - + )}
diff --git a/src/components/pages/closing/ClosingSapronakCalculationTable.tsx b/src/components/pages/closing/ClosingSapronakCalculationTable.tsx index 22b4d2e2..6e3b1a95 100644 --- a/src/components/pages/closing/ClosingSapronakCalculationTable.tsx +++ b/src/components/pages/closing/ClosingSapronakCalculationTable.tsx @@ -13,15 +13,16 @@ import { useMemo } from 'react'; import useSWR from 'swr'; import { ClosingApi } from '@/services/api/closing'; import { isResponseSuccess } from '@/lib/api-helper'; +import { ClosingGeneralInformation } from '@/types/api/closing'; interface ClosingSapronakCalculationTableProps { - type?: 'detail'; projectFlockId: number; + closingGeneralInformation?: ClosingGeneralInformation; } const ClosingSapronakCalculationTable = ({ - type, projectFlockId, + closingGeneralInformation, }: ClosingSapronakCalculationTableProps) => { const { data: sapronakCalculation, isLoading } = useSWR( `/closing/sapronak-calculation/${projectFlockId}`, @@ -182,8 +183,13 @@ const ClosingSapronakCalculationTable = ({ return (
+ {/* Table DOC jika kategori Project Flock Growing */} data={ isResponseSuccess(sapronakCalculation) - ? (sapronakCalculation.data?.doc?.rows ?? []) + ? ((closingGeneralInformation?.project_category === 'GROWING' + ? sapronakCalculation.data?.doc?.rows + : sapronakCalculation.data?.pullet?.rows) ?? []) : [] } - columns={docColumns} + columns={ + closingGeneralInformation?.project_category === 'GROWING' + ? docColumns + : pulletColumns + } className={{ containerClassName: 'my-4', }} @@ -250,29 +262,6 @@ const ClosingSapronakCalculationTable = ({ renderFooter={isResponseSuccess(sapronakCalculation)} /> - - - - data={ - isResponseSuccess(sapronakCalculation) - ? (sapronakCalculation.data?.pullet?.rows ?? []) - : [] - } - columns={pulletColumns} - className={{ - containerClassName: 'my-4', - }} - renderFooter={isResponseSuccess(sapronakCalculation)} - /> -
); }; diff --git a/src/components/pages/expense/ExpenseRequestContent.tsx b/src/components/pages/expense/ExpenseRequestContent.tsx index 2b9086e0..657c5e5c 100644 --- a/src/components/pages/expense/ExpenseRequestContent.tsx +++ b/src/components/pages/expense/ExpenseRequestContent.tsx @@ -140,17 +140,17 @@ const ExpenseRequestContent = ({ const confirmationModalDeleteClickHandler = async () => { setIsDeleteLoading(true); - try { - await ExpenseApi.delete(initialValues?.id as number); + const deleteResponse = await ExpenseApi.delete(initialValues?.id as number); + if (isResponseSuccess(deleteResponse)) { toast.success('Berhasil menghapus data biaya operasional!'); router.push('/expense'); - } catch (error) { + } else { toast.error('Gagal menghapus data biaya operasional!'); - } finally { - deleteModal.closeModal(); - setIsDeleteLoading(false); } + + deleteModal.closeModal(); + setIsDeleteLoading(false); }; const confirmationModalCompleteClickHandler = async () => { diff --git a/src/components/pages/expense/ExpenseStatusBadge.tsx b/src/components/pages/expense/ExpenseStatusBadge.tsx index 3a84f6bc..a70b6454 100644 --- a/src/components/pages/expense/ExpenseStatusBadge.tsx +++ b/src/components/pages/expense/ExpenseStatusBadge.tsx @@ -21,7 +21,7 @@ const ExpenseStatusBadge = ({ approval }: ExpenseStatusBadgeProps) => { switch (latestApprovalStepNumber) { case 1: - expenseStatusPillBadgeColor = 'yellow'; + expenseStatusPillBadgeColor = 'gray'; break; case 2: @@ -33,7 +33,7 @@ const ExpenseStatusBadge = ({ approval }: ExpenseStatusBadgeProps) => { break; case 4: - expenseStatusPillBadgeColor = 'red'; + expenseStatusPillBadgeColor = 'yellow'; break; case 5: diff --git a/src/components/pages/expense/ExpensesTable.tsx b/src/components/pages/expense/ExpensesTable.tsx index 9ae3ed34..1f3e9df5 100644 --- a/src/components/pages/expense/ExpensesTable.tsx +++ b/src/components/pages/expense/ExpensesTable.tsx @@ -420,11 +420,19 @@ const ExpensesTable = () => { const confirmationModalDeleteClickHandler = async () => { setIsDeleteLoading(true); - await ExpenseApi.delete(selectedExpense?.id as number); - refreshExpenses(); + const deleteResponse = await ExpenseApi.delete( + selectedExpense?.id as number + ); + + if (isResponseSuccess(deleteResponse)) { + refreshExpenses(); + deleteModal.closeModal(); + toast.success('Berhasil menghapus biaya operasional!'); + } else { + deleteModal.closeModal(); + toast.error('Gagal menghapus biaya operasional!'); + } - deleteModal.closeModal(); - toast.success('Berhasil menghapus biaya operasional!'); setIsDeleteLoading(false); }; diff --git a/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx b/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx index f134369e..525b81bb 100644 --- a/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx +++ b/src/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.tsx @@ -125,6 +125,7 @@ const InventoryAdjustmentForm = ({ const warehouseUrl = `${WarehouseApi.basePath}?${new URLSearchParams({ search: '', + limit: '100', }).toString()}`; const { data: warehouses, isLoading: isLoadingWarehouses } = useSWR( warehouseUrl, diff --git a/src/components/pages/inventory/movement/form/MovementForm.schema.ts b/src/components/pages/inventory/movement/form/MovementForm.schema.ts index 9b2c8557..048b1bd2 100644 --- a/src/components/pages/inventory/movement/form/MovementForm.schema.ts +++ b/src/components/pages/inventory/movement/form/MovementForm.schema.ts @@ -85,7 +85,10 @@ const ProductObjectSchema: Yup.ObjectSchema = Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), }).nullable(), - product_id: Yup.number().required('Produk wajib diisi!'), + product_id: Yup.number() + .required('Produk wajib diisi!') + .min(1, 'Produk wajib diisi!') + .typeError('Produk wajib diisi!'), product_qty: Yup.number() .required('Qty wajib diisi!') .min(1, 'Qty minimal 1!') @@ -97,7 +100,10 @@ const DeliveryProductObjectSchema = Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), }).nullable(), - product_id: Yup.number().required('Produk wajib diisi!'), + product_id: Yup.number() + .required('Produk wajib diisi!') + .min(1, 'Produk wajib diisi!') + .typeError('Produk wajib diisi!'), product_qty: Yup.number() .required('Qty wajib diisi!') .min(1, 'Qty minimal 1!') @@ -127,13 +133,13 @@ const DeliveryObjectSchema: Yup.ObjectSchema = Yup.object({ (delivery_cost !== undefined && delivery_cost > 0) ); }), - document_path: Yup.string().optional(), + document_path: Yup.string().nullable().optional(), document_index: Yup.number().optional(), document: Yup.mixed() .nullable() - .test('fileSize', 'Ukuran dokumen maksimal 2 MB', (value) => { + .test('fileSize', 'Ukuran dokumen maksimal 5 MB', (value) => { if (!value) return true; - if (value instanceof File) return value.size <= 2 * 1024 * 1024; + if (value instanceof File) return value.size <= 5 * 1024 * 1024; return true; }), driver_name: Yup.string().required('Nama sopir wajib diisi!'), @@ -142,7 +148,10 @@ const DeliveryObjectSchema: Yup.ObjectSchema = Yup.object({ value: Yup.number().min(1).required(), label: Yup.string().required(), }).nullable(), - supplier_id: Yup.number().required('Supplier wajib diisi!'), + supplier_id: Yup.number() + .required('Supplier wajib diisi!') + .min(1, 'Supplier wajib diisi!') + .typeError('Supplier wajib diisi!'), products: Yup.array() .of(DeliveryProductObjectSchema) .min(1, 'Minimal harus ada 1 produk!') @@ -161,6 +170,7 @@ export const MovementFormSchema: Yup.ObjectSchema = }).nullable(), source_warehouse_id: Yup.number() .required('Gudang asal wajib diisi!') + .min(1, 'Gudang asal wajib diisi!') .typeError('Gudang asal wajib diisi!'), destination_warehouse: Yup.object({ value: Yup.number().min(1).required(), @@ -170,6 +180,7 @@ export const MovementFormSchema: Yup.ObjectSchema = }).nullable(), destination_warehouse_id: Yup.number() .required('Gudang tujuan wajib diisi!') + .min(1, 'Gudang tujuan wajib diisi!') .typeError('Gudang tujuan wajib diisi!') .test( 'different-warehouse', @@ -226,41 +237,62 @@ export const getMovementFormInitialValues = ( } : null, destination_warehouse_id: initialValues?.destination_warehouse?.id ?? 0, - products: - initialValues?.details?.map((detail) => ({ - product: { - value: detail.product.id, - label: detail.product.name, - }, - product_id: detail.product.id, - product_qty: detail.quantity, - })) ?? [], - deliveries: - initialValues?.deliveries?.map((d) => ({ - delivery_cost: d.shipping_cost_total ?? undefined, - delivery_cost_per_item: d.shipping_cost_item ?? undefined, - document_number: d.document_number ?? '', - document: d.document ?? null, - document_path: d.document_path ?? null, - driver_name: d.driver_name ?? '', - vehicle_plate: d.vehicle_plate ?? '', - supplier: d.supplier - ? { value: d.supplier.id, label: d.supplier.name } - : null, - supplier_id: d.supplier?.id ?? 0, - products: - d.items?.map((item) => { - const productData = detailIdToProductId.get( - item.stock_transfer_detail_id - ); - return { - product: productData - ? { value: productData.id, label: productData.name } - : null, - product_id: productData?.id ?? 0, - product_qty: item.quantity, - }; - }) ?? [], - })) ?? [], + products: initialValues?.details?.map((detail) => ({ + product: { + value: detail.product.id, + label: detail.product.name, + }, + product_id: detail.product.id, + product_qty: detail.quantity, + })) ?? [ + { + product: null, + product_id: 0, + product_qty: '', + }, + ], + deliveries: initialValues?.deliveries?.map((d) => ({ + delivery_cost: d.shipping_cost_total ?? undefined, + delivery_cost_per_item: d.shipping_cost_item ?? undefined, + document: d.document ?? null, + document_path: d.document_path ?? null, + driver_name: d.driver_name ?? '', + vehicle_plate: d.vehicle_plate ?? '', + supplier: d.supplier + ? { value: d.supplier.id, label: d.supplier.name } + : null, + supplier_id: d.supplier?.id ?? 0, + products: + d.items?.map((item) => { + const productData = detailIdToProductId.get( + item.stock_transfer_detail_id + ); + return { + product: productData + ? { value: productData.id, label: productData.name } + : null, + product_id: productData?.id ?? 0, + product_qty: item.quantity, + }; + }) ?? [], + })) ?? [ + { + delivery_cost: undefined, + delivery_cost_per_item: undefined, + document: null, + document_path: null, + driver_name: '', + vehicle_plate: '', + supplier: null, + supplier_id: 0, + products: [ + { + product: null, + product_id: 0, + product_qty: '', + }, + ], + }, + ], }; }; diff --git a/src/components/pages/inventory/movement/form/MovementForm.tsx b/src/components/pages/inventory/movement/form/MovementForm.tsx index 3c49295e..d9aef6cd 100644 --- a/src/components/pages/inventory/movement/form/MovementForm.tsx +++ b/src/components/pages/inventory/movement/form/MovementForm.tsx @@ -36,6 +36,8 @@ import CheckboxInput from '@/components/input/CheckboxInput'; import Badge from '@/components/Badge'; import Card from '@/components/Card'; import { S3_PUBLIC_BASE_URL } from '@/config/constant'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; +import AlertErrorList from '@/components/helper/form/FormErrors'; interface MovementFormProps { type?: 'add' | 'edit' | 'detail'; @@ -53,6 +55,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { ] = useState(''); const [selectedProducts, setSelectedProducts] = useState([]); const [selectedDeliveries, setSelectedDeliveries] = useState([]); + const [formErrorList, setFormErrorList] = useState([]); // ===== FORM HANDLERS ===== const createMovementHandler = useCallback( @@ -186,12 +189,45 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { return; } const documents: File[] = []; + const documentNameToIndex = new Map(); + let sequentialDocumentIndex = 0; + const deliveriesPayload = values.deliveries.map((d) => { - let documentIndex = 0; + let documentIndex = -1; if (d.document && d.document instanceof File) { - documents.push(d.document); - documentIndex = documents.length - 1; + const fileName = d.document.name; + + if (documentNameToIndex.has(fileName)) { + documentIndex = documentNameToIndex.get(fileName)!; + } else { + documents.push(d.document); + documentIndex = sequentialDocumentIndex; + documentNameToIndex.set(fileName, documentIndex); + sequentialDocumentIndex++; + } + } else if (d.document_path) { + const pathFileName = + d.document_path.split('/').pop() || d.document_path; + + if (documentNameToIndex.has(pathFileName)) { + documentIndex = documentNameToIndex.get(pathFileName)!; + } else { + documentIndex = sequentialDocumentIndex; + documentNameToIndex.set(pathFileName, documentIndex); + sequentialDocumentIndex++; + } + } else if (d.document && !(d.document instanceof File)) { + const existingDocFileName = + d.document.path.split('/').pop() || d.document.path; + + if (documentNameToIndex.has(existingDocFileName)) { + documentIndex = documentNameToIndex.get(existingDocFileName)!; + } else { + documentIndex = sequentialDocumentIndex; + documentNameToIndex.set(existingDocFileName, documentIndex); + sequentialDocumentIndex++; + } } return { @@ -199,7 +235,6 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { delivery_cost_per_item: parseInt((d.delivery_cost_per_item || '').toString()) || 0, document_index: documentIndex, - document_path: d.document_path, driver_name: d.driver_name, vehicle_plate: d.vehicle_plate, supplier_id: d.supplier_id, @@ -761,8 +796,36 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { type !== 'edit' && type !== 'detail' ) { - formik.setFieldValue('products', []); - formik.setFieldValue('deliveries', []); + if (formik.values.products.length === 0) { + formik.setFieldValue('products', [ + { + product: null, + product_id: 0, + product_qty: '', + }, + ]); + } + if (formik.values.deliveries.length === 0) { + formik.setFieldValue('deliveries', [ + { + delivery_cost: undefined, + delivery_cost_per_item: undefined, + document: null, + document_path: null, + driver_name: '', + vehicle_plate: '', + supplier: null, + supplier_id: 0, + products: [ + { + product: null, + product_id: 0, + product_qty: '', + }, + ], + }, + ]); + } } }, [formik.values.source_warehouse_id]); @@ -791,6 +854,22 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { formik.errors.destination_warehouse_id, ]); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + return ( <>
@@ -810,10 +889,29 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
+ {movementFormErrorMessage && ( +
+ + {movementFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {/* Top card - Movement details */} { Produk * @@ -1106,7 +1204,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Qty * @@ -1119,7 +1217,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { {formik.values.products?.map((product, idx) => ( {type !== 'detail' && ( - + { Produk * @@ -1320,7 +1418,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Qty * @@ -1329,7 +1427,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Supplier * @@ -1338,7 +1436,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Plat Nomor * @@ -1348,7 +1446,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Biaya Pengiriman (Rp.) * @@ -1357,7 +1455,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Biaya Per Item (Rp.) * @@ -1366,7 +1464,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { Nama Sopir * @@ -1379,7 +1477,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => { {formik.values.deliveries?.map((delivery, idx) => ( {type !== 'detail' && ( - + { width={20} height={20} /> - {delivery.document.name} + + {delivery.document.name} + ) : (
)} - - {movementFormErrorMessage && ( -
- - {movementFormErrorMessage} -
- )} diff --git a/src/components/pages/marketing/MarketingTable.tsx b/src/components/pages/marketing/MarketingTable.tsx index 507819e3..1c37dbbb 100644 --- a/src/components/pages/marketing/MarketingTable.tsx +++ b/src/components/pages/marketing/MarketingTable.tsx @@ -682,7 +682,7 @@ const MarketingTable = () => { @@ -724,6 +724,7 @@ const MarketingTable = () => { }, ]} className={{ + containerClassName: 'p-6', tableWrapperClassName: 'overflow-x-auto min-h-full!', tableClassName: 'font-inter w-full table-auto min-h-full!', headerRowClassName: 'border-b border-b-gray-200', diff --git a/src/components/pages/marketing/detail/MarketingDetail.tsx b/src/components/pages/marketing/detail/MarketingDetail.tsx index 677ea422..12ebda20 100644 --- a/src/components/pages/marketing/detail/MarketingDetail.tsx +++ b/src/components/pages/marketing/detail/MarketingDetail.tsx @@ -124,7 +124,10 @@ const MarketingDetail = ({ return ( <>
- + 2 ? 'Delivery Order' : 'Sales Order'}`} + backUrl='/marketing' + /> {!isLoadingApproval && approvals && ( )} @@ -202,8 +205,23 @@ const MarketingDetail = ({ No. Sales Order : - {initialValues?.so_number} + + {initialValues?.so_number} + + {Number(initialValues?.latest_approval?.step_number) > 2 && ( + + + No. Delivery Order + + : + + {initialValues?.delivery_order + ?.map((item) => item.do_number) + .join(', ')} + + + )} Nama Pelanggan : @@ -230,12 +248,27 @@ const MarketingDetail = ({ {initialValues?.notes ?? '-'} - Dokumen + Dokumen Penjualan : + {Number(initialValues?.latest_approval?.step_number) > 2 && ( + + Dokumen Pengiriman + : + + {initialValues?.delivery_order?.map((item, index) => ( + + ))} + + + )}
diff --git a/src/components/pages/marketing/form/MarketingForm.tsx b/src/components/pages/marketing/form/MarketingForm.tsx index 1c5322e1..51c20d8e 100644 --- a/src/components/pages/marketing/form/MarketingForm.tsx +++ b/src/components/pages/marketing/form/MarketingForm.tsx @@ -48,6 +48,8 @@ import DeliveryOrderProductForm from '@/components/pages/marketing/form/repeater import { SalesOrderProductFormValues } from '@/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema'; import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/form/repeater/delivery-order/DeliverOrderProduct.schema'; import RequirePermission from '@/components/helper/RequirePermission'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; +import AlertErrorList from '@/components/helper/form/FormErrors'; const MemoizedSalesOrderProductTable = memo(SalesOrderProductTable); const MemoizedSalesOrderProductForm = memo(SalesOrderProductForm); @@ -217,6 +219,7 @@ const MarketingForm = ({ const [deliveryFormState, setDeliveryFormState] = useState<'add' | 'edit'>( 'add' ); + const [formErrorList, setFormErrorList] = useState([]); const [deliveryOrderValues, setDeliveryOrderValues] = useState< DeliveryOrderProductFormValues[] >( @@ -558,11 +561,28 @@ const MarketingForm = ({ ); }, [memoSalesOrder]); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + // Parse and display errors + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; // Stop submission + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(); + }; + return ( <>
+ {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {/* Form Actions */}
+
+
+ {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
diff --git a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema.ts b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema.ts index b2f42254..e62ed701 100644 --- a/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema.ts +++ b/src/components/pages/marketing/form/repeater/sales-order/SalesOrderProduct.schema.ts @@ -25,15 +25,19 @@ export const SalesOrderProductSchema: Yup.ObjectSchema { const [formErrorMessage, setFormErrorMessage] = useState(''); const [currentInput, setCurrentInput] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); + // ============ Formik ============ const formik = useFormik({ enableReinitialize: true, initialValues: { @@ -58,6 +66,7 @@ const SalesOrderProductForm = ({ isInitialValid: false, }); + // ===== Options ===== const { options: kandangSourceOptions, isLoadingOptions: isLoadingKandangSourceOptions, @@ -86,12 +95,13 @@ const SalesOrderProductForm = ({ ); }, [warehouseSourceOptions, exisitingValues]); + // ===== Handler ===== const kandangChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldValue('kandang', val as OptionType); formik.setFieldValue('kandang_id', (val as OptionType)?.value); formik.setFieldValue('product_warehouse_id', null); formik.setFieldValue('product_warehouse', null); - formik.setFieldValue('qty', null); + formik.setFieldValue('qty', ''); }; const warehouseChangeHandler = (val: OptionType | OptionType[] | null) => { @@ -106,7 +116,7 @@ const SalesOrderProductForm = ({ formik.setFieldValue('qty', productWarehouse?.quantity); handleBlurField('qty'); } else { - formik.setFieldValue('qty', null); + formik.setFieldValue('qty', ''); } }; @@ -162,15 +172,29 @@ const SalesOrderProductForm = ({ } }; + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + // Parse and display errors + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; // Stop submission + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleBlurField(currentInput); + handleValidateForm(); + formik.handleSubmit(e); + }; + return ( <> { - e.preventDefault(); - handleBlurField(currentInput); - formik.handleSubmit(e); - }} + onSubmit={handleFormSubmit} onReset={handleResetForm} > {formErrorMessage && ( @@ -248,7 +272,24 @@ const SalesOrderProductForm = ({ isError={formik.touched.qty && Boolean(formik.errors.qty)} errorMessage={formik.errors.qty} placeholder='Masukan Kuantitas' + bottomLabel={ + isResponseSuccess(warehouseSourceRawData) && + formik.values.product_warehouse_id + ? `Stok tersedia: ${formatNumber( + warehouseSourceRawData?.data?.find( + (item) => item.id === formik.values.product_warehouse_id + )?.quantity ?? 0 + )} ${ + warehouseSourceRawData?.data?.find( + (item) => item.id === formik.values.product_warehouse_id + )?.product?.uom?.name ?? '' + }` + : '' + } /> +
+
+
+ + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
diff --git a/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx b/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx index 7acd3a01..d241a3dd 100644 --- a/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx +++ b/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx @@ -11,6 +11,8 @@ import TextInput from '@/components/input/TextInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { ProductCategoryFormSchema, @@ -39,6 +41,7 @@ const ProductCategoryForm = ({ const deleteModal = useModal(); const [formErrorMessage, setFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const createProductCategoryHandler = useCallback( @@ -129,6 +132,22 @@ const ProductCategoryForm = ({ formikSetValues(formikInitialValues); }, [formikSetValues, formikInitialValues]); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + return ( <>
@@ -150,10 +169,29 @@ const ProductCategoryForm = ({ + {formErrorMessage && ( +
+ + {formErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
Submit @@ -244,17 +282,6 @@ const ProductCategoryForm = ({
)}
- - {formErrorMessage && ( -
- - {formErrorMessage} -
- )} diff --git a/src/components/pages/master-data/product/form/ProductForm.schema.ts b/src/components/pages/master-data/product/form/ProductForm.schema.ts index 37881636..9dcf713e 100644 --- a/src/components/pages/master-data/product/form/ProductForm.schema.ts +++ b/src/components/pages/master-data/product/form/ProductForm.schema.ts @@ -29,36 +29,38 @@ export const ProductFormSchema: Yup.ObjectSchema = sku: Yup.string().required('SKU wajib diisi!'), uom: Yup.object({ - value: Yup.number().min(1).required(), - label: Yup.string().required(), - }) - .nullable() - .required('Satuan wajib diisi!'), + value: Yup.number() + .min(1, 'Satuan wajib dipilih!') + .required('Satuan wajib dipilih!'), + label: Yup.string().required('Satuan wajib dipilih!'), + }).nullable(), uom_id: Yup.number() - .required('Satuan wajib diisi!') - .typeError('Satuan wajib diisi!'), + .min(1, 'Satuan wajib dipilih!') + .required('Satuan wajib dipilih!') + .typeError('Satuan wajib dipilih!'), product_category: Yup.object({ - value: Yup.number().min(1).required(), - label: Yup.string().required(), - }) - .nullable() - .required('Kategori produk wajib diisi!'), + value: Yup.number() + .min(1, 'Kategori produk wajib dipilih!') + .required('Kategori produk wajib dipilih!'), + label: Yup.string().required('Kategori produk wajib dipilih!'), + }).nullable(), product_category_id: Yup.number() - .required('Kategori produk wajib diisi!') - .typeError('Kategori produk wajib diisi!'), + .min(1, 'Kategori produk wajib dipilih!') + .required('Kategori produk wajib dipilih!') + .typeError('Kategori produk wajib dipilih!'), product_price: Yup.number() .required('Harga produk wajib diisi!') .typeError('Harga produk wajib diisi!') - .min(0, 'Harga produk tidak boleh kurang dari 0!'), + .min(1, 'Harga produk tidak boleh kurang dari 1!'), selling_price: Yup.number() .required('Harga jual wajib diisi!') .typeError('Harga jual wajib diisi!') - .min(0, 'Harga jual tidak boleh kurang dari 0!'), + .min(1, 'Harga jual tidak boleh kurang dari 1!'), tax: Yup.number() .required('Pajak wajib diisi!') @@ -69,7 +71,7 @@ export const ProductFormSchema: Yup.ObjectSchema = expiry_period: Yup.number() .required('Periode kadaluarsa wajib diisi!') .typeError('Periode kadaluarsa wajib diisi!') - .min(0, 'Periode kadaluarsa tidak boleh kurang dari 0!'), + .min(1, 'Periode kadaluarsa tidak boleh kurang dari 1 hari!'), supplier_ids: Yup.array() .of(Yup.number().required().typeError('Supplier tidak valid!')) diff --git a/src/components/pages/master-data/product/form/ProductForm.tsx b/src/components/pages/master-data/product/form/ProductForm.tsx index 5b304419..bf4cf1ee 100644 --- a/src/components/pages/master-data/product/form/ProductForm.tsx +++ b/src/components/pages/master-data/product/form/ProductForm.tsx @@ -17,6 +17,8 @@ import SelectInput, { import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { ProductFormSchema, @@ -48,6 +50,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { const deleteModal = useModal(); const [productFormErrorMessage, setProductFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const createProductHandler = useCallback( @@ -201,6 +204,22 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { formikSetValues(formikInitialValues); }, [formikSetValues, formikInitialValues]); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + return ( <>
@@ -220,11 +239,30 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
-
+ {productFormErrorMessage && ( +
+ + {productFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + +
{ errorMessage={formik.errors.name} readOnly={type === 'detail'} /> - - - - - - - - - - (formik.values.supplier_ids || []).includes(opt.value) - )} - onChange={supplierChangeHandler} - options={supplierOptions} - onInputChange={setSupplierSelectInputValue} - isLoading={isLoadingSuppliers} - isError={ - formik.touched.supplier_ids && - Boolean(formik.errors.supplier_ids) - } - errorMessage={formik.errors.supplier_ids as string} - isDisabled={type === 'detail'} - isClearable - /> - - (formik.values.flags || []).includes(opt.value) - )} - onChange={(val) => { - const arr = Array.isArray(val) ? val : val ? [val] : []; - formik.setFieldValue( - 'flags', - arr.map((v) => (v as OptionType).value) - ); - }} - options={PRODUCT_FLAG_OPTIONS} - isError={formik.touched.flags && Boolean(formik.errors.flags)} - errorMessage={formik.errors.flags as string} - isDisabled={type === 'detail'} - isClearable - /> +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + (formik.values.supplier_ids || []).includes(opt.value) + )} + onChange={supplierChangeHandler} + options={supplierOptions} + onInputChange={setSupplierSelectInputValue} + isLoading={isLoadingSuppliers} + isError={ + formik.touched.supplier_ids && + Boolean(formik.errors.supplier_ids) + } + errorMessage={formik.errors.supplier_ids as string} + isDisabled={type === 'detail'} + isClearable + /> + + (formik.values.flags || []).includes(opt.value) + )} + onChange={(val) => { + const arr = Array.isArray(val) ? val : val ? [val] : []; + formik.setFieldValue( + 'flags', + arr.map((v) => (v as OptionType).value) + ); + }} + options={PRODUCT_FLAG_OPTIONS} + isError={formik.touched.flags && Boolean(formik.errors.flags)} + errorMessage={formik.errors.flags as string} + isDisabled={type === 'detail'} + isClearable + /> +
{type !== 'add' && ( @@ -463,7 +515,7 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { type='submit' color='primary' isLoading={formik.isSubmitting} - disabled={!formik.isValid || formik.isSubmitting} + disabled={formik.isSubmitting} className='px-4' > Submit @@ -471,16 +523,6 @@ const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => {
)}
- {productFormErrorMessage && ( -
- - {productFormErrorMessage} -
- )}
{type !== 'add' && ( diff --git a/src/components/pages/production/chickin/form/ChickinForm.tsx b/src/components/pages/production/chickin/form/ChickinForm.tsx index 7d8a4c7c..b5b1dc4d 100644 --- a/src/components/pages/production/chickin/form/ChickinForm.tsx +++ b/src/components/pages/production/chickin/form/ChickinForm.tsx @@ -18,6 +18,7 @@ import { Icon } from '@iconify/react'; import Badge from '@/components/Badge'; import { CHICKINS_APPROVAL_LINE } from '@/config/approval-line'; import RequirePermission from '@/components/helper/RequirePermission'; +import { BaseApproval } from '@/types/api/api-general'; const ChickinFormKandang = ({ formType = 'add', initialValues, @@ -33,11 +34,16 @@ const ChickinFormKandang = ({ approvals, isLoading: approvalsLoading, refresh: refreshApprovals, + rawDataApprovals, } = useApprovalSteps({ - latestApproval: initialValues?.approval, + latestApproval: initialValues?.chickin_approval, approvalLines: CHICKINS_APPROVAL_LINE, moduleName: 'CHICKINS', moduleId: initialValues?.id.toString() ?? '', + params: { + limit: 'limit', + group_step_number: false, + }, }); const afterSubmitFormChickin = () => { @@ -180,6 +186,7 @@ const ChickinFormKandang = ({ {openChickin && ( diff --git a/src/components/pages/production/chickin/form/tabs/ChickLogsView.tsx b/src/components/pages/production/chickin/form/tabs/ChickLogsView.tsx index 17c76822..e800ee68 100644 --- a/src/components/pages/production/chickin/form/tabs/ChickLogsView.tsx +++ b/src/components/pages/production/chickin/form/tabs/ChickLogsView.tsx @@ -8,6 +8,7 @@ import PillBadge from '@/components/PillBadge'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { formatDate, formatNumber } from '@/lib/helper'; import { ChickinApi } from '@/services/api/production/chickin'; +import { BaseApproval } from '@/types/api/api-general'; import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; import { Icon } from '@iconify/react'; import { useState } from 'react'; @@ -16,9 +17,11 @@ import toast from 'react-hot-toast'; const ChickinLogsView = ({ initialValues, afterSubmit, + rawDataApprovals, }: { initialValues: ProjectFlockKandang; afterSubmit?: () => void; + rawDataApprovals: BaseApproval[]; }) => { const confirmModal = useModal(); const [isApproveLoading, setIsApproveLoading] = useState(false); @@ -60,8 +63,15 @@ const ChickinLogsView = ({ ) : ( (initialValues?.chickins || []).map((chickin, index) => { - const isApproved = chickin.usage_qty !== 0; - const isPending = chickin.pending_usage_qty !== 0; + const latestApproval = rawDataApprovals[0]; + const isApproved = + index == (initialValues?.chickins || []).length - 1 + ? latestApproval?.step_number === 2 + : true; + const isPending = + index == (initialValues?.chickins || []).length - 1 + ? latestApproval?.step_number === 1 + : false; const quantity = isApproved ? chickin.usage_qty : isPending @@ -81,7 +91,7 @@ const ChickinLogsView = ({ {/* Header with Status Badge */}
- Chick In #{index + 1} + Chick In #{index + 1} - {latestApproval?.step_number}
- - - )} + {initialValues.chickin_approval && + initialValues?.chickin_approval?.step_number < 2 && ( + + + + )} {chickinErrorMessage && (
setChickinErrorMessage('')}> diff --git a/src/components/pages/production/project-flock/ProjectFlockTable.tsx b/src/components/pages/production/project-flock/ProjectFlockTable.tsx index 7d9ce7da..f6888c3d 100644 --- a/src/components/pages/production/project-flock/ProjectFlockTable.tsx +++ b/src/components/pages/production/project-flock/ProjectFlockTable.tsx @@ -308,7 +308,10 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
)} - {approvals && !approvalsLoading && formType == 'detail' && ( - - )} - {formType == 'detail' && ( -
- - - - - - -
- )} +
{ + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }} onReset={formik.handleReset} > {/* Form Informasi Umum */} @@ -872,23 +801,6 @@ const ProjectFlockForm = ({ isClearable isDisabled={formType != 'add'} /> - { - optionChangeHandler(val, 'production_standard'); - }} - options={optionsProductionStandards} - isLoading={isLoadingProductionStandards} - isError={ - formik.touched.production_standard && - Boolean(formik.errors.production_standard) - } - errorMessage={formik.errors.production_standard as string} - isClearable - isDisabled={formType != 'add'} - /> + { + optionChangeHandler(val, 'production_standard'); + }} + options={optionsProductionStandards} + isLoading={isLoadingProductionStandards} + isError={ + formik.touched.production_standard_id && + Boolean(formik.errors.production_standard_id) + } + errorMessage={formik.errors.production_standard_id as string} + isClearable + isDisabled={formType != 'add'} + /> + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
- {/*
-
- {JSON.stringify(formik.values)} -
-
- {JSON.stringify(formik.errors)} -
-
*/} {formType !== 'detail' && ( @@ -1200,27 +1129,6 @@ const ProjectFlockForm = ({ onClick: confirmationModalDeleteClickHandler, }} /> - - { - confirmApprovalHandler(notes, approvalAction); - }, - }} - /> ); }; diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 3a6f8071..4a9d6c13 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -17,6 +17,7 @@ import CheckboxInput from '@/components/input/CheckboxInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes'; import { useModal } from '@/components/Modal'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { ProjectFlockKandangApi, @@ -52,6 +53,7 @@ import { import { isResponseSuccess, isResponseError } from '@/lib/api-helper'; import { formatDate, formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import toast from 'react-hot-toast'; import ApprovalSteps, { useApprovalSteps, @@ -60,7 +62,6 @@ import { GROWING_RECORDING_APPROVAL_LINE, LAYING_RECORDING_APPROVAL_LINE, } from '@/config/approval-line'; -import Table from '@/components/Table'; interface RecordingFormProps { type?: 'add' | 'edit' | 'detail'; @@ -92,6 +93,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const [, setApprovalNotes] = useState(''); const [recordingFormErrorMessage, setRecordingFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [, setNewRecordingData] = useState(null); const [nextDayRecording, setNextDayRecording] = @@ -758,6 +760,22 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== HELPER FUNCTIONS ===== useCallback((): OptionType | null => { if ( @@ -1323,9 +1341,28 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} + {recordingFormErrorMessage && ( +
+ + {recordingFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {/* Basic Info Card */} {(type === 'add' || type === 'edit') && ( { color='primary' className='px-4' isLoading={formik.isSubmitting} - disabled={ - hasExceededStock || !formik.isValid || formik.isSubmitting - } + disabled={hasExceededStock || formik.isSubmitting} > Submit @@ -2534,9 +2569,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { color='primary' className='px-4' isLoading={formik.isSubmitting} - disabled={ - hasExceededStock || !formik.isValid || formik.isSubmitting - } + disabled={hasExceededStock || formik.isSubmitting} > Submit @@ -2544,16 +2577,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )}
- {recordingFormErrorMessage && ( -
- - {recordingFormErrorMessage} -
- )} diff --git a/src/components/pages/production/uniformity/UniformityChart.tsx b/src/components/pages/production/uniformity/UniformityChart.tsx index 77d1608d..6ddf50d3 100644 --- a/src/components/pages/production/uniformity/UniformityChart.tsx +++ b/src/components/pages/production/uniformity/UniformityChart.tsx @@ -1,93 +1,104 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useState, useEffect } from 'react'; import Card from '@/components/Card'; import UniformityBarChart from '@/components/pages/production/uniformity/chart/UniformityBarChart'; import UniformityGaugeChart from '@/components/pages/production/uniformity/chart/UniformityGaugeChart'; import UniformityBarChartSkeleton from '@/components/pages/production/uniformity/skeleton/UniformityBarChartSkeleton'; import UniformityGaugeChartSkeleton from '@/components/pages/production/uniformity/skeleton/UniformityGaugeChartSkeleton'; -import { - UniformityDetailItem, - Uniformity, -} from '@/types/api/production/uniformity'; +import { Uniformity, type ChartData } from '@/types/api/production/uniformity'; interface UniformityChartProps { uniformityData?: Uniformity | null; - uniformityDetails?: UniformityDetailItem[]; + isFiltered?: boolean; } const UniformityChart = ({ uniformityData, - uniformityDetails, + isFiltered = false, }: UniformityChartProps) => { - const defaultUniformityDetails: UniformityDetailItem[] = [ - { id: 1, weight: 61, range: 'Ideal' }, - { id: 2, weight: 62, range: 'Ideal' }, - { id: 3, weight: 63, range: 'Ideal' }, - { id: 4, weight: 64, range: 'Ideal' }, - { id: 5, weight: 65, range: 'Ideal' }, - { id: 6, weight: 66, range: 'Ideal' }, - { id: 7, weight: 67, range: 'Ideal' }, - ]; + const [currentWeekIndex, setCurrentWeekIndex] = useState(0); - const detailsToUse = uniformityDetails || defaultUniformityDetails; + const chartData = useMemo((): ChartData | undefined => { + if (!uniformityData?.chart_data) return undefined; + return uniformityData.chart_data; + }, [uniformityData]); + + useEffect(() => { + if (uniformityData?.chart_data?.gauge_chart?.week_info) { + const { current_week_index } = + uniformityData.chart_data.gauge_chart.week_info; + setCurrentWeekIndex(current_week_index); + } + }, [uniformityData]); const barChartData = useMemo(() => { - if (!uniformityData) { + if (!chartData?.bar_chart || !chartData?.gauge_chart) { return []; } - if (!detailsToUse || detailsToUse.length === 0) { + const { bar_chart, gauge_chart } = chartData; + const currentWeekData = gauge_chart.available_weeks[currentWeekIndex]; + + if (!currentWeekData || !currentWeekData.has_data) { return []; } - const weights = detailsToUse.map((d) => d.weight); - const minWeight = Math.floor(Math.min(...weights) / 5) * 5; - const maxWeight = Math.ceil(Math.max(...weights) / 5) * 5; + const currentWeekStr = String(currentWeekData.week); + const weekData = bar_chart.all_weeks[currentWeekStr]; - const rangeSize = maxWeight - minWeight < 11 ? 4 : 5; - const ranges: string[] = []; - - for (let start = minWeight; start <= maxWeight; start += rangeSize) { - const end = start + rangeSize; - ranges.push(`${start}-${end}`); + if (!weekData || !weekData.has_data) { + return []; } - const totalIdealCount = detailsToUse.filter( - (d) => d.range === 'Ideal' - ).length; - - return ranges.map((range) => { - const [minStr, maxStr] = range.split('-').map(Number); - const min = minStr; - const max = maxStr; - - const birdsInRange = detailsToUse.filter( - (d) => d.weight >= min && d.weight < max - ).length; - - const hasIdeal = detailsToUse.some( - (d) => d.range === 'Ideal' && d.weight >= min && d.weight < max - ); - - return { - name: range, - uv: birdsInRange, - isIdeal: hasIdeal, - idealCount: hasIdeal ? totalIdealCount : undefined, - }; - }); - }, [uniformityData, detailsToUse]); + return weekData.weight_distribution.map((range) => ({ + name: range.range, + uv: range.bird_count, + isIdeal: range.is_ideal_range, + idealRange: range.ideal_range, + outsideRange: range.outside_range, + })); + }, [chartData, currentWeekIndex]); const gaugeChartData = useMemo(() => { - if (!uniformityData) return undefined; + if (!chartData?.gauge_chart || !uniformityData) return undefined; + + const { gauge_chart } = chartData; + const currentWeekData = gauge_chart.available_weeks[currentWeekIndex]; + + if (!currentWeekData || !currentWeekData.has_data) { + return undefined; + } + + const hasPrevWeek = currentWeekIndex > 0; + const hasNextWeek = + currentWeekIndex < gauge_chart.available_weeks.length - 1; return { - value: uniformityData.uniformity, + value: currentWeekData.uniformity_percentage, label: 'Uniformity', - week: `Week ${uniformityData.week}`, - currentValue: uniformityData.uniform_qty, - totalValue: uniformityData.chick_qty_of_weight, + week: `Week ${currentWeekData.week}`, + currentValue: currentWeekData.ideal_count, + totalValue: currentWeekData.total_count, + hasPrevWeek, + hasNextWeek, }; - }, [uniformityData]); + }, [chartData, currentWeekIndex, uniformityData]); + + const handleWeekChange = (direction: 'prev' | 'next') => { + if (!chartData?.gauge_chart) return; + + const { available_weeks } = chartData.gauge_chart; + + if (direction === 'prev' && currentWeekIndex > 0) { + setCurrentWeekIndex((prev) => prev - 1); + } else if ( + direction === 'next' && + currentWeekIndex < available_weeks.length - 1 + ) { + setCurrentWeekIndex((prev) => prev + 1); + } + }; + + const shouldShowEmptyState = !isFiltered; return (
@@ -100,14 +111,16 @@ const UniformityChart = ({ }} >
- {!uniformityData || barChartData.length === 0 ? ( + {shouldShowEmptyState || + !uniformityData || + barChartData.length === 0 ? ( ) : ( )}
- {!uniformityData || !gaugeChartData ? ( + {shouldShowEmptyState || !uniformityData || !gaugeChartData ? ( )} diff --git a/src/components/pages/production/uniformity/UniformityTable.tsx b/src/components/pages/production/uniformity/UniformityTable.tsx index e031e2c4..63c446ac 100644 --- a/src/components/pages/production/uniformity/UniformityTable.tsx +++ b/src/components/pages/production/uniformity/UniformityTable.tsx @@ -51,8 +51,10 @@ import MenuItem from '@/components/menu/MenuItem'; const UniformityConfirmationPreview = ({ uniformity, + uniformityDetail, }: { uniformity?: Uniformity; + uniformityDetail?: UniformityDetail; }) => { const data: DetailOptionType[] = [ { @@ -60,32 +62,42 @@ const UniformityConfirmationPreview = ({ label: 'Tanggal', value: uniformity ? formatDate(uniformity.applied_at, 'DD MMM YYYY') - : '-', + : uniformityDetail + ? formatDate(uniformityDetail.info_umum.tanggal, 'DD MMM YYYY') + : '-', }, { id: 'lokasi-farm', label: 'Lokasi Farm', - value: uniformity?.location_name || '-', + value: + uniformity?.location_name || + uniformityDetail?.info_umum?.lokasi_farm || + '-', }, { id: 'project-flock', label: 'Project Flock', - value: uniformity?.flock_name || '-', + value: + uniformity?.flock_name || + uniformityDetail?.info_umum?.project_flock || + '-', }, { id: 'kandang', label: 'Kandang', - value: uniformity?.kandang_name || '-', + value: + uniformity?.kandang_name || uniformityDetail?.info_umum?.kandang || '-', }, { id: 'file-uniformity', label: 'File Uniformity', - value: '-', + value: + uniformity?.file_name || uniformityDetail?.info_umum?.file_name || '-', }, { id: 'status', label: 'Status', - value: uniformity?.status || '-', + value: uniformity?.status || (uniformityDetail ? 'CREATED' : '-'), }, ]; @@ -139,8 +151,10 @@ const UniformityConfirmationPreview = ({ const UniformityChartWrapper = ({ uniformitySwrKey, + isFiltered, }: { uniformitySwrKey: string; + isFiltered: boolean; }) => { const { data: uniformities } = useSWR( uniformitySwrKey, @@ -154,31 +168,8 @@ const UniformityChartWrapper = ({ return null; }, [uniformities]); - const shouldFetchDetails = !!uniformityData; - const uniformityDetailSwrKey = useMemo(() => { - if (!uniformityData) return null; - return `${UniformityApi.basePath}/${uniformityData.id}?with_details=true`; - }, [uniformityData]); - - const { data: uniformityDetailResponse } = useSWR( - uniformityDetailSwrKey, - shouldFetchDetails ? UniformityApi.getAllFetcher : null - ); - - const uniformityDetails = useMemo(() => { - if (shouldFetchDetails && isResponseSuccess(uniformityDetailResponse)) { - const detailData = - uniformityDetailResponse.data as unknown as UniformityDetail; - return detailData.uniformity_details; - } - return undefined; - }, [shouldFetchDetails, uniformityDetailResponse]); - return ( - + ); }; @@ -239,12 +230,15 @@ const UniformityTable = () => { const [filterStartDate, setFilterStartDate] = useState(''); const [filterEndDate, setFilterEndDate] = useState(''); const [projectFlockSearchValue, setProjectFlockSearchValue] = useState(''); + const [filterErrors, setFilterErrors] = useState>({}); const { setInputValue: setFilterLocationInputValue, options: filterLocationOptions, isLoadingOptions: isLoadingFilterLocations, - } = useSelect(LocationApi.basePath, 'id', 'name', 'search'); + } = useSelect(LocationApi.basePath, 'id', 'name', 'search', { + limit: '100', + }); // ===== FETCH PROJECT FLOCKS DATA FOR FILTER ===== const filterProjectFlocksUrl = useMemo(() => { @@ -316,6 +310,7 @@ const UniformityTable = () => { project_flock_id: filterProjectFlock.value.toString(), kandang_id: filterKandang.value.toString(), withpopulation: Boolean(true).toString(), + limit: '100', }); return `${ProjectFlockApi.basePath}/kandangs/lookup?${params.toString()}`; }, [filterProjectFlock, filterKandang]); @@ -362,6 +357,7 @@ const UniformityTable = () => { if (filterEndDate) { queryParams.append('end_date', filterEndDate); } + queryParams.append('with_chart', 'true'); } const tableQueryString = getTableFilterQueryString(); @@ -421,6 +417,7 @@ const UniformityTable = () => { ); const handleResetFilters = useCallback(() => { + setIsSubmitted(false); setFilterLocation(null); setFilterProjectFlock(null); setFilterKandang(null); @@ -430,9 +427,38 @@ const UniformityTable = () => { }, []); const handleApplyFilters = useCallback(() => { - setIsSubmitted(true); - filterModal.closeModal(); - }, [filterModal]); + const errors: Record = {}; + + if (!filterStartDate) { + errors.start_date = 'Tanggal mulai wajib diisi'; + } + if (!filterEndDate) { + errors.end_date = 'Tanggal akhir wajib diisi'; + } + if (!filterLocation) { + errors.location = 'Lokasi wajib dipilih'; + } + if (!filterProjectFlock) { + errors.project_flock = 'Project Flock wajib dipilih'; + } + if (!filterKandang) { + errors.kandang = 'Kandang wajib dipilih'; + } + + setFilterErrors(errors); + + if (Object.keys(errors).length === 0) { + setIsSubmitted(true); + filterModal.closeModal(); + } + }, [ + filterModal, + filterStartDate, + filterEndDate, + filterLocation, + filterProjectFlock, + filterKandang, + ]); const selectedRowIds = useMemo(() => { return Object.keys(rowSelection) @@ -448,9 +474,15 @@ const UniformityTable = () => { const canApproveReject = useMemo(() => { return ( selectedUniformities.length > 0 && - selectedUniformities.every( - (u) => u.status === 'CREATED' || u.status === 'Pengajuan' - ) + selectedUniformities.every((u) => { + const approvalAction = u.latest_approval?.action; + return ( + approvalAction === 'CREATED' || + approvalAction === 'Pengajuan' || + (!approvalAction && + (u.status === 'CREATED' || u.status === 'Pengajuan')) + ); + }) ); }, [selectedUniformities]); @@ -615,7 +647,7 @@ const UniformityTable = () => { if (filterEndDate) { queryParams.append('end_date', filterEndDate); } - queryParams.append('limit', '10000'); + queryParams.append('limit', '100'); queryParams.append('page', '1'); const queryString = queryParams.toString(); @@ -805,7 +837,9 @@ const UniformityTable = () => { accessorKey: 'status', header: 'Status', cell: (props) => { - const status = props.row.original.status; + const uniformity = props.row.original; + const status = + uniformity.latest_approval?.action ?? uniformity.status; return (
{
- +
{
{createdUniformity ? ( ) : selectedRowIds.length === 1 ? ( {
- setFilterStartDate(e.target.value)} - className={{ wrapper: 'w-full' }} - /> +
+ { + setFilterStartDate(e.target.value); + setFilterErrors((prev) => ({ ...prev, start_date: '' })); + }} + className={{ wrapper: 'w-full' }} + /> + {filterErrors.start_date && ( +

+ {filterErrors.start_date} +

+ )} +
- setFilterEndDate(e.target.value)} - className={{ wrapper: 'w-full' }} - /> +
+ { + setFilterEndDate(e.target.value); + setFilterErrors((prev) => ({ ...prev, end_date: '' })); + }} + className={{ wrapper: 'w-full' }} + /> + {filterErrors.end_date && ( +

+ {filterErrors.end_date} +

+ )} +
- +
+ { + handleFilterLocationChange(value); + setFilterErrors((prev) => ({ ...prev, location: '' })); + }} + options={filterLocationOptions} + onInputChange={setFilterLocationInputValue} + isLoading={isLoadingFilterLocations} + className={{ wrapper: 'w-full' }} + /> + {filterErrors.location && ( +

+ {filterErrors.location} +

+ )} +
- +
+ { + handleFilterProjectFlockChange(value); + setFilterErrors((prev) => ({ ...prev, project_flock: '' })); + }} + options={filterProjectFlockOptions} + onInputChange={setProjectFlockSearchValue} + isLoading={isLoadingFilterProjectFlocks} + isDisabled={!filterLocation} + className={{ wrapper: 'w-full' }} + /> + {filterErrors.project_flock && ( +

+ {filterErrors.project_flock} +

+ )} +
- +
+ { + handleFilterKandangChange(value); + setFilterErrors((prev) => ({ ...prev, kandang: '' })); + }} + options={filterKandangOptions} + isDisabled={!filterProjectFlock} + className={{ wrapper: 'w-full' }} + /> + {filterErrors.kandang && ( +

+ {filterErrors.kandang} +

+ )} +
{/* Action Buttons */} diff --git a/src/components/pages/production/uniformity/chart/UniformityBarChart.tsx b/src/components/pages/production/uniformity/chart/UniformityBarChart.tsx index 9f1f8656..88d0dc59 100644 --- a/src/components/pages/production/uniformity/chart/UniformityBarChart.tsx +++ b/src/components/pages/production/uniformity/chart/UniformityBarChart.tsx @@ -27,7 +27,8 @@ interface BarChartData { name: string; uv: number; isIdeal?: boolean; - idealCount?: number; + idealRange?: string; + outsideRange?: string; } interface UniformityBarChartProps { @@ -40,30 +41,117 @@ function CustomTooltip({ payload, label, active }: CustomTooltipProps) { const chartData = data.payload as BarChartData; const labelStr = String(label); - if (chartData.isIdeal && chartData.idealCount !== undefined) { + // If the range has both ideal and outside ranges (like 340-344) + if (chartData.idealRange && chartData.outsideRange) { + return ( +
+

Uniformity 2025

+
+
+
+
+ Ideal +
+ + {chartData.idealRange} + +
+
+
+
+ Outside +
+ + {chartData.outsideRange} + +
+
+
+ Total Birds: + {payload[0].value} +
+
+
{labelStr}
+
+
+ ); + } + + // If the range has only ideal range + if (chartData.idealRange) { return (

Uniformity 2025

- {chartData.idealCount} of Birds + Ideal
- {labelStr} + {chartData.idealRange} +
+
+
+ Birds: + {payload[0].value} +
+
+
+ {labelStr}
); } + // If the range has only outside range + if (chartData.outsideRange) { + return ( +
+

Uniformity 2025

+
+
+
+ Outside +
+ + {chartData.outsideRange} + +
+
+
+ Birds: + {payload[0].value} +
+
+
+ {labelStr} +
+
+ ); + } + + // Fallback for backward compatibility return (

Uniformity 2025

-
- {payload[0].value} of Birds +
+ + {chartData.isIdeal ? 'Ideal' : 'Outside'} + +
+ {labelStr} +
+
+
+ Birds: + {payload[0].value}
- {labelStr}
); diff --git a/src/components/pages/production/uniformity/detail/UniformityDetail.tsx b/src/components/pages/production/uniformity/detail/UniformityDetail.tsx index 4d0cd887..e8e5f1b3 100644 --- a/src/components/pages/production/uniformity/detail/UniformityDetail.tsx +++ b/src/components/pages/production/uniformity/detail/UniformityDetail.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useMemo, useEffect } from 'react'; +import { useMemo, useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { Icon } from '@iconify/react'; import { ColumnDef } from '@tanstack/react-table'; @@ -11,9 +11,12 @@ import Badge from '@/components/Badge'; import Tooltip from '@/components/Tooltip'; import RequirePermission from '@/components/helper/RequirePermission'; import { UniformityDetail as UniformityDetailType } from '@/types/api/production/uniformity'; -import { formatDate } from '@/lib/helper'; +import { formatDate, formatNumber } from '@/lib/helper'; import { useUiStore } from '@/stores/ui/ui.store'; import UniformityDetailsPreview from '@/components/pages/production/uniformity/detail/UniformityDetailsPreview'; +import { UniformityApi } from '@/services/api/uniformity'; +import useSWR from 'swr'; +import { isResponseSuccess } from '@/lib/api-helper'; import { getStatusColor, getStatusIndicatorColor, @@ -33,6 +36,22 @@ const UniformityDetail: React.FC = ({ const setExpandedDrawerContent = useUiStore( (s) => s.setExpandedDrawerContent ); + const [shouldFetchDetails, setShouldFetchDetails] = useState(false); + const [hasFetchedDetails, setHasFetchedDetails] = useState(false); + + const { data: uniformityDetailResponse, isLoading } = useSWR( + shouldFetchDetails + ? `uniformity-detail-${initialValues.id}-with-details` + : null, + () => UniformityApi.getUniformityDetail(initialValues.id, true) + ); + + const uniformity_details = useMemo(() => { + if (shouldFetchDetails && isResponseSuccess(uniformityDetailResponse)) { + return uniformityDetailResponse.data.uniformity_details; + } + return initialValues.uniformity_details; + }, [shouldFetchDetails, uniformityDetailResponse, initialValues]); const handleApprove = () => { router.push(`/production/uniformity?action=approve&id=${initialValues.id}`); @@ -43,12 +62,15 @@ const UniformityDetail: React.FC = ({ }; const handleViewUniformityDetails = () => { + if (!uniformity_details || uniformity_details.length === 0) { + setShouldFetchDetails(true); + return; + } + setExpandedDrawerContent( ); @@ -58,6 +80,28 @@ const UniformityDetail: React.FC = ({ }, 0); }; + useEffect(() => { + if ( + shouldFetchDetails && + uniformity_details && + uniformity_details.length > 0 && + !hasFetchedDetails + ) { + setExpandedDrawerContent( + + ); + + setHasFetchedDetails(true); + setTimeout(() => { + setExpandedDrawerOpen(true); + }, 0); + } + }, [shouldFetchDetails, uniformity_details, hasFetchedDetails]); + useEffect(() => { return () => { setExpandedDrawerOpen(false); @@ -154,12 +198,22 @@ const UniformityDetail: React.FC = ({ return (
{valueMap[id]} - +
@@ -173,6 +227,92 @@ const UniformityDetail: React.FC = ({ [initialValues] ); + const samplingTableData: DetailOptionType[] = useMemo(() => { + if (!initialValues.sampling) return []; + + return [ + { + id: 'sampling-size', + label: 'Sampling size', + value: `${formatNumber(initialValues.sampling.chick_qty_of_weight)} of Birds`, + }, + { + id: 'mean-weight', + label: 'Mean Weight', + value: `${initialValues.sampling.mean_weight} g`, + }, + { + id: 'min-limit', + label: 'Min Limit (-10%)', + value: `${initialValues.sampling.mean_down} g`, + }, + { + id: 'max-limit', + label: 'Max Limit (+10%)', + value: `${initialValues.sampling.mean_up} g`, + }, + ]; + }, [initialValues.sampling]); + + const columnsSampling: ColumnDef[] = useMemo( + () => [ + { + accessorKey: 'label', + header: 'Label', + cell: (props) => props.row.original.label, + }, + { + accessorKey: 'value', + header: 'Value', + cell: (props) => {props.row.original.value}, + }, + ], + [] + ); + + const resultTableData: DetailOptionType[] = useMemo(() => { + if (!initialValues.result) return []; + + return [ + { + id: 'ideal-birds', + label: 'Ideal Birds', + value: `${formatNumber(initialValues.result.uniform_qty)} of Birds`, + }, + { + id: 'outside-range', + label: 'Outside Range', + value: `${formatNumber(initialValues.result.outside_qty)} of Birds`, + }, + { + id: 'uniformity', + label: 'Uniformity', + value: `${initialValues.result.uniformity} %`, + }, + { + id: 'cv', + label: 'CV', + value: `${initialValues.result.cv} %`, + }, + ]; + }, [initialValues.result]); + + const resultColumns: ColumnDef[] = useMemo( + () => [ + { + accessorKey: 'label', + header: 'Label', + cell: (props) => props.row.original.label, + }, + { + accessorKey: 'value', + header: 'Value', + cell: (props) => {props.row.original.value}, + }, + ], + [] + ); + return (
{/* Header */} @@ -185,7 +325,7 @@ const UniformityDetail: React.FC = ({ {/* Form Section */}
-
+
{initialValues ? (
{/* Info Umum */} @@ -200,23 +340,55 @@ const UniformityDetail: React.FC = ({ paginationClassName: 'hidden', }} /> - - {/* Approve/Reject Buttons */} - {initialValues.result && - initialValues.latest_approval?.step_name === 'CREATED' ? ( - <> -
- -
- - -
-
- - ) : null}
+ + {/* Sampling and Range */} + {initialValues.sampling && ( +
+

Sampling and Range

+ + data={samplingTableData} + columns={columnsSampling} + pageSize={4} + className={{ + containerClassName: 'mb-0', + paginationClassName: 'hidden', + }} + /> +
+ )} + + {/* Result */} + {initialValues.result && ( +
+

Result

+ + data={resultTableData} + columns={resultColumns} + pageSize={4} + className={{ + containerClassName: 'mb-0', + paginationClassName: 'hidden', + }} + /> +
+ )} + + {/* Approve/Reject Buttons */} + {initialValues.result && + initialValues.latest_approval?.step_name === 'CREATED' ? ( + <> +
+ +
+ + +
+
+ + ) : null}
) : (
diff --git a/src/components/pages/production/uniformity/detail/UniformityDetailsPreview.tsx b/src/components/pages/production/uniformity/detail/UniformityDetailsPreview.tsx index 21be03d7..05d21535 100644 --- a/src/components/pages/production/uniformity/detail/UniformityDetailsPreview.tsx +++ b/src/components/pages/production/uniformity/detail/UniformityDetailsPreview.tsx @@ -1,152 +1,39 @@ 'use client'; -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { Icon } from '@iconify/react'; import { ColumnDef } from '@tanstack/react-table'; import DrawerHeader from '@/components/helper/drawer/DrawerHeader'; import { useUiStore } from '@/stores/ui/ui.store'; import { UniformityDetailItem, - UniformitySampling, - UniformityResult, UniformityInfoUmum, } from '@/types/api/production/uniformity'; import Table from '@/components/Table'; import Badge from '@/components/Badge'; -import { formatNumber } from '@/lib/helper'; -import { DetailOptionType } from '@/types/api/production/uniformity'; import { getWeightStatusColor, getWeightStatusIndicatorColor, getWeightStatusText, } from '@/components/pages/production/uniformity/uniformity-utils'; import { BodyWeightData } from '@/types/api/production/uniformity'; -import Button from '@/components/Button'; -import { UniformityApi } from '@/services/api/uniformity'; -import useSWR from 'swr'; -import { isResponseSuccess } from '@/lib/api-helper'; interface UniformityDetailsPreviewProps { info_umum: UniformityInfoUmum; - sampling: UniformitySampling; - result: UniformityResult; uniformity_details?: UniformityDetailItem[]; uniformityId: number; } const UniformityDetailsPreview = ({ info_umum, - uniformity_details: initialUniformityDetails, - sampling, - result, - uniformityId, + uniformity_details, }: UniformityDetailsPreviewProps) => { const setExpandedDrawerOpen = useUiStore((s) => s.setExpandedDrawerOpen); - const [shouldFetchDetails, setShouldFetchDetails] = useState(false); - - const { data: uniformityDetailResponse, isLoading } = useSWR( - shouldFetchDetails - ? `uniformity-detail-${uniformityId}-with-details` - : null, - () => UniformityApi.getUniformityDetail(uniformityId, true) - ); - - const uniformity_details = useMemo(() => { - if (shouldFetchDetails && isResponseSuccess(uniformityDetailResponse)) { - return uniformityDetailResponse.data.uniformity_details; - } - return initialUniformityDetails; - }, [shouldFetchDetails, uniformityDetailResponse, initialUniformityDetails]); const handleClose = () => { setExpandedDrawerOpen(false); }; - const fetchWeightData = () => { - setShouldFetchDetails(true); - }; - - const samplingTableData: DetailOptionType[] = useMemo(() => { - if (!sampling) return []; - - return [ - { - id: 'sampling-size', - label: 'Sampling size', - value: `${formatNumber(sampling.chick_qty_of_weight)} of Birds`, - }, - { - id: 'mean-weight', - label: 'Mean Weight', - value: `${sampling.mean_weight} g`, - }, - { - id: 'min-limit', - label: 'Min Limit (-10%)', - value: `${sampling.mean_down} g`, - }, - { - id: 'max-limit', - label: 'Max Limit (+10%)', - value: `${sampling.mean_up} g`, - }, - ]; - }, [sampling]); - - const columnsSampling: ColumnDef[] = useMemo( - () => [ - { - accessorKey: 'label', - header: 'Label', - cell: (props) => props.row.original.label, - }, - { - accessorKey: 'value', - header: 'Value', - cell: (props) => {props.row.original.value}, - }, - ], - [] - ); - - const resultTableData: DetailOptionType[] = useMemo(() => { - if (!result) return []; - - return [ - { - id: 'ideal-birds', - label: 'Ideal Birds', - value: `${formatNumber(result.uniform_qty)} of Birds`, - }, - { - id: 'outside-range', - label: 'Outside Range', - value: `${formatNumber(result.outside_qty)} of Birds`, - }, - { - id: 'uniformity', - label: 'Uniformity', - value: `${result.uniformity} %`, - }, - ]; - }, [result]); - - const resultColumns: ColumnDef[] = useMemo( - () => [ - { - accessorKey: 'label', - header: 'Label', - cell: (props) => props.row.original.label, - }, - { - accessorKey: 'value', - header: 'Value', - cell: (props) => {props.row.original.value}, - }, - ], - [] - ); - const tableData = useMemo(() => { if (!uniformity_details) return []; @@ -229,55 +116,10 @@ const UniformityDetailsPreview = ({ {/* Form Section */}
- {info_umum || sampling || result ? ( + {info_umum ? (
- {/* Sampling and Range */} - {sampling && ( -
-

Sampling and Range

- - data={samplingTableData} - columns={columnsSampling} - pageSize={4} - className={{ - containerClassName: 'mb-0', - paginationClassName: 'hidden', - }} - /> -
- )} - - {/* Result */} - {result && ( -
-

Result

- - data={resultTableData} - columns={resultColumns} - pageSize={4} - className={{ - containerClassName: 'mb-0', - paginationClassName: 'hidden', - }} - /> -
- )} - - {!uniformity_details || uniformity_details.length === 0 ? ( -
- -
- ) : null} - {/* Body Weight Details */} - {uniformity_details && uniformity_details.length > 0 && ( + {uniformity_details && uniformity_details.length > 0 ? (
data={tableData} @@ -286,6 +128,17 @@ const UniformityDetailsPreview = ({ className={{ containerClassName: 'mb-5' }} />
+ ) : ( +
+ +

No data available

+

Body weight details not found

+
)}
) : ( diff --git a/src/components/pages/production/uniformity/form/UniformityForm.schema.ts b/src/components/pages/production/uniformity/form/UniformityForm.schema.ts index 273e5326..037180f0 100644 --- a/src/components/pages/production/uniformity/form/UniformityForm.schema.ts +++ b/src/components/pages/production/uniformity/form/UniformityForm.schema.ts @@ -24,9 +24,9 @@ type UniformityFormSchemaType = { }; const FileSchema = Yup.mixed() - .test('documentSize', 'Ukuran file maksimal 2 MB', (value): boolean => { + .test('documentSize', 'Ukuran file maksimal 5 MB', (value): boolean => { if (!value) return true; - if (value instanceof File) return value.size <= 2 * 1024 * 1024; + if (value instanceof File) return value.size <= 5 * 1024 * 1024; return false; }) .test('documentType', 'Format file harus Excel', (value): boolean => { diff --git a/src/components/pages/production/uniformity/form/UniformityForm.tsx b/src/components/pages/production/uniformity/form/UniformityForm.tsx index bbca72f8..54b4ee2b 100644 --- a/src/components/pages/production/uniformity/form/UniformityForm.tsx +++ b/src/components/pages/production/uniformity/form/UniformityForm.tsx @@ -43,7 +43,9 @@ import UniformityResultForm from '@/components/pages/production/uniformity/form/ import { generateUniformityTemplate } from '@/components/pages/production/uniformity/export/UniformityTemplate'; import useSWR from 'swr'; import { cn, formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import Tooltip from '@/components/Tooltip'; +import AlertErrorList from '@/components/helper/form/FormErrors'; interface UniformityFormProps { formType?: 'add' | 'edit'; @@ -77,6 +79,7 @@ const UniformityForm = ({ const [uniformityFormErrorMessage, setUniformityFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const fileInputRef = useRef(null); @@ -282,6 +285,22 @@ const UniformityForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== FORM HANDLERS ===== const handleLocationChange = useCallback( (val: OptionType | OptionType[] | null) => { @@ -339,8 +358,8 @@ const UniformityForm = ({ return; } - if (document.size > 2 * 1024 * 1024) { - toast.error(`Ukuran file ${document.name} maksimal 2 MB!`); + if (document.size > 5 * 1024 * 1024) { + toast.error(`Ukuran file ${document.name} maksimal 5 MB!`); return; } @@ -454,7 +473,7 @@ const UniformityForm = ({

Informasi Umum

-
+ {uniformityFormErrorMessage && (
)} + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {formik.isSubmitting ? ( diff --git a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx index b90a7c91..2b18afee 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useFormik } from 'formik'; import { Icon } from '@iconify/react'; import { toast } from 'react-hot-toast'; @@ -14,6 +14,7 @@ import SelectInput, { useSelect, } from '@/components/input/SelectInput'; import { useRouter } from 'next/navigation'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { PurchaseRequestAcceptApprovalFormDefaultValues, @@ -28,6 +29,7 @@ import { } from '@/types/api/purchase/purchase'; import DateInput from '@/components/input/DateInput'; import { formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { Supplier } from '@/types/api/master-data/supplier'; import { SupplierApi } from '@/services/api/master-data'; @@ -52,7 +54,9 @@ const PurchaseOrderAcceptApprovalForm = ({ const searchParams = useSearchParams(); const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [key, setKey] = useState(0); + const fileInputRef = useRef(null); const isRejected = initialValues?.latest_approval?.action === 'REJECTED'; @@ -67,7 +71,6 @@ const PurchaseOrderAcceptApprovalForm = ({ | 'purchase_item_id' | 'received_date' | 'travel_number' - | 'travel_document_path' | 'vehicle_number' | 'expedition_vendor_id' | 'received_qty' @@ -180,7 +183,6 @@ const PurchaseOrderAcceptApprovalForm = ({ purchase_item_id: formItem.purchase_item_id || 0, received_date: formItem.received_date || '', travel_number: formItem.travel_number || '', - travel_document_path: formItem.travel_document_path || '', vehicle_number: formItem.vehicle_number || '', expedition_vendor_id: formItem.expedition_vendor_id || 0, received_qty: @@ -210,6 +212,22 @@ const PurchaseOrderAcceptApprovalForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== API DATA FETCHING ===== const purchaseItems = useMemo(() => { if (initialValues?.items) { @@ -235,6 +253,9 @@ const PurchaseOrderAcceptApprovalForm = ({ useEffect(() => { if (purchaseItems.length > 0 && initialValues?.items) { const updatedItems = initialValues.items.map((item) => { + const expeditionVendorId = + item.expedition_vendor_id || item.expedition_vendor?.id || 0; + return { purchase_item: null, purchase_item_id: item.id, @@ -242,7 +263,6 @@ const PurchaseOrderAcceptApprovalForm = ({ ? new Date(item.received_date).toISOString().split('T')[0] : '', travel_number: item.travel_number || '', - travel_document_path: item.travel_document_path || '', vehicle_number: item.vehicle_number || '', expedition_vendor: item.expedition_vendor ? { @@ -250,7 +270,7 @@ const PurchaseOrderAcceptApprovalForm = ({ label: item.expedition_vendor.name, } : null, - expedition_vendor_id: item.expedition_vendor_id || 0, + expedition_vendor_id: expeditionVendorId, received_qty: item.total_qty || '', transport_per_item: item.transport_per_item || '', }; @@ -259,20 +279,6 @@ const PurchaseOrderAcceptApprovalForm = ({ } }, [purchaseItems, initialValues, key]); - useEffect(() => { - if ( - formik.values.travel_documents && - formik.values.travel_documents.length > 0 - ) { - const fileNames = formik.values.travel_documents - .map((file) => file.name) - .join(', '); - formik.values.items?.forEach((item, idx) => { - formik.setFieldValue(`items.${idx}.travel_document_path`, fileNames); - }); - } - }, [formik.values.travel_documents]); - // ===== HELPER FUNCTIONS ===== const getQuantityExceededError = useCallback( (idx: number, receivedQty: number) => { @@ -349,7 +355,7 @@ const PurchaseOrderAcceptApprovalForm = ({ return (
@@ -358,6 +364,24 @@ const PurchaseOrderAcceptApprovalForm = ({ ? 'Konfirmasi Penerimaan Produk' : 'Edit Penerimaan Produk'} + {purchaseOrderFormErrorMessage && ( +
+ + {purchaseOrderFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )}
@@ -510,33 +534,6 @@ const PurchaseOrderAcceptApprovalForm = ({ }} /> -
- - formik.setFieldValue( - `items.${idx}.travel_document_path`, - e.target.value - ) - } - onBlur={formik.handleBlur} - isError={ - isRepeaterInputError(idx, 'travel_document_path') - .isError - } - errorMessage={ - isRepeaterInputError(idx, 'travel_document_path') - .errorMessage - } - placeholder='Masukkan path dokumen' - className={{ - wrapper: 'min-w-52 md:min-w-72 lg:min-w-80', - }} - /> - { const files = Array.from(e.target.files || []); + const invalidFiles = files.filter( + (file) => file.size > 5 * 1024 * 1024 + ); + + if (invalidFiles.length > 0) { + toast.error('Ukuran dokumen maksimal 5 MB!'); + e.target.value = ''; + return; + } + formik.setFieldValue('travel_documents', files); }} onBlur={formik.handleBlur} @@ -716,6 +724,10 @@ const PurchaseOrderAcceptApprovalForm = ({ onClick={() => { if (type === 'add') { formik.resetForm(); + formik.setFieldValue('travel_documents', []); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } } setPurchaseOrderFormErrorMessage(''); onCancel?.(); @@ -731,27 +743,13 @@ const PurchaseOrderAcceptApprovalForm = ({ className='px-4' isLoading={formik.isSubmitting} disabled={ - !formik.isValid || - formik.isSubmitting || - hasQuantityExceededErrors || - isRejected + formik.isSubmitting || hasQuantityExceededErrors || isRejected } > Submit - - {purchaseOrderFormErrorMessage && ( -
- - {purchaseOrderFormErrorMessage} -
- )} ); diff --git a/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts b/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts index bb70053f..a1b60249 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts +++ b/src/components/pages/purchase/form/order/PurchaseOrderForm.schema.ts @@ -38,7 +38,6 @@ type PurchaseRequestAcceptApprovalFormSchemaType = { purchase_item_id: number; received_date: string; travel_number: string; - travel_document_path: string; vehicle_number: string; expedition_vendor?: { value: number; @@ -76,7 +75,6 @@ export type PurchaseAcceptApprovalItemSchema = { purchase_item_id: number; received_date: string; travel_number: string; - travel_document_path: string; vehicle_number: string; expedition_vendor?: { value: number; @@ -185,9 +183,6 @@ const PurchaseAcceptApprovalItemObjectSchema: Yup.ObjectSchema { return { action: 'APPROVED', @@ -331,8 +327,18 @@ export const PurchaseRequestStaffApprovalFormDefaultValues = ( label: item.warehouse?.name || '', }, qty: item.sub_qty || item.qty || 0, - price: item.price, - total_price: item.total_price, + price: + type === 'add' + ? 'ProductPrice' in item.product + ? item.product.ProductPrice || item.price || '' + : item.price + : item.price, + total_price: + type === 'add' + ? ('ProductPrice' in item.product + ? item.product.ProductPrice || item.price || 0 + : item.price) * (item.sub_qty || item.qty || 0) + : item.total_price, })) : [ { @@ -381,7 +387,15 @@ export const PurchaseRequestAcceptApprovalFormSchema: Yup.ObjectSchema().required()) + .of( + Yup.mixed() + .required('Dokumen surat jalan wajib diupload!') + .test('fileSize', 'Ukuran dokumen maksimal 5 MB', (value) => { + if (!value) return true; + if (value instanceof File) return value.size <= 5 * 1024 * 1024; + return true; + }) + ) .required('Dokumen surat jalan wajib diupload!') .min(1, 'Minimal upload 1 dokumen surat jalan!') .typeError('Dokumen surat jalan wajib diupload!'), @@ -396,7 +410,6 @@ export const PurchaseRequestAcceptApprovalFormInitialValues: PurchaseRequestAcce purchase_item_id: 0, received_date: '', travel_number: '', - travel_document_path: '', vehicle_number: '', expedition_vendor_id: 0, received_qty: '', @@ -417,7 +430,6 @@ export const PurchaseRequestAcceptApprovalFormDefaultValues = ( purchase_item_id: item.id, received_date: '', travel_number: '', - travel_document_path: '', vehicle_number: '', expedition_vendor_id: 0, received_qty: '', @@ -428,7 +440,6 @@ export const PurchaseRequestAcceptApprovalFormDefaultValues = ( purchase_item_id: 0, received_date: '', travel_number: '', - travel_document_path: '', vehicle_number: '', expedition_vendor_id: 0, received_qty: '', diff --git a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx index 76d9c11d..729b6782 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx @@ -12,10 +12,12 @@ import NumberInput from '@/components/input/NumberInput'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { SupplierApi } from '@/services/api/master-data'; import { SupplierProducts } from '@/types/api/master-data/supplier'; import { isResponseSuccess } from '@/lib/api-helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { PurchaseRequestStaffApprovalFormDefaultValues, PurchaseRequestStaffApprovalFormInitialValues, @@ -87,6 +89,7 @@ const PurchaseOrderStaffApprovalForm = ({ const deleteModal = useModal(); const [purchaseOrderFormErrorMessage, setPurchaseOrderFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); const [selectedItemForDelete, setSelectedItemForDelete] = useState< number | null >(null); @@ -294,9 +297,9 @@ const PurchaseOrderStaffApprovalForm = ({ // ===== FORM CONFIGURATION ===== const formikInitialValues = useMemo(() => { return initialValues - ? PurchaseRequestStaffApprovalFormDefaultValues(initialValues) + ? PurchaseRequestStaffApprovalFormDefaultValues(initialValues, type) : PurchaseRequestStaffApprovalFormInitialValues; - }, [initialValues]); + }, [initialValues, type]); const formik = useFormik({ initialValues: formikInitialValues, @@ -415,6 +418,22 @@ const PurchaseOrderStaffApprovalForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + const supplierProductOptions = baseSupplierProductOptions; // ===== API DATA FETCHING ===== @@ -485,9 +504,18 @@ const PurchaseOrderStaffApprovalForm = ({ }, warehouse_id: purchaseItem.warehouse_id || 0, qty: originalItem?.qty || purchaseItem.quantity || 0, - price: type === 'edit' && originalItem ? originalItem.price : '', + price: + type === 'edit' && originalItem + ? originalItem.price + : originalItem?.product && 'ProductPrice' in originalItem.product + ? originalItem.product.ProductPrice || '' + : '', total_price: - type === 'edit' && originalItem ? originalItem.total_price : '', + type === 'edit' && originalItem + ? originalItem.total_price + : (originalItem?.product && 'ProductPrice' in originalItem.product + ? originalItem.product.ProductPrice || 0 + : 0) * (originalItem?.qty || purchaseItem.quantity || 0), }; return itemData; }); @@ -643,16 +671,32 @@ const PurchaseOrderStaffApprovalForm = ({ return ( <> -
+

{type === 'add' ? 'Konfirmasi Item Pembelian' : 'Edit Item Pembelian'}

+ {purchaseOrderFormErrorMessage && ( +
+ + {purchaseOrderFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} +
{groupedPurchaseItems.length > 0 ? (
@@ -1140,6 +1184,7 @@ const PurchaseOrderStaffApprovalForm = ({ color='warning' className='px-4' onClick={() => { + formik.setValues(formikInitialValues); formik.resetForm(); setPurchaseOrderFormErrorMessage(''); onCancel?.(); @@ -1154,23 +1199,12 @@ const PurchaseOrderStaffApprovalForm = ({ color='primary' className='px-4' isLoading={formik.isSubmitting} - disabled={!formik.isValid || formik.isSubmitting || isRejected} + disabled={formik.isSubmitting || isRejected} > Submit
- - {purchaseOrderFormErrorMessage && ( -
- - {purchaseOrderFormErrorMessage} -
- )}
diff --git a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx index 396ce7bb..0c319f5a 100644 --- a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx +++ b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx @@ -16,6 +16,7 @@ import SelectInput, { } from '@/components/input/SelectInput'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useModal } from '@/components/Modal'; +import AlertErrorList from '@/components/helper/form/FormErrors'; import { PurchaseRequestFormSchema, @@ -32,6 +33,7 @@ import { import { Supplier, SupplierProducts } from '@/types/api/master-data/supplier'; import { isResponseSuccess, isResponseError } from '@/lib/api-helper'; import { formatNumber } from '@/lib/helper'; +import { getUniqueFormikErrors } from '@/lib/formik-helper'; import { PurchaseApi } from '@/services/api/purchase'; import Card from '@/components/Card'; @@ -59,6 +61,7 @@ const PurchaseRequestForm = ({ ); const [purchaseRequestFormErrorMessage, setPurchaseRequestFormErrorMessage] = useState(''); + const [formErrorList, setFormErrorList] = useState([]); // ===== TYPE DEFINITIONS ===== interface ProductOptionType { @@ -211,6 +214,22 @@ const PurchaseRequestForm = ({ }, }); + const handleValidateForm = async () => { + const errors = await formik.validateForm(); + + if (Object.keys(errors).length > 0) { + const errorMessages = getUniqueFormikErrors(errors); + setFormErrorList(errorMessages); + return; + } + }; + + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault(); + handleValidateForm(); + formik.handleSubmit(e); + }; + // ===== API DATA FETCHING ===== const { data: supplierData, isLoading: isLoadingProducts } = useSWR( formik.values.supplier_id && Number(formik.values.supplier_id) > 0 @@ -487,10 +506,29 @@ const PurchaseRequestForm = ({
+ {purchaseRequestFormErrorMessage && ( +
+ + {purchaseRequestFormErrorMessage} +
+ )} + + {/* Error List Alert */} + {formErrorList.length > 0 && ( + setFormErrorList([])} + /> + )} + {/* Basic Info Card */} Submit @@ -935,17 +973,6 @@ const PurchaseRequestForm = ({ )} - - {purchaseRequestFormErrorMessage && ( -
- - {purchaseRequestFormErrorMessage} -
- )} diff --git a/src/config/constant.ts b/src/config/constant.ts index 839bcd83..f7f2255e 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -6,6 +6,64 @@ export const MAIN_DRAWER_LINKS: SidebarMenuItem[] = [ link: '/dashboard', icon: 'heroicons-outline:chart-bar-square', }, + { + text: 'Daily Checklist', + link: '/daily-checklist', + icon: 'heroicons-outline:clipboard-check', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + submenu: [ + { + text: 'Dashboard', + link: '/daily-checklist/dashboard', + icon: 'lucide:layout-dashboard', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + { + text: 'Daily Checklist', + link: '/daily-checklist/daily-checklist', + icon: 'lucide:clipboard-check', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + { + text: 'Daftar Daily Checklist', + link: '/daily-checklist/list-daily-checklist', + icon: 'lucide:circle-check', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + { + text: 'Laporan', + link: '/daily-checklist/reports', + icon: 'lucide:file-text', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + { + text: 'Master Data', + link: '/daily-checklist/master-data', + icon: 'lucide:database', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + submenu: [ + { + text: 'Employee (ABK)', + link: '/daily-checklist/master-data/employee', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + { + text: 'Aktivitas', + link: '/daily-checklist/master-data/activity', + // TODO: add permission + // permission: ['lti.daily_checklist.list'], + }, + ], + }, + ], + }, { text: 'Produksi', link: '/production', diff --git a/src/config/route-permission.ts b/src/config/route-permission.ts index 7c256795..ca720f28 100644 --- a/src/config/route-permission.ts +++ b/src/config/route-permission.ts @@ -4,6 +4,23 @@ export const ROUTE_PERMISSIONS: Record = { // Dashboard '/dashboard/': ['lti.dashboard.list'], + // Daily Checklist + // TODO: use real daily checklist permission name + // '/daily-checklist/': ['lti.daily_checklist.list'], + // '/daily-checklist/dashboard/': ['lti.daily_checklist.list'], + // '/daily-checklist/list-daily-checklist/': ['lti.daily_checklist.list'], + // '/daily-checklist/list-daily-checklist/detail/': ['lti.daily_checklist.detail'], + // '/daily-checklist/reports/': ['lti.daily_checklist.reports'], + // '/daily-checklist/master-data/employee/': ['lti.dashboard.master_data.employee'], + // '/daily-checklist/master-data/activity/': ['lti.dashboard.master_data.activity'], + '/daily-checklist/dashboard/': ['lti.dashboard.list'], + '/daily-checklist/daily-checklist/': ['lti.dashboard.list'], + '/daily-checklist/list-daily-checklist/': ['lti.dashboard.list'], + '/daily-checklist/list-daily-checklist/detail/': ['lti.dashboard.list'], + '/daily-checklist/reports/': ['lti.dashboard.list'], + '/daily-checklist/master-data/employee/': ['lti.dashboard.list'], + '/daily-checklist/master-data/activity/': ['lti.dashboard.list'], + // Production // Production - Project Flock '/production/project-flock/': ['lti.production.project_flocks.list'], diff --git a/src/figma-make/components/base/accordion.tsx b/src/figma-make/components/base/accordion.tsx new file mode 100644 index 00000000..8ee5962e --- /dev/null +++ b/src/figma-make/components/base/accordion.tsx @@ -0,0 +1,66 @@ +'use client'; + +import * as React from 'react'; +import * as AccordionPrimitive from '@radix-ui/react-accordion'; +import { ChevronDownIcon } from 'lucide-react'; + +import { cn } from '@/lib/helper'; + +function Accordion({ + ...props +}: React.ComponentProps) { + return ; +} + +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180', + className + )} + {...props} + > + {children} + + + + ); +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + +
{children}
+
+ ); +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/src/figma-make/components/base/alert-dialog.tsx b/src/figma-make/components/base/alert-dialog.tsx new file mode 100644 index 00000000..57cb4888 --- /dev/null +++ b/src/figma-make/components/base/alert-dialog.tsx @@ -0,0 +1,157 @@ +'use client'; + +import * as React from 'react'; +import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'; + +import { cn } from '@/lib/helper'; +import { buttonVariants } from '@/figma-make/components/base/button'; + +function AlertDialog({ + ...props +}: React.ComponentProps) { + return ; +} + +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + ); +} + +function AlertDialogHeader({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +}; diff --git a/src/figma-make/components/base/alert.tsx b/src/figma-make/components/base/alert.tsx new file mode 100644 index 00000000..0bf997df --- /dev/null +++ b/src/figma-make/components/base/alert.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '@/lib/helper'; + +const alertVariants = cva( + 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', + { + variants: { + variant: { + default: 'bg-card text-card-foreground', + destructive: + 'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +function Alert({ + className, + variant, + ...props +}: React.ComponentProps<'div'> & VariantProps) { + return ( +
+ ); +} + +function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +function AlertDescription({ + className, + ...props +}: React.ComponentProps<'div'>) { + return ( +
+ ); +} + +export { Alert, AlertTitle, AlertDescription }; diff --git a/src/figma-make/components/base/aspect-ratio.tsx b/src/figma-make/components/base/aspect-ratio.tsx new file mode 100644 index 00000000..f43071bd --- /dev/null +++ b/src/figma-make/components/base/aspect-ratio.tsx @@ -0,0 +1,11 @@ +'use client'; + +import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'; + +function AspectRatio({ + ...props +}: React.ComponentProps) { + return ; +} + +export { AspectRatio }; diff --git a/src/figma-make/components/base/avatar.tsx b/src/figma-make/components/base/avatar.tsx new file mode 100644 index 00000000..3f3be511 --- /dev/null +++ b/src/figma-make/components/base/avatar.tsx @@ -0,0 +1,53 @@ +'use client'; + +import * as React from 'react'; +import * as AvatarPrimitive from '@radix-ui/react-avatar'; + +import { cn } from '@/lib/helper'; + +function Avatar({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/src/figma-make/components/base/badge.tsx b/src/figma-make/components/base/badge.tsx new file mode 100644 index 00000000..32aad05e --- /dev/null +++ b/src/figma-make/components/base/badge.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { cn } from '@/lib/helper'; + +export interface BadgeProps extends React.HTMLAttributes { + variant?: 'default' | 'success' | 'secondary' | 'destructive' | 'outline'; +} + +function Badge({ className, variant = 'default', ...props }: BadgeProps) { + return ( +
+ ); +} + +export { Badge }; diff --git a/src/figma-make/components/base/breadcrumb.tsx b/src/figma-make/components/base/breadcrumb.tsx new file mode 100644 index 00000000..f1837b8d --- /dev/null +++ b/src/figma-make/components/base/breadcrumb.tsx @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { ChevronRight, MoreHorizontal } from 'lucide-react'; + +import { cn } from '@/lib/helper'; + +function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) { + return