From 2e1b0fef2b9d2ef4c087cac6826ae16e3f27fd40 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Fri, 26 Sep 2025 11:06:31 +0700 Subject: [PATCH 001/327] init --- .gitignore | 41 + README.md | 101 +- eslint.config.mjs | 25 + next.config.ts | 8 + package-lock.json | 7007 ++++++++++++++++++++++++ package.json | 40 + postcss.config.mjs | 5 + public/assets/img/lti-logo.png | Bin 0 -> 323372 bytes src/app/favicon.ico | Bin 0 -> 15406 bytes src/app/globals.css | 14 + src/app/layout.tsx | 33 + src/app/page.tsx | 7 + src/components/Button.tsx | 84 + src/components/Drawer.tsx | 60 + src/components/Navbar.tsx | 54 + src/components/Pagination.tsx | 324 ++ src/components/Table.tsx | 199 + src/components/input/FileInput.tsx | 88 + src/components/input/PasswordInput.tsx | 47 + src/components/input/SelectInput.tsx | 203 + src/components/input/TextInput.tsx | 130 + src/components/menu/Menu.tsx | 16 + src/components/menu/MenuItem.tsx | 64 + src/config/constant.ts | 0 src/lib/api-helper.ts | 7 + src/lib/helper.ts | 29 + src/lib/validation/rules.ts | 13 + src/services/api/auth.ts | 0 src/services/hooks/useAuth.tsx | 25 + src/services/http/base.ts | 22 + src/services/http/client.ts | 63 + src/stores/ui/ui.store.ts | 12 + src/types/api.d.ts | 35 + src/types/stores.d.ts | 1 + src/types/theme.d.ts | 11 + tsconfig.json | 27 + 36 files changed, 8716 insertions(+), 79 deletions(-) create mode 100644 .gitignore create mode 100644 eslint.config.mjs create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.mjs create mode 100644 public/assets/img/lti-logo.png create mode 100644 src/app/favicon.ico create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/Button.tsx create mode 100644 src/components/Drawer.tsx create mode 100644 src/components/Navbar.tsx create mode 100644 src/components/Pagination.tsx create mode 100644 src/components/Table.tsx create mode 100644 src/components/input/FileInput.tsx create mode 100644 src/components/input/PasswordInput.tsx create mode 100644 src/components/input/SelectInput.tsx create mode 100644 src/components/input/TextInput.tsx create mode 100644 src/components/menu/Menu.tsx create mode 100644 src/components/menu/MenuItem.tsx create mode 100644 src/config/constant.ts create mode 100644 src/lib/api-helper.ts create mode 100644 src/lib/helper.ts create mode 100644 src/lib/validation/rules.ts create mode 100644 src/services/api/auth.ts create mode 100644 src/services/hooks/useAuth.tsx create mode 100644 src/services/http/base.ts create mode 100644 src/services/http/client.ts create mode 100644 src/stores/ui/ui.store.ts create mode 100644 src/types/api.d.ts create mode 100644 src/types/stores.d.ts create mode 100644 src/types/theme.d.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5ef6a520 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md index e4daae0a..e215bc4c 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,36 @@ -# LTI - Client +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +## Getting Started +First, run the development server: -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.com/mbugroup/lti-client.git -git branch -M main -git push -uf origin main +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev ``` -## Integrate with your tools +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -- [ ] [Set up project integrations](https://gitlab.com/mbugroup/lti-client/-/settings/integrations) +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. -## Collaborate with your team +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/) +## Learn More -## Test and Deploy +To learn more about Next.js, take a look at the following resources: -Use the built-in continuous integration in GitLab. +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! -*** +## Deploy on Vercel -# Editing this README +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..719cea2b --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,25 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + ignores: [ + "node_modules/**", + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ], + }, +]; + +export default eslintConfig; diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 00000000..c781a8ac --- /dev/null +++ b/next.config.ts @@ -0,0 +1,8 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + output: 'export', + images: { unoptimized: true }, +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..ba8fc9b0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7007 @@ +{ + "name": "lti-web-client", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lti-web-client", + "version": "0.1.0", + "dependencies": { + "@tanstack/match-sorter-utils": "^8.19.4", + "@tanstack/react-table": "^8.21.3", + "axios": "^1.12.2", + "clsx": "^2.1.1", + "formik": "^2.4.6", + "moment": "^2.30.1", + "next": "15.5.3", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-select": "^5.10.2", + "swr": "^2.3.6", + "tailwind-merge": "^3.3.1", + "yup": "^1.7.0", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@iconify/react": "^6.0.2", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "daisyui": "^5.1.12", + "eslint": "^9", + "eslint-config-next": "15.5.3", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", + "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", + "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@iconify/react": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-6.0.2.tgz", + "integrity": "sha512-SMmC2sactfpJD427WJEDN6PMyznTFMhByK9yLW0gOTtnjzzbsi/Ke/XqsumsavFPwNiXs8jSiYeZTmLCLwO+Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", + "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.3.tgz", + "integrity": "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.3.tgz", + "integrity": "sha512-SdhaKdko6dpsSr0DldkESItVrnPYB1NS2NpShCSX5lc7SSQmLZt5Mug6t2xbiuVWEVDLZSuIAoQyYVBYp0dR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.3.tgz", + "integrity": "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.3.tgz", + "integrity": "sha512-w83w4SkOOhekJOcA5HBvHyGzgV1W/XvOfpkrxIse4uPWhYTTRwtGEM4v/jiXwNSJvfRvah0H8/uTLBKRXlef8g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.3.tgz", + "integrity": "sha512-+m7pfIs0/yvgVu26ieaKrifV8C8yiLe7jVp9SpcIzg7XmyyNE7toC1fy5IOQozmr6kWl/JONC51osih2RyoXRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.3.tgz", + "integrity": "sha512-u3PEIzuguSenoZviZJahNLgCexGFhso5mxWCrrIMdvpZn6lkME5vc/ADZG8UUk5K1uWRy4hqSFECrON6UKQBbQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.3.tgz", + "integrity": "sha512-lDtOOScYDZxI2BENN9m0pfVPJDSuUkAD1YXSvlJF0DKwZt0WlA7T7o3wrcEr4Q+iHYGzEaVuZcsIbCps4K27sA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.3.tgz", + "integrity": "sha512-9vWVUnsx9PrY2NwdVRJ4dUURAQ8Su0sLRPqcCCxtX5zIQUBES12eRVHq6b70bbfaVaxIDGJN2afHui0eDm+cLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.3.tgz", + "integrity": "sha512-1CU20FZzY9LFQigRi6jM45oJMU3KziA5/sSG+dXeVaTm661snQP6xu3ykGxxwU5sLG3sh14teO/IOEPVsQMRfA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.3.tgz", + "integrity": "sha512-JMoLAq3n3y5tKXPQwCK5c+6tmwkuFDa2XAxz8Wm4+IVthdBZdZGh+lmiLUHg9f9IDwIQpUjp+ysd6OkYTyZRZw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", + "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.5.1", + "lightningcss": "1.30.1", + "magic-string": "^0.30.18", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.13" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", + "integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.13", + "@tailwindcss/oxide-darwin-arm64": "4.1.13", + "@tailwindcss/oxide-darwin-x64": "4.1.13", + "@tailwindcss/oxide-freebsd-x64": "4.1.13", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", + "@tailwindcss/oxide-linux-x64-musl": "4.1.13", + "@tailwindcss/oxide-wasm32-wasi": "4.1.13", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", + "integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", + "integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", + "integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", + "integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", + "integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", + "integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", + "integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", + "integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", + "integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", + "integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@emnapi/wasi-threads": "^1.0.4", + "@napi-rs/wasm-runtime": "^0.2.12", + "@tybys/wasm-util": "^0.10.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", + "integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", + "integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz", + "integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.13", + "@tailwindcss/oxide": "4.1.13", + "postcss": "^8.4.41", + "tailwindcss": "4.1.13" + } + }, + "node_modules/@tanstack/match-sorter-utils": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.19.4.tgz", + "integrity": "sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==", + "license": "MIT", + "dependencies": { + "remove-accents": "0.5.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "license": "MIT", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.14.tgz", + "integrity": "sha512-gqiKWld3YIkmtrrg9zDvg9jfksZCcPywXVN7IauUGhilwGV/yOyeUsvpR796m/Jye0zUzMXPKe8Ct1B79A7N5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz", + "integrity": "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", + "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", + "integrity": "sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/type-utils": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.43.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.43.0.tgz", + "integrity": "sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.43.0.tgz", + "integrity": "sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.43.0", + "@typescript-eslint/types": "^8.43.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.43.0.tgz", + "integrity": "sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.43.0.tgz", + "integrity": "sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.43.0.tgz", + "integrity": "sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0", + "@typescript-eslint/utils": "8.43.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.43.0.tgz", + "integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.43.0.tgz", + "integrity": "sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.43.0", + "@typescript-eslint/tsconfig-utils": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/visitor-keys": "8.43.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.43.0.tgz", + "integrity": "sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.43.0", + "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/typescript-estree": "8.43.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.43.0.tgz", + "integrity": "sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.43.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/daisyui": { + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.1.12.tgz", + "integrity": "sha512-wPk6TfH6cPjYFcJIj1Zn2IYjrXLHtKbHD7GesfTDpH86d6Mgy1GTgl8mhKUqpbnVnTUNgkV7L2diPsvOGSpBIw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/saadeghi/daisyui?sponsor=1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz", + "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", + "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.35.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.3.tgz", + "integrity": "sha512-e6j+QhQFOr5pfsc8VJbuTD9xTXJaRvMHYjEeLPA2pFkheNlgPLCkxdvhxhfuM4KGcqSZj2qEnpHisdTVs3BxuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.5.3", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT", + "optional": true + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "15.5.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.3.tgz", + "integrity": "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.3", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.3", + "@next/swc-darwin-x64": "15.5.3", + "@next/swc-linux-arm64-gnu": "15.5.3", + "@next/swc-linux-arm64-musl": "15.5.3", + "@next/swc-linux-x64-gnu": "15.5.3", + "@next/swc-linux-x64-musl": "15.5.3", + "@next/swc-win32-arm64-msvc": "15.5.3", + "@next/swc-win32-x64-msvc": "15.5.3", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", + "license": "MIT" + }, + "node_modules/react-is": { + "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" + }, + "node_modules/react-select": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", + "integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", + "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.4", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.3", + "@img/sharp-darwin-x64": "0.34.3", + "@img/sharp-libvips-darwin-arm64": "1.2.0", + "@img/sharp-libvips-darwin-x64": "1.2.0", + "@img/sharp-libvips-linux-arm": "1.2.0", + "@img/sharp-libvips-linux-arm64": "1.2.0", + "@img/sharp-libvips-linux-ppc64": "1.2.0", + "@img/sharp-libvips-linux-s390x": "1.2.0", + "@img/sharp-libvips-linux-x64": "1.2.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", + "@img/sharp-libvips-linuxmusl-x64": "1.2.0", + "@img/sharp-linux-arm": "0.34.3", + "@img/sharp-linux-arm64": "0.34.3", + "@img/sharp-linux-ppc64": "0.34.3", + "@img/sharp-linux-s390x": "0.34.3", + "@img/sharp-linux-x64": "0.34.3", + "@img/sharp-linuxmusl-arm64": "0.34.3", + "@img/sharp-linuxmusl-x64": "0.34.3", + "@img/sharp-wasm32": "0.34.3", + "@img/sharp-win32-arm64": "0.34.3", + "@img/sharp-win32-ia32": "0.34.3", + "@img/sharp-win32-x64": "0.34.3" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz", + "integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/tailwind-merge": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", + "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "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/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.0.tgz", + "integrity": "sha512-VJce62dBd+JQvoc+fCVq+KZfPHr+hXaxCcVgotfwWvlR0Ja3ffYKaJBT8rptPOSKOGJDCUnW2C2JWpud7aRP6Q==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/zustand": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.8.tgz", + "integrity": "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..c88a9618 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "lti-web-client", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build --turbopack", + "start": "next start", + "lint": "eslint" + }, + "dependencies": { + "@tanstack/match-sorter-utils": "^8.19.4", + "@tanstack/react-table": "^8.21.3", + "axios": "^1.12.2", + "clsx": "^2.1.1", + "formik": "^2.4.6", + "moment": "^2.30.1", + "next": "15.5.3", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-select": "^5.10.2", + "swr": "^2.3.6", + "tailwind-merge": "^3.3.1", + "yup": "^1.7.0", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@iconify/react": "^6.0.2", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "daisyui": "^5.1.12", + "eslint": "^9", + "eslint-config-next": "15.5.3", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 00000000..c7bcb4b1 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,5 @@ +const config = { + plugins: ["@tailwindcss/postcss"], +}; + +export default config; diff --git a/public/assets/img/lti-logo.png b/public/assets/img/lti-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0e7d559179093d961a9fc37397e55ff13af35913 GIT binary patch literal 323372 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 PSa7eY_API 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
    LNdRazqnr34S#EDapXlG`>qQDI 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 Y$cQ%~ZgoNpflnahr9VkkNf-tF54NWI(f|Me literal 0 HcmV?d00001 diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..76559e5e576b4b0d377a372652c94ba9e51154ab GIT binary patch literal 15406 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 { + return ( + + + {children} + + + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 00000000..8ac3364a --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,7 @@ +export default function Home() { + return ( +
    +

    LTI ERP

    +
    + ); +} diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 00000000..79ecb6d9 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,84 @@ +import react, { JSX } from 'react'; + +import Link from 'next/link'; + +import { cn } from '@/lib/helper'; +import { Color } from '@/types/theme'; + +interface ButtonProps extends react.ComponentProps<'button'> { + variant?: 'soft' | 'outline' | 'dash' | 'ghost' | 'link' | 'active'; + color?: Color; + href?: string; + isLoading?: boolean; +} + +const Button = ({ + children, + type, + href, + variant, + color, + isLoading, + className, + disabled, + onClick, +}: ButtonProps) => { + const btnBaseClassName = cn( + 'btn', + { + 'btn-soft': variant === 'soft', + 'btn-outline': variant === 'outline', + 'btn-dash': variant === 'dash', + 'btn-ghost': variant === 'ghost', + 'btn-link': variant === 'link', + 'btn-active': variant === 'active', + + 'btn-primary': color === 'primary', + 'btn-secondary': color === 'secondary', + 'btn-accent': color === 'accent', + 'btn-neutral': color === 'neutral', + 'btn-info': color === 'info', + 'btn-success': color === 'success', + 'btn-warning': color === 'warning', + 'btn-error': color === 'error', + }, + 'h-fit justify-center items-center gap-2 rounded-xl p-2 text-base transition-all' + ); + + return ( + <> + {!href && ( + + )} + + {href && ( + + {!isLoading && children} + {isLoading && } + + )} + + ); +}; + +export default Button; diff --git a/src/components/Drawer.tsx b/src/components/Drawer.tsx new file mode 100644 index 00000000..f0efb417 --- /dev/null +++ b/src/components/Drawer.tsx @@ -0,0 +1,60 @@ +'use client'; + +import { ReactNode } from 'react'; + +import { cn } from '@/lib/helper'; + +interface DrawerProps { + children?: ReactNode; + sidebarContent?: ReactNode; + open: boolean; + setOpen: (newOpenState: boolean) => void; + openOnLarge?: boolean; +} + +const Drawer = ({ + children, + sidebarContent, + open, + setOpen, + openOnLarge, +}: DrawerProps) => { + const toggleDrawer = () => { + setOpen(!open); + }; + + const closeDrawer = () => { + setOpen(false); + }; + + return ( +
    + + +
    {children}
    + +
    +
    +
    + ); +}; + +export default Drawer; diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx new file mode 100644 index 00000000..f7cfbb6a --- /dev/null +++ b/src/components/Navbar.tsx @@ -0,0 +1,54 @@ +'use client'; + +import { Icon } from '@iconify/react'; +import Menu from '@/components/menu/Menu'; +import MenuItem from '@/components/menu/MenuItem'; +import Button from '@/components/Button'; + +interface NavbarProps { + title: string; + toggleSidebar?: () => void; +} + +const Navbar = ({ title, toggleSidebar }: NavbarProps) => { + return ( +
    +
    +
    + {toggleSidebar && ( + + )} + + {title} +
    +
    + +
    +
    +
    +
    + +
    +
    + + + + + +
    +
    +
    + ); +}; + +export default Navbar; diff --git a/src/components/Pagination.tsx b/src/components/Pagination.tsx new file mode 100644 index 00000000..0eace3f0 --- /dev/null +++ b/src/components/Pagination.tsx @@ -0,0 +1,324 @@ +'use client'; + +import { ReactNode } from 'react'; +import { Icon } from '@iconify/react'; + +import { cn } from '@/lib/helper'; + +const range = (start: number, end: number) => + Array.from({ length: end - start + 1 }, (_, i) => i + start); + +const PaginationButton = ({ + content = '', + disabled = false, + onClick = () => {}, +}: { + content?: ReactNode; + disabled?: boolean; + onClick?: () => void; +}) => ( + +); + +const EtcPaginationButton = ({ + startPage = 0, + endPage = 0, + onPageItemClick = (pageNumber: number) => {}, +}) => { + const pages = range(startPage, endPage); + + return ( + <> + {startPage > 0 && endPage >= startPage && ( +
    + + +
    +
      + {pages.map((pageNumber) => ( +
    • + onPageItemClick(pageNumber)} + /> +
    • + ))} +
    +
    +
    + )} + + {(startPage === 0 || endPage < startPage) && ( + + )} + + ); +}; + +const Pagination = ({ + currentPage = 1, + totalItems = 0, + itemsPerPage = 10, + onPageChange = (pageNumber: number) => {}, + onPrevPage = () => {}, + onNextPage = () => {}, +}) => { + const totalPages = + Math.ceil(totalItems / itemsPerPage) === 0 + ? 1 + : Math.ceil(totalItems / itemsPerPage); + + const pageChangeHandler = (pageNumber: number) => onPageChange(pageNumber); + + return ( +
    +
    + + + {totalPages <= 7 && ( +
    + {range(1, totalPages).map((pageNumber) => ( + pageChangeHandler(pageNumber)} + /> + ))} +
    + )} + + {totalPages > 7 && ( +
    + pageChangeHandler(1)} + /> + + {totalPages >= 2 && + (currentPage <= 3 || currentPage >= totalPages - 2) && ( + pageChangeHandler(2)} + /> + )} + + {totalPages >= 2 && + currentPage > 3 && + currentPage < totalPages - 2 && ( + + )} + + {totalPages >= 3 && + (currentPage <= 4 || currentPage >= totalPages - 2) && + currentPage !== totalPages - 2 && ( + pageChangeHandler(3)} + /> + )} + + {totalPages >= 7 && + (currentPage <= 2 || currentPage >= totalPages - 2) && ( + = totalPages - 1 + ? 4 + : 1 + } + endPage={ + currentPage <= 2 || currentPage >= totalPages - 1 + ? totalPages - 3 + : currentPage === totalPages - 2 + ? totalPages - 4 + : 2 + } + onPageItemClick={pageChangeHandler} + /> + )} + + {totalPages >= 3 && + currentPage > 4 && + currentPage < totalPages - 1 && ( + pageChangeHandler(currentPage - 1)} + /> + )} + + {totalPages >= 7 && + currentPage > 3 && + currentPage < totalPages - 2 && ( + + )} + + {totalPages >= 5 && + currentPage > 2 && + currentPage < totalPages - 2 && ( + pageChangeHandler(currentPage + 1)} + /> + )} + + {totalPages >= 5 && + (currentPage <= 2 || currentPage >= totalPages - 2) && ( + pageChangeHandler(totalPages - 2)} + /> + )} + + {totalPages >= 6 && + currentPage > 2 && + currentPage < totalPages - 3 && ( + = 4 + ? currentPage + 2 + : 1 + } + endPage={ + currentPage <= 3 + ? totalPages - 2 + : currentPage >= 4 + ? totalPages - 1 + : 0 + } + onPageItemClick={pageChangeHandler} + /> + )} + + {totalPages >= 6 && + (currentPage <= 3 || currentPage >= totalPages - 3) && ( + pageChangeHandler(totalPages - 1)} + /> + )} + + {totalPages >= 7 && ( + pageChangeHandler(totalPages)} + /> + )} +
    + )} + + +
    + +
    + + + +
    +
    + ); +}; + +export default Pagination; diff --git a/src/components/Table.tsx b/src/components/Table.tsx new file mode 100644 index 00000000..53665386 --- /dev/null +++ b/src/components/Table.tsx @@ -0,0 +1,199 @@ +'use client'; + +import { useState } from 'react'; +import { + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + TableOptions, + useReactTable, + ColumnDef, +} from '@tanstack/react-table'; +import { rankItem } from '@tanstack/match-sorter-utils'; +import { Icon } from '@iconify/react'; + +import Pagination from '@/components/Pagination'; +import { cn } from '@/lib/helper'; + +interface TableClassNames { + containerClassName?: string; + tableWrapperClassName?: string; + tableClassName?: string; + tableHeaderClassName?: string; + headerRowClassName?: string; + headerColumnClassName?: string; + tableBodyClassName?: string; + bodyRowClassName?: string; + bodyColumnClassName?: string; + paginationClassName?: string; +} + +// Type for the Table component props +interface TableProps { + data: TData[]; + columns: ColumnDef[]; + pageSize?: number; + isLoading?: boolean; + fuzzySearchValue?: string | null; + onFuzzySearchValueChange?: (value: string) => void; + className?: TableClassNames; +} + +const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; + +const fuzzyFilter = ( + row: any, + columnId: string, + value: string, + addMeta: (meta: any) => void +) => { + const itemRank = rankItem(row.getValue(columnId), value); + addMeta({ itemRank }); + return itemRank.passed; +}; + +const Table = ({ + data = [], + columns = [], + pageSize = 10, + isLoading = false, + fuzzySearchValue = null, + onFuzzySearchValueChange = () => {}, + className = { + containerClassName: '', + tableWrapperClassName: '', + tableClassName: '', + tableHeaderClassName: '', + headerRowClassName: '', + headerColumnClassName: '', + tableBodyClassName: '', + bodyRowClassName: '', + bodyColumnClassName: '', + paginationClassName: '', + }, +}: TableProps) => { + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: pageSize, + }); + + const tableOptions: TableOptions = { + columns, + data: isLoading ? (DUMMY_SKELETON_DATA as TData[]) : data, // Type assertion + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onPaginationChange: setPagination, + state: { + pagination, + globalFilter: fuzzySearchValue, + }, + filterFns: { + fuzzy: fuzzyFilter, + }, + globalFilterFn: fuzzyFilter, + }; + + if (fuzzySearchValue !== null) { + tableOptions.onGlobalFilterChange = onFuzzySearchValueChange; + tableOptions.getFilteredRowModel = getFilteredRowModel(); + } + + const table = useReactTable(tableOptions); + + return ( +
    +
    + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + +
    +
    + {flexRender( + header.column.columnDef.header, + header.getContext() + )} + + {header.column.getCanSort() && ( +
    + + +
    + )} +
    +
    + {!isLoading && + flexRender(cell.column.columnDef.cell, cell.getContext())} + + {isLoading &&
    } +
    +
    + + {data.length > 0 && !isLoading && ( +
    + table.previousPage()} + onNextPage={() => table.nextPage()} + onPageChange={(pageNumber) => + table.setPageIndex(pageNumber ? pageNumber - 1 : 0) + } + /> +
    + )} +
    + ); +}; + +export default Table; diff --git a/src/components/input/FileInput.tsx b/src/components/input/FileInput.tsx new file mode 100644 index 00000000..6218970c --- /dev/null +++ b/src/components/input/FileInput.tsx @@ -0,0 +1,88 @@ +import { Ref } from 'react'; + +import { cn } from '@/lib/helper'; +import { TextInputProps } from '@/components/input/TextInput'; + +interface FileInputProps + extends Omit< + TextInputProps, + | 'type' + | 'value' + | 'isValid' + | 'startAdornment' + | 'endAdornment' + | 'isLoading' + > { + ref?: Ref; + accept?: string; + className?: { + wrapper?: string; + label?: string; + input?: string; + }; +} + +const FileInput = ({ + ref, + label, + bottomLabel, + name, + placeholder, + accept = '*', + className, + isError, + errorMessage, + disabled = false, + onChange, + onBlur, + readOnly = false, +}: FileInputProps) => { + return ( +
    + {label && ( + + )} + + + + {bottomLabel && ( +

    {bottomLabel}

    + )} + + {isError &&

    {errorMessage}

    } +
    + ); +}; + +export default FileInput; diff --git a/src/components/input/PasswordInput.tsx b/src/components/input/PasswordInput.tsx new file mode 100644 index 00000000..993915fc --- /dev/null +++ b/src/components/input/PasswordInput.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useState } from 'react'; + +import { Icon } from '@iconify/react'; +import TextInput, { TextInputProps } from '@/components/input/TextInput'; +import Button from '@/components/Button'; + +interface PasswordInputProps + extends Omit {} + +const PasswordInput = (props: PasswordInputProps) => { + const [type, setType] = useState('password'); + + const showPasswordHandler = () => { + setType((prevType) => { + if (prevType === 'password') return 'text'; + + return 'password'; + }); + }; + + return ( + + + + } + /> + ); +}; + +export default PasswordInput; diff --git a/src/components/input/SelectInput.tsx b/src/components/input/SelectInput.tsx new file mode 100644 index 00000000..5b6ae098 --- /dev/null +++ b/src/components/input/SelectInput.tsx @@ -0,0 +1,203 @@ +'use client'; + +import { ComponentType, ReactNode, useMemo } from 'react'; +import Select, { OptionProps, GroupBase } from 'react-select'; +import makeAnimated from 'react-select/animated'; + +import { cn } from '@/lib/helper'; + +export interface OptionType { + value: string | number; + label: string; + className?: string; // for multi select + labelClassName?: string; // for multi select +} + +export type OptionComponent = ComponentType< + OptionProps> +>; + +interface SelectInputProps { + label?: ReactNode; + bottomLabel?: ReactNode; + value?: T | T[]; + onChange?: (val: T | T[] | null) => void; + options: T[]; + optionComponent?: OptionComponent; + isDisabled?: boolean; + isLoading?: boolean; + isClearable?: boolean; + isRtl?: boolean; + isSearchable?: boolean; + isMulti?: boolean; + placeholder?: string; + required?: boolean; + className?: { + wrapper?: string; + label?: string; + select?: string; + }; + isError?: boolean; + errorMessage?: string; + isAnimated?: boolean; + openMenu?: boolean; +} + +const animatedComponents = makeAnimated(); + +const SelectInput = ({ + label, + bottomLabel, + value, + onChange, + options, + optionComponent, + isDisabled, + isLoading, + isClearable, + isRtl, + isSearchable = true, + isMulti, + placeholder, + required, + className, + isError, + errorMessage, + isAnimated = true, + openMenu, +}: SelectInputProps) => { + const components = useMemo(() => { + const base = isAnimated ? animatedComponents : {}; + + return { + ...base, + IndicatorSeparator: () => null, + }; + }, [isAnimated]); + + return ( +
    + {label && ( + + {label} + {required && ( + <> + {' '} + + * + + + )} + + )} + + + + {(isLoading || endAdornment) && ( +
    + {isLoading && } + + {endAdornment && endAdornment} +
    + )} +
    + + {!isError && bottomLabel && ( +

    {bottomLabel}

    + )} + {isError &&

    {errorMessage}

    } + + ); +}; + +export default TextInput; diff --git a/src/components/menu/Menu.tsx b/src/components/menu/Menu.tsx new file mode 100644 index 00000000..b3981065 --- /dev/null +++ b/src/components/menu/Menu.tsx @@ -0,0 +1,16 @@ +import { ReactNode } from 'react'; + +import { cn } from '@/lib/helper'; + +interface MenuProps { + children?: ReactNode; + className?: string; +} + +const Menu = ({ children, className }: MenuProps) => { + return ( +
      {children}
    + ); +}; + +export default Menu; diff --git a/src/components/menu/MenuItem.tsx b/src/components/menu/MenuItem.tsx new file mode 100644 index 00000000..55206d20 --- /dev/null +++ b/src/components/menu/MenuItem.tsx @@ -0,0 +1,64 @@ +import Link from 'next/link'; +import { Icon } from '@iconify/react'; + +import { cn } from '@/lib/helper'; + +interface MenuItemProps { + title: string; + href?: string; + icon?: string; + active?: boolean; + onClick?: () => void; + className?: string; +} + +const MenuItem = ({ + title, + href, + icon, + active = false, + className, + onClick, +}: MenuItemProps) => { + const menuItemBaseClassName = cn( + 'group px-3 py-2 text-base text-black font-semibold flex flex-row items-center rounded-md', + { 'bg-gray-100 border-l-2 border-l-primary': active }, + className + ); + + const menuItemContent = ( + <> + {icon && ( + + )} + + + {title} + + + ); + + return ( +
  1. + {href && ( + + {menuItemContent} + + )} + + {!href && {menuItemContent}} +
  2. + ); +}; + +export default MenuItem; diff --git a/src/config/constant.ts b/src/config/constant.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/api-helper.ts b/src/lib/api-helper.ts new file mode 100644 index 00000000..3e85ecf0 --- /dev/null +++ b/src/lib/api-helper.ts @@ -0,0 +1,7 @@ +import { BaseApiResponse, SuccessApiResponse } from '@/types/api'; + +export const isResponseSuccess = ( + res?: BaseApiResponse +): res is SuccessApiResponse => { + return res?.status === 'success'; +}; diff --git a/src/lib/helper.ts b/src/lib/helper.ts new file mode 100644 index 00000000..d85b7b16 --- /dev/null +++ b/src/lib/helper.ts @@ -0,0 +1,29 @@ +import moment from 'moment'; +import { twMerge } from 'tailwind-merge'; +import clsx, { ClassValue } from 'clsx'; + +export const sleep = (ms: number = 1000) => + new Promise((resolve) => setTimeout(resolve, ms)); + +export const formatDate = (date: moment.MomentInput, format?: string) => { + return moment(date).format(format); +}; + +export const cn = (...inputs: ClassValue[]) => { + return twMerge(clsx(inputs)); +}; + +export const formatCurrency = ( + value: number | bigint | Intl.StringNumericLiteral, + currency = 'USD', + locale = 'en-US', + minimumFractionDigits = 0, + maximumFractionDigits = 2 +) => { + return new Intl.NumberFormat(locale, { + style: 'currency', + currency, + minimumFractionDigits, + maximumFractionDigits, + }).format(value); +}; diff --git a/src/lib/validation/rules.ts b/src/lib/validation/rules.ts new file mode 100644 index 00000000..34a72a64 --- /dev/null +++ b/src/lib/validation/rules.ts @@ -0,0 +1,13 @@ +import * as Yup from 'yup'; + +export const EmailSchema = Yup.string().email('Format email invalid!'); + +export const PasswordSchema = Yup.string() + .min(8, 'Password harus setidaknya memiliki 8 karakter') + .matches(/[a-z]/, 'Harus memiliki setidaknya 1 huruf kecil') + .matches(/[A-Z]/, 'Harus memiliki setidaknya 1 huruf besar') + .matches(/\d/, 'Harus memiliki setidaknya 1 angka') + .matches( + /[@$!%*?&^#()_\-+={}[\]|:;"'<>,.\\/]/, + 'Harus memiliki setidaknya 1 karakter spesial' + ); diff --git a/src/services/api/auth.ts b/src/services/api/auth.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/services/hooks/useAuth.tsx b/src/services/hooks/useAuth.tsx new file mode 100644 index 00000000..012badfa --- /dev/null +++ b/src/services/hooks/useAuth.tsx @@ -0,0 +1,25 @@ +import { create } from 'zustand'; +import { UserWithRoles } from '@/types/api'; + +type AuthStore = { + user?: UserWithRoles; + isLoadingUser?: boolean; + setUser: (newUserData?: UserWithRoles) => void; + setIsLoadingUser: (isLoading?: boolean) => void; +}; + +const useAuthStore = create()((set) => ({ + user: undefined, + isLoadingUser: false, + setUser: (newUserData) => set({ user: newUserData }), + setIsLoadingUser: (isLoading) => set({ isLoadingUser: Boolean(isLoading) }), +})); + +export const useAuth = () => { + const { user, setUser } = useAuthStore(); + + return { + user, + setUser, + }; +}; diff --git a/src/services/http/base.ts b/src/services/http/base.ts new file mode 100644 index 00000000..83bb5ee6 --- /dev/null +++ b/src/services/http/base.ts @@ -0,0 +1,22 @@ +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; +export type AuthMode = 'none' | 'cookie' | 'bearer'; + +export type RequestOptions = { + method?: HttpMethod; + body?: B; + query?: Record; + headers?: Record; + auth?: AuthMode; // 'cookie' | 'bearer' | 'none' + token?: string; // required if auth === 'bearer' + timeoutMs?: number; +}; + +export class HttpError extends Error { + constructor( + public status: number, + public code?: string, + public data?: unknown + ) { + super(`HTTP ${status}${code ? ` ${code}` : ''}`); + } +} diff --git a/src/services/http/client.ts b/src/services/http/client.ts new file mode 100644 index 00000000..29ffc6db --- /dev/null +++ b/src/services/http/client.ts @@ -0,0 +1,63 @@ +import axios from 'axios'; +import type { AxiosRequestConfig } from 'axios'; +import { HttpError, RequestOptions } from '@/services/http/base'; + +const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ''; +const axiosClient = axios.create({ baseURL: BASE_URL, timeout: 10_000 }); + +export async function httpClient( + path: string, + opts: RequestOptions = {} +): Promise { + const isCookieAuth = opts.auth === 'cookie'; + const isBearerAuth = opts.auth === 'bearer' && !!opts.token; + + const config: AxiosRequestConfig = { + url: path, + method: opts.method ?? 'GET', + params: opts.query, + data: opts.body, + timeout: opts.timeoutMs ?? 10_000, + withCredentials: isCookieAuth, + headers: { + 'Content-Type': 'application/json', + ...(opts.headers ?? {}), + ...(isBearerAuth ? { Authorization: `Bearer ${opts.token}` } : {}), + }, + }; + + try { + const res = await axiosClient.request(config); + return res.data; + } catch (e: any) { + if (axios.isAxiosError(e)) { + throw e; + } + + throw new HttpError(e.response?.status ?? 0, e.code, e.response?.data); + } +} + +type SWRHttpKey = + | string + | [path: string, opts?: RequestOptions] + | { path: string; opts?: RequestOptions }; + +export async function httpClientFetcher( + key: SWRHttpKey +): Promise { + if (!key) throw new Error('Invalid SWR key'); + + let path: string; + let opts: RequestOptions | undefined; + + if (typeof key === 'string') { + path = key; + } else if (Array.isArray(key)) { + [path, opts] = key; + } else { + ({ path, opts } = key); + } + + return httpClient(path, opts); +} diff --git a/src/stores/ui/ui.store.ts b/src/stores/ui/ui.store.ts new file mode 100644 index 00000000..86016974 --- /dev/null +++ b/src/stores/ui/ui.store.ts @@ -0,0 +1,12 @@ +'use client'; + +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; + +import { UIStore } from '@/types/stores'; + +export const useUiStore = create()( + devtools((...args) => ({}), { + name: 'UIStore', + }) +); diff --git a/src/types/api.d.ts b/src/types/api.d.ts new file mode 100644 index 00000000..1ae9f613 --- /dev/null +++ b/src/types/api.d.ts @@ -0,0 +1,35 @@ +type ErrorApiResponse = { + code: number; + status: 'error'; + message: string; + errors?: { [key: string]: string }; +}; + +type SuccessApiResponse = { + code: number; + status: 'success'; + message: string; + meta?: { + page: number; + limit: number; + total_pages: number; + total_results: number; + }; + data: T; +}; + +type BaseApiResponse = ErrorApiResponse | SuccessApiResponse; + +export type User = { + id: number; + email: string; + npk: string; + name: string; + image?: string | null; + created_at: string; + updated_at: string; +}; + +export type UserWithRoles = User & { + roles: RoleWithPermissions[]; +}; diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts new file mode 100644 index 00000000..08900862 --- /dev/null +++ b/src/types/stores.d.ts @@ -0,0 +1 @@ +export type UIStore = {}; diff --git a/src/types/theme.d.ts b/src/types/theme.d.ts new file mode 100644 index 00000000..cff880fd --- /dev/null +++ b/src/types/theme.d.ts @@ -0,0 +1,11 @@ +type Color = + | 'primary' + | 'secondary' + | 'accent' + | 'neutral' + | 'info' + | 'success' + | 'warning' + | 'error'; + +export { Color }; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..c1334095 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} From f127e16c7cfc12cfb5eaccb11124296123c1907c Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Fri, 26 Sep 2025 11:36:53 +0700 Subject: [PATCH 002/327] chore: change copywriting --- src/app/layout.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 20654194..793f0b93 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -14,8 +14,8 @@ export const viewport: Viewport = { }; export const metadata: Metadata = { - title: 'Single Sign-On MBU Group', - description: 'Single Sign-On MBU', + title: 'LTI', + description: 'PT. Lumbung Telur Indonesia', }; export default function RootLayout({ From 7e57debb987d8a23079ca1b3546fb3177ebe6033 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 29 Sep 2025 11:58:19 +0700 Subject: [PATCH 003/327] chore: update MenuItem component --- src/components/menu/MenuItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/menu/MenuItem.tsx b/src/components/menu/MenuItem.tsx index 55206d20..5046f8ff 100644 --- a/src/components/menu/MenuItem.tsx +++ b/src/components/menu/MenuItem.tsx @@ -33,7 +33,7 @@ const MenuItem = ({ icon={icon} width={20} height={20} - className={cn({ + className={cn('group-active:text-[inherit]', { 'text-gray-400': !active, 'text-black': active, })} From 978285021e1a19d13c03be28f8642550ed2637d1 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 29 Sep 2025 11:58:57 +0700 Subject: [PATCH 004/327] feat: add Collapse component --- src/components/Collapse.tsx | 132 ++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/components/Collapse.tsx diff --git a/src/components/Collapse.tsx b/src/components/Collapse.tsx new file mode 100644 index 00000000..d076888d --- /dev/null +++ b/src/components/Collapse.tsx @@ -0,0 +1,132 @@ +import React, { useCallback, useId, useMemo, useState } from 'react'; +import { cn } from '@/lib/helper'; + +export type CollapseVariant = 'default' | 'arrow' | 'plus'; + +export type CollapseProps = { + /** Unique name used when `asRadio` is true (Accordion single-open). */ + name?: string; + /** If provided, component is controlled. */ + open?: boolean; + /** Initial open state for uncontrolled usage. */ + defaultOpen?: boolean; + /** Callback when open state changes. */ + onOpenChange?: (open: boolean) => void; + /** Title row content. Accepts string or custom node. */ + title?: React.ReactNode; + /** Optional secondary text displayed under/next to title. */ + subtitle?: React.ReactNode; + /** Content of the panel. */ + children?: React.ReactNode; + /** Visual variant: default / arrow / plus */ + variant?: CollapseVariant; + /** Add a bordered look */ + bordered?: boolean; + /** Disable interactions */ + disabled?: boolean; + /** Allow only one open at a time by switching to radio input */ + asRadio?: boolean; + /** Extra classnames */ + className?: string; + titleClassName?: string; + contentClassName?: string; +}; + +export const Collapse = ({ + name, + open, + defaultOpen, + onOpenChange, + title, + subtitle, + children, + variant = 'default', + bordered, + disabled, + asRadio = false, + className, + titleClassName, + contentClassName, +}: CollapseProps) => { + const inputId = useId(); + const isControlled = typeof open === 'boolean'; + const [internalOpen, setInternalOpen] = useState(!!defaultOpen); + const isOpen = isControlled ? !!open : internalOpen; + + // Manage change from checkbox/radio + const handleChange = useCallback( + (next: boolean) => { + if (!isControlled) setInternalOpen(next); + onOpenChange?.(next); + }, + [isControlled, onOpenChange] + ); + + const inputType = asRadio ? 'radio' : 'checkbox'; + + const rootClass = cn( + 'collapse', + variant === 'arrow' && 'collapse-arrow', + variant === 'plus' && 'collapse-plus', + bordered && 'border base-content/20 border-opacity-20 rounded-box', + disabled && 'opacity-60 pointer-events-none', + className + ); + + const titleNode = useMemo(() => { + if (subtitle) { + return ( +
    + {title} + {subtitle} +
    + ); + } + return
    {title}
    ; + }, [title, subtitle]); + + return ( +
    + handleChange(e.currentTarget.checked)} + aria-expanded={isOpen} + aria-controls={`${inputId}-content`} + disabled={disabled} + /> + +
    { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + handleChange(!isOpen); + } + }} + onClick={() => handleChange(!isOpen)} + > + {titleNode} +
    + +
    + {children} +
    +
    + ); +}; + +export default Collapse; From 02c44ced92bf5f041226bb5e7d52c7a61a5aa7ca Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 11:25:38 +0700 Subject: [PATCH 005/327] chore: update Collapse component --- src/components/Collapse.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/Collapse.tsx b/src/components/Collapse.tsx index d076888d..4007cae0 100644 --- a/src/components/Collapse.tsx +++ b/src/components/Collapse.tsx @@ -92,10 +92,8 @@ export const Collapse = ({ type={inputType} name={asRadio ? name : undefined} className='peer p-0 hidden' - checked={isControlled ? isOpen : undefined} - defaultChecked={!isControlled ? isOpen : undefined} + checked={isOpen} onChange={(e) => handleChange(e.currentTarget.checked)} - aria-expanded={isOpen} aria-controls={`${inputId}-content`} disabled={disabled} /> From 33f5ca2a578dfe01a0f28821f5ddacff9adbd776 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:33:57 +0700 Subject: [PATCH 006/327] chore: update Table component --- src/components/Table.tsx | 81 +++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 53665386..97f767aa 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { ReactNode, useState } from 'react'; import { flexRender, getCoreRowModel, @@ -30,15 +30,18 @@ interface TableClassNames { paginationClassName?: string; } -// Type for the Table component props -interface TableProps { +export interface TableProps { data: TData[]; columns: ColumnDef[]; pageSize?: number; + totalItems?: number; + page?: number; + onPageChange?: (page: number) => void; isLoading?: boolean; fuzzySearchValue?: string | null; onFuzzySearchValueChange?: (value: string) => void; className?: TableClassNames; + emptyContent?: ReactNode; } const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; @@ -54,13 +57,24 @@ const fuzzyFilter = ( return itemRank.passed; }; +const emptyContentDefaultValue = ( +
    + + Tidak ada data yang dapat ditampilkan... + +
    +); + const Table = ({ data = [], columns = [], pageSize = 10, + totalItems, + page, + onPageChange, isLoading = false, - fuzzySearchValue = null, - onFuzzySearchValueChange = () => {}, + fuzzySearchValue, + onFuzzySearchValueChange, className = { containerClassName: '', tableWrapperClassName: '', @@ -73,7 +87,13 @@ const Table = ({ bodyColumnClassName: '', paginationClassName: '', }, + emptyContent = emptyContentDefaultValue, }: TableProps) => { + const isServerSideTable = + totalItems !== undefined && + page !== undefined && + onPageChange !== undefined; + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: pageSize, @@ -103,6 +123,32 @@ const Table = ({ const table = useReactTable(tableOptions); + const prevPageClickHandler = () => { + table.previousPage(); + + if (isServerSideTable) { + onPageChange(page - 1); + } + }; + + const nextPageClickHandler = () => { + table.nextPage(); + + if (isServerSideTable) { + onPageChange(page + 1); + } + }; + + const pageChangeHandler = (pageNumber: number) => { + const currentPage = pageNumber - 1; + + table.setPageIndex(pageNumber ? currentPage : 0); + + if (isServerSideTable) { + onPageChange(pageNumber); + } + }; + return (
    @@ -178,17 +224,26 @@ const Table = ({
    - {data.length > 0 && !isLoading && ( + {(data.length === 0 || table.getRowModel().rows.length === 0) && + emptyContent} + + {data.length > 0 && table.getRowModel().rows.length > 0 && !isLoading && (
    table.previousPage()} - onNextPage={() => table.nextPage()} - onPageChange={(pageNumber) => - table.setPageIndex(pageNumber ? pageNumber - 1 : 0) + totalItems={isServerSideTable ? totalItems : table.getRowCount()} + itemsPerPage={ + isServerSideTable + ? undefined + : table.getState().pagination.pageSize } + currentPage={ + isServerSideTable + ? page + : table.getState().pagination.pageIndex + 1 + } + onPrevPage={prevPageClickHandler} + onNextPage={nextPageClickHandler} + onPageChange={pageChangeHandler} />
    )} From 691b49a9025cc2e41bc0b6656bc6b4c79766de03 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:42:03 +0700 Subject: [PATCH 007/327] chore: update Table component --- src/components/Table.tsx | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 97f767aa..e20d4d11 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ReactNode, useState } from 'react'; +import { ReactNode, useCallback, useState } from 'react'; import { flexRender, getCoreRowModel, @@ -10,6 +10,7 @@ import { TableOptions, useReactTable, ColumnDef, + FilterFn, } from '@tanstack/react-table'; import { rankItem } from '@tanstack/match-sorter-utils'; import { Icon } from '@iconify/react'; @@ -32,7 +33,7 @@ interface TableClassNames { export interface TableProps { data: TData[]; - columns: ColumnDef[]; + columns: ColumnDef[]; pageSize?: number; totalItems?: number; page?: number; @@ -46,17 +47,6 @@ export interface TableProps { const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; -const fuzzyFilter = ( - row: any, - columnId: string, - value: string, - addMeta: (meta: any) => void -) => { - const itemRank = rankItem(row.getValue(columnId), value); - addMeta({ itemRank }); - return itemRank.passed; -}; - const emptyContentDefaultValue = (
    @@ -99,6 +89,15 @@ const Table = ({ pageSize: pageSize, }); + const fuzzyFilter: FilterFn = useCallback( + (row, columnId, value, addMeta) => { + const itemRank = rankItem(row.getValue(columnId), value); + addMeta({ itemRank }); + return itemRank.passed; + }, + [] + ); + const tableOptions: TableOptions = { columns, data: isLoading ? (DUMMY_SKELETON_DATA as TData[]) : data, // Type assertion @@ -231,11 +230,7 @@ const Table = ({
    Date: Tue, 30 Sep 2025 15:42:25 +0700 Subject: [PATCH 008/327] chore: update Pagination component --- src/components/Pagination.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/Pagination.tsx b/src/components/Pagination.tsx index 0eace3f0..86d3a67a 100644 --- a/src/components/Pagination.tsx +++ b/src/components/Pagination.tsx @@ -32,7 +32,11 @@ const PaginationButton = ({ const EtcPaginationButton = ({ startPage = 0, endPage = 0, - onPageItemClick = (pageNumber: number) => {}, + onPageItemClick, +}: { + startPage: number; + endPage: number; + onPageItemClick: (a: number) => void; }) => { const pages = range(startPage, endPage); @@ -86,9 +90,16 @@ const Pagination = ({ currentPage = 1, totalItems = 0, itemsPerPage = 10, - onPageChange = (pageNumber: number) => {}, + onPageChange, onPrevPage = () => {}, onNextPage = () => {}, +}: { + currentPage: number; + totalItems: number; + itemsPerPage: number; + onPageChange: (pageNumber: number) => void; + onPrevPage: () => void; + onNextPage: () => void; }) => { const totalPages = Math.ceil(totalItems / itemsPerPage) === 0 From 8e23a805a9824c4cf4c35fa2bdce9e206ccb38b8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:43:04 +0700 Subject: [PATCH 009/327] chore: update Button component --- src/components/Button.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 79ecb6d9..a74a7e4f 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,4 +1,4 @@ -import react, { JSX } from 'react'; +import react from 'react'; import Link from 'next/link'; @@ -17,11 +17,12 @@ const Button = ({ type, href, variant, - color, + color = 'primary', isLoading, className, disabled, onClick, + ...props }: ButtonProps) => { const btnBaseClassName = cn( 'btn', @@ -49,6 +50,7 @@ const Button = ({ <> {!href && ( )} From a364a860fa5dc0ba4cfa1d224419fe5e8ba8e126 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:43:48 +0700 Subject: [PATCH 010/327] chore: update PasswordInput component --- src/components/input/PasswordInput.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/input/PasswordInput.tsx b/src/components/input/PasswordInput.tsx index 993915fc..86be59d7 100644 --- a/src/components/input/PasswordInput.tsx +++ b/src/components/input/PasswordInput.tsx @@ -6,8 +6,10 @@ import { Icon } from '@iconify/react'; import TextInput, { TextInputProps } from '@/components/input/TextInput'; import Button from '@/components/Button'; -interface PasswordInputProps - extends Omit {} +type PasswordInputProps = Omit< + TextInputProps, + 'type' | 'startAdornment' | 'endAdornment' +>; const PasswordInput = (props: PasswordInputProps) => { const [type, setType] = useState('password'); From 3be69eeff82dcb39cb6fda0aa484d903fb6e8b5e Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:44:48 +0700 Subject: [PATCH 011/327] fix: error type --- src/services/http/client.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/services/http/client.ts b/src/services/http/client.ts index 29ffc6db..1a898e13 100644 --- a/src/services/http/client.ts +++ b/src/services/http/client.ts @@ -1,6 +1,6 @@ import axios from 'axios'; import type { AxiosRequestConfig } from 'axios'; -import { HttpError, RequestOptions } from '@/services/http/base'; +import { RequestOptions } from '@/services/http/base'; const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ''; const axiosClient = axios.create({ baseURL: BASE_URL, timeout: 10_000 }); @@ -29,12 +29,8 @@ export async function httpClient( try { const res = await axiosClient.request(config); return res.data; - } catch (e: any) { - if (axios.isAxiosError(e)) { - throw e; - } - - throw new HttpError(e.response?.status ?? 0, e.code, e.response?.data); + } catch (e: unknown) { + throw e; } } From 037e4776a8af78da3d1f9a41c7fc95ae0d80cb32 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Sep 2025 15:45:33 +0700 Subject: [PATCH 012/327] chore: run eslint command in dev command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c88a9618..93fd5b8d 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --turbopack", + "dev": "eslint && next dev --turbopack", "build": "next build --turbopack", "start": "next start", "lint": "eslint" From 19b7c53ec2a5343a8492bc1ca66901a293331331 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:44:02 +0700 Subject: [PATCH 013/327] feat(FE-40): use MainDrawer component in root layout --- src/app/layout.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 793f0b93..9d807425 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata, Viewport } from 'next'; import { Inter } from 'next/font/google'; -import './globals.css'; +import '@/app/globals.css'; +import MainDrawer from '@/components/MainDrawer'; const inter = Inter({ variable: '--font-inter', @@ -26,7 +27,7 @@ export default function RootLayout({ return ( - {children} + {children} ); From c068fe51665c3a36056714d41951757880a7ef2d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:44:18 +0700 Subject: [PATCH 014/327] feat(FE-40): redirect to /dashboard --- src/app/page.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/page.tsx b/src/app/page.tsx index 8ac3364a..db9638df 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,8 @@ +import { redirect } from 'next/navigation'; + export default function Home() { + redirect('/dashboard'); + return (

    LTI ERP

    From 2456d64a685804574228474c9bd3f5ec39d596e8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:44:26 +0700 Subject: [PATCH 015/327] feat(FE-40): create MainDrawer component --- src/components/MainDrawer.tsx | 205 ++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/components/MainDrawer.tsx diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx new file mode 100644 index 00000000..ad9a7a9c --- /dev/null +++ b/src/components/MainDrawer.tsx @@ -0,0 +1,205 @@ +'use client'; + +import { useState } from 'react'; +import { usePathname } from 'next/navigation'; + +import Image from 'next/image'; +import { Icon } from '@iconify/react'; +import Drawer from '@/components/Drawer'; +import Menu from '@/components/menu/Menu'; +import MenuItem from '@/components/menu/MenuItem'; +import Navbar from '@/components/Navbar'; +import Collapse from '@/components/Collapse'; + +import { useUiStore } from '@/stores/ui/ui.store'; +import { MAIN_DRAWER_LINKS } from '@/config/constant'; +import { cn } from '@/lib/helper'; + +type CollapseMenuProps = { + title: string; + link: string; + icon: string; + submenu?: CollapseMenuProps[]; + depth?: number; +}; + +const isPathActive = (pathname: string, link?: string) => { + if (!link) return false; + + const splittedPathname = pathname.split('/'); + const splittedLink = link.split('/'); + + return splittedPathname.every((pathnameChunk, idx) => { + return pathnameChunk === splittedLink[idx]; + }); +}; + +const isCollapseActive = (pathname: string, link?: string) => { + if (!link) return false; + + return pathname === link || pathname.startsWith(link); +}; + +const CollapseMenu = ({ + title, + link, + icon, + submenu, + depth = 0, +}: CollapseMenuProps) => { + const pathname = usePathname(); + const [open, setOpen] = useState(isCollapseActive(pathname, link)); + + const menuCollapseTitle = ( +
    +
    + + {title} +
    + + +
    + ); + + const paddingLeftDepth = `pl-${4 * (depth + 1)}`; + + return ( + + + {submenu?.map((item, idx) => { + const hasSubmenu = item.submenu && item.submenu.length > 0; + + if (!hasSubmenu) { + return ( + + ); + } + + return ( + + ); + })} + + + ); +}; + +const MainDrawerMenu = () => { + const pathname = usePathname(); + + return ( + + {MAIN_DRAWER_LINKS.map((item, idx) => { + const hasSubmenu = item.submenu && item.submenu.length > 0; + + if (!hasSubmenu) { + return ( + + ); + } + + return ( + + ); + })} + + ); +}; + +const MainDrawerContent = () => { + return ( +
    +
    + MBU Logo + +

    LTI ERP

    +
    + + +
    + ); +}; +const MainDrawer = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + const { mainDrawerOpen, setMainDrawerOpen } = useUiStore(); + const pathname = usePathname(); + + const pageTitle = MAIN_DRAWER_LINKS.find((item) => + pathname.startsWith(item.link) + )?.title; + + const toggleSidebar = () => { + setMainDrawerOpen(!mainDrawerOpen); + }; + + return ( + } + > +
    + + + {children} +
    +
    + ); +}; + +export default MainDrawer; From 87ce1e50aae93ebcc416da3e3a4b15b6cdb8739c Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:44:42 +0700 Subject: [PATCH 016/327] feat(FE-40): create MAIN_DRAWER_LINKS constant --- src/config/constant.ts | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/config/constant.ts b/src/config/constant.ts index e69de29b..84b24e04 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -0,0 +1,75 @@ +export const MAIN_DRAWER_LINKS = [ + { + title: 'Dashboard', + link: '/dashboard', + icon: 'gg:chart', + }, + + { + title: 'Master Data', + link: '/master-data', + icon: 'majesticons:data-line', + submenu: [ + { + title: 'Product', + link: '/master-data/product', + icon: 'fluent-mdl2:product-variant', + }, + { + title: 'Product Category', + link: '/master-data/product-category', + icon: 'carbon:categories', + }, + { + title: 'Bank', + link: '/master-data/Bank', + icon: 'mdi:bank-outline', + }, + { + title: 'Area', + link: '/master-data/area', + icon: 'majesticons:map-marker-area-line', + }, + { + title: 'Location', + link: '/master-data/location', + icon: 'mingcute:location-line', + }, + { + title: 'Kandang', + link: '/master-data/kandang', + icon: 'mdi:farm-home-outline', + }, + { + title: 'Warehouse', + link: '/master-data/warehouse', + icon: 'hugeicons:warehouse', + }, + { + title: 'Customer', + link: '/master-data/customer', + icon: 'ix:customer', + }, + { + title: 'UOM', + link: '/master-data/uom', + icon: 'lsicon:measure-outline', + }, + { + title: 'Non-Stock', + link: '/master-data/nonstock', + icon: 'fluent:box-32-regular', + }, + { + title: 'FCR', + link: '/master-data/FCR', + icon: 'fluent:food-chicken-leg-16-regular', + }, + { + title: 'Supplier', + link: '/master-data/supplier', + icon: 'material-symbols:add-business-outline-rounded', + }, + ], + }, +]; From 6cbdff5398ea7b4bcb80abb84b664f2dad0705be Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:45:00 +0700 Subject: [PATCH 017/327] feat(FE-40): add main UI slice to useUiStore --- src/stores/ui/ui.store.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/stores/ui/ui.store.ts b/src/stores/ui/ui.store.ts index 86016974..2e64dcc1 100644 --- a/src/stores/ui/ui.store.ts +++ b/src/stores/ui/ui.store.ts @@ -4,9 +4,15 @@ import { create } from 'zustand'; import { devtools } from 'zustand/middleware'; import { UIStore } from '@/types/stores'; +import { createMainUiSlice } from './slices/main.slice'; export const useUiStore = create()( - devtools((...args) => ({}), { - name: 'UIStore', - }) + devtools( + (...args) => ({ + ...createMainUiSlice(...args), + }), + { + name: 'UIStore', + } + ) ); From a5b392ae76863a8344cd70a32bffe6ce23e05352 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:45:16 +0700 Subject: [PATCH 018/327] feat(FE-40): create main UI slice --- src/stores/ui/slices/main.slice.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/stores/ui/slices/main.slice.ts diff --git a/src/stores/ui/slices/main.slice.ts b/src/stores/ui/slices/main.slice.ts new file mode 100644 index 00000000..31f8f447 --- /dev/null +++ b/src/stores/ui/slices/main.slice.ts @@ -0,0 +1,12 @@ +import { StateCreator } from 'zustand'; +import { MainUiSlice } from '@/types/stores'; + +export const createMainUiSlice: StateCreator< + MainUiSlice, + [], + [], + MainUiSlice +> = (set): MainUiSlice => ({ + mainDrawerOpen: false, + setMainDrawerOpen: (open) => set(() => ({ mainDrawerOpen: open })), +}); From 8206f7de5f3c6893bfe9f13f82c484ec0add3ccc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:45:25 +0700 Subject: [PATCH 019/327] feat(FE-40): create MainUiSlice type --- src/types/stores.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts index 08900862..1a3046ae 100644 --- a/src/types/stores.d.ts +++ b/src/types/stores.d.ts @@ -1 +1,6 @@ -export type UIStore = {}; +type MainUiSlice = { + mainDrawerOpen: boolean; + setMainDrawerOpen: (open: boolean) => void; +}; + +export type UIStore = MainUiSlice; From 6969a2bcb8193c4eba4e484a20ae923449284ffb Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 13:56:59 +0700 Subject: [PATCH 020/327] chore(FE-40): move api.d.ts to /types/api/api-general.d.ts --- src/types/{api.d.ts => api/api-general.d.ts} | 4 ++++ 1 file changed, 4 insertions(+) rename src/types/{api.d.ts => api/api-general.d.ts} (85%) diff --git a/src/types/api.d.ts b/src/types/api/api-general.d.ts similarity index 85% rename from src/types/api.d.ts rename to src/types/api/api-general.d.ts index 1ae9f613..dfede516 100644 --- a/src/types/api.d.ts +++ b/src/types/api/api-general.d.ts @@ -20,6 +20,10 @@ type SuccessApiResponse = { type BaseApiResponse = ErrorApiResponse | SuccessApiResponse; +export type LogoutResponse = BaseApiResponse; + +export type GetMeResponse = BaseApiResponse; + export type User = { id: number; email: string; From a3470241881c330ee46134c78e0bd76b3e8f2d64 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 14:04:50 +0700 Subject: [PATCH 021/327] chore(FE-40): update CollapseMenu styling --- src/components/MainDrawer.tsx | 56 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx index ad9a7a9c..4a21b7df 100644 --- a/src/components/MainDrawer.tsx +++ b/src/components/MainDrawer.tsx @@ -48,14 +48,15 @@ const CollapseMenu = ({ depth = 0, }: CollapseMenuProps) => { const pathname = usePathname(); - const [open, setOpen] = useState(isCollapseActive(pathname, link)); + const isActive = isCollapseActive(pathname, link); + const [open, setOpen] = useState(isActive); const menuCollapseTitle = (
    @@ -76,8 +77,6 @@ const CollapseMenu = ({
    ); - const paddingLeftDepth = `pl-${4 * (depth + 1)}`; - return ( - - {submenu?.map((item, idx) => { - const hasSubmenu = item.submenu && item.submenu.length > 0; + +
    + {submenu?.map((item, idx) => { + const hasSubmenu = item.submenu && item.submenu.length > 0; + + if (!hasSubmenu) { + return ( + + ); + } - if (!hasSubmenu) { return ( - ); - } - - return ( - - ); - })} + })} +
    ); From 05886896f1d20d09f00507eac8e93d936377e1c8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 14:07:04 +0700 Subject: [PATCH 022/327] chore(FE-40): update import path --- src/lib/api-helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/api-helper.ts b/src/lib/api-helper.ts index 3e85ecf0..9081e41f 100644 --- a/src/lib/api-helper.ts +++ b/src/lib/api-helper.ts @@ -1,4 +1,4 @@ -import { BaseApiResponse, SuccessApiResponse } from '@/types/api'; +import { BaseApiResponse, SuccessApiResponse } from '@/types/api/api-general'; export const isResponseSuccess = ( res?: BaseApiResponse From 3d3df42576ff8687df0c332b3d7deb95185226ad Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 14:07:30 +0700 Subject: [PATCH 023/327] chore(FE-40): update import path and return isLoadingUser and setIsLoadingUser in useAuth --- src/services/hooks/useAuth.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/services/hooks/useAuth.tsx b/src/services/hooks/useAuth.tsx index 012badfa..86bf43ed 100644 --- a/src/services/hooks/useAuth.tsx +++ b/src/services/hooks/useAuth.tsx @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import { UserWithRoles } from '@/types/api'; +import { UserWithRoles } from '@/types/api/api-general'; type AuthStore = { user?: UserWithRoles; @@ -16,10 +16,12 @@ const useAuthStore = create()((set) => ({ })); export const useAuth = () => { - const { user, setUser } = useAuthStore(); + const { user, setUser, isLoadingUser, setIsLoadingUser } = useAuthStore(); return { user, setUser, + isLoadingUser, + setIsLoadingUser, }; }; From fa96d7a98aec7bb999147716a34fbf44d7d03c4a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 14:08:02 +0700 Subject: [PATCH 024/327] chore(FE-40): set opts.auth default to 'cookie' and export SWRHttpKey type --- src/services/http/client.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/services/http/client.ts b/src/services/http/client.ts index 1a898e13..adba75e9 100644 --- a/src/services/http/client.ts +++ b/src/services/http/client.ts @@ -9,7 +9,9 @@ export async function httpClient( path: string, opts: RequestOptions = {} ): Promise { - const isCookieAuth = opts.auth === 'cookie'; + const isCookieAuth = + opts.auth === 'cookie' || + (!opts.auth && opts.auth !== 'none' && opts.auth !== 'bearer'); const isBearerAuth = opts.auth === 'bearer' && !!opts.token; const config: AxiosRequestConfig = { @@ -18,11 +20,13 @@ export async function httpClient( params: opts.query, data: opts.body, timeout: opts.timeoutMs ?? 10_000, - withCredentials: isCookieAuth, + withCredentials: isCookieAuth && !isBearerAuth, headers: { 'Content-Type': 'application/json', ...(opts.headers ?? {}), - ...(isBearerAuth ? { Authorization: `Bearer ${opts.token}` } : {}), + ...(isBearerAuth && !isCookieAuth + ? { Authorization: `Bearer ${opts.token}` } + : {}), }, }; @@ -34,7 +38,7 @@ export async function httpClient( } } -type SWRHttpKey = +export type SWRHttpKey = | string | [path: string, opts?: RequestOptions] | { path: string; opts?: RequestOptions }; From 6924aef8c47667c5f3a58ec58706e81926805bc4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 14:59:46 +0700 Subject: [PATCH 025/327] feat(FE-40): create RequireAuth helper component --- src/components/helper/RequireAuth.tsx | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/components/helper/RequireAuth.tsx diff --git a/src/components/helper/RequireAuth.tsx b/src/components/helper/RequireAuth.tsx new file mode 100644 index 00000000..9bc199f9 --- /dev/null +++ b/src/components/helper/RequireAuth.tsx @@ -0,0 +1,55 @@ +'use client'; + +import { ReactNode, useEffect } from 'react'; +import { useRouter } from 'next/navigation'; +import useSWRImmutable from 'swr/immutable'; + +import { useAuth } from '@/services/hooks/useAuth'; +import { httpClientFetcher, SWRHttpKey } from '@/services/http/client'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { GetMeResponse } from '@/types/api/api-general'; + +interface RequireAuthProps { + children?: ReactNode; +} + +const RequireAuth = ({ children }: RequireAuthProps) => { + const router = useRouter(); + const { setUser, setIsLoadingUser } = useAuth(); + + const { data: userResponse, isLoading: isLoadingUserResponse } = + useSWRImmutable( + '/auth/get-me', + httpClientFetcher, + { + shouldRetryOnError: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshInterval: 0, + } + ); + + useEffect(() => { + setIsLoadingUser(isLoadingUserResponse); + }, [isLoadingUserResponse, setIsLoadingUser]); + + useEffect(() => { + if (isResponseSuccess(userResponse)) { + setUser(userResponse.data); + } else { + router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string); + } + }, [userResponse, setIsLoadingUser, setUser]); + + if (isLoadingUserResponse && !userResponse) { + return ( +
    + +
    + ); + } + + return <>{children}; +}; + +export default RequireAuth; From 8a6a1e6b5caca0604101a38457ee1d4f90d5a0b4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 15:00:06 +0700 Subject: [PATCH 026/327] chore(FE-40): use RequireAuth in root layout --- src/app/layout.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9d807425..8843cc64 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,9 @@ import type { Metadata, Viewport } from 'next'; import { Inter } from 'next/font/google'; import '@/app/globals.css'; + import MainDrawer from '@/components/MainDrawer'; +import RequireAuth from '@/components/helper/RequireAuth'; const inter = Inter({ variable: '--font-inter', @@ -27,7 +29,9 @@ export default function RootLayout({ return ( - {children} + + {children} + ); From 9b2930375d486ffdd4dce2ec617fdb0f169aaac2 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 15:00:44 +0700 Subject: [PATCH 027/327] chore(FE-40): fix bank link --- src/config/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/constant.ts b/src/config/constant.ts index 84b24e04..1abf588a 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -22,7 +22,7 @@ export const MAIN_DRAWER_LINKS = [ }, { title: 'Bank', - link: '/master-data/Bank', + link: '/master-data/bank', icon: 'mdi:bank-outline', }, { From 0afde48135667baf14afb99c4ea255575d7ab661 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 15:24:33 +0700 Subject: [PATCH 028/327] chore(FE-40): set correct page title --- src/components/MainDrawer.tsx | 48 ++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx index 4a21b7df..5851ee2b 100644 --- a/src/components/MainDrawer.tsx +++ b/src/components/MainDrawer.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useCallback, useState } from 'react'; import { usePathname } from 'next/navigation'; import Image from 'next/image'; @@ -29,15 +29,11 @@ const isPathActive = (pathname: string, link?: string) => { const splittedPathname = pathname.split('/'); const splittedLink = link.split('/'); - return splittedPathname.every((pathnameChunk, idx) => { - return pathnameChunk === splittedLink[idx]; + const isActiveLinkValid = splittedLink.every((linkChunk, idx) => { + return linkChunk === splittedPathname[idx]; }); -}; -const isCollapseActive = (pathname: string, link?: string) => { - if (!link) return false; - - return pathname === link || pathname.startsWith(link); + return pathname.startsWith(link) && isActiveLinkValid; }; const CollapseMenu = ({ @@ -48,7 +44,7 @@ const CollapseMenu = ({ depth = 0, }: CollapseMenuProps) => { const pathname = usePathname(); - const isActive = isCollapseActive(pathname, link); + const isActive = isPathActive(pathname, link); const [open, setOpen] = useState(isActive); const menuCollapseTitle = ( @@ -184,9 +180,37 @@ const MainDrawer = ({ const { mainDrawerOpen, setMainDrawerOpen } = useUiStore(); const pathname = usePathname(); - const pageTitle = MAIN_DRAWER_LINKS.find((item) => - pathname.startsWith(item.link) - )?.title; + const getPageTitle = useCallback(() => { + let title = ''; + + const activeMenu = MAIN_DRAWER_LINKS.find((item) => + isPathActive(pathname, item.link) + ); + + const traverseMenuTitle = (menu: typeof activeMenu) => { + const hasSubmenu = menu?.submenu && menu?.submenu.length > 0; + + if (!title) { + title += menu?.title; + } else { + title += ' - ' + menu?.title; + } + + if (!hasSubmenu) return; + + const activeSubmenu = menu.submenu.find((item) => + isPathActive(pathname, item.link) + ); + + traverseMenuTitle(activeSubmenu); + }; + + traverseMenuTitle(activeMenu); + + return title; + }, [pathname]); + + const pageTitle = getPageTitle(); const toggleSidebar = () => { setMainDrawerOpen(!mainDrawerOpen); From 4ff196cb9d1740ed2dc9aee42888475946fdaec2 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 15:32:35 +0700 Subject: [PATCH 029/327] chore(FE-40): remove unnecessary gap --- src/components/MainDrawer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx index 5851ee2b..8cf3d3b3 100644 --- a/src/components/MainDrawer.tsx +++ b/src/components/MainDrawer.tsx @@ -223,7 +223,7 @@ const MainDrawer = ({ openOnLarge sidebarContent={} > -
    +
    {children} From 8ad49a448002a0f4ab337600bf11a098843b9078 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 16:01:47 +0700 Subject: [PATCH 030/327] chore(FE-40): export ErrorApiResponse and SucessApiResponse type --- src/types/api/api-general.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/api/api-general.d.ts b/src/types/api/api-general.d.ts index dfede516..90df754b 100644 --- a/src/types/api/api-general.d.ts +++ b/src/types/api/api-general.d.ts @@ -1,11 +1,11 @@ -type ErrorApiResponse = { +export type ErrorApiResponse = { code: number; status: 'error'; message: string; errors?: { [key: string]: string }; }; -type SuccessApiResponse = { +export type SuccessApiResponse = { code: number; status: 'success'; message: string; From 14046a1add4da75675d832831fdbdb8e2fdb4b81 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 1 Oct 2025 16:02:12 +0700 Subject: [PATCH 031/327] chore(FE-40): create isResponseError api helper function --- src/lib/api-helper.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/api-helper.ts b/src/lib/api-helper.ts index 9081e41f..7ce3ac64 100644 --- a/src/lib/api-helper.ts +++ b/src/lib/api-helper.ts @@ -1,7 +1,17 @@ -import { BaseApiResponse, SuccessApiResponse } from '@/types/api/api-general'; +import { + BaseApiResponse, + ErrorApiResponse, + SuccessApiResponse, +} from '@/types/api/api-general'; export const isResponseSuccess = ( res?: BaseApiResponse ): res is SuccessApiResponse => { return res?.status === 'success'; }; + +export const isResponseError = ( + res?: BaseApiResponse +): res is ErrorApiResponse => { + return res?.status === 'error'; +}; From ca9205618aa05cfe853e90b6c0449c93a2974b5c Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 11:45:11 +0700 Subject: [PATCH 032/327] feat: add Modal component --- src/components/Modal.tsx | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/components/Modal.tsx diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx new file mode 100644 index 00000000..ec503392 --- /dev/null +++ b/src/components/Modal.tsx @@ -0,0 +1,62 @@ +'use client'; + +import { ReactNode, RefObject, useCallback, useRef, useState } from 'react'; +import { cn } from '@/lib/helper'; + +export const useModal = () => { + const ref = useRef(null); + const [open, setOpen] = useState(false); + + const openModal = useCallback(() => { + setOpen(true); + + ref.current?.showModal(); + }, []); + + const closeModal = useCallback(() => { + setOpen(false); + ref.current?.close(); + }, []); + + const toggle = useCallback(() => { + if (open) { + closeModal(); + } else { + openModal(); + } + }, [open]); + + if (ref.current) { + ref.current.addEventListener('close', () => { + closeModal(); + }); + } + + return { ref, open, setOpen, openModal, closeModal, toggle } as const; +}; + +interface ModalProps { + ref: RefObject; + children?: ReactNode; + closeOnBackdrop?: boolean; + className?: { + modal?: string; + modalBox?: string; + }; +} + +const Modal = ({ ref, children, closeOnBackdrop, className }: ModalProps) => { + return ( + +
    {children}
    + + {closeOnBackdrop && ( +
    + +
    + )} +
    + ); +}; + +export default Modal; From d40a5dd898e1e2874dfc1701f4f443a3e85bc0e8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 11:46:09 +0700 Subject: [PATCH 033/327] chore: update Collapse styling --- src/components/Collapse.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Collapse.tsx b/src/components/Collapse.tsx index 4007cae0..cb05d5b0 100644 --- a/src/components/Collapse.tsx +++ b/src/components/Collapse.tsx @@ -70,6 +70,7 @@ export const Collapse = ({ variant === 'plus' && 'collapse-plus', bordered && 'border base-content/20 border-opacity-20 rounded-box', disabled && 'opacity-60 pointer-events-none', + !open && 'w-fit', className ); @@ -82,7 +83,7 @@ export const Collapse = ({
    ); } - return
    {title}
    ; + return title; }, [title, subtitle]); return ( @@ -102,7 +103,7 @@ export const Collapse = ({ role='button' tabIndex={0} className={cn( - 'collapse-title p-0', + 'collapse-title w-fit p-0', 'focus:outline-none focus-visible:ring focus-visible:ring-primary/40', titleClassName )} From 2a6f2a164609ddce711921e6bffb55f4b8cc4094 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 11:46:27 +0700 Subject: [PATCH 034/327] chore(FE-40): update MainDrawer component styling --- src/components/MainDrawer.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MainDrawer.tsx b/src/components/MainDrawer.tsx index 8cf3d3b3..6a5e6f38 100644 --- a/src/components/MainDrawer.tsx +++ b/src/components/MainDrawer.tsx @@ -78,7 +78,8 @@ const CollapseMenu = ({ open={open} title={menuCollapseTitle} onOpenChange={setOpen} - titleClassName='p-0!' + className='w-full' + titleClassName='w-full p-0!' >
    Date: Thu, 2 Oct 2025 12:00:02 +0700 Subject: [PATCH 035/327] chore: update toggle dependencies --- src/components/Modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index ec503392..a84c1827 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -24,7 +24,7 @@ export const useModal = () => { } else { openModal(); } - }, [open]); + }, [open, closeModal, openModal]); if (ref.current) { ref.current.addEventListener('close', () => { From 36b66d9b2fa48c7d294734b41f76058a88b5e2fc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:00:18 +0700 Subject: [PATCH 036/327] feat(FE-40): create Dashboard page --- src/app/dashboard/page.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/app/dashboard/page.tsx diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 00000000..4f2c344e --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,9 @@ +const Dashboard = () => { + return ( +
    +

    Dashboard

    +
    + ); +}; + +export default Dashboard; From e6acfc12147f9323ecf44c03691783cc72a675dd Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:01:00 +0700 Subject: [PATCH 037/327] feat(FE-40): create NonstockForm component --- .../nonstock/form/NonstockForm.schema.ts | 9 + .../nonstock/form/NonstockForm.tsx | 178 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts create mode 100644 src/components/pages/master-data/nonstock/form/NonstockForm.tsx diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts b/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts new file mode 100644 index 00000000..50f69c7d --- /dev/null +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts @@ -0,0 +1,9 @@ +import * as Yup from 'yup'; + +export const NonstockFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), +}); + +export const UpdateNonstockFormSchema = NonstockFormSchema; + +export type NonstockFormValues = Yup.InferType; diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx new file mode 100644 index 00000000..bf2fce73 --- /dev/null +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx @@ -0,0 +1,178 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; + +import { + NonstockFormSchema, + NonstockFormValues, + UpdateNonstockFormSchema, +} from '@/components/pages/master-data/nonstock/form/NonstockForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + CreateNonstockPayload, + Nonstock, + UpdateNonstockPayload, +} from '@/types/api/master-data/nonstock'; +import { + createNonstock, + updateNonstock, +} from '@/services/api/master-data/nonstock'; + +interface NonstockFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Nonstock; +} + +const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { + const router = useRouter(); + + const [nonstockFormErrorMessage, setNonstockFormErrorMessage] = useState(''); + + const createNonstockHandler = useCallback( + async (payload: CreateNonstockPayload) => { + const createNonstockRes = await createNonstock(payload); + + if (isResponseError(createNonstockRes)) { + setNonstockFormErrorMessage(createNonstockRes.message); + return; + } + + alert(createNonstockRes?.message); + router.push('/master-data/nonstock'); + }, + [router] + ); + + const updateNonstockHandler = useCallback( + async (nonstockId: number, payload: UpdateNonstockPayload) => { + const updateNonstockRes = await updateNonstock(nonstockId, payload); + + if (updateNonstockRes?.status === 'error') { + setNonstockFormErrorMessage(updateNonstockRes.message); + return; + } + + alert(updateNonstockRes?.message); + router.refresh(); + router.push('/master-data/nonstock'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: + type === 'edit' ? UpdateNonstockFormSchema : NonstockFormSchema, + onSubmit: async (values) => { + setNonstockFormErrorMessage(''); + + const nonstockPayload: CreateNonstockPayload = { + name: values.name, + }; + + switch (type) { + case 'add': + await createNonstockHandler(nonstockPayload); + break; + + case 'edit': + await updateNonstockHandler( + initialValues?.id as number, + nonstockPayload + ); + break; + } + }, + }); + + useEffect(() => { + formik.setValues(formikInitialValues); + }, [formikInitialValues]); + + return ( +
    +
    + + +

    + {type === 'add' && 'Tambah Non Stock'} + {type === 'edit' && 'Edit Non Stock'} + {type === 'detail' && 'Detail Non Stock'} +

    +
    + +
    +
    + +
    + + {type !== 'detail' && ( + <> +
    + + + +
    + + {nonstockFormErrorMessage && ( +
    + + {nonstockFormErrorMessage} +
    + )} + + )} +
    +
    + ); +}; + +export default NonstockForm; From 35c809193ba2bab5295db28f2be8ac37b8b2d931 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:01:14 +0700 Subject: [PATCH 038/327] feat(FE-40): create NonstocksTable component --- .../master-data/nonstock/NonstocksTable.tsx | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 src/components/pages/master-data/nonstock/NonstocksTable.tsx diff --git a/src/components/pages/master-data/nonstock/NonstocksTable.tsx b/src/components/pages/master-data/nonstock/NonstocksTable.tsx new file mode 100644 index 00000000..4a2dbc5b --- /dev/null +++ b/src/components/pages/master-data/nonstock/NonstocksTable.tsx @@ -0,0 +1,243 @@ +'use client'; + +import { ChangeEventHandler, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef } from '@tanstack/react-table'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import TextInput from '@/components/input/TextInput'; +import Button from '@/components/Button'; +import Collapse from '@/components/Collapse'; + +import { httpClientFetcher } from '@/services/http/client'; +import { Nonstock, NonstocksResponse } from '@/types/api/master-data/nonstock'; +import { cn } from '@/lib/helper'; +import { deleteNonstock } from '@/services/api/master-data/nonstock'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => Promise; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const RowDropdownOptions = ({ + props, + isLast2Rows, + deleteClickHandler, +}: { + props: CellContext; + isLast2Rows: boolean; + deleteClickHandler: () => Promise; +}) => { + return ( +
    + + + +
    + ); +}; + +const RowCollapseOptions = ({ + props, + deleteClickHandler, +}: { + props: CellContext; + deleteClickHandler: () => Promise; +}) => { + return ( + + + + } + className='w-fit' + titleClassName='p-0! justify-self-end' + > + + + ); +}; + +const NonstocksTable = () => { + const { + data: nonstocks, + isLoading, + mutate: refreshNonstocks, + } = useSWR('/master-data/nonstocks', httpClientFetcher); + + const [searchValue, setSearchValue] = useState(''); + + const nonstocksColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => props.row.index + 1, + }, + { + header: 'Nama', + accessorKey: 'name', + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = async () => { + const confirmation = confirm( + 'Apakah anda yakin untuk menghapus non stock ini?' + ); + + if (confirmation) { + await deleteNonstock(props.row.original.id); + refreshNonstocks(); + alert('Nonstock berhasil dihapus!'); + } + }; + + return ( + <> + {currentPageSize > 2 && ( + + )} + + {currentPageSize <= 2 && ( + + )} + + ); + }, + }, + ]; + + const searchChangeHandler: ChangeEventHandler = (e) => { + setSearchValue(e.target.value); + }; + + return ( +
    +
    +
    + +
    + + +
    + + + data={isResponseSuccess(nonstocks) ? nonstocks?.data : []} + columns={nonstocksColumns} + pageSize={10} + fuzzySearchValue={searchValue} + onFuzzySearchValueChange={setSearchValue} + isLoading={isLoading} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(nonstocks) && nonstocks?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + ); +}; + +export default NonstocksTable; From 8dd1ebdfe447fa8d6bff97c876209d6b6a2135d3 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:01:43 +0700 Subject: [PATCH 039/327] feat(FE-40): create api service for nonstock --- src/services/api/master-data/nonstock.ts | 87 ++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/services/api/master-data/nonstock.ts diff --git a/src/services/api/master-data/nonstock.ts b/src/services/api/master-data/nonstock.ts new file mode 100644 index 00000000..7340e37b --- /dev/null +++ b/src/services/api/master-data/nonstock.ts @@ -0,0 +1,87 @@ +import axios from 'axios'; +import { httpClient } from '@/services/http/client'; + +import { + CreateNonstockPayload, + DeleteNonstockResponse, + NonstockResponse, + UpdateNonstockPayload, +} from '@/types/api/master-data/nonstock'; + +export const getNonstock = async (nonstockId: number) => { + try { + const getNonstockRes = await httpClient( + `/master-data/nonstocks/${nonstockId}` + ); + + return getNonstockRes; + } catch (error: unknown) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } +}; + +export const createNonstock = async (payload: CreateNonstockPayload) => { + try { + const createNonstockRes = await httpClient( + '/master-data/nonstocks', + { + method: 'POST', + body: payload, + } + ); + + return createNonstockRes; + } catch (error: unknown) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } +}; + +export const updateNonstock = async ( + nonstockId: number, + payload: UpdateNonstockPayload +) => { + try { + const updateNonstockRes = await httpClient( + `/master-data/nonstocks/${nonstockId}`, + { + method: 'PATCH', + body: payload, + } + ); + + return updateNonstockRes; + } catch (error: unknown) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } +}; + +export const deleteNonstock = async (nonstockId: number) => { + try { + const deleteNonstockRes = await httpClient( + `/master-data/nonstocks/${nonstockId}`, + { + method: 'DELETE', + } + ); + + return deleteNonstockRes; + } catch (error) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } +}; From 62b38949830bd93edbf422cc01c4a5180683e670 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:02:02 +0700 Subject: [PATCH 040/327] feat(FE-40): create api type for nonstock --- src/types/api/master-data/nonstock.d.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/types/api/master-data/nonstock.d.ts diff --git a/src/types/api/master-data/nonstock.d.ts b/src/types/api/master-data/nonstock.d.ts new file mode 100644 index 00000000..682f7852 --- /dev/null +++ b/src/types/api/master-data/nonstock.d.ts @@ -0,0 +1,18 @@ +import { BaseApiResponse } from '@/types/api/api-general'; + +export type Nonstock = { + id: number; + name: string; +}; + +export type CreateNonstockPayload = { + name: string; +}; + +export type UpdateNonstockPayload = CreateNonstockPayload; + +export type NonstockResponse = BaseApiResponse; + +export type NonstocksResponse = BaseApiResponse; + +export type DeleteNonstockResponse = BaseApiResponse; From 230e96619788e87856f22c566e19955c3b511e32 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:02:11 +0700 Subject: [PATCH 041/327] feat(FE-40): create Nonstock page --- src/app/master-data/nonstock/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/nonstock/page.tsx diff --git a/src/app/master-data/nonstock/page.tsx b/src/app/master-data/nonstock/page.tsx new file mode 100644 index 00000000..0812a5e2 --- /dev/null +++ b/src/app/master-data/nonstock/page.tsx @@ -0,0 +1,11 @@ +import NonstocksTable from '@/components/pages/master-data/nonstock/NonstocksTable'; + +const Nonstock = () => { + return ( +
    + +
    + ); +}; + +export default Nonstock; From c3da39ef1b4de77c71fb304e0d11da0bc1a8bf1a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:02:21 +0700 Subject: [PATCH 042/327] feat(FE-40): create Add Nonstock page --- src/app/master-data/nonstock/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/nonstock/add/page.tsx diff --git a/src/app/master-data/nonstock/add/page.tsx b/src/app/master-data/nonstock/add/page.tsx new file mode 100644 index 00000000..2bde94ed --- /dev/null +++ b/src/app/master-data/nonstock/add/page.tsx @@ -0,0 +1,11 @@ +import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From c40c707c1786fee4dea9685cf7892568e1466a84 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:03:06 +0700 Subject: [PATCH 043/327] feat(FE-40): create Nonstock Detail page --- src/app/master-data/nonstock/detail/page.tsx | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/nonstock/detail/page.tsx diff --git a/src/app/master-data/nonstock/detail/page.tsx b/src/app/master-data/nonstock/detail/page.tsx new file mode 100644 index 00000000..375ec999 --- /dev/null +++ b/src/app/master-data/nonstock/detail/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm'; + +import { getNonstock } from '@/services/api/master-data/nonstock'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const NonstockDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const nonstockId = searchParams.get('nonstockId'); + + const { data: nonstock, isLoading: isLoadingNonstock } = useSWR( + nonstockId, + getNonstock + ); + + if (!nonstockId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingNonstock && !nonstock) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingNonstock && ( + + )} + {!isLoadingNonstock && isResponseSuccess(nonstock) && ( + + )} +
    + ); +}; + +export default NonstockDetail; From 75a5caa63b87cefb436c9c6db740c7a839fa071d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 12:03:23 +0700 Subject: [PATCH 044/327] feat(FE-40): create Nonstock Edit page --- .../master-data/nonstock/detail/edit/page.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/nonstock/detail/edit/page.tsx diff --git a/src/app/master-data/nonstock/detail/edit/page.tsx b/src/app/master-data/nonstock/detail/edit/page.tsx new file mode 100644 index 00000000..a0fbb6b3 --- /dev/null +++ b/src/app/master-data/nonstock/detail/edit/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm'; + +import { getNonstock } from '@/services/api/master-data/nonstock'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const NonstockEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const nonstockId = searchParams.get('nonstockId'); + + const { data: nonstock, isLoading: isLoadingNonstock } = useSWR( + nonstockId, + getNonstock + ); + + if (!nonstockId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingNonstock && !nonstock) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingNonstock && ( + + )} + {!isLoadingNonstock && isResponseSuccess(nonstock) && ( + + )} +
    + ); +}; + +export default NonstockEdit; From e765a7a5fbdd158034bfb90fe9107009555ce7ff Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 2 Oct 2025 16:50:37 +0700 Subject: [PATCH 045/327] chore(FE-40): hide empty content if is loading --- src/components/Table.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index e20d4d11..d28f6e72 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -224,6 +224,7 @@ const Table = ({
    {(data.length === 0 || table.getRowModel().rows.length === 0) && + !isLoading && emptyContent} {data.length > 0 && table.getRowModel().rows.length > 0 && !isLoading && ( From 83701a9689bd3f130e97070de0789c6d8d6c70a9 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Fri, 3 Oct 2025 14:12:02 +0700 Subject: [PATCH 046/327] chore(FE-40): update table pageSize if it change --- src/components/Table.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index d28f6e72..ef99f6a7 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ReactNode, useCallback, useState } from 'react'; +import { ReactNode, useCallback, useEffect, useState } from 'react'; import { flexRender, getCoreRowModel, @@ -148,6 +148,10 @@ const Table = ({ } }; + useEffect(() => { + table.setPageSize(pageSize); + }, [pageSize]); + return (
    From 88fe135cb40a7d0db9a4d5b35319d5bf9fc17309 Mon Sep 17 00:00:00 2001 From: Adnan Zahir Date: Fri, 3 Oct 2025 21:58:55 +0700 Subject: [PATCH 047/327] chore(CI): added gitlab ci yaml file for notify MR and MR-merged events --- .gitlab-ci.yml | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..efda72f0 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,76 @@ +stages: [notify] + +# --- Notify when MR is opened/updated --- +notify_discord_mr: + stage: notify + image: alpine:3.20 + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + variables: + WEBHOOK_URL: $DISCORD_WEBHOOK_URL + before_script: + - apk add --no-cache curl jq + script: | + MR_URL="${CI_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}" + + jq -n \ + --arg repo "$CI_PROJECT_PATH" \ + --arg mr "#${CI_MERGE_REQUEST_IID}" \ + --arg url "$MR_URL" \ + --arg requestor "${GITLAB_USER_LOGIN:-$GITLAB_USER_NAME}" \ + --arg source "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \ + --arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \ + --arg title "$CI_MERGE_REQUEST_TITLE" \ + '{ + username: "CI Bot - FE", + embeds: [{ + title: "📣 [LTI WEB CLIENT] Merge Request Opened/Updated", + description: ($mr + " in " + $repo), + url: $url, + color: 3447003, + fields: [ + {name: "Author", value: $requestor, inline: true}, + {name: "Source → Target", value: ($source + " → " + $target), inline: true}, + {name: "Title", value: $title} + ] + }] + }' \ + | curl -sS -H "Content-Type: application/json" -d @- "$WEBHOOK_URL" + +# --- Notify when MR is merged --- +notify_discord_merge: + stage: notify + image: alpine:3.20 + rules: + # Only run for merge request pipelines that are in merged state + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_STATE == "merged"' + variables: + WEBHOOK_URL: $DISCORD_WEBHOOK_URL + before_script: + - apk add --no-cache curl jq + script: | + MR_URL="${CI_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}" + + jq -n \ + --arg repo "$CI_PROJECT_PATH" \ + --arg mr "#${CI_MERGE_REQUEST_IID}" \ + --arg url "$MR_URL" \ + --arg requestor "${CI_MERGE_REQUEST_AUTHOR}" \ + --arg source "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \ + --arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \ + --arg title "$CI_MERGE_REQUEST_TITLE" \ + '{ + username: "CI Bot - FE", + embeds: [{ + title: "✅ [LTI WEB CLIENT] Merge Request Merged", + description: ($mr + " has been merged into " + $repo), + url: $url, + color: 3066993, + fields: [ + {name: "Author", value: $requestor, inline: true}, + {name: "Source → Target", value: ($source + " → " + $target), inline: true}, + {name: "Title", value: $title} + ] + }] + }' \ + | curl -sS -H "Content-Type: application/json" -d @- "$WEBHOOK_URL" From 60d0d77dffe15eab9b4e65276952893879f9cdbf Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Fri, 3 Oct 2025 22:13:35 +0700 Subject: [PATCH 048/327] feat(FE-40): add Alert component --- src/components/Alert.tsx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/components/Alert.tsx diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx new file mode 100644 index 00000000..61792d0c --- /dev/null +++ b/src/components/Alert.tsx @@ -0,0 +1,27 @@ +import { ReactNode } from 'react'; + +import { cn } from '@/lib/helper'; + +interface AlertProps { + variant?: 'outline' | 'dash' | 'soft'; + color?: 'info' | 'success' | 'warning' | 'error'; + children?: ReactNode; + className?: string; +} + +const Alert = ({ children, variant, color, className }: AlertProps) => { + const alertBaseClassName = cn('alert', { + 'alert-soft': variant === 'soft', + 'alert-outline': variant === 'outline', + 'alert-dash': variant === 'dash', + + 'alert-info': color === 'info', + 'alert-success': color === 'success', + 'alert-warning': color === 'warning', + 'alert-error': color === 'error', + }); + + return
    {children}
    ; +}; + +export default Alert; From 42dd91117e568e1bea955b1671d8602cfb511b94 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 11:01:21 +0700 Subject: [PATCH 049/327] chore(FE-40): install react-hot-toast --- package-lock.json | 27 +++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 28 insertions(+) diff --git a/package-lock.json b/package-lock.json index ba8fc9b0..632d5b21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0", + "react-hot-toast": "^2.6.0", "react-select": "^5.10.2", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", @@ -4039,6 +4040,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -5760,6 +5770,23 @@ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", "license": "MIT" }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 93fd5b8d..55c2e5ba 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0", + "react-hot-toast": "^2.6.0", "react-select": "^5.10.2", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", From 5983a4431103512f1fa23a75a23218872e1a6277 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 11:18:08 +0700 Subject: [PATCH 050/327] chore(FE-40): add DebouncedTextInput component --- src/components/input/DebouncedTextInput.tsx | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/components/input/DebouncedTextInput.tsx diff --git a/src/components/input/DebouncedTextInput.tsx b/src/components/input/DebouncedTextInput.tsx new file mode 100644 index 00000000..61dbf61c --- /dev/null +++ b/src/components/input/DebouncedTextInput.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { ChangeEvent, ChangeEventHandler, useEffect, useState } from 'react'; +import { useDebounce } from 'use-debounce'; + +import TextInput, { TextInputProps } from '@/components/input/TextInput'; + +interface DebouncedTextInputProps extends TextInputProps { + delay?: number; +} + +const DebouncedTextInput = (props: DebouncedTextInputProps) => { + const { delay, onChange } = props; + + const [internalChangeEvent, setInternalChangeEvent] = + useState>(); + const [internalValue, setInternalValue] = useState(props.value); + + const [debouncedChangeEvent] = useDebounce(internalChangeEvent, delay ?? 300); + const [debouncedValue] = useDebounce(internalValue, delay ?? 300); + + const internalChangeHandler: ChangeEventHandler = (e) => { + setInternalValue(e.target.value); + setInternalChangeEvent(e); + }; + + useEffect(() => { + if (debouncedChangeEvent) { + onChange?.(debouncedChangeEvent); + } + }, [debouncedValue, debouncedChangeEvent, onChange]); + + return ( + + ); +}; + +export default DebouncedTextInput; From 2976ffffbfc2e46f03d1447c9226f372d8671023 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 11:18:23 +0700 Subject: [PATCH 051/327] chore(FE-40): install use-debounce --- package-lock.json | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) diff --git a/package-lock.json b/package-lock.json index 632d5b21..1aa69d33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "react-select": "^5.10.2", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", + "use-debounce": "^10.0.6", "yup": "^1.7.0", "zustand": "^5.0.8" }, @@ -6819,6 +6820,18 @@ "punycode": "^2.1.0" } }, + "node_modules/use-debounce": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.6.tgz", + "integrity": "sha512-C5OtPyhAZgVoteO9heXMTdW7v/IbFI+8bSVKYCJrSmiWWCLsbUxiBSp4t9v0hNBTGY97bT72ydDIDyGSFWfwXg==", + "license": "MIT", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/use-isomorphic-layout-effect": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", diff --git a/package.json b/package.json index 55c2e5ba..8adf6787 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react-select": "^5.10.2", "swr": "^2.3.6", "tailwind-merge": "^3.3.1", + "use-debounce": "^10.0.6", "yup": "^1.7.0", "zustand": "^5.0.8" }, From 18027f0bb9910c5930392f55621beeab1f740343 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 11:31:23 +0700 Subject: [PATCH 052/327] chore(FE-43): get setPageSize from table object --- src/components/Table.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index ef99f6a7..100fb595 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -121,6 +121,7 @@ const Table = ({ } const table = useReactTable(tableOptions); + const { setPageSize } = table; const prevPageClickHandler = () => { table.previousPage(); @@ -149,8 +150,8 @@ const Table = ({ }; useEffect(() => { - table.setPageSize(pageSize); - }, [pageSize]); + setPageSize(pageSize); + }, [pageSize, setPageSize]); return (
    From 20f6686afc4a5ea02b2fb2b7c1a1f977037e7b2b Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:08:08 +0700 Subject: [PATCH 053/327] chore(FE-43): add sorting and setSorting props --- src/components/Table.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 100fb595..882c1fe1 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -11,6 +11,8 @@ import { useReactTable, ColumnDef, FilterFn, + SortingState, + OnChangeFn, } from '@tanstack/react-table'; import { rankItem } from '@tanstack/match-sorter-utils'; import { Icon } from '@iconify/react'; @@ -43,6 +45,8 @@ export interface TableProps { onFuzzySearchValueChange?: (value: string) => void; className?: TableClassNames; emptyContent?: ReactNode; + sorting?: SortingState; + setSorting?: OnChangeFn; } const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; @@ -78,6 +82,8 @@ const Table = ({ paginationClassName: '', }, emptyContent = emptyContentDefaultValue, + sorting, + setSorting, }: TableProps) => { const isServerSideTable = totalItems !== undefined && @@ -105,9 +111,11 @@ const Table = ({ getSortedRowModel: getSortedRowModel(), getPaginationRowModel: getPaginationRowModel(), onPaginationChange: setPagination, + onSortingChange: setSorting, state: { pagination, globalFilter: fuzzySearchValue, + sorting, }, filterFns: { fuzzy: fuzzyFilter, From df1b4c29e55792069851ef22bd8ffc9736273703 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:13:49 +0700 Subject: [PATCH 054/327] feat(FE-43): create useTableFilter hooks --- src/services/hooks/useTableFilter.tsx | 246 ++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 src/services/hooks/useTableFilter.tsx diff --git a/src/services/hooks/useTableFilter.tsx b/src/services/hooks/useTableFilter.tsx new file mode 100644 index 00000000..d11d477f --- /dev/null +++ b/src/services/hooks/useTableFilter.tsx @@ -0,0 +1,246 @@ +import { useCallback, useMemo, useReducer } from 'react'; + +/** Core filter shape (page + pageSize) extended by your custom fields */ +export type TableFilterState> = { + page: number; + pageSize: number; +} & TExtra; + +type Action> = + | { type: 'SET_PAGE'; page: number } + | { type: 'SET_PAGE_SIZE'; pageSize: number; resetPage?: boolean } + | { type: 'SET_FILTERS'; filters: Partial; resetPage?: boolean } + | { + type: 'UPDATE_FILTER'; + key: keyof TExtra; + value: TExtra[keyof TExtra]; + resetPage?: boolean; + } + | { type: 'REPLACE_ALL'; next: TableFilterState } + | { type: 'RESET' }; + +export type UseTableFilterOptions> = { + /** Initial state; anything you omit falls back to defaults */ + initial?: Partial>; + /** Called after any state change */ + onChange?: (state: TableFilterState) => void; + /** Default page size (if not provided in initial) */ + defaultPageSize?: number; + /** Optional mapping to rename keys when exporting to URL (e.g., { pageSize: "rows" }) */ + paramMap?: Partial, string>>; + /** If true, `toSearchParams`/`toQueryString` will omit values equal to defaults */ + omitDefaultsInUrl?: boolean; +}; + +function clampToInt(n: number, min = 1) { + const v = Number.isFinite(n) ? Math.floor(n) : min; + return v < min ? min : v; +} + +function createInitialState>( + opts: UseTableFilterOptions | undefined +): TableFilterState { + const defaults = { + page: 1, + pageSize: opts?.defaultPageSize ?? 10, + } as TableFilterState; + + return { + ...defaults, + ...(opts?.initial as object), + } as TableFilterState; +} + +function serializeValue(v: unknown): string | null { + if (v === undefined || v === null) return null; + if (v instanceof Date) return v.toISOString(); + if (Array.isArray(v)) return v.map((x) => x ?? '').join(','); // e.g., ids=1,2,3 + const t = typeof v; + if (t === 'string' || t === 'number' || t === 'boolean') return String(v); + try { + return JSON.stringify(v); + } catch { + return null; + } +} + +// function shallowEqual(a: unknown, b: unknown): boolean { +// if (a === b) return true; +// if (!a || !b) return false; +// const ka = Object.keys(a); +// const kb = Object.keys(b); +// if (ka.length !== kb.length) return false; +// for (const k of ka) if (a[k] !== b[k]) return false; +// return true; +// } + +function shallowEqual>( + a: T | undefined | null, + b: T | undefined | null +): boolean { + if (a === b) return true; + if (!a || !b) return false; + const ka = Object.keys(a) as (keyof T)[]; + const kb = Object.keys(b) as (keyof T)[]; + if (ka.length !== kb.length) return false; + for (const k of ka) if (a[k] !== b[k]) return false; + return true; +} + +export function useTableFilter>( + options?: UseTableFilterOptions +) { + const defaults = useMemo( + () => createInitialState(options), + [options] + ); + + const [state, dispatch] = useReducer( + ( + s: TableFilterState, + a: Action + ): TableFilterState => { + switch (a.type) { + case 'SET_PAGE': + return { ...s, page: clampToInt(a.page) }; + case 'SET_PAGE_SIZE': { + const pageSize = clampToInt(a.pageSize); + const page = a.resetPage ? 1 : s.page; + return { ...s, pageSize, page }; + } + case 'SET_FILTERS': { + const page = a.resetPage ? 1 : s.page; + return { ...s, ...a.filters, page }; + } + case 'UPDATE_FILTER': { + const page = a.resetPage ? 1 : s.page; + return { ...s, [a.key]: a.value, page } as TableFilterState; + } + case 'REPLACE_ALL': + return { + ...a.next, + page: clampToInt(a.next.page), + pageSize: clampToInt(a.next.pageSize), + }; + case 'RESET': + return defaults; + default: + return s; + } + }, + defaults + ); + + // Notify consumer on change (stable ref) + const onChange = options?.onChange; + useMemo(() => { + if (onChange) onChange(state); + }, [state, onChange]); + + // Helpers (stable) + const setPage = useCallback((page: number) => { + dispatch({ type: 'SET_PAGE', page }); + }, []); + + const setPageSize = useCallback((pageSize: number, resetPage = true) => { + dispatch({ type: 'SET_PAGE_SIZE', pageSize, resetPage }); + }, []); + + const setFilters = useCallback( + (filters: Partial, resetPage = true) => { + dispatch({ type: 'SET_FILTERS', filters, resetPage }); + }, + [] + ); + + const updateFilter = useCallback( + (key: K, value: TExtra[K], resetPage = true) => { + dispatch({ type: 'UPDATE_FILTER', key, value, resetPage }); + }, + [dispatch] + ); + + const replaceAll = useCallback((next: TableFilterState) => { + dispatch({ type: 'REPLACE_ALL', next }); + }, []); + + const reset = useCallback(() => dispatch({ type: 'RESET' }), []); + + const core = useMemo( + () => ({ page: state.page, pageSize: state.pageSize }), + [state.page, state.pageSize] + ); + + const extras = useMemo(() => { + const { page, pageSize, ...rest } = state as TableFilterState< + Record + >; + return rest as TExtra; + }, [state]); + + /** Map a key using paramMap (if provided) */ + const mapKey = useCallback( + (key: string) => { + const m = options?.paramMap as Record | undefined; + return (m && m[key]) || key; + }, + [options?.paramMap] + ); + + /** Build URLSearchParams from current state */ + const toSearchParams = useCallback(() => { + const params = new URLSearchParams(); + const source = state as Record; + const baseline = options?.omitDefaultsInUrl + ? (defaults as Record) + : null; + + for (const key of Object.keys(source)) { + const value = source[key]; + if (value === undefined || value === null) continue; + + if ( + baseline && + shallowEqual( + value as Record, + baseline[key] as Record + ) + ) { + continue; + } + + const mapped = mapKey(key); + const serialized = serializeValue(value); + if (serialized !== null) params.set(mapped, serialized); + } + return params; + }, [state, defaults, options?.omitDefaultsInUrl, mapKey]); + + /** Build query string (prefixed with '?', or empty string if none) */ + const toQueryString = useCallback(() => { + const sp = toSearchParams(); + const s = sp.toString(); + return s ? `?${s}` : ''; + }, [toSearchParams]); + + return { + /** Full state (page, pageSize, and extras) */ + state, + /** Convenience accessors */ + page: state.page, + pageSize: state.pageSize, + filters: extras, + /** Setters */ + setPage, + setPageSize, + setFilters, + updateFilter, + replaceAll, + reset, + /** Sometimes handy to have just the core pair */ + core, + /** URL helpers */ + toSearchParams, + toQueryString, + }; +} From fa5d09e4fbed13cfe292d6cc006ed3c387b39f98 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:14:18 +0700 Subject: [PATCH 055/327] chore(FE-40): add Toaster component in root layout --- src/app/layout.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 8843cc64..ef28da38 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata, Viewport } from 'next'; import { Inter } from 'next/font/google'; import '@/app/globals.css'; +import { Toaster } from 'react-hot-toast'; import MainDrawer from '@/components/MainDrawer'; import RequireAuth from '@/components/helper/RequireAuth'; @@ -32,6 +33,8 @@ export default function RootLayout({ {children} + + ); From 56476c7dd99d5354189dd18a1a668228ff724028 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:14:47 +0700 Subject: [PATCH 056/327] chore(FE-40): adjust loading dots size --- src/components/Button.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Button.tsx b/src/components/Button.tsx index a74a7e4f..c67a29c2 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -61,7 +61,7 @@ const Button = ({ )} > {!isLoading && children} - {isLoading && } + {isLoading && } )} @@ -76,7 +76,7 @@ const Button = ({ )} > {!isLoading && children} - {isLoading && } + {isLoading && } )} From ae159b9617e7beea83bc3b84bf7e8344325c6c20 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:15:06 +0700 Subject: [PATCH 057/327] chore(FE-40): remove unnecessary dependencies --- src/components/input/DebouncedTextInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/input/DebouncedTextInput.tsx b/src/components/input/DebouncedTextInput.tsx index 61dbf61c..4b62aaf7 100644 --- a/src/components/input/DebouncedTextInput.tsx +++ b/src/components/input/DebouncedTextInput.tsx @@ -28,7 +28,7 @@ const DebouncedTextInput = (props: DebouncedTextInputProps) => { if (debouncedChangeEvent) { onChange?.(debouncedChangeEvent); } - }, [debouncedValue, debouncedChangeEvent, onChange]); + }, [debouncedValue]); return ( Date: Sat, 4 Oct 2025 12:17:17 +0700 Subject: [PATCH 058/327] feat(FE-40): create ConfirmationModal component --- src/components/modal/ConfirmationModal.tsx | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/components/modal/ConfirmationModal.tsx diff --git a/src/components/modal/ConfirmationModal.tsx b/src/components/modal/ConfirmationModal.tsx new file mode 100644 index 00000000..04c221e6 --- /dev/null +++ b/src/components/modal/ConfirmationModal.tsx @@ -0,0 +1,124 @@ +'use client'; + +import { RefObject } from 'react'; + +import { Icon } from '@iconify/react'; +import Modal from '@/components/Modal'; +import Button from '@/components/Button'; + +import { cn } from '@/lib/helper'; +import { Color } from '@/types/theme'; + +interface ConfirmationModalProps { + ref: RefObject; + type?: 'info' | 'success' | 'error'; + text?: string; + closeOnBackdrop?: boolean; + primaryButton?: { + text?: string; + color?: Color; + isLoading?: boolean; + onClick?: () => void; + }; + secondaryButton?: { + text?: string; + color?: Color; + isLoading?: boolean; + onClick?: () => void; + }; + className?: { + modal?: string; + modalBox?: string; + }; +} + +const ConfirmationModal = ({ + ref, + type = 'info', + text, + closeOnBackdrop, + primaryButton, + secondaryButton, + className, +}: ConfirmationModalProps) => { + const closeModalHandler = () => { + ref.current?.close(); + }; + + return ( + +
    +
    + {type === 'info' && ( + + )} + + {type === 'success' && ( + + )} + + {type === 'error' && ( + + )} +
    + +

    + {text ?? 'Apakah anda yakin ingin melakukan hal ini?'} +

    + +
    + {secondaryButton && secondaryButton.text && ( + + )} + + {primaryButton && primaryButton.text && ( + + )} +
    +
    +
    + ); +}; + +export default ConfirmationModal; From e259d1720c9583f0da9e3e7e8e6b66505fe098a4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:17:42 +0700 Subject: [PATCH 059/327] feat(FE-43): create UomsTable component --- .../pages/master-data/uom/UomsTable.tsx | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/components/pages/master-data/uom/UomsTable.tsx diff --git a/src/components/pages/master-data/uom/UomsTable.tsx b/src/components/pages/master-data/uom/UomsTable.tsx new file mode 100644 index 00000000..080dfaf8 --- /dev/null +++ b/src/components/pages/master-data/uom/UomsTable.tsx @@ -0,0 +1,276 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Uom } from '@/types/api/master-data/uom'; +import { UomApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const UomsTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '' }, + paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + }); + + const { + data: uoms, + isLoading, + mutate: refreshUoms, + } = useSWR( + `${UomApi.basePath}${getTableFilterQueryString()}`, + UomApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedUom, setSelectedUom] = useState(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const uomsColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedUom(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await UomApi.delete(selectedUom?.id as number); + refreshUoms(); + + deleteModal.closeModal(); + toast.success('Successfully delete UOM!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(uoms) ? uoms?.data : []} + columns={uomsColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(uoms) ? uoms?.meta?.page : 0} + totalItems={isResponseSuccess(uoms) ? uoms?.meta?.total_results : 0} + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': isResponseSuccess(uoms) && uoms?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default UomsTable; From 36113f6c2ad839a0c47f5dfb9762598ac6687701 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:18:15 +0700 Subject: [PATCH 060/327] feat(FE-40,41): create UomForm component --- .../pages/master-data/uom/form/UomForm.tsx | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/components/pages/master-data/uom/form/UomForm.tsx diff --git a/src/components/pages/master-data/uom/form/UomForm.tsx b/src/components/pages/master-data/uom/form/UomForm.tsx new file mode 100644 index 00000000..87cbdf34 --- /dev/null +++ b/src/components/pages/master-data/uom/form/UomForm.tsx @@ -0,0 +1,174 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; + +import { + UomFormSchema, + UomFormValues, + UpdateUomFormSchema, +} from '@/components/pages/master-data/uom/form/UomForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + CreateUomPayload, + Uom, + UpdateUomPayload, +} from '@/types/api/master-data/uom'; +import { UomApi } from '@/services/api/master-data'; + +interface UomFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Uom; +} + +const UomForm = ({ type = 'add', initialValues }: UomFormProps) => { + const router = useRouter(); + + const [uomFormErrorMessage, setUomFormErrorMessage] = useState(''); + + const createUomHandler = useCallback( + async (payload: CreateUomPayload) => { + const createUomRes = await UomApi.create(payload); + + if (isResponseError(createUomRes)) { + setUomFormErrorMessage(createUomRes.message); + return; + } + + toast.success(createUomRes?.message as string); + router.push('/master-data/uom'); + }, + [router] + ); + + const updateUomHandler = useCallback( + async (uomId: number, payload: UpdateUomPayload) => { + const updateUomRes = await UomApi.update(uomId, payload); + + if (updateUomRes?.status === 'error') { + setUomFormErrorMessage(updateUomRes.message); + return; + } + + toast.success(updateUomRes?.message as string); + router.refresh(); + router.push('/master-data/uom'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateUomFormSchema : UomFormSchema, + onSubmit: async (values) => { + setUomFormErrorMessage(''); + + const uomPayload: CreateUomPayload = { + name: values.name, + }; + + switch (type) { + case 'add': + await createUomHandler(uomPayload); + break; + + case 'edit': + await updateUomHandler(initialValues?.id as number, uomPayload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( +
    +
    + + +

    + {type === 'add' && 'Tambah UOM'} + {type === 'edit' && 'Edit UOM'} + {type === 'detail' && 'Detail UOM'} +

    +
    + +
    +
    + +
    + + {type !== 'detail' && ( + <> +
    + + + +
    + + {uomFormErrorMessage && ( +
    + + {uomFormErrorMessage} +
    + )} + + )} +
    +
    + ); +}; + +export default UomForm; From f1a8fda6678b01221902da1e2963978413856b10 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:18:39 +0700 Subject: [PATCH 061/327] feat(FE-42): create UOM form validation schema --- .../pages/master-data/uom/form/UomForm.schema.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/components/pages/master-data/uom/form/UomForm.schema.ts diff --git a/src/components/pages/master-data/uom/form/UomForm.schema.ts b/src/components/pages/master-data/uom/form/UomForm.schema.ts new file mode 100644 index 00000000..e7cb5d06 --- /dev/null +++ b/src/components/pages/master-data/uom/form/UomForm.schema.ts @@ -0,0 +1,9 @@ +import * as Yup from 'yup'; + +export const UomFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), +}); + +export const UpdateUomFormSchema = UomFormSchema; + +export type UomFormValues = Yup.InferType; From 34e9e6017388e1363089f50da7edc9fb748aaca7 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:19:01 +0700 Subject: [PATCH 062/327] feat(FE-43): create RowCollapseOptions component --- src/components/table/RowCollapseOptions.tsx | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/components/table/RowCollapseOptions.tsx diff --git a/src/components/table/RowCollapseOptions.tsx b/src/components/table/RowCollapseOptions.tsx new file mode 100644 index 00000000..42f9720a --- /dev/null +++ b/src/components/table/RowCollapseOptions.tsx @@ -0,0 +1,27 @@ +import { ReactNode } from 'react'; + +import { Icon } from '@iconify/react'; +import Collapse from '@/components/Collapse'; +import Button from '@/components/Button'; + +interface RowCollapseOptionsProps { + children?: ReactNode; +} + +const RowCollapseOptions = ({ children }: RowCollapseOptionsProps) => { + return ( + + + + } + className='w-fit' + titleClassName='p-0! justify-self-end' + > + {children} + + ); +}; + +export default RowCollapseOptions; From 65e3833cd51ca78a66d32d4d82b20365d354eea5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:19:15 +0700 Subject: [PATCH 063/327] feat(FE-43): create RowDropdownOptions component --- src/components/table/RowDropdownOptions.tsx | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/components/table/RowDropdownOptions.tsx diff --git a/src/components/table/RowDropdownOptions.tsx b/src/components/table/RowDropdownOptions.tsx new file mode 100644 index 00000000..1f1bc81b --- /dev/null +++ b/src/components/table/RowDropdownOptions.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from 'react'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; + +import { cn } from '@/lib/helper'; + +interface RowDropdownOptionsProps { + children?: ReactNode; + isLast2Rows: boolean; +} + +const RowDropdownOptions = ({ + children, + isLast2Rows, +}: RowDropdownOptionsProps) => { + return ( +
    + + + {children} +
    + ); +}; + +export default RowDropdownOptions; From 6a396ccce6953bf9b261c75e6928bc23796ee0b8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:19:52 +0700 Subject: [PATCH 064/327] feat(FE-43): create Master Data UOM page --- src/app/master-data/uom/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/uom/page.tsx diff --git a/src/app/master-data/uom/page.tsx b/src/app/master-data/uom/page.tsx new file mode 100644 index 00000000..689b9d0d --- /dev/null +++ b/src/app/master-data/uom/page.tsx @@ -0,0 +1,11 @@ +import UomsTable from '@/components/pages/master-data/uom/UomsTable'; + +const Nonstock = () => { + return ( +
    + +
    + ); +}; + +export default Nonstock; From f27b261869fff3ac00d41ee8433407913a25dc19 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:20:19 +0700 Subject: [PATCH 065/327] feat(FE-40,41): create Master Data Add UOM page --- src/app/master-data/uom/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/uom/add/page.tsx diff --git a/src/app/master-data/uom/add/page.tsx b/src/app/master-data/uom/add/page.tsx new file mode 100644 index 00000000..452aadf8 --- /dev/null +++ b/src/app/master-data/uom/add/page.tsx @@ -0,0 +1,11 @@ +import UomForm from '@/components/pages/master-data/uom/form/UomForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From e6c14f57d9f14956273cbe9ef72c6e4be8d3d845 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:21:14 +0700 Subject: [PATCH 066/327] feat(FE-40,41): create Master Data Detail UOM page --- src/app/master-data/uom/detail/page.tsx | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/app/master-data/uom/detail/page.tsx diff --git a/src/app/master-data/uom/detail/page.tsx b/src/app/master-data/uom/detail/page.tsx new file mode 100644 index 00000000..59ad0755 --- /dev/null +++ b/src/app/master-data/uom/detail/page.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import UomForm from '@/components/pages/master-data/uom/form/UomForm'; + +import { UomApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const UomDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const uomId = searchParams.get('uomId'); + + const { data: uom, isLoading: isLoadingUom } = useSWR(uomId, (id: number) => + UomApi.getSingle(id) + ); + + if (!uomId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingUom && !uom) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingUom && } + {!isLoadingUom && isResponseSuccess(uom) && ( + + )} +
    + ); +}; + +export default UomDetail; From d941674f9a66fb9e3279d03a6bad2127fa6304b6 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:21:38 +0700 Subject: [PATCH 067/327] feat(FE-40,41): create Master Data Edit UOM page --- src/app/master-data/uom/detail/edit/page.tsx | 46 ++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/app/master-data/uom/detail/edit/page.tsx diff --git a/src/app/master-data/uom/detail/edit/page.tsx b/src/app/master-data/uom/detail/edit/page.tsx new file mode 100644 index 00000000..95566351 --- /dev/null +++ b/src/app/master-data/uom/detail/edit/page.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import UomForm from '@/components/pages/master-data/uom/form/UomForm'; + +import { UomApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const UomEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const uomId = searchParams.get('uomId'); + + const { data: uom, isLoading: isLoadingUom } = useSWR(uomId, (id: number) => + UomApi.getSingle(id) + ); + + if (!uomId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingUom && !uom) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingUom && } + {!isLoadingUom && isResponseSuccess(uom) && ( + + )} +
    + ); +}; + +export default UomEdit; From b5d9c55fbc78c22f15af2e1f7ee31e3cca767e4b Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:22:00 +0700 Subject: [PATCH 068/327] chore(FE-41): create UOM type --- src/types/api/master-data/uom.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/types/api/master-data/uom.ts diff --git a/src/types/api/master-data/uom.ts b/src/types/api/master-data/uom.ts new file mode 100644 index 00000000..394f6050 --- /dev/null +++ b/src/types/api/master-data/uom.ts @@ -0,0 +1,12 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type Uom = BaseMetadata & { + id: number; + name: string; +}; + +export type CreateUomPayload = { + name: string; +}; + +export type UpdateUomPayload = CreateUomPayload; From 6dec9268c95641820fd38ad766f34d2734e42f04 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:22:25 +0700 Subject: [PATCH 069/327] feat(FE-41): create Master Data API Service class --- src/services/api/master-data.ts | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/services/api/master-data.ts diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts new file mode 100644 index 00000000..10d7bbee --- /dev/null +++ b/src/services/api/master-data.ts @@ -0,0 +1,93 @@ +import axios from 'axios'; +import { httpClient, httpClientFetcher } from '@/services/http/client'; +import { BaseApiResponse } from '@/types/api/api-general'; +import { + CreateUomPayload, + Uom, + UpdateUomPayload, +} from '@/types/api/master-data/uom'; + +export class MasterDataApi { + basePath: string; + + constructor(basePath: string) { + this.basePath = basePath; + } + + async getAllFetcher(endpoint: string): Promise> { + return await httpClientFetcher>(endpoint); + } + + async getSingle(id: number) { + try { + const getSinglePath = `${this.basePath}/${id}`; + const getSingleRes = await httpClient>(getSinglePath); + + return getSingleRes; + } catch (error) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async create(payload: CreatePayloadGeneric) { + try { + const createRes = await httpClient>(this.basePath, { + method: 'POST', + body: payload, + }); + + return createRes; + } catch (error: unknown) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async update(id: number, payload: UpdatePayloadGeneric) { + try { + const updatePath = `${this.basePath}/${id}`; + const updateRes = await httpClient>(updatePath, { + method: 'PATCH', + body: payload, + }); + + return updateRes; + } catch (error: unknown) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async delete(id: number) { + try { + const deletePath = `${this.basePath}/${id}`; + const deleteRes = await httpClient(deletePath, { + method: 'DELETE', + }); + + return deleteRes; + } catch (error) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } + } +} + +export const UomApi = new MasterDataApi< + Uom, + CreateUomPayload, + UpdateUomPayload +>('/master-data/uoms'); From bbe55ee4c38b8cb8f8804982b5b54b57e7bdc0c8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:22:43 +0700 Subject: [PATCH 070/327] chore(FE-43): add ROWS_OPTIONS constant --- src/config/constant.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/config/constant.ts b/src/config/constant.ts index 1abf588a..269f5da9 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -72,4 +72,23 @@ export const MAIN_DRAWER_LINKS = [ }, ], }, +] as const; + +export const ROWS_OPTIONS = [ + { + label: '10', + value: 10, + }, + { + label: '20', + value: 20, + }, + { + label: '50', + value: 50, + }, + { + label: '100', + value: 100, + }, ]; From d29d1f27f8760aade741a64a27750d4b26e987b4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:23:14 +0700 Subject: [PATCH 071/327] chore(FE-41): create CreatedUser and BaseMetadata type --- src/types/api/api-general.d.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/types/api/api-general.d.ts b/src/types/api/api-general.d.ts index 90df754b..f33b94ee 100644 --- a/src/types/api/api-general.d.ts +++ b/src/types/api/api-general.d.ts @@ -37,3 +37,16 @@ export type User = { export type UserWithRoles = User & { roles: RoleWithPermissions[]; }; + +export type CreatedUser = { + id: number; + id_user: number; + email: string; + name: string; +}; + +export type BaseMetadata = { + created_user: CreatedUser; + created_at: string; + updated_at: string; +}; From 777f0f5e8132311007bd10c6fdd281796d060901 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 12:23:31 +0700 Subject: [PATCH 072/327] feat(FE-40): add none type to Color --- src/types/theme.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/types/theme.d.ts b/src/types/theme.d.ts index cff880fd..f83750e4 100644 --- a/src/types/theme.d.ts +++ b/src/types/theme.d.ts @@ -6,6 +6,7 @@ type Color = | 'info' | 'success' | 'warning' - | 'error'; + | 'error' + | 'none'; export { Color }; From eebc9940cc71f39965761a7cb603cbfffb445431 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:55:28 +0700 Subject: [PATCH 073/327] feat(FE-43): create AreasTable component --- .../pages/master-data/area/AreasTable.tsx | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/components/pages/master-data/area/AreasTable.tsx diff --git a/src/components/pages/master-data/area/AreasTable.tsx b/src/components/pages/master-data/area/AreasTable.tsx new file mode 100644 index 00000000..4d0bec73 --- /dev/null +++ b/src/components/pages/master-data/area/AreasTable.tsx @@ -0,0 +1,276 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Area } from '@/types/api/master-data/area'; +import { AreaApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const AreasTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '' }, + paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + }); + + const { + data: areas, + isLoading, + mutate: refreshAreas, + } = useSWR( + `${AreaApi.basePath}${getTableFilterQueryString()}`, + AreaApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedArea, setSelectedArea] = useState(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const areasColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedArea(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await AreaApi.delete(selectedArea?.id as number); + refreshAreas(); + + deleteModal.closeModal(); + toast.success('Successfully delete Area!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(areas) ? areas?.data : []} + columns={areasColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(areas) ? areas?.meta?.page : 0} + totalItems={isResponseSuccess(areas) ? areas?.meta?.total_results : 0} + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': isResponseSuccess(areas) && areas?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default AreasTable; From b82637fb3b01988838fa85a507849d0a9f460b16 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:55:52 +0700 Subject: [PATCH 074/327] feat(FE-40,41): create AreaForm component --- .../pages/master-data/area/form/AreaForm.tsx | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 src/components/pages/master-data/area/form/AreaForm.tsx diff --git a/src/components/pages/master-data/area/form/AreaForm.tsx b/src/components/pages/master-data/area/form/AreaForm.tsx new file mode 100644 index 00000000..6cdb4c5d --- /dev/null +++ b/src/components/pages/master-data/area/form/AreaForm.tsx @@ -0,0 +1,236 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + AreaFormSchema, + AreaFormValues, + UpdateAreaFormSchema, +} from '@/components/pages/master-data/area/form/AreaForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + Area, + CreateAreaPayload, + UpdateAreaPayload, +} from '@/types/api/master-data/area'; +import { AreaApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; + +interface AreaFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Area; +} + +const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [areaFormErrorMessage, setAreaFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createAreaHandler = useCallback( + async (payload: CreateAreaPayload) => { + const createAreaRes = await AreaApi.create(payload); + + if (isResponseError(createAreaRes)) { + setAreaFormErrorMessage(createAreaRes.message); + return; + } + + toast.success(createAreaRes?.message as string); + router.push('/master-data/area'); + }, + [router] + ); + + const updateAreaHandler = useCallback( + async (areaId: number, payload: UpdateAreaPayload) => { + const updateAreaRes = await AreaApi.update(areaId, payload); + + if (updateAreaRes?.status === 'error') { + setAreaFormErrorMessage(updateAreaRes.message); + return; + } + + toast.success(updateAreaRes?.message as string); + router.refresh(); + router.push('/master-data/area'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateAreaFormSchema : AreaFormSchema, + onSubmit: async (values) => { + setAreaFormErrorMessage(''); + + const areaPayload: CreateAreaPayload = { + name: values.name, + }; + + switch (type) { + case 'add': + await createAreaHandler(areaPayload); + break; + + case 'edit': + await updateAreaHandler(initialValues?.id as number, areaPayload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + const deleteAreaClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await AreaApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Area!'); + setIsDeleteLoading(false); + router.push('/master-data/area'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Area'} + {type === 'edit' && 'Edit Area'} + {type === 'detail' && 'Detail Area'} +

    +
    + +
    +
    + +
    + +
    + {type !== 'add' && ( +
    + +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {areaFormErrorMessage && ( +
    + + {areaFormErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default AreaForm; From 211951132aecfe01d5d018338bec36785d4af31c Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:56:17 +0700 Subject: [PATCH 075/327] feat(FE-42): create Area form validation schema --- .../pages/master-data/area/form/AreaForm.schema.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/components/pages/master-data/area/form/AreaForm.schema.ts diff --git a/src/components/pages/master-data/area/form/AreaForm.schema.ts b/src/components/pages/master-data/area/form/AreaForm.schema.ts new file mode 100644 index 00000000..96c70243 --- /dev/null +++ b/src/components/pages/master-data/area/form/AreaForm.schema.ts @@ -0,0 +1,9 @@ +import * as Yup from 'yup'; + +export const AreaFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), +}); + +export const UpdateAreaFormSchema = AreaFormSchema; + +export type AreaFormValues = Yup.InferType; From c494f8dbd5158debc9c6d5e35701e37e90f1acfb Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:56:51 +0700 Subject: [PATCH 076/327] feat(FE-41): create Area type --- src/types/api/master-data/area.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/types/api/master-data/area.ts diff --git a/src/types/api/master-data/area.ts b/src/types/api/master-data/area.ts new file mode 100644 index 00000000..e9db38db --- /dev/null +++ b/src/types/api/master-data/area.ts @@ -0,0 +1,12 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type Area = BaseMetadata & { + id: number; + name: string; +}; + +export type CreateAreaPayload = { + name: string; +}; + +export type UpdateAreaPayload = CreateAreaPayload; From 6dd6147c29d0f3899498a65408e1c5fd7b837623 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:57:05 +0700 Subject: [PATCH 077/327] feat(FE-41): create AreaApi service --- src/services/api/master-data.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 10d7bbee..941fa77b 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -6,6 +6,11 @@ import { Uom, UpdateUomPayload, } from '@/types/api/master-data/uom'; +import { + Area, + CreateAreaPayload, + UpdateAreaPayload, +} from '@/types/api/master-data/area'; export class MasterDataApi { basePath: string; @@ -91,3 +96,9 @@ export const UomApi = new MasterDataApi< CreateUomPayload, UpdateUomPayload >('/master-data/uoms'); + +export const AreaApi = new MasterDataApi< + Area, + CreateAreaPayload, + UpdateAreaPayload +>('/master-data/areas'); From 4bf4981fd4587613fabcc830f173f9bcee451a23 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:57:21 +0700 Subject: [PATCH 078/327] feat(FE-43): create Master Data Area page --- src/app/master-data/area/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/area/page.tsx diff --git a/src/app/master-data/area/page.tsx b/src/app/master-data/area/page.tsx new file mode 100644 index 00000000..f8789af2 --- /dev/null +++ b/src/app/master-data/area/page.tsx @@ -0,0 +1,11 @@ +import AreasTable from '@/components/pages/master-data/area/AreasTable'; + +const Nonstock = () => { + return ( +
    + +
    + ); +}; + +export default Nonstock; From 69ecacc1be17f88b83a82c83a95d2d9a0292f617 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:57:48 +0700 Subject: [PATCH 079/327] feat(FE-40,41): create Master Data Add Area page --- src/app/master-data/area/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/area/add/page.tsx diff --git a/src/app/master-data/area/add/page.tsx b/src/app/master-data/area/add/page.tsx new file mode 100644 index 00000000..ed23b0b7 --- /dev/null +++ b/src/app/master-data/area/add/page.tsx @@ -0,0 +1,11 @@ +import AreaForm from '@/components/pages/master-data/area/form/AreaForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From 172d8efd8e88061b9c053fceecf41297079db4a6 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:58:11 +0700 Subject: [PATCH 080/327] feat(FE-40,41): create Master Data Detail Area page --- src/app/master-data/area/detail/page.tsx | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/app/master-data/area/detail/page.tsx diff --git a/src/app/master-data/area/detail/page.tsx b/src/app/master-data/area/detail/page.tsx new file mode 100644 index 00000000..55bfbc7d --- /dev/null +++ b/src/app/master-data/area/detail/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import AreaForm from '@/components/pages/master-data/area/form/AreaForm'; + +import { AreaApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const AreaDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const areaId = searchParams.get('areaId'); + + const { data: area, isLoading: isLoadingArea } = useSWR( + areaId, + (id: number) => AreaApi.getSingle(id) + ); + + if (!areaId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingArea && !area) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingArea && } + {!isLoadingArea && isResponseSuccess(area) && ( + + )} +
    + ); +}; + +export default AreaDetail; From 9ba7b5dba4f5b4dcb672cd4f2fcd495e2857d2f5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 13:58:53 +0700 Subject: [PATCH 081/327] feat(FE-40,41): create Master Data Edit Area page --- src/app/master-data/area/detail/edit/page.tsx | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/app/master-data/area/detail/edit/page.tsx diff --git a/src/app/master-data/area/detail/edit/page.tsx b/src/app/master-data/area/detail/edit/page.tsx new file mode 100644 index 00000000..a8b5138f --- /dev/null +++ b/src/app/master-data/area/detail/edit/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import AreaForm from '@/components/pages/master-data/area/form/AreaForm'; + +import { AreaApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const AreaEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const areaId = searchParams.get('areaId'); + + const { data: area, isLoading: isLoadingArea } = useSWR( + areaId, + (id: number) => AreaApi.getSingle(id) + ); + + if (!areaId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingArea && !area) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingArea && } + {!isLoadingArea && isResponseSuccess(area) && ( + + )} +
    + ); +}; + +export default AreaEdit; From 73cefbb7a31b654e26da4474e872f42b56fa30e6 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:03:27 +0700 Subject: [PATCH 082/327] chore(FE-40): change delete confirmation modal text --- src/components/pages/master-data/area/form/AreaForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pages/master-data/area/form/AreaForm.tsx b/src/components/pages/master-data/area/form/AreaForm.tsx index 6cdb4c5d..d61b1b84 100644 --- a/src/components/pages/master-data/area/form/AreaForm.tsx +++ b/src/components/pages/master-data/area/form/AreaForm.tsx @@ -217,7 +217,7 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => { Date: Sat, 4 Oct 2025 14:03:53 +0700 Subject: [PATCH 083/327] chore(FE-40): add delete button and delete confirmation modal --- .../pages/master-data/uom/form/UomForm.tsx | 194 ++++++++++++------ 1 file changed, 128 insertions(+), 66 deletions(-) diff --git a/src/components/pages/master-data/uom/form/UomForm.tsx b/src/components/pages/master-data/uom/form/UomForm.tsx index 87cbdf34..8ece22a8 100644 --- a/src/components/pages/master-data/uom/form/UomForm.tsx +++ b/src/components/pages/master-data/uom/form/UomForm.tsx @@ -8,6 +8,8 @@ import { toast } from 'react-hot-toast'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { UomFormSchema, @@ -21,6 +23,7 @@ import { UpdateUomPayload, } from '@/types/api/master-data/uom'; import { UomApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; interface UomFormProps { type?: 'add' | 'edit' | 'detail'; @@ -29,8 +32,10 @@ interface UomFormProps { const UomForm = ({ type = 'add', initialValues }: UomFormProps) => { const router = useRouter(); + const deleteModal = useModal(); const [uomFormErrorMessage, setUomFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); const createUomHandler = useCallback( async (payload: CreateUomPayload) => { @@ -93,81 +98,138 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => { const { setValues: formikSetValues } = formik; + const deleteUomClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await UomApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete UOM!'); + setIsDeleteLoading(false); + router.push('/master-data/uom'); + }; + useEffect(() => { formikSetValues(formikInitialValues); }, [formikSetValues, formikInitialValues]); return ( -
    -
    - + +

    + {type === 'add' && 'Tambah UOM'} + {type === 'edit' && 'Edit UOM'} + {type === 'detail' && 'Detail UOM'} +

    +
    + +
    - - Kembali - +
    + +
    -

    - {type === 'add' && 'Tambah UOM'} - {type === 'edit' && 'Edit UOM'} - {type === 'detail' && 'Detail UOM'} -

    - - - -
    - -
    - - {type !== 'detail' && ( - <> -
    - - - -
    - - {uomFormErrorMessage && ( -
    - - {uomFormErrorMessage} +
    + {type !== 'add' && ( +
    +
    )} - - )} - -
    + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {uomFormErrorMessage && ( +
    + + {uomFormErrorMessage} +
    + )} + + + + {type !== 'add' && ( + + )} + ); }; From e1c34cf0fb2a60d9ae58d0a3c80032d904905808 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:08:53 +0700 Subject: [PATCH 084/327] chore(FE-41): create BaseUom type --- src/types/api/master-data/uom.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types/api/master-data/uom.ts b/src/types/api/master-data/uom.ts index 394f6050..0d2f0210 100644 --- a/src/types/api/master-data/uom.ts +++ b/src/types/api/master-data/uom.ts @@ -1,10 +1,12 @@ import { BaseMetadata } from '@/types/api/api-general'; -export type Uom = BaseMetadata & { +export type BaseUom = { id: number; name: string; }; +export type Uom = BaseMetadata & BaseUom; + export type CreateUomPayload = { name: string; }; From a2345165c14f5566b59577401c0ef2422354712d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:09:03 +0700 Subject: [PATCH 085/327] chore(FE-41): create BaseArea type --- src/types/api/master-data/area.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types/api/master-data/area.ts b/src/types/api/master-data/area.ts index e9db38db..74e0196e 100644 --- a/src/types/api/master-data/area.ts +++ b/src/types/api/master-data/area.ts @@ -1,10 +1,12 @@ import { BaseMetadata } from '@/types/api/api-general'; -export type Area = BaseMetadata & { +export type BaseArea = { id: number; name: string; }; +export type Area = BaseMetadata & BaseArea; + export type CreateAreaPayload = { name: string; }; From 7ea599168cc65f64bbf8c1272aeb93cee5270912 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:25:29 +0700 Subject: [PATCH 086/327] chore(FE-43): add conditional to set sorting and setSorting and add manualSorting props --- src/components/Table.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index 882c1fe1..cfd77df6 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -47,6 +47,7 @@ export interface TableProps { emptyContent?: ReactNode; sorting?: SortingState; setSorting?: OnChangeFn; + manualSorting?: boolean; } const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; @@ -84,6 +85,7 @@ const Table = ({ emptyContent = emptyContentDefaultValue, sorting, setSorting, + manualSorting = false, }: TableProps) => { const isServerSideTable = totalItems !== undefined && @@ -111,11 +113,10 @@ const Table = ({ getSortedRowModel: getSortedRowModel(), getPaginationRowModel: getPaginationRowModel(), onPaginationChange: setPagination, - onSortingChange: setSorting, + manualSorting, state: { pagination, globalFilter: fuzzySearchValue, - sorting, }, filterFns: { fuzzy: fuzzyFilter, @@ -128,6 +129,14 @@ const Table = ({ tableOptions.getFilteredRowModel = getFilteredRowModel(); } + if (sorting && setSorting) { + tableOptions.onSortingChange = setSorting; + tableOptions.state = { + ...tableOptions.state, + sorting, + }; + } + const table = useReactTable(tableOptions); const { setPageSize } = table; From 8ed12578b437362119c19487e8cf17da82d8b5b4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:32:42 +0700 Subject: [PATCH 087/327] chore(FE-40): fix name input placeholder --- src/components/pages/master-data/area/form/AreaForm.tsx | 2 +- src/components/pages/master-data/nonstock/form/NonstockForm.tsx | 2 +- src/components/pages/master-data/uom/form/UomForm.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/pages/master-data/area/form/AreaForm.tsx b/src/components/pages/master-data/area/form/AreaForm.tsx index d61b1b84..d0a80105 100644 --- a/src/components/pages/master-data/area/form/AreaForm.tsx +++ b/src/components/pages/master-data/area/form/AreaForm.tsx @@ -147,7 +147,7 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => { required label='Nama' name='name' - placeholder='Masukkan nama user' + placeholder='Masukkan nama area' value={formik.values.name} onChange={formik.handleChange} onBlur={formik.handleBlur} diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx index bf2fce73..33dcba54 100644 --- a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx @@ -130,7 +130,7 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { required label='Nama' name='name' - placeholder='Masukkan nama user' + placeholder='Masukkan nama nonstock' value={formik.values.name} onChange={formik.handleChange} onBlur={formik.handleBlur} diff --git a/src/components/pages/master-data/uom/form/UomForm.tsx b/src/components/pages/master-data/uom/form/UomForm.tsx index 8ece22a8..da99f813 100644 --- a/src/components/pages/master-data/uom/form/UomForm.tsx +++ b/src/components/pages/master-data/uom/form/UomForm.tsx @@ -147,7 +147,7 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => { required label='Nama' name='name' - placeholder='Masukkan nama user' + placeholder='Masukkan nama UOM' value={formik.values.name} onChange={formik.handleChange} onBlur={formik.handleBlur} From 5b1dab286036614ed257d1707c77dd4287a6d536 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:53:05 +0700 Subject: [PATCH 088/327] feat(FE-40): add onInputChange prop --- src/components/input/SelectInput.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/components/input/SelectInput.tsx b/src/components/input/SelectInput.tsx index 5b6ae098..930b5ed5 100644 --- a/src/components/input/SelectInput.tsx +++ b/src/components/input/SelectInput.tsx @@ -1,8 +1,9 @@ 'use client'; -import { ComponentType, ReactNode, useMemo } from 'react'; -import Select, { OptionProps, GroupBase } from 'react-select'; +import { ComponentType, ReactNode, useEffect, useMemo, useState } from 'react'; +import Select, { OptionProps, GroupBase, InputActionMeta } from 'react-select'; import makeAnimated from 'react-select/animated'; +import { useDebounce } from 'use-debounce'; import { cn } from '@/lib/helper'; @@ -41,6 +42,8 @@ interface SelectInputProps { errorMessage?: string; isAnimated?: boolean; openMenu?: boolean; + delay?: number; + onInputChange?: (search: string) => void; } const animatedComponents = makeAnimated(); @@ -65,7 +68,13 @@ const SelectInput = ({ errorMessage, isAnimated = true, openMenu, + delay = 300, + onInputChange, }: SelectInputProps) => { + const [internalInputValue, setInternalInputValue] = useState(''); + + const [debouncedInputValue] = useDebounce(internalInputValue, delay ?? 300); + const components = useMemo(() => { const base = isAnimated ? animatedComponents : {}; @@ -75,6 +84,14 @@ const SelectInput = ({ }; }, [isAnimated]); + const internalInputChangeHandler = (value: string, meta: InputActionMeta) => { + if (meta.action === 'input-change') setInternalInputValue(value); + if (meta.action === 'menu-close') setInternalInputValue(''); + }; + + useEffect(() => { + onInputChange?.(debouncedInputValue); + }, [debouncedInputValue]); return (
    ({ onChange={(val) => onChange?.(val as T)} options={options} menuIsOpen={openMenu} + inputValue={internalInputValue} + onInputChange={internalInputChangeHandler} isMulti={isMulti} isDisabled={isDisabled} isLoading={isLoading} From d3977a0951f3808e8fc3820f043ad9d18d85944e Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:57:17 +0700 Subject: [PATCH 089/327] feat(FE-41): create Location type --- src/types/api/master-data/location.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/types/api/master-data/location.ts diff --git a/src/types/api/master-data/location.ts b/src/types/api/master-data/location.ts new file mode 100644 index 00000000..91912ab7 --- /dev/null +++ b/src/types/api/master-data/location.ts @@ -0,0 +1,19 @@ +import { BaseMetadata } from '@/types/api/api-general'; +import { BaseArea } from '@/types/api/master-data/area'; + +export type BaseLocation = { + id: number; + name: string; + address: string; + area: BaseArea; +}; + +export type Location = BaseMetadata & BaseLocation; + +export type CreateLocationPayload = { + name: string; + address: string; + area_id: number; +}; + +export type UpdateLocationPayload = CreateLocationPayload; From e7e5456d15ed3a44fbb45dc38acfcf12fa874397 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:57:43 +0700 Subject: [PATCH 090/327] feat(FE-41): create LocationApi service --- src/services/api/master-data.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 941fa77b..e1748c59 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -11,6 +11,11 @@ import { CreateAreaPayload, UpdateAreaPayload, } from '@/types/api/master-data/area'; +import { + CreateLocationPayload, + Location, + UpdateLocationPayload, +} from '@/types/api/master-data/location'; export class MasterDataApi { basePath: string; @@ -102,3 +107,9 @@ export const AreaApi = new MasterDataApi< CreateAreaPayload, UpdateAreaPayload >('/master-data/areas'); + +export const LocationApi = new MasterDataApi< + Location, + CreateLocationPayload, + UpdateLocationPayload +>('/master-data/locations'); From 3c0babb62bbfe1241283beea21b84298b1ae9d01 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:57:59 +0700 Subject: [PATCH 091/327] feat(FE-43): create LocationsTable component --- .../master-data/location/LocationsTable.tsx | 290 ++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 src/components/pages/master-data/location/LocationsTable.tsx diff --git a/src/components/pages/master-data/location/LocationsTable.tsx b/src/components/pages/master-data/location/LocationsTable.tsx new file mode 100644 index 00000000..2879d114 --- /dev/null +++ b/src/components/pages/master-data/location/LocationsTable.tsx @@ -0,0 +1,290 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Location } from '@/types/api/master-data/location'; +import { LocationApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const LocationsTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '' }, + paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + }); + + const { + data: locations, + isLoading, + mutate: refreshLocations, + } = useSWR( + `${LocationApi.basePath}${getTableFilterQueryString()}`, + LocationApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedLocation, setSelectedLocation] = useState< + Location | undefined + >(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const locationsColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'address', + header: 'Alamat', + }, + { + accessorKey: 'area', + header: 'Area', + cell: (props) => props.row.original.area.name, + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedLocation(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await LocationApi.delete(selectedLocation?.id as number); + refreshLocations(); + + deleteModal.closeModal(); + toast.success('Successfully delete Location!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(locations) ? locations?.data : []} + columns={locationsColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(locations) ? locations?.meta?.page : 0} + totalItems={ + isResponseSuccess(locations) ? locations?.meta?.total_results : 0 + } + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(locations) && locations?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default LocationsTable; From e53d4e22b2b073a1deea914d6e520e5f880af16d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:58:25 +0700 Subject: [PATCH 092/327] feat(FE-40,41): create LocationForm component --- .../location/form/LocationForm.tsx | 305 ++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src/components/pages/master-data/location/form/LocationForm.tsx diff --git a/src/components/pages/master-data/location/form/LocationForm.tsx b/src/components/pages/master-data/location/form/LocationForm.tsx new file mode 100644 index 00000000..50a5f664 --- /dev/null +++ b/src/components/pages/master-data/location/form/LocationForm.tsx @@ -0,0 +1,305 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; +import useSWR from 'swr'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + LocationFormSchema, + LocationFormValues, + UpdateLocationFormSchema, +} from '@/components/pages/master-data/location/form/LocationForm.schema'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { + Location, + CreateLocationPayload, + UpdateLocationPayload, +} from '@/types/api/master-data/location'; +import { AreaApi, LocationApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; + +interface LocationFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Location; +} + +const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [locationFormErrorMessage, setLocationFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createLocationHandler = useCallback( + async (payload: CreateLocationPayload) => { + const createLocationRes = await LocationApi.create(payload); + + if (isResponseError(createLocationRes)) { + setLocationFormErrorMessage(createLocationRes.message); + return; + } + + toast.success(createLocationRes?.message as string); + router.push('/master-data/location'); + }, + [router] + ); + + const updateLocationHandler = useCallback( + async (locationId: number, payload: UpdateLocationPayload) => { + const updateLocationRes = await LocationApi.update(locationId, payload); + + if (updateLocationRes?.status === 'error') { + setLocationFormErrorMessage(updateLocationRes.message); + return; + } + + toast.success(updateLocationRes?.message as string); + router.refresh(); + router.push('/master-data/location'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + address: initialValues?.address ?? '', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: + type === 'edit' ? UpdateLocationFormSchema : LocationFormSchema, + onSubmit: async (values) => { + setLocationFormErrorMessage(''); + + const locationPayload: CreateLocationPayload = { + name: values.name, + address: values.address, + area_id: values.areaId, + }; + + switch (type) { + case 'add': + await createLocationHandler(locationPayload); + break; + + case 'edit': + await updateLocationHandler( + initialValues?.id as number, + locationPayload + ); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + const [areaSelectInputValue, setAreaSelectInputValue] = useState(''); + + const areasUrl = `${AreaApi.basePath}?${new URLSearchParams({ + search: areaSelectInputValue ?? '', + }).toString()}`; + + const { data: areas, isLoading: isLoadingAreas } = useSWR( + areasUrl, + AreaApi.getAllFetcher + ); + + const areaOptions = isResponseSuccess(areas) + ? areas?.data.map((area) => ({ + value: area.id, + label: area.name, + })) + : []; + + const areaChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('area', true); + formik.setFieldValue('area', val); + + formik.setFieldTouched('areaId', true); + formik.setFieldValue('areaId', (val as OptionType)?.value); + }; + + const deleteLocationClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await LocationApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Location!'); + setIsDeleteLoading(false); + router.push('/master-data/location'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Location'} + {type === 'edit' && 'Edit Location'} + {type === 'detail' && 'Detail Location'} +

    +
    + +
    +
    + + + + + +
    + +
    + {type !== 'add' && ( +
    + +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {locationFormErrorMessage && ( +
    + + {locationFormErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default LocationForm; From 57e5fafabd26d090acb9531eeb4fd78c406114fc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:58:45 +0700 Subject: [PATCH 093/327] feat(FE-42): create Location form validation schema --- .../location/form/LocationForm.schema.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/components/pages/master-data/location/form/LocationForm.schema.ts diff --git a/src/components/pages/master-data/location/form/LocationForm.schema.ts b/src/components/pages/master-data/location/form/LocationForm.schema.ts new file mode 100644 index 00000000..4aa8e847 --- /dev/null +++ b/src/components/pages/master-data/location/form/LocationForm.schema.ts @@ -0,0 +1,18 @@ +import * as Yup from 'yup'; + +export const LocationFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), + address: Yup.string().required('Alamat wajib diisi!'), + + areaId: Yup.number() + .min(1, 'Area wajib diisi!') + .required('Area wajib diisi!'), + area: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), +}); + +export const UpdateLocationFormSchema = LocationFormSchema; + +export type LocationFormValues = Yup.InferType; From 7e0dd1bdb18a47dec28d4f736b02b9cb29b47c51 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:59:03 +0700 Subject: [PATCH 094/327] feat(FE-43): create Master Data Location page --- src/app/master-data/location/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/location/page.tsx diff --git a/src/app/master-data/location/page.tsx b/src/app/master-data/location/page.tsx new file mode 100644 index 00000000..338fdbff --- /dev/null +++ b/src/app/master-data/location/page.tsx @@ -0,0 +1,11 @@ +import LocationsTable from '@/components/pages/master-data/location/LocationsTable'; + +const Nonstock = () => { + return ( +
    + +
    + ); +}; + +export default Nonstock; From 288e4b92ff7dc89b9f19e27abfa8e972cbcdac04 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:59:16 +0700 Subject: [PATCH 095/327] feat(FE-40,41): create Master Data Add Location page --- src/app/master-data/location/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/location/add/page.tsx diff --git a/src/app/master-data/location/add/page.tsx b/src/app/master-data/location/add/page.tsx new file mode 100644 index 00000000..56f668fd --- /dev/null +++ b/src/app/master-data/location/add/page.tsx @@ -0,0 +1,11 @@ +import LocationForm from '@/components/pages/master-data/location/form/LocationForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From 54d2c85677aeba5958de4fa62c10ba2ad1f6a56a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:59:30 +0700 Subject: [PATCH 096/327] feat(FE-40,41): create Master Data Detail Location page --- src/app/master-data/location/detail/page.tsx | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/location/detail/page.tsx diff --git a/src/app/master-data/location/detail/page.tsx b/src/app/master-data/location/detail/page.tsx new file mode 100644 index 00000000..bff4d12e --- /dev/null +++ b/src/app/master-data/location/detail/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import LocationForm from '@/components/pages/master-data/location/form/LocationForm'; + +import { LocationApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const LocationDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const locationId = searchParams.get('locationId'); + + const { data: location, isLoading: isLoadingLocation } = useSWR( + locationId, + (id: number) => LocationApi.getSingle(id) + ); + + if (!locationId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingLocation && !location) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingLocation && ( + + )} + {!isLoadingLocation && isResponseSuccess(location) && ( + + )} +
    + ); +}; + +export default LocationDetail; From 05a67bdc75b916096c04d47e1cfcd0fc6481c18d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sat, 4 Oct 2025 14:59:44 +0700 Subject: [PATCH 097/327] feat(FE-40,41): create Master Data Edit Location page --- .../master-data/location/detail/edit/page.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/location/detail/edit/page.tsx diff --git a/src/app/master-data/location/detail/edit/page.tsx b/src/app/master-data/location/detail/edit/page.tsx new file mode 100644 index 00000000..853254d9 --- /dev/null +++ b/src/app/master-data/location/detail/edit/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import LocationForm from '@/components/pages/master-data/location/form/LocationForm'; + +import { LocationApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const LocationEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const locationId = searchParams.get('locationId'); + + const { data: location, isLoading: isLoadingLocation } = useSWR( + locationId, + (id: number) => LocationApi.getSingle(id) + ); + + if (!locationId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingLocation && !location) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingLocation && ( + + )} + {!isLoadingLocation && isResponseSuccess(location) && ( + + )} +
    + ); +}; + +export default LocationEdit; From 508a530c3a44ff5403b883a9602dcc109b14b0d5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 12:32:51 +0700 Subject: [PATCH 098/327] chore(FE-43): add address and area sorting --- .../master-data/location/LocationsTable.tsx | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/components/pages/master-data/location/LocationsTable.tsx b/src/components/pages/master-data/location/LocationsTable.tsx index 2879d114..8dc6b0d6 100644 --- a/src/components/pages/master-data/location/LocationsTable.tsx +++ b/src/components/pages/master-data/location/LocationsTable.tsx @@ -1,8 +1,13 @@ 'use client'; -import { ChangeEventHandler, useEffect, useState } from 'react'; +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; import useSWR from 'swr'; -import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import { + CellContext, + ColumnDef, + ColumnSort, + SortingState, +} from '@tanstack/react-table'; import toast from 'react-hot-toast'; import { Icon } from '@iconify/react'; @@ -88,8 +93,14 @@ const LocationsTable = () => { setPageSize, toQueryString: getTableFilterQueryString, } = useTableFilter({ - initial: { search: '', nameSort: '' }, - paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + initial: { search: '', nameSort: '', addressSort: '', areaSort: '' }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + addressSort: 'sort_address', + areaSort: ' sort_area', + }, }); const { @@ -194,15 +205,36 @@ const LocationsTable = () => { setPageSize(newVal.value as number); }; + const updateSortingFilter = useCallback( + ( + sortName: Exclude, + sortFilter: ColumnSort | undefined + ) => { + if (!sortFilter) { + updateFilter(sortName, ''); + } else { + updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc'); + } + }, + [updateFilter] + ); + + console.log({ + sorting, + getTableFilterQueryString: getTableFilterQueryString(), + }); + // track sorting useEffect(() => { - const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); + const addressSortFilter = sorting.find( + (sortItem) => sortItem.id === 'address' + ); + const areaSortFilter = sorting.find((sortItem) => sortItem.id === 'area'); - if (!isNameSorted) { - updateFilter('nameSort', ''); - } else { - updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); - } + updateSortingFilter('nameSort', nameSortFilter); + updateSortingFilter('addressSort', addressSortFilter); + updateSortingFilter('areaSort', areaSortFilter); }, [sorting]); return ( From f7b0933c0f3bfb435b1ace816adff92a15fc86f8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 12:59:15 +0700 Subject: [PATCH 099/327] feat(FE-41): create BaseApiService class --- src/services/api/base.ts | 82 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/services/api/base.ts diff --git a/src/services/api/base.ts b/src/services/api/base.ts new file mode 100644 index 00000000..d1ac4729 --- /dev/null +++ b/src/services/api/base.ts @@ -0,0 +1,82 @@ +import axios from 'axios'; +import { httpClient, httpClientFetcher } from '@/services/http/client'; +import { BaseApiResponse } from '@/types/api/api-general'; + +export class BaseApiService { + basePath: string; + + constructor(basePath: string) { + this.basePath = basePath; + } + + async getAllFetcher(endpoint: string): Promise> { + return await httpClientFetcher>(endpoint); + } + + async getSingle(id: number) { + try { + const getSinglePath = `${this.basePath}/${id}`; + const getSingleRes = await httpClient>(getSinglePath); + + return getSingleRes; + } catch (error) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async create(payload: CreatePayloadGeneric) { + try { + const createRes = await httpClient>(this.basePath, { + method: 'POST', + body: payload, + }); + + return createRes; + } catch (error: unknown) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async update(id: number, payload: UpdatePayloadGeneric) { + try { + const updatePath = `${this.basePath}/${id}`; + const updateRes = await httpClient>(updatePath, { + method: 'PATCH', + body: payload, + }); + + return updateRes; + } catch (error: unknown) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + + return undefined; + } + } + + async delete(id: number) { + try { + const deletePath = `${this.basePath}/${id}`; + const deleteRes = await httpClient(deletePath, { + method: 'DELETE', + }); + + return deleteRes; + } catch (error) { + if (axios.isAxiosError(error)) { + return error.response?.data; + } + + return undefined; + } + } +} From f32e1ceec4dce9f815541d042ef769f7f146931b Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 12:59:35 +0700 Subject: [PATCH 100/327] chore(FE-41): use BaseApiService class --- src/services/api/master-data.ts | 89 ++------------------------------- 1 file changed, 4 insertions(+), 85 deletions(-) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index e1748c59..25bceae0 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -1,6 +1,4 @@ -import axios from 'axios'; -import { httpClient, httpClientFetcher } from '@/services/http/client'; -import { BaseApiResponse } from '@/types/api/api-general'; +import { BaseApiService } from '@/services/api/base'; import { CreateUomPayload, Uom, @@ -17,98 +15,19 @@ import { UpdateLocationPayload, } from '@/types/api/master-data/location'; -export class MasterDataApi { - basePath: string; - - constructor(basePath: string) { - this.basePath = basePath; - } - - async getAllFetcher(endpoint: string): Promise> { - return await httpClientFetcher>(endpoint); - } - - async getSingle(id: number) { - try { - const getSinglePath = `${this.basePath}/${id}`; - const getSingleRes = await httpClient>(getSinglePath); - - return getSingleRes; - } catch (error) { - if (axios.isAxiosError>(error)) { - return error.response?.data; - } - - return undefined; - } - } - - async create(payload: CreatePayloadGeneric) { - try { - const createRes = await httpClient>(this.basePath, { - method: 'POST', - body: payload, - }); - - return createRes; - } catch (error: unknown) { - if (axios.isAxiosError>(error)) { - return error.response?.data; - } - - return undefined; - } - } - - async update(id: number, payload: UpdatePayloadGeneric) { - try { - const updatePath = `${this.basePath}/${id}`; - const updateRes = await httpClient>(updatePath, { - method: 'PATCH', - body: payload, - }); - - return updateRes; - } catch (error: unknown) { - if (axios.isAxiosError>(error)) { - return error.response?.data; - } - - return undefined; - } - } - - async delete(id: number) { - try { - const deletePath = `${this.basePath}/${id}`; - const deleteRes = await httpClient(deletePath, { - method: 'DELETE', - }); - - return deleteRes; - } catch (error) { - if (axios.isAxiosError(error)) { - return error.response?.data; - } - - return undefined; - } - } -} - -export const UomApi = new MasterDataApi< +export const UomApi = new BaseApiService< Uom, CreateUomPayload, UpdateUomPayload >('/master-data/uoms'); -export const AreaApi = new MasterDataApi< +export const AreaApi = new BaseApiService< Area, CreateAreaPayload, UpdateAreaPayload >('/master-data/areas'); -export const LocationApi = new MasterDataApi< +export const LocationApi = new BaseApiService< Location, CreateLocationPayload, UpdateLocationPayload From 8c84e08f3b242d7e79d4f6b47c4dd5f56c683c34 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:00:58 +0700 Subject: [PATCH 101/327] chore(FE-41): use .d.ts extension for types --- src/types/api/master-data/{area.ts => area.d.ts} | 0 src/types/api/master-data/{location.ts => location.d.ts} | 0 src/types/api/master-data/{uom.ts => uom.d.ts} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/types/api/master-data/{area.ts => area.d.ts} (100%) rename src/types/api/master-data/{location.ts => location.d.ts} (100%) rename src/types/api/master-data/{uom.ts => uom.d.ts} (100%) diff --git a/src/types/api/master-data/area.ts b/src/types/api/master-data/area.d.ts similarity index 100% rename from src/types/api/master-data/area.ts rename to src/types/api/master-data/area.d.ts diff --git a/src/types/api/master-data/location.ts b/src/types/api/master-data/location.d.ts similarity index 100% rename from src/types/api/master-data/location.ts rename to src/types/api/master-data/location.d.ts diff --git a/src/types/api/master-data/uom.ts b/src/types/api/master-data/uom.d.ts similarity index 100% rename from src/types/api/master-data/uom.ts rename to src/types/api/master-data/uom.d.ts From d5294e9b0b4bef04b30268d994282f07434860cc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:01:30 +0700 Subject: [PATCH 102/327] chore(FE-43): remove unnecessary code --- src/components/pages/master-data/location/LocationsTable.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/pages/master-data/location/LocationsTable.tsx b/src/components/pages/master-data/location/LocationsTable.tsx index 8dc6b0d6..ebbb798f 100644 --- a/src/components/pages/master-data/location/LocationsTable.tsx +++ b/src/components/pages/master-data/location/LocationsTable.tsx @@ -219,11 +219,6 @@ const LocationsTable = () => { [updateFilter] ); - console.log({ - sorting, - getTableFilterQueryString: getTableFilterQueryString(), - }); - // track sorting useEffect(() => { const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); From 0675d95a2abe533907efb5b5453e07612acbaaf6 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:39:16 +0700 Subject: [PATCH 103/327] feat(FE-41): create user type --- src/types/api/user.d.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/types/api/user.d.ts diff --git a/src/types/api/user.d.ts b/src/types/api/user.d.ts new file mode 100644 index 00000000..2190e1a8 --- /dev/null +++ b/src/types/api/user.d.ts @@ -0,0 +1,18 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type BaseUser = { + id: number; + id_user: number; + email: string; + name: string; +}; + +export type User = BaseMetadata & BaseUser; + +export type CreateUserPayload = { + id_user: number; + name: string; + email: string; +}; + +export type UpdateUserPayload = CreateUserPayload; From 0e5b718fd7f66537c61b903f83b68ac3028b93ad Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:39:25 +0700 Subject: [PATCH 104/327] feat(FE-41): create kandang type --- src/types/api/master-data/kandang.d.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/types/api/master-data/kandang.d.ts diff --git a/src/types/api/master-data/kandang.d.ts b/src/types/api/master-data/kandang.d.ts new file mode 100644 index 00000000..e05006d1 --- /dev/null +++ b/src/types/api/master-data/kandang.d.ts @@ -0,0 +1,20 @@ +import { BaseMetadata } from '@/types/api/api-general'; +import { BaseLocation } from '@/types/api/master-data/location'; +import { BaseUser } from '@/types/api/user'; + +export type BaseKandang = { + id: number; + name: string; + location: BaseLocation; + pic: BaseUser; +}; + +export type Kandang = BaseMetadata & BaseKandang; + +export type CreateKandangPayload = { + name: string; + location_id: number; + pic_id: number; +}; + +export type UpdateKandangPayload = CreateKandangPayload; From 26093034fa44ff96b8b6e1ea34549db616f98f1a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:39:38 +0700 Subject: [PATCH 105/327] feat(FE-41): create user API service --- src/services/api/user.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/services/api/user.ts diff --git a/src/services/api/user.ts b/src/services/api/user.ts new file mode 100644 index 00000000..779cca07 --- /dev/null +++ b/src/services/api/user.ts @@ -0,0 +1,8 @@ +import { BaseApiService } from '@/services/api/base'; +import { CreateUserPayload, UpdateUserPayload, User } from '@/types/api/user'; + +export const UserApi = new BaseApiService< + User, + CreateUserPayload, + UpdateUserPayload +>('/users'); From 6ff19f05fd44ec4fda9972d684545d8ebc9bc91d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:40:09 +0700 Subject: [PATCH 106/327] feat(FE-41): craete KandangApi service --- src/services/api/master-data.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 25bceae0..01d1cbc6 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -14,6 +14,11 @@ import { Location, UpdateLocationPayload, } from '@/types/api/master-data/location'; +import { + CreateKandangPayload, + Kandang, + UpdateKandangPayload, +} from '@/types/api/master-data/kandang'; export const UomApi = new BaseApiService< Uom, @@ -32,3 +37,9 @@ export const LocationApi = new BaseApiService< CreateLocationPayload, UpdateLocationPayload >('/master-data/locations'); + +export const KandangApi = new BaseApiService< + Kandang, + CreateKandangPayload, + UpdateKandangPayload +>('/master-data/kandangs'); From be844312d3262d174be59936fa431fac0113dd0d Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:40:46 +0700 Subject: [PATCH 107/327] feat(FE-43): create KandangsTable component --- .../master-data/kandang/KandangsTable.tsx | 318 ++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 src/components/pages/master-data/kandang/KandangsTable.tsx diff --git a/src/components/pages/master-data/kandang/KandangsTable.tsx b/src/components/pages/master-data/kandang/KandangsTable.tsx new file mode 100644 index 00000000..c3571452 --- /dev/null +++ b/src/components/pages/master-data/kandang/KandangsTable.tsx @@ -0,0 +1,318 @@ +'use client'; + +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { + CellContext, + ColumnDef, + ColumnSort, + SortingState, +} from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Kandang } from '@/types/api/master-data/kandang'; +import { KandangApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const KandangsTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '', locationSort: '', picSort: '' }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + locationSort: 'sort_location', + picSort: ' sort_pic', + }, + }); + + const { + data: kandangs, + isLoading, + mutate: refreshKandangs, + } = useSWR( + `${KandangApi.basePath}${getTableFilterQueryString()}`, + KandangApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedKandang, setSelectedKandang] = useState( + undefined + ); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const kandangsColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'location', + header: 'Lokasi', + cell: (props) => props.row.original.location.name, + }, + { + accessorKey: 'pic', + header: 'PIC', + cell: (props) => props.row.original.pic.name, + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedKandang(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await KandangApi.delete(selectedKandang?.id as number); + refreshKandangs(); + + deleteModal.closeModal(); + toast.success('Successfully delete Kandang!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + const updateSortingFilter = useCallback( + ( + sortName: Exclude, + sortFilter: ColumnSort | undefined + ) => { + if (!sortFilter) { + updateFilter(sortName, ''); + } else { + updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc'); + } + }, + [updateFilter] + ); + + // track sorting + useEffect(() => { + const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); + const locationSortFilter = sorting.find( + (sortItem) => sortItem.id === 'location' + ); + const picSortFilter = sorting.find((sortItem) => sortItem.id === 'pic'); + + updateSortingFilter('nameSort', nameSortFilter); + updateSortingFilter('locationSort', locationSortFilter); + updateSortingFilter('picSort', picSortFilter); + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(kandangs) ? kandangs?.data : []} + columns={kandangsColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(kandangs) ? kandangs?.meta?.page : 0} + totalItems={ + isResponseSuccess(kandangs) ? kandangs?.meta?.total_results : 0 + } + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(kandangs) && kandangs?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default KandangsTable; From 531a257e788a87bc82485163cbd33ff0609c1ed7 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:41:08 +0700 Subject: [PATCH 108/327] feat(FE-40,41): create KandangForm component --- .../master-data/kandang/form/KandangForm.tsx | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 src/components/pages/master-data/kandang/form/KandangForm.tsx diff --git a/src/components/pages/master-data/kandang/form/KandangForm.tsx b/src/components/pages/master-data/kandang/form/KandangForm.tsx new file mode 100644 index 00000000..f0d68983 --- /dev/null +++ b/src/components/pages/master-data/kandang/form/KandangForm.tsx @@ -0,0 +1,360 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; +import useSWR from 'swr'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + KandangFormSchema, + KandangFormValues, + UpdateKandangFormSchema, +} from '@/components/pages/master-data/kandang/form/KandangForm.schema'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { + Kandang, + CreateKandangPayload, + UpdateKandangPayload, +} from '@/types/api/master-data/kandang'; +import { LocationApi, KandangApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { UserApi } from '@/services/api/user'; + +interface KandangFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Kandang; +} + +const KandangForm = ({ type = 'add', initialValues }: KandangFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [kandangFormErrorMessage, setKandangFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createKandangHandler = useCallback( + async (payload: CreateKandangPayload) => { + const createKandangRes = await KandangApi.create(payload); + + if (isResponseError(createKandangRes)) { + setKandangFormErrorMessage(createKandangRes.message); + return; + } + + toast.success(createKandangRes?.message as string); + router.push('/master-data/kandang'); + }, + [router] + ); + + const updateKandangHandler = useCallback( + async (kandangId: number, payload: UpdateKandangPayload) => { + const updateKandangRes = await KandangApi.update(kandangId, payload); + + if (updateKandangRes?.status === 'error') { + setKandangFormErrorMessage(updateKandangRes.message); + return; + } + + toast.success(updateKandangRes?.message as string); + router.refresh(); + router.push('/master-data/kandang'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + locationId: initialValues?.location?.id ?? 0, + location: initialValues?.location + ? { + value: initialValues.location.id, + label: initialValues.location.name, + } + : null, + picId: initialValues?.pic?.id ?? 0, + pic: initialValues?.pic + ? { + value: initialValues.pic.id, + label: initialValues.pic.name, + } + : null, + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: + type === 'edit' ? UpdateKandangFormSchema : KandangFormSchema, + onSubmit: async (values) => { + setKandangFormErrorMessage(''); + + const kandangPayload: CreateKandangPayload = { + name: values.name, + location_id: values.locationId, + pic_id: values.picId, + }; + + switch (type) { + case 'add': + await createKandangHandler(kandangPayload); + break; + + case 'edit': + await updateKandangHandler( + initialValues?.id as number, + kandangPayload + ); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + // location + const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); + + const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({ + search: locationSelectInputValue ?? '', + }).toString()}`; + + const { data: locations, isLoading: isLoadingLocations } = useSWR( + locationsUrl, + LocationApi.getAllFetcher + ); + + const locationOptions = isResponseSuccess(locations) + ? locations?.data.map((location) => ({ + value: location.id, + label: location.name, + })) + : []; + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('location', true); + formik.setFieldValue('location', val); + + formik.setFieldTouched('locationId', true); + formik.setFieldValue('locationId', (val as OptionType)?.value); + }; + + // PIC + const [picSelectInputValue, setPicSelectInputValue] = useState(''); + + const picsUrl = `${UserApi.basePath}?${new URLSearchParams({ + search: picSelectInputValue ?? '', + }).toString()}`; + + const { data: pics, isLoading: isLoadingPics } = useSWR( + picsUrl, + LocationApi.getAllFetcher + ); + + const picOptions = isResponseSuccess(pics) + ? pics?.data.map((pic) => ({ + value: pic.id, + label: pic.name, + })) + : []; + + const picChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('pic', true); + formik.setFieldValue('pic', val); + + formik.setFieldTouched('picId', true); + formik.setFieldValue('picId', (val as OptionType)?.value); + }; + + const deleteKandangClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await KandangApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Kandang!'); + setIsDeleteLoading(false); + router.push('/master-data/kandang'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Kandang'} + {type === 'edit' && 'Edit Kandang'} + {type === 'detail' && 'Detail Kandang'} +

    +
    + +
    +
    + + + + + +
    + +
    + {type !== 'add' && ( +
    + + + {type !== 'edit' && ( + + )} +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {kandangFormErrorMessage && ( +
    + + {kandangFormErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default KandangForm; From 6441a38a9df6b3d3c9af885a841ab62353834ba7 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:41:27 +0700 Subject: [PATCH 109/327] feat(FE-42): create Kandang form validation schema --- .../kandang/form/KandangForm.schema.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/components/pages/master-data/kandang/form/KandangForm.schema.ts diff --git a/src/components/pages/master-data/kandang/form/KandangForm.schema.ts b/src/components/pages/master-data/kandang/form/KandangForm.schema.ts new file mode 100644 index 00000000..9a0e42a0 --- /dev/null +++ b/src/components/pages/master-data/kandang/form/KandangForm.schema.ts @@ -0,0 +1,23 @@ +import * as Yup from 'yup'; + +export const KandangFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), + + locationId: Yup.number() + .min(1, 'Lokasi wajib diisi!') + .required('Lokasi wajib diisi!'), + location: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + + picId: Yup.number().min(1, 'PIC wajib diisi!').required('PIC wajib diisi!'), + pic: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), +}); + +export const UpdateKandangFormSchema = KandangFormSchema; + +export type KandangFormValues = Yup.InferType; From 952110d7af437f3df90c7bb859d63daeb1222bf0 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:41:45 +0700 Subject: [PATCH 110/327] feat(FE-43): create Master Data Kandang page --- src/app/master-data/kandang/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/kandang/page.tsx diff --git a/src/app/master-data/kandang/page.tsx b/src/app/master-data/kandang/page.tsx new file mode 100644 index 00000000..293eb0da --- /dev/null +++ b/src/app/master-data/kandang/page.tsx @@ -0,0 +1,11 @@ +import KandangsTable from '@/components/pages/master-data/kandang/KandangsTable'; + +const Nonstock = () => { + return ( +
    + +
    + ); +}; + +export default Nonstock; From f0c291046934174a86f543947d635496ce47e51f Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:42:05 +0700 Subject: [PATCH 111/327] feat(FE-40,41): create Master Data Add Kandang page --- src/app/master-data/kandang/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/kandang/add/page.tsx diff --git a/src/app/master-data/kandang/add/page.tsx b/src/app/master-data/kandang/add/page.tsx new file mode 100644 index 00000000..238799cd --- /dev/null +++ b/src/app/master-data/kandang/add/page.tsx @@ -0,0 +1,11 @@ +import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From 64bb87f92faeabd8f70d098b2ef43a9657ba2e55 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:42:14 +0700 Subject: [PATCH 112/327] feat(FE-40,41): create Master Data Detail Kandang page --- src/app/master-data/kandang/detail/page.tsx | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/kandang/detail/page.tsx diff --git a/src/app/master-data/kandang/detail/page.tsx b/src/app/master-data/kandang/detail/page.tsx new file mode 100644 index 00000000..1b91bad7 --- /dev/null +++ b/src/app/master-data/kandang/detail/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm'; + +import { KandangApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const KandangDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const kandangId = searchParams.get('kandangId'); + + const { data: kandang, isLoading: isLoadingKandang } = useSWR( + kandangId, + (id: number) => KandangApi.getSingle(id) + ); + + if (!kandangId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingKandang && !kandang) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingKandang && ( + + )} + {!isLoadingKandang && isResponseSuccess(kandang) && ( + + )} +
    + ); +}; + +export default KandangDetail; From bfc81da349ce80780fc0b8fe33855978c7f4729a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 13:42:22 +0700 Subject: [PATCH 113/327] feat(FE-40,41): create Master Data Edit Kandang page --- .../master-data/kandang/detail/edit/page.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/kandang/detail/edit/page.tsx diff --git a/src/app/master-data/kandang/detail/edit/page.tsx b/src/app/master-data/kandang/detail/edit/page.tsx new file mode 100644 index 00000000..426aabc0 --- /dev/null +++ b/src/app/master-data/kandang/detail/edit/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm'; + +import { KandangApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const KandangEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const kandangId = searchParams.get('kandangId'); + + const { data: kandang, isLoading: isLoadingKandang } = useSWR( + kandangId, + (id: number) => KandangApi.getSingle(id) + ); + + if (!kandangId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingKandang && !kandang) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingKandang && ( + + )} + {!isLoadingKandang && isResponseSuccess(kandang) && ( + + )} +
    + ); +}; + +export default KandangEdit; From acd28e5debcb22c21f0c0ec300455714d7f65a68 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:04:46 +0700 Subject: [PATCH 114/327] feat(FE-41): create warehouse api type --- src/types/api/master-data/warehouse.d.ts | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/types/api/master-data/warehouse.d.ts diff --git a/src/types/api/master-data/warehouse.d.ts b/src/types/api/master-data/warehouse.d.ts new file mode 100644 index 00000000..41c5b1cd --- /dev/null +++ b/src/types/api/master-data/warehouse.d.ts @@ -0,0 +1,81 @@ +import { BaseMetadata, Override } from '@/types/api/api-general'; +import { BaseArea } from '@/types/api/master-data/area'; +import { BaseLocation } from '@/types/api/master-data/location'; +import { BaseKandang } from '@/types/api/master-data/kandang'; +import { BaseUser } from '@/types/api/master-data/user'; + +export type WarehouseType = 'AREA' | 'LOKASI' | 'KANDANG'; + +export type BaseWarehouse = { + id: number; + name: string; +}; + +export type BaseWarehouseArea = BaseWarehouse & { + type: 'AREA'; + area: BaseArea; +}; + +export type BaseWarehouseLocation = BaseWarehouse & { + type: 'LOKASI'; + area: BaseArea; + location: Override< + BaseLocation, + { + area: BaseArea | null; + } + >; +}; + +export type BaseWarehouseKandang = BaseWarehouse & { + type: 'KANDANG'; + area: BaseArea; + location: Override< + BaseLocation, + { + area: BaseArea | null; + } + >; + kandang: Override< + BaseKandang, + { + location: BaseLocation | null; + pic: BaseUser | null; + } + >; +}; + +export type Warehouse = BaseMetadata & + (BaseWarehouseArea | BaseWarehouseLocation | BaseWarehouseKandang); + +export type BaseCreateWarehousePayload = { + name: string; +}; + +export type BaseCreateWarehouseAreaPayload = BaseCreateWarehousePayload & { + type: 'AREA'; + area_id: number; +}; + +export type BaseCreateWarehouseLocationPayload = Override< + BaseCreateWarehouseAreaPayload, + { + type: 'LOKASI'; + location_id: number; + } +>; + +export type BaseCreateWarehouseKandangPayload = Override< + BaseCreateWarehouseLocationPayload, + { + type: 'KANDANG'; + kandang_id: number; + } +>; + +export type CreateWarehousePayload = + | BaseCreateWarehouseAreaPayload + | BaseCreateWarehouseLocationPayload + | BaseCreateWarehouseKandangPayload; + +export type UpdateWarehousePayload = CreateWarehousePayload; From a136ee11909362510499c800bd87d5049d982735 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:04:59 +0700 Subject: [PATCH 115/327] chore(FE-41): create Override type --- src/types/api/api-general.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/api/api-general.d.ts b/src/types/api/api-general.d.ts index f33b94ee..8a4c4de7 100644 --- a/src/types/api/api-general.d.ts +++ b/src/types/api/api-general.d.ts @@ -50,3 +50,6 @@ export type BaseMetadata = { created_at: string; updated_at: string; }; + +export type Override = Omit & + Overrides; From 19ce3989ba3ad246720e73c1a6ae3f3088b30f53 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:05:18 +0700 Subject: [PATCH 116/327] feat(FE-41): create Warehouse API service --- src/services/api/master-data.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 01d1cbc6..785a1ca1 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -19,6 +19,11 @@ import { Kandang, UpdateKandangPayload, } from '@/types/api/master-data/kandang'; +import { + CreateWarehousePayload, + UpdateWarehousePayload, + Warehouse, +} from '@/types/api/master-data/warehouse'; export const UomApi = new BaseApiService< Uom, @@ -43,3 +48,9 @@ export const KandangApi = new BaseApiService< CreateKandangPayload, UpdateKandangPayload >('/master-data/kandangs'); + +export const WarehouseApi = new BaseApiService< + Warehouse, + CreateWarehousePayload, + UpdateWarehousePayload +>('/master-data/warehouses'); From 1f0c58d264e99530863c81c3bf4260e123468695 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:05:33 +0700 Subject: [PATCH 117/327] feat(FE-40): create WAREHOUSE_TYPE_OPTIONS constant --- src/config/constant.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/config/constant.ts b/src/config/constant.ts index 269f5da9..55eed0b3 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -92,3 +92,18 @@ export const ROWS_OPTIONS = [ value: 100, }, ]; + +export const WAREHOUSE_TYPE_OPTIONS = [ + { + label: 'AREA', + value: 'AREA', + }, + { + label: 'LOKASI', + value: 'LOKASI', + }, + { + label: 'KANDANG', + value: 'KANDANG', + }, +]; From 07691bfd9e02c3308d8942d82ee5fb3e4c3c45d6 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:05:58 +0700 Subject: [PATCH 118/327] feat(FE-40,41): create WarehouseForm component --- .../warehouse/form/WarehouseForm.tsx | 528 ++++++++++++++++++ 1 file changed, 528 insertions(+) create mode 100644 src/components/pages/master-data/warehouse/form/WarehouseForm.tsx diff --git a/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx new file mode 100644 index 00000000..90b9e4e0 --- /dev/null +++ b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx @@ -0,0 +1,528 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; +import useSWR from 'swr'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + WarehouseFormSchema, + WarehouseFormValues, + UpdateWarehouseFormSchema, +} from '@/components/pages/master-data/warehouse/form/WarehouseForm.schema'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { + Warehouse, + CreateWarehousePayload, + UpdateWarehousePayload, +} from '@/types/api/master-data/warehouse'; +import { + AreaApi, + KandangApi, + LocationApi, + WarehouseApi, +} from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant'; + +interface WarehouseFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Warehouse; +} + +const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [warehouseFormErrorMessage, setWarehouseFormErrorMessage] = + useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createWarehouseHandler = useCallback( + async (payload: CreateWarehousePayload) => { + const createWarehouseRes = await WarehouseApi.create(payload); + + if (isResponseError(createWarehouseRes)) { + setWarehouseFormErrorMessage(createWarehouseRes.message); + return; + } + + toast.success(createWarehouseRes?.message as string); + router.push('/master-data/warehouse'); + }, + [router] + ); + + const updateWarehouseHandler = useCallback( + async (warehouseId: number, payload: UpdateWarehousePayload) => { + const updateWarehouseRes = await WarehouseApi.update( + warehouseId, + payload + ); + + if (updateWarehouseRes?.status === 'error') { + setWarehouseFormErrorMessage(updateWarehouseRes.message); + return; + } + + toast.success(updateWarehouseRes?.message as string); + router.refresh(); + router.push('/master-data/warehouse'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + switch (initialValues?.type) { + case 'AREA': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'AREA', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: 0, + location: null, + kandangId: 0, + kandang: null, + }; + + case 'LOKASI': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'LOKASI', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: initialValues?.location?.id ?? 0, + location: initialValues?.location + ? { + value: initialValues.location.id, + label: initialValues.location.name, + } + : null, + kandangId: 0, + kandang: null, + }; + + case 'KANDANG': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'KANDANG', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: initialValues?.location?.id ?? 0, + location: initialValues?.location + ? { + value: initialValues.location.id, + label: initialValues.location.name, + } + : null, + kandangId: initialValues?.kandang?.id ?? 0, + kandang: initialValues?.kandang + ? { + value: initialValues.kandang.id, + label: initialValues.kandang.name, + } + : null, + }; + + default: + return { + name: '', + type: 'AREA', + areaId: 0, + area: null, + locationId: 0, + location: null, + kandangId: 0, + kandang: null, + }; + } + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: + type === 'edit' ? UpdateWarehouseFormSchema : WarehouseFormSchema, + onSubmit: async (values) => { + setWarehouseFormErrorMessage(''); + + let warehousePayload: CreateWarehousePayload | undefined = undefined; + + switch (values.type) { + case 'AREA': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + }; + break; + + case 'LOKASI': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + location_id: values.locationId as number, + }; + break; + + case 'KANDANG': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + location_id: values.locationId as number, + kandang_id: values.kandangId as number, + }; + break; + } + + switch (type) { + case 'add': + await createWarehouseHandler(warehousePayload); + break; + + case 'edit': + await updateWarehouseHandler( + initialValues?.id as number, + warehousePayload + ); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + // Area + const [areaSelectInputValue, setAreaSelectInputValue] = useState(''); + + const areasUrl = `${AreaApi.basePath}?${new URLSearchParams({ + search: areaSelectInputValue ?? '', + }).toString()}`; + + const { data: areas, isLoading: isLoadingAreas } = useSWR( + areasUrl, + AreaApi.getAllFetcher + ); + + const areaOptions = isResponseSuccess(areas) + ? areas?.data.map((area) => ({ + value: area.id, + label: area.name, + })) + : []; + + // Location + const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); + + const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({ + search: locationSelectInputValue ?? '', + }).toString()}`; + + const { data: locations, isLoading: isLoadingLocations } = useSWR( + locationsUrl, + LocationApi.getAllFetcher + ); + + const locationOptions = isResponseSuccess(locations) + ? locations?.data.map((location) => ({ + value: location.id, + label: location.name, + })) + : []; + + // Kandang + const [kandangSelectInputValue, setKandangSelectInputValue] = useState(''); + + const kandangsUrl = `${KandangApi.basePath}?${new URLSearchParams({ + search: kandangSelectInputValue ?? '', + }).toString()}`; + + const { data: kandangs, isLoading: isLoadingKandangs } = useSWR( + kandangsUrl, + KandangApi.getAllFetcher + ); + + const kandangOptions = isResponseSuccess(kandangs) + ? kandangs?.data.map((kandang) => ({ + value: kandang.id, + label: kandang.name, + })) + : []; + + const typeChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('type', true); + formik.setFieldValue('type', (val as OptionType)?.value); + }; + + const areaChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('area', true); + formik.setFieldValue('area', val); + + formik.setFieldTouched('areaId', true); + formik.setFieldValue('areaId', (val as OptionType)?.value); + }; + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('location', true); + formik.setFieldValue('location', val); + + formik.setFieldTouched('locationId', true); + formik.setFieldValue('locationId', (val as OptionType)?.value); + }; + + const kandangChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('kandang', true); + formik.setFieldValue('kandang', val); + + formik.setFieldTouched('kandangId', true); + formik.setFieldValue('kandangId', (val as OptionType)?.value); + }; + + const deleteWarehouseClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await WarehouseApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Warehouse!'); + setIsDeleteLoading(false); + router.push('/master-data/warehouse'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Warehouse'} + {type === 'edit' && 'Edit Warehouse'} + {type === 'detail' && 'Detail Warehouse'} +

    +
    + +
    +
    + + + + + + + {(formik.values.type === 'LOKASI' || + formik.values.type === 'KANDANG') && ( + + )} + + {formik.values.type === 'KANDANG' && ( + + )} +
    + +
    + {type !== 'add' && ( +
    + + + {type !== 'edit' && ( + + )} +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {warehouseFormErrorMessage && ( +
    + + {warehouseFormErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default WarehouseForm; From 76cd64de5b3c5fbed5b6ea70fb4aaac6d04c5f03 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:06:21 +0700 Subject: [PATCH 119/327] feat(FE-42): create Warehouse form validation schema --- .../warehouse/form/WarehouseForm.schema.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/components/pages/master-data/warehouse/form/WarehouseForm.schema.ts diff --git a/src/components/pages/master-data/warehouse/form/WarehouseForm.schema.ts b/src/components/pages/master-data/warehouse/form/WarehouseForm.schema.ts new file mode 100644 index 00000000..36459e8f --- /dev/null +++ b/src/components/pages/master-data/warehouse/form/WarehouseForm.schema.ts @@ -0,0 +1,80 @@ +import * as Yup from 'yup'; +import { WarehouseType } from '@/types/api/master-data/warehouse'; + +const TYPE_VALUES = ['AREA', 'LOKASI', 'KANDANG'] as const; + +export const WarehouseFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), + + type: Yup.string() + .oneOf(TYPE_VALUES) + .required('Tipe wajib diisi!'), + + areaId: Yup.number() + .transform((v, orig) => + orig === '' || orig === 0 || Number.isNaN(v) ? undefined : v + ) + .when('type', { + is: (t: WarehouseType | undefined) => + t === 'AREA' || t === 'LOKASI' || t === 'KANDANG', + then: (s) => s.min(1, 'Area wajib diisi!').required('Area wajib diisi!'), + otherwise: (s) => s.notRequired(), + }), + area: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) + .nullable() + .when('type', { + is: (t: WarehouseType | undefined) => + t === 'AREA' || t === 'LOKASI' || t === 'KANDANG', + then: (s) => s.notRequired(), + otherwise: (s) => s.notRequired(), + }), + + locationId: Yup.number() + .transform((v, orig) => + orig === '' || orig === 0 || Number.isNaN(v) ? undefined : v + ) + .when('type', { + is: (t: WarehouseType | undefined) => t === 'LOKASI' || t === 'KANDANG', + then: (s) => + s.min(1, 'Lokasi wajib diisi!').required('Lokasi wajib diisi!'), + otherwise: (s) => s.notRequired(), + }), + location: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) + .nullable() + .when('type', { + is: (t: WarehouseType | undefined) => t === 'LOKASI' || t === 'KANDANG', + then: (s) => s.notRequired(), + otherwise: (s) => s.notRequired(), + }), + + kandangId: Yup.number() + .transform((v, orig) => + orig === '' || orig === 0 || Number.isNaN(v) ? undefined : v + ) + .when('type', { + is: (t: WarehouseType | undefined) => t === 'KANDANG', + then: (s) => + s.min(1, 'Kandang wajib diisi!').required('Kandang wajib diisi!'), + otherwise: (s) => s.notRequired(), + }), + kandang: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }) + .nullable() + .when('type', { + is: (t: WarehouseType | undefined) => t === 'KANDANG', + then: (s) => s.notRequired(), + otherwise: (s) => s.notRequired(), + }), +}); + +export const UpdateWarehouseFormSchema = WarehouseFormSchema; + +export type WarehouseFormValues = Yup.InferType; From c1bc7beb4a3e61da63845840be022628a6689675 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:06:36 +0700 Subject: [PATCH 120/327] feat(FE-43): create WarehousesTable component --- .../master-data/warehouse/WarehousesTable.tsx | 357 ++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 src/components/pages/master-data/warehouse/WarehousesTable.tsx diff --git a/src/components/pages/master-data/warehouse/WarehousesTable.tsx b/src/components/pages/master-data/warehouse/WarehousesTable.tsx new file mode 100644 index 00000000..b3eed86b --- /dev/null +++ b/src/components/pages/master-data/warehouse/WarehousesTable.tsx @@ -0,0 +1,357 @@ +'use client'; + +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { + CellContext, + ColumnDef, + ColumnSort, + SortingState, +} from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Warehouse } from '@/types/api/master-data/warehouse'; +import { WarehouseApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const WarehousesTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { + search: '', + nameSort: '', + typeSort: '', + areaSort: '', + locationSort: '', + kandangSort: '', + }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + typeSort: 'sort_type', + areaSort: ' sort_area', + locationSort: ' sort_location', + kandangSort: ' sort_kandang', + }, + }); + + const { + data: warehouses, + isLoading, + mutate: refreshWarehouses, + } = useSWR( + `${WarehouseApi.basePath}${getTableFilterQueryString()}`, + WarehouseApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedWarehouse, setSelectedWarehouse] = useState< + Warehouse | undefined + >(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const warehousesColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'type', + header: 'Tipe', + }, + { + accessorKey: 'area', + header: 'Area', + cell: (props) => props.row.original.area.name, + }, + { + accessorKey: 'location', + header: 'Lokasi', + cell: (props) => { + if ( + props.row.original.type === 'LOKASI' || + props.row.original.type === 'KANDANG' + ) { + return props.row.original.location.name; + } else { + return '-'; + } + }, + }, + { + accessorKey: 'kandang', + header: 'Kandang', + cell: (props) => { + if (props.row.original.type === 'KANDANG') { + return props.row.original.kandang.name; + } else { + return '-'; + } + }, + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedWarehouse(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await WarehouseApi.delete(selectedWarehouse?.id as number); + refreshWarehouses(); + + deleteModal.closeModal(); + toast.success('Successfully delete Warehouse!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + const updateSortingFilter = useCallback( + ( + sortName: Exclude, + sortFilter: ColumnSort | undefined + ) => { + if (!sortFilter) { + updateFilter(sortName, ''); + } else { + updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc'); + } + }, + [updateFilter] + ); + + // track sorting + useEffect(() => { + const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); + const typeSortFilter = sorting.find((sortItem) => sortItem.id === 'type'); + const areaSortFilter = sorting.find((sortItem) => sortItem.id === 'area'); + const locationSortFilter = sorting.find( + (sortItem) => sortItem.id === 'location' + ); + const kandangSortFilter = sorting.find( + (sortItem) => sortItem.id === 'kandang' + ); + + updateSortingFilter('nameSort', nameSortFilter); + updateSortingFilter('typeSort', typeSortFilter); + updateSortingFilter('areaSort', areaSortFilter); + updateSortingFilter('locationSort', locationSortFilter); + updateSortingFilter('kandangSort', kandangSortFilter); + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(warehouses) ? warehouses?.data : []} + columns={warehousesColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(warehouses) ? warehouses?.meta?.page : 0} + totalItems={ + isResponseSuccess(warehouses) ? warehouses?.meta?.total_results : 0 + } + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(warehouses) && warehouses?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default WarehousesTable; From 70bdfc3b4320eaf88cccac20a8de9d23660f0690 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:06:51 +0700 Subject: [PATCH 121/327] feat(FE-43): create Master Data Warehouse page --- src/app/master-data/warehouse/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/warehouse/page.tsx diff --git a/src/app/master-data/warehouse/page.tsx b/src/app/master-data/warehouse/page.tsx new file mode 100644 index 00000000..eb5ae416 --- /dev/null +++ b/src/app/master-data/warehouse/page.tsx @@ -0,0 +1,11 @@ +import WarehousesTable from '@/components/pages/master-data/warehouse/WarehousesTable'; + +const Warehouse = () => { + return ( +
    + +
    + ); +}; + +export default Warehouse; From eb10dfe29f0178f1073b19140aa40c40629a6f39 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:07:06 +0700 Subject: [PATCH 122/327] feat(FE-40,41): create Master Data Add Warehouse page --- src/app/master-data/warehouse/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/warehouse/add/page.tsx diff --git a/src/app/master-data/warehouse/add/page.tsx b/src/app/master-data/warehouse/add/page.tsx new file mode 100644 index 00000000..7a8105a1 --- /dev/null +++ b/src/app/master-data/warehouse/add/page.tsx @@ -0,0 +1,11 @@ +import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm'; + +const AddNonstock = () => { + return ( +
    + +
    + ); +}; + +export default AddNonstock; From 452139eeedc8155d8e8d8aeed312cf6c50e00eb2 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:07:17 +0700 Subject: [PATCH 123/327] feat(FE-40,41): create Master Data Detail Warehouse page --- src/app/master-data/warehouse/detail/page.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/warehouse/detail/page.tsx diff --git a/src/app/master-data/warehouse/detail/page.tsx b/src/app/master-data/warehouse/detail/page.tsx new file mode 100644 index 00000000..7d6381e3 --- /dev/null +++ b/src/app/master-data/warehouse/detail/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm'; + +import { WarehouseApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const WarehouseDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const warehouseId = searchParams.get('warehouseId'); + + const { data: warehouse, isLoading: isLoadingWarehouse } = useSWR( + warehouseId, + (id: number) => WarehouseApi.getSingle(id) + ); + + if (!warehouseId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingWarehouse && !warehouse) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingWarehouse && ( + + )} + {!isLoadingWarehouse && isResponseSuccess(warehouse) && ( + + )} +
    + ); +}; + +export default WarehouseDetail; From 1ae2d13335540808c57dc70c4c12757882ba4ef7 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:07:27 +0700 Subject: [PATCH 124/327] feat(FE-40,41): create Master Data Edit Warehouse page --- .../warehouse/detail/edit/page.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/app/master-data/warehouse/detail/edit/page.tsx diff --git a/src/app/master-data/warehouse/detail/edit/page.tsx b/src/app/master-data/warehouse/detail/edit/page.tsx new file mode 100644 index 00000000..e4151226 --- /dev/null +++ b/src/app/master-data/warehouse/detail/edit/page.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm'; + +import { WarehouseApi } from '@/services/api/master-data'; +import { isResponseSuccess } from '@/lib/api-helper'; + +const WarehouseEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const warehouseId = searchParams.get('warehouseId'); + + const { data: warehouse, isLoading: isLoadingWarehouse } = useSWR( + warehouseId, + (id: number) => WarehouseApi.getSingle(id) + ); + + if (!warehouseId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingWarehouse && !warehouse) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingWarehouse && ( + + )} + {!isLoadingWarehouse && isResponseSuccess(warehouse) && ( + + )} +
    + ); +}; + +export default WarehouseEdit; From dcebd53c45b1555ec961b2ca1354d0883e701938 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:13:04 +0700 Subject: [PATCH 125/327] feat(FE-40): add edit button --- .../pages/master-data/area/form/AreaForm.tsx | 17 +++++++++++++++++ .../master-data/location/form/LocationForm.tsx | 17 +++++++++++++++++ .../pages/master-data/uom/form/UomForm.tsx | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/components/pages/master-data/area/form/AreaForm.tsx b/src/components/pages/master-data/area/form/AreaForm.tsx index d0a80105..41113b61 100644 --- a/src/components/pages/master-data/area/form/AreaForm.tsx +++ b/src/components/pages/master-data/area/form/AreaForm.tsx @@ -174,6 +174,23 @@ const AreaForm = ({ type = 'add', initialValues }: AreaFormProps) => { /> Delete + + {type !== 'edit' && ( + + )}
    )} diff --git a/src/components/pages/master-data/location/form/LocationForm.tsx b/src/components/pages/master-data/location/form/LocationForm.tsx index 50a5f664..c477edf3 100644 --- a/src/components/pages/master-data/location/form/LocationForm.tsx +++ b/src/components/pages/master-data/location/form/LocationForm.tsx @@ -243,6 +243,23 @@ const LocationForm = ({ type = 'add', initialValues }: LocationFormProps) => { /> Delete + + {type !== 'edit' && ( + + )}
    )} diff --git a/src/components/pages/master-data/uom/form/UomForm.tsx b/src/components/pages/master-data/uom/form/UomForm.tsx index da99f813..ad14c666 100644 --- a/src/components/pages/master-data/uom/form/UomForm.tsx +++ b/src/components/pages/master-data/uom/form/UomForm.tsx @@ -174,6 +174,23 @@ const UomForm = ({ type = 'add', initialValues }: UomFormProps) => { /> Delete + + {type !== 'edit' && ( + + )}
    )} From af60e682ee6c0dec443eb4ca574e1c025e15dddd Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Sun, 5 Oct 2025 16:19:37 +0700 Subject: [PATCH 126/327] chore(FE-41): redirect to /404 if response error --- src/app/master-data/area/detail/edit/page.tsx | 4 ++-- src/app/master-data/area/detail/page.tsx | 4 ++-- src/app/master-data/kandang/detail/edit/page.tsx | 4 ++-- src/app/master-data/kandang/detail/page.tsx | 4 ++-- src/app/master-data/location/detail/edit/page.tsx | 4 ++-- src/app/master-data/location/detail/page.tsx | 4 ++-- src/app/master-data/uom/detail/edit/page.tsx | 4 ++-- src/app/master-data/uom/detail/page.tsx | 4 ++-- src/app/master-data/warehouse/detail/edit/page.tsx | 4 ++-- src/app/master-data/warehouse/detail/page.tsx | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/app/master-data/area/detail/edit/page.tsx b/src/app/master-data/area/detail/edit/page.tsx index a8b5138f..4b29d792 100644 --- a/src/app/master-data/area/detail/edit/page.tsx +++ b/src/app/master-data/area/detail/edit/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import AreaForm from '@/components/pages/master-data/area/form/AreaForm'; import { AreaApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const AreaEdit = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const AreaEdit = () => { ); } - if (!isLoadingArea && !area) { + if (!isLoadingArea && (!area || isResponseError(area))) { router.replace('/404'); return; } diff --git a/src/app/master-data/area/detail/page.tsx b/src/app/master-data/area/detail/page.tsx index 55bfbc7d..c786ac0d 100644 --- a/src/app/master-data/area/detail/page.tsx +++ b/src/app/master-data/area/detail/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import AreaForm from '@/components/pages/master-data/area/form/AreaForm'; import { AreaApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const AreaDetail = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const AreaDetail = () => { ); } - if (!isLoadingArea && !area) { + if (!isLoadingArea && (!area || isResponseError(area))) { router.replace('/404'); return; } diff --git a/src/app/master-data/kandang/detail/edit/page.tsx b/src/app/master-data/kandang/detail/edit/page.tsx index 426aabc0..561d6f1f 100644 --- a/src/app/master-data/kandang/detail/edit/page.tsx +++ b/src/app/master-data/kandang/detail/edit/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm'; import { KandangApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const KandangEdit = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const KandangEdit = () => { ); } - if (!isLoadingKandang && !kandang) { + if (!isLoadingKandang && (!kandang || isResponseError(kandang))) { router.replace('/404'); return; } diff --git a/src/app/master-data/kandang/detail/page.tsx b/src/app/master-data/kandang/detail/page.tsx index 1b91bad7..a5b4f0e9 100644 --- a/src/app/master-data/kandang/detail/page.tsx +++ b/src/app/master-data/kandang/detail/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm'; import { KandangApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const KandangDetail = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const KandangDetail = () => { ); } - if (!isLoadingKandang && !kandang) { + if (!isLoadingKandang && (!kandang || isResponseError(kandang))) { router.replace('/404'); return; } diff --git a/src/app/master-data/location/detail/edit/page.tsx b/src/app/master-data/location/detail/edit/page.tsx index 853254d9..a97f5672 100644 --- a/src/app/master-data/location/detail/edit/page.tsx +++ b/src/app/master-data/location/detail/edit/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import LocationForm from '@/components/pages/master-data/location/form/LocationForm'; import { LocationApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const LocationEdit = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const LocationEdit = () => { ); } - if (!isLoadingLocation && !location) { + if (!isLoadingLocation && (!location || isResponseError(location))) { router.replace('/404'); return; } diff --git a/src/app/master-data/location/detail/page.tsx b/src/app/master-data/location/detail/page.tsx index bff4d12e..bb0fbe4c 100644 --- a/src/app/master-data/location/detail/page.tsx +++ b/src/app/master-data/location/detail/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import LocationForm from '@/components/pages/master-data/location/form/LocationForm'; import { LocationApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const LocationDetail = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const LocationDetail = () => { ); } - if (!isLoadingLocation && !location) { + if (!isLoadingLocation && (!location || isResponseError(location))) { router.replace('/404'); return; } diff --git a/src/app/master-data/uom/detail/edit/page.tsx b/src/app/master-data/uom/detail/edit/page.tsx index 95566351..48d7c823 100644 --- a/src/app/master-data/uom/detail/edit/page.tsx +++ b/src/app/master-data/uom/detail/edit/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import UomForm from '@/components/pages/master-data/uom/form/UomForm'; import { UomApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const UomEdit = () => { const router = useRouter(); @@ -28,7 +28,7 @@ const UomEdit = () => { ); } - if (!isLoadingUom && !uom) { + if (!isLoadingUom && (!uom || isResponseError(uom))) { router.replace('/404'); return; } diff --git a/src/app/master-data/uom/detail/page.tsx b/src/app/master-data/uom/detail/page.tsx index 59ad0755..b02af02b 100644 --- a/src/app/master-data/uom/detail/page.tsx +++ b/src/app/master-data/uom/detail/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import UomForm from '@/components/pages/master-data/uom/form/UomForm'; import { UomApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const UomDetail = () => { const router = useRouter(); @@ -28,7 +28,7 @@ const UomDetail = () => { ); } - if (!isLoadingUom && !uom) { + if (!isLoadingUom && (!uom || isResponseError(uom))) { router.replace('/404'); return; } diff --git a/src/app/master-data/warehouse/detail/edit/page.tsx b/src/app/master-data/warehouse/detail/edit/page.tsx index e4151226..a6498834 100644 --- a/src/app/master-data/warehouse/detail/edit/page.tsx +++ b/src/app/master-data/warehouse/detail/edit/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm'; import { WarehouseApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const WarehouseEdit = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const WarehouseEdit = () => { ); } - if (!isLoadingWarehouse && !warehouse) { + if (!isLoadingWarehouse && (!warehouse || isResponseError(warehouse))) { router.replace('/404'); return; } diff --git a/src/app/master-data/warehouse/detail/page.tsx b/src/app/master-data/warehouse/detail/page.tsx index 7d6381e3..5a7c7042 100644 --- a/src/app/master-data/warehouse/detail/page.tsx +++ b/src/app/master-data/warehouse/detail/page.tsx @@ -6,7 +6,7 @@ import useSWR from 'swr'; import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm'; import { WarehouseApi } from '@/services/api/master-data'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const WarehouseDetail = () => { const router = useRouter(); @@ -29,7 +29,7 @@ const WarehouseDetail = () => { ); } - if (!isLoadingWarehouse && !warehouse) { + if (!isLoadingWarehouse && (!warehouse || isResponseError(warehouse))) { router.replace('/404'); return; } From 4f0e02a93b84e5ac4a1823794431ed8edcbbefba Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 17:23:58 +0700 Subject: [PATCH 127/327] chore: add .idea to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 5ef6a520..2b4315f8 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# idea +.idea \ No newline at end of file From 3cac49725fefb5b508d404061ff16434b30a39e0 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 18:56:58 +0700 Subject: [PATCH 128/327] feat(FE-42): add Product Category API and form validation schema --- .../form/ProductCategoryForm.schema.ts | 10 ++++++++++ src/services/api/master-data.ts | 11 +++++++++++ src/types/api/master-data/product-category.d.ts | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/components/pages/master-data/product-category/form/ProductCategoryForm.schema.ts create mode 100644 src/types/api/master-data/product-category.d.ts diff --git a/src/components/pages/master-data/product-category/form/ProductCategoryForm.schema.ts b/src/components/pages/master-data/product-category/form/ProductCategoryForm.schema.ts new file mode 100644 index 00000000..102bb812 --- /dev/null +++ b/src/components/pages/master-data/product-category/form/ProductCategoryForm.schema.ts @@ -0,0 +1,10 @@ +import * as Yup from 'yup'; + +export const ProductCategoryFormSchema = Yup.object({ + code: Yup.string().required('Kode wajib diisi!').max(3, 'Kode kategori produk melebihi 3 karakter!'), + name: Yup.string().required('Nama wajib diisi!'), +}); + +export const UpdateProductCategoryFormSchema = ProductCategoryFormSchema; + +export type ProductCategoryFormValues = Yup.InferType; \ No newline at end of file diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 785a1ca1..53ea26c6 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -24,6 +24,11 @@ import { UpdateWarehousePayload, Warehouse, } from '@/types/api/master-data/warehouse'; +import { + CreateProductCategoryPayload, + ProductCategory, + UpdateProductCategoryPayload, +} from '@/types/api/master-data/product-category'; export const UomApi = new BaseApiService< Uom, @@ -54,3 +59,9 @@ export const WarehouseApi = new BaseApiService< CreateWarehousePayload, UpdateWarehousePayload >('/master-data/warehouses'); + +export const ProductCategoryApi = new BaseApiService< + ProductCategory, + CreateProductCategoryPayload, + UpdateProductCategoryPayload +>('/master-data/product-categories'); \ No newline at end of file diff --git a/src/types/api/master-data/product-category.d.ts b/src/types/api/master-data/product-category.d.ts new file mode 100644 index 00000000..3dd6203e --- /dev/null +++ b/src/types/api/master-data/product-category.d.ts @@ -0,0 +1,16 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type BaseProductCategory = { + id: number; + code: string; + name: string; +}; + +export type ProductCategory = BaseMetadata & BaseProductCategory; + +export type CreateProductCategoryPayload = { + code: string; + name: string; +}; + +export type UpdateProductCategoryPayload = CreateProductCategoryPayload; From 2b9b8e99202dbb6104ec91ea28abc5a32de5880b Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 18:58:38 +0700 Subject: [PATCH 129/327] feat(FE-41,43): implement Product Category table with CRUD operations --- .../product-category/ProductCategoryTable.tsx | 262 ++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 src/components/pages/master-data/product-category/ProductCategoryTable.tsx diff --git a/src/components/pages/master-data/product-category/ProductCategoryTable.tsx b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx new file mode 100644 index 00000000..f5226387 --- /dev/null +++ b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx @@ -0,0 +1,262 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { ProductCategory } from '@/types/api/master-data/product-category'; +import { ProductCategoryApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + +
    + ); +}; + +const ProductCategoryTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '' }, + paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + }); + + const { + data: productCategories, + isLoading, + mutate: refreshProductCategories, + } = useSWR( + `${ProductCategoryApi.basePath}${getTableFilterQueryString()}`, + ProductCategoryApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedProductCategory, setSelectedProductCategory] = useState(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const productCategoryColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedProductCategory(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await ProductCategoryApi.delete(selectedProductCategory?.id as number); + refreshProductCategories(); + + deleteModal.closeModal(); + toast.success('Successfully delete Product Category!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + setPageSize(newVal.value as number); + }; + + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    + + data={isResponseSuccess(productCategories) ? productCategories?.data : []} + columns={productCategoryColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(productCategories) ? productCategories?.meta?.page : 0} + totalItems={isResponseSuccess(productCategories) ? productCategories?.meta?.total_results : 0} + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': isResponseSuccess(productCategories) && productCategories?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + ); +}; + +export default ProductCategoryTable; \ No newline at end of file From 26ec4569375fbf3f5f40dbefcae63269901a7a8e Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 18:59:31 +0700 Subject: [PATCH 130/327] feat(FE-40,41,42): add Product Category detail and edit pages with form handling --- .../master-data/product-category/add/page.tsx | 11 + .../product-category/detail/edit/page.tsx | 47 ++++ .../product-category/detail/page.tsx | 47 ++++ src/app/master-data/product-category/page.tsx | 11 + .../form/ProductCategoryForm.tsx | 266 ++++++++++++++++++ 5 files changed, 382 insertions(+) create mode 100644 src/app/master-data/product-category/add/page.tsx create mode 100644 src/app/master-data/product-category/detail/edit/page.tsx create mode 100644 src/app/master-data/product-category/detail/page.tsx create mode 100644 src/app/master-data/product-category/page.tsx create mode 100644 src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx diff --git a/src/app/master-data/product-category/add/page.tsx b/src/app/master-data/product-category/add/page.tsx new file mode 100644 index 00000000..0993ba7a --- /dev/null +++ b/src/app/master-data/product-category/add/page.tsx @@ -0,0 +1,11 @@ +import ProductCategoryForm from "@/components/pages/master-data/product-category/form/ProductCategoryForm"; + +const AddProductCategory = () => { + return ( +
    + +
    + ); +}; + +export default AddProductCategory; \ No newline at end of file diff --git a/src/app/master-data/product-category/detail/edit/page.tsx b/src/app/master-data/product-category/detail/edit/page.tsx new file mode 100644 index 00000000..6bc10644 --- /dev/null +++ b/src/app/master-data/product-category/detail/edit/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import ProductCategoryForm from '@/components/pages/master-data/product-category/form/ProductCategoryForm'; + +import { ProductCategoryApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const ProductCategoryEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const productCategoryId = searchParams.get('productCategoryId'); + + const { data: productCategory, isLoading: isLoadingProductCategory } = useSWR( + productCategoryId, + (id: number) => ProductCategoryApi.getSingle(id) + ); + + if (!productCategoryId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingProductCategory && (!productCategory || isResponseError(productCategory))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingProductCategory && } + {!isLoadingProductCategory && isResponseSuccess(productCategory) && ( + + )} +
    + ); +} + +export default ProductCategoryEdit; \ No newline at end of file diff --git a/src/app/master-data/product-category/detail/page.tsx b/src/app/master-data/product-category/detail/page.tsx new file mode 100644 index 00000000..cba06fdb --- /dev/null +++ b/src/app/master-data/product-category/detail/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import ProductCategoryForm from '@/components/pages/master-data/product-category/form/ProductCategoryForm'; + +import { ProductCategoryApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const ProductCategoryDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const productCategoryId = searchParams.get('productCategoryId'); + + const { data: productCategory, isLoading: isLoadingProductCategory } = useSWR( + productCategoryId, + (id: number) => ProductCategoryApi.getSingle(id) + ); + + if (!productCategoryId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingProductCategory && (!productCategory || isResponseError(productCategory))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingProductCategory && } + {!isLoadingProductCategory && isResponseSuccess(productCategory) && ( + + )} +
    + ); +}; + +export default ProductCategoryDetail; diff --git a/src/app/master-data/product-category/page.tsx b/src/app/master-data/product-category/page.tsx new file mode 100644 index 00000000..5ec6d555 --- /dev/null +++ b/src/app/master-data/product-category/page.tsx @@ -0,0 +1,11 @@ +import ProductCategoryTable from "@/components/pages/master-data/product-category/ProductCategoryTable"; + +const ProductCategory = () => { + return ( +
    + +
    + ); +}; + +export default ProductCategory; \ No newline at end of file diff --git a/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx b/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx new file mode 100644 index 00000000..453670f3 --- /dev/null +++ b/src/components/pages/master-data/product-category/form/ProductCategoryForm.tsx @@ -0,0 +1,266 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + ProductCategoryFormSchema, + ProductCategoryFormValues, + UpdateProductCategoryFormSchema, +} from '@/components/pages/master-data/product-category/form/ProductCategoryForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + ProductCategory, + CreateProductCategoryPayload, + UpdateProductCategoryPayload, +} from '@/types/api/master-data/product-category'; +import { ProductCategoryApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; + +interface ProductCategoryFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: ProductCategory; +} + +const ProductCategoryForm = ({ type = 'add', initialValues }: ProductCategoryFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [formErrorMessage, setFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createProductCategoryHandler = useCallback( + async (payload: CreateProductCategoryPayload) => { + const res = await ProductCategoryApi.create(payload); + + if (isResponseError(res)) { + setFormErrorMessage(res.message); + return; + } + + toast.success(res?.message as string); + router.push('/master-data/product-category'); + }, + [router] + ); + + const updateProductCategoryHandler = useCallback( + async (id: number, payload: UpdateProductCategoryPayload) => { + const res = await ProductCategoryApi.update(id, payload); + + if (res?.status === 'error') { + setFormErrorMessage(res.message); + return; + } + + toast.success(res?.message as string); + router.refresh(); + router.push('/master-data/product-category'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + code: initialValues?.code ?? '', + name: initialValues?.name ?? '', + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateProductCategoryFormSchema : ProductCategoryFormSchema, + onSubmit: async (values) => { + setFormErrorMessage(''); + + const payload: CreateProductCategoryPayload = { + code: values.code, + name: values.name, + }; + + switch (type) { + case 'add': + await createProductCategoryHandler(payload); + break; + case 'edit': + await updateProductCategoryHandler(initialValues?.id as number, payload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + const deleteProductCategoryClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await ProductCategoryApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Product Category!'); + setIsDeleteLoading(false); + router.push('/master-data/product-category'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Product Category'} + {type === 'edit' && 'Edit Product Category'} + {type === 'detail' && 'Detail Product Category'} +

    +
    + +
    +
    + + +
    + +
    + {type !== 'add' && ( +
    + + + {type !== 'edit' && ( + + )} +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {formErrorMessage && ( +
    + + {formErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default ProductCategoryForm; \ No newline at end of file From 3241cc98683afd77024c9d420ca3e11b4fadccda Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 21:21:24 +0700 Subject: [PATCH 131/327] feat(FE-42): add Product API and form validation schema with product flags --- .../product/form/ProductForm.schema.ts | 53 +++++++++++++++++++ src/config/constant.ts | 13 +++++ src/services/api/master-data.ts | 13 ++++- src/types/api/master-data/product.d.ts | 37 +++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/components/pages/master-data/product/form/ProductForm.schema.ts create mode 100644 src/types/api/master-data/product.d.ts diff --git a/src/components/pages/master-data/product/form/ProductForm.schema.ts b/src/components/pages/master-data/product/form/ProductForm.schema.ts new file mode 100644 index 00000000..eea9abf7 --- /dev/null +++ b/src/components/pages/master-data/product/form/ProductForm.schema.ts @@ -0,0 +1,53 @@ +import * as Yup from 'yup'; + +export const ProductFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), + brand: Yup.string().required('Merek wajib diisi!'), + sku: Yup.string().required('SKU wajib diisi!'), + uom: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + uom_id: Yup.number().required('Satuan wajib diisi!').typeError('Satuan wajib diisi!'), + product_category: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + product_category_id: Yup.number() + .required('Kategori produk wajib diisi!') + .typeError('Kategori produk wajib diisi!'), + product_price: Yup.number() + .required('Harga produk wajib diisi!') + .typeError('Harga produk wajib diisi!') + .min(0, 'Harga produk tidak boleh kurang dari 0!'), + selling_price: Yup.number() + .required('Harga jual wajib diisi!') + .typeError('Harga jual wajib diisi!') + .min(0, 'Harga jual tidak boleh kurang dari 0!'), + tax: Yup.number() + .required('Pajak wajib diisi!') + .typeError('Pajak wajib diisi!') + .min(0, 'Pajak tidak boleh kurang dari 0!') + .max(100, 'Pajak tidak boleh lebih dari 100%!'), + expiry_period: Yup.number() + .required('Periode kadaluarsa wajib diisi!') + .typeError('Periode kadaluarsa wajib diisi!') + .min(0, 'Periode kadaluarsa tidak boleh kurang dari 0!'), + supplier: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + supplier_ids: Yup.array() + .of(Yup.number().typeError('Supplier tidak valid!')) + .min(1, 'Minimal harus ada 1 supplier!') + .required('Supplier wajib diisi!'), + flags: Yup.array() + .of(Yup.string()) + .min(1, 'Minimal harus ada 1 flag!') + .required('Flag wajib diisi!'), +}); + +export const UpdateProductFormSchema = ProductFormSchema; + +export type ProductFormValues = Yup.InferType; + diff --git a/src/config/constant.ts b/src/config/constant.ts index 55eed0b3..1fbef81f 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -107,3 +107,16 @@ export const WAREHOUSE_TYPE_OPTIONS = [ value: 'KANDANG', }, ]; + +export const PRODUCT_FLAG_OPTIONS = [ + { label: 'DOC', value: 'DOC' }, + { label: 'PAKAN', value: 'PAKAN' }, + { label: 'PRE-STARTER', value: 'PRE-STARTER' }, + { label: 'STARTER', value: 'STARTER' }, + { label: 'FINISHER', value: 'FINISHER' }, + { label: 'OVK', value: 'OVK' }, + { label: 'OBAT', value: 'OBAT' }, + { label: 'VITAMIN', value: 'VITAMIN' }, + { label: 'KIMIA', value: 'KIMIA' }, +]; + diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 53ea26c6..e1a4db17 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -29,6 +29,11 @@ import { ProductCategory, UpdateProductCategoryPayload, } from '@/types/api/master-data/product-category'; +import { + CreateProductPayload, + Product, + UpdateProductPayload, +} from '@/types/api/master-data/product'; export const UomApi = new BaseApiService< Uom, @@ -64,4 +69,10 @@ export const ProductCategoryApi = new BaseApiService< ProductCategory, CreateProductCategoryPayload, UpdateProductCategoryPayload ->('/master-data/product-categories'); \ No newline at end of file +>('/master-data/product-categories'); + +export const ProductApi = new BaseApiService< + Product, + CreateProductPayload, + UpdateProductPayload +>('/master-data/products'); diff --git a/src/types/api/master-data/product.d.ts b/src/types/api/master-data/product.d.ts new file mode 100644 index 00000000..d4039750 --- /dev/null +++ b/src/types/api/master-data/product.d.ts @@ -0,0 +1,37 @@ +import { BaseMetadata } from '@/types/api/api-general'; +import { Uom } from '@/types/api/master-data/uom'; +import { ProductCategory } from '@/types/api/master-data/product-category'; +import { Supplier } from '@/types/api/master-data/supplier'; + +export type BaseProduct = { + id: number; + name: string; + brand: string; + sku: string; + product_price: number; + selling_price?: number; + tax?: number; + expiry_period: number; + uom: Uom; + product_category: ProductCategory; + suppliers: Supplier[]; + flags: string[]; +}; + +export type Product = BaseMetadata & BaseProduct; + +export type CreateProductPayload = { + name: string; + brand: string; + sku: string; + uom_id: number; + product_category_id: number; + product_price: number; + selling_price: number; + tax: number; + expiry_period: number; + supplier_ids: number[]; + flags: string[]; +}; + +export type UpdateProductPayload = CreateProductPayload; \ No newline at end of file From e1569c607cc4c125f5a83ef04489a06d26d76e53 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 21:22:05 +0700 Subject: [PATCH 132/327] feat(FE-41,43): add Products table with CRUD operations and search functionality --- .../master-data/product/ProductTable.tsx | 350 ++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 src/components/pages/master-data/product/ProductTable.tsx diff --git a/src/components/pages/master-data/product/ProductTable.tsx b/src/components/pages/master-data/product/ProductTable.tsx new file mode 100644 index 00000000..ab256548 --- /dev/null +++ b/src/components/pages/master-data/product/ProductTable.tsx @@ -0,0 +1,350 @@ +'use client'; + +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { + CellContext, + ColumnDef, + ColumnSort, + SortingState, +} from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Product } from '@/types/api/master-data/product'; +import { ProductApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => ( +
    + + + +
    +); + +const ProductsTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { + search: '', + nameSort: '', + skuSort: '', + brandSort: '', + categorySort: '', + }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + skuSort: 'sort_sku', + brandSort: 'sort_brand', + categorySort: 'sort_category', + }, + }); + + const { + data: products, + isLoading, + mutate: refreshProducts, + } = useSWR( + `${ProductApi.basePath}${getTableFilterQueryString()}`, + ProductApi.getAllFetcher + ); + + const deleteModal = useModal(); + const [selectedProduct, setSelectedProduct] = useState(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + const [sorting, setSorting] = useState([]); + + const productsColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'sku', + header: 'SKU', + }, + { + accessorKey: 'brand', + header: 'Merek', + }, + { + accessorKey: 'product_category', + header: 'Kategori', + cell: (props) => props.row.original.product_category?.name ?? '-', + }, + { + accessorKey: 'uom', + header: 'Satuan', + cell: (props) => props.row.original.uom?.name ?? '-', + }, + { + accessorKey: 'product_price', + header: 'Harga Produk', + cell: (props) => props.row.original.product_price?.toLocaleString() ?? '-', + }, + { + accessorKey: 'selling_price', + header: 'Harga Jual', + cell: (props) => props.row.original.selling_price?.toLocaleString() ?? '-', + }, + { + accessorKey: 'tax', + header: 'Pajak (%)', + cell: (props) => props.row.original.tax ?? '-', + }, + { + accessorKey: 'expiry_period', + header: 'Kadaluarsa (hari)', + cell: (props) => props.row.original.expiry_period ?? '-', + }, + { + accessorKey: 'suppliers', + header: 'Supplier', + cell: (props) => + props.row.original.suppliers?.map((s) => s.name).join(', ') || '-', + }, + { + accessorKey: 'flags', + header: 'Flags', + cell: (props) => + props.row.original.flags?.length + ? props.row.original.flags.join(', ') + : '-', + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedProduct(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + await ProductApi.delete(selectedProduct?.id as number); + refreshProducts(); + deleteModal.closeModal(); + toast.success('Successfully delete Product!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + setPageSize(newVal.value as number); + }; + + const updateSortingFilter = useCallback( + ( + sortName: Exclude, + sortFilter: ColumnSort | undefined + ) => { + if (!sortFilter) { + updateFilter(sortName, ''); + } else { + updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc'); + } + }, + [updateFilter] + ); + + useEffect(() => { + const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); + const skuSortFilter = sorting.find((sortItem) => sortItem.id === 'sku'); + const brandSortFilter = sorting.find((sortItem) => sortItem.id === 'brand'); + const categorySortFilter = sorting.find((sortItem) => sortItem.id === 'product_category'); + + updateSortingFilter('nameSort', nameSortFilter); + updateSortingFilter('skuSort', skuSortFilter); + updateSortingFilter('brandSort', brandSortFilter); + updateSortingFilter('categorySort', categorySortFilter); + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    + + data={isResponseSuccess(products) ? products?.data : []} + columns={productsColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(products) ? products?.meta?.page : 0} + totalItems={ + isResponseSuccess(products) ? products?.meta?.total_results : 0 + } + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(products) && products?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + ); +}; + +export default ProductsTable; \ No newline at end of file From 250c42a04b43c4e3c614792a3795cab063f65a58 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 7 Oct 2025 21:23:12 +0700 Subject: [PATCH 133/327] feat(FE-40,41,42): add Product management pages with form handling and table display --- src/app/master-data/product/add/page.tsx | 11 + .../master-data/product/detail/edit/page.tsx | 45 ++ src/app/master-data/product/detail/page.tsx | 45 ++ src/app/master-data/product/page.tsx | 11 + .../master-data/product/form/ProductForm.tsx | 438 ++++++++++++++++++ 5 files changed, 550 insertions(+) create mode 100644 src/app/master-data/product/add/page.tsx create mode 100644 src/app/master-data/product/detail/edit/page.tsx create mode 100644 src/app/master-data/product/detail/page.tsx create mode 100644 src/app/master-data/product/page.tsx create mode 100644 src/components/pages/master-data/product/form/ProductForm.tsx diff --git a/src/app/master-data/product/add/page.tsx b/src/app/master-data/product/add/page.tsx new file mode 100644 index 00000000..7cc995b6 --- /dev/null +++ b/src/app/master-data/product/add/page.tsx @@ -0,0 +1,11 @@ +import ProductForm from '@/components/pages/master-data/product/form/ProductForm'; + +const AddProduct = () => { + return ( +
    + +
    + ); +}; + +export default AddProduct; \ No newline at end of file diff --git a/src/app/master-data/product/detail/edit/page.tsx b/src/app/master-data/product/detail/edit/page.tsx new file mode 100644 index 00000000..96cfdc42 --- /dev/null +++ b/src/app/master-data/product/detail/edit/page.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import ProductForm from '@/components/pages/master-data/product/form/ProductForm'; +import { ProductApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const ProductEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const productId = searchParams.get('productId'); + + const { data: product, isLoading } = useSWR( + productId, + (id: number) => ProductApi.getSingle(id) + ); + + if (!productId) { + router.back(); + return ( +
    + +
    + ); + } + + if (!isLoading && (!product || isResponseError(product))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoading && } + {!isLoading && isResponseSuccess(product) && ( + + )} +
    + ); +}; + +export default ProductEdit; \ No newline at end of file diff --git a/src/app/master-data/product/detail/page.tsx b/src/app/master-data/product/detail/page.tsx new file mode 100644 index 00000000..916a44d0 --- /dev/null +++ b/src/app/master-data/product/detail/page.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import ProductForm from '@/components/pages/master-data/product/form/ProductForm'; +import { ProductApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const ProductDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const productId = searchParams.get('productId'); + + const { data: product, isLoading } = useSWR( + productId, + (id: number) => ProductApi.getSingle(id) + ); + + if (!productId) { + router.back(); + return ( +
    + +
    + ); + } + + if (!isLoading && (!product || isResponseError(product))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoading && } + {!isLoading && isResponseSuccess(product) && ( + + )} +
    + ); +}; + +export default ProductDetail; \ No newline at end of file diff --git a/src/app/master-data/product/page.tsx b/src/app/master-data/product/page.tsx new file mode 100644 index 00000000..6014aeb9 --- /dev/null +++ b/src/app/master-data/product/page.tsx @@ -0,0 +1,11 @@ +import ProductsTable from "@/components/pages/master-data/product/ProductTable"; + +const Product = () => { + return ( +
    + +
    + ); +}; + +export default Product; \ No newline at end of file diff --git a/src/components/pages/master-data/product/form/ProductForm.tsx b/src/components/pages/master-data/product/form/ProductForm.tsx new file mode 100644 index 00000000..02afbfc9 --- /dev/null +++ b/src/components/pages/master-data/product/form/ProductForm.tsx @@ -0,0 +1,438 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; +import useSWR from 'swr'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + ProductFormSchema, + ProductFormValues, + UpdateProductFormSchema, +} from '@/components/pages/master-data/product/form/ProductForm.schema'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { + Product, + CreateProductPayload, + UpdateProductPayload, +} from '@/types/api/master-data/product'; +import { UomApi, ProductCategoryApi, SupplierApi, ProductApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { PRODUCT_FLAG_OPTIONS } from '@/config/constant'; + +interface ProductFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Product; +} + +const ProductForm = ({ type = 'add', initialValues }: ProductFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [productFormErrorMessage, setProductFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createProductHandler = useCallback( + async (payload: CreateProductPayload) => { + const res = await ProductApi.create(payload); + if (isResponseError(res)) { + setProductFormErrorMessage(res.message); + return; + } + toast.success(res?.message as string); + router.push('/master-data/product'); + }, + [router] + ); + + const updateProductHandler = useCallback( + async (productId: number, payload: UpdateProductPayload) => { + const res = await ProductApi.update(productId, payload); + if (res?.status === 'error') { + setProductFormErrorMessage(res.message); + return; + } + toast.success(res?.message as string); + router.refresh(); + router.push('/master-data/product'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => ({ + name: initialValues?.name ?? '', + brand: initialValues?.brand ?? '', + sku: initialValues?.sku ?? '', + uom: initialValues?.uom + ? { value: initialValues.uom.id, label: initialValues.uom.name } + : null, + uom_id: initialValues?.uom?.id ?? 0, + product_category: initialValues?.product_category + ? { value: initialValues.product_category.id, label: initialValues.product_category.name } + : null, + product_category_id: initialValues?.product_category?.id ?? 0, + product_price: initialValues?.product_price ?? 0, + selling_price: initialValues?.selling_price ?? 0, + tax: initialValues?.tax ?? 0, + expiry_period: initialValues?.expiry_period ?? 0, + supplier: null, // not used for payload, just for UI + supplier_ids: initialValues?.suppliers?.map(s => s.id) ?? [], + flags: initialValues?.flags ?? [], + }), [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateProductFormSchema : ProductFormSchema, + onSubmit: async (values) => { + setProductFormErrorMessage(''); + const payload: CreateProductPayload = { + name: values.name, + brand: values.brand, + sku: values.sku, + uom_id: values.uom_id, + product_category_id: values.product_category_id, + product_price: values.product_price, + selling_price: values.selling_price, + tax: values.tax, + expiry_period: values.expiry_period, + supplier_ids: (values.supplier_ids ?? []).filter((id): id is number => typeof id === 'number'), + flags: (values.flags ?? []).filter((f): f is string => typeof f === 'string'), + }; + switch (type) { + case 'add': + await createProductHandler(payload); + break; + case 'edit': + await updateProductHandler(initialValues?.id as number, payload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + // UOM + const [uomSelectInputValue, setUomSelectInputValue] = useState(''); + const uomsUrl = `${UomApi.basePath}?${new URLSearchParams({ search: uomSelectInputValue ?? '' }).toString()}`; + const { data: uoms, isLoading: isLoadingUoms } = useSWR(uomsUrl, UomApi.getAllFetcher); + const uomOptions = isResponseSuccess(uoms) + ? uoms?.data.map((uom) => ({ value: uom.id, label: uom.name })) + : []; + const uomChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('uom', true); + formik.setFieldValue('uom', val); + formik.setFieldTouched('uom_id', true); + formik.setFieldValue('uom_id', (val as OptionType)?.value); + }; + + // Product Category + const [categorySelectInputValue, setCategorySelectInputValue] = useState(''); + const categoriesUrl = `${ProductCategoryApi.basePath}?${new URLSearchParams({ search: categorySelectInputValue ?? '' }).toString()}`; + const { data: categories, isLoading: isLoadingCategories } = useSWR(categoriesUrl, ProductCategoryApi.getAllFetcher); + const categoryOptions = isResponseSuccess(categories) + ? categories?.data.map((cat) => ({ value: cat.id, label: cat.name })) + : []; + const categoryChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('product_category', true); + formik.setFieldValue('product_category', val); + formik.setFieldTouched('product_category_id', true); + formik.setFieldValue('product_category_id', (val as OptionType)?.value); + }; + + // Supplier (multi select) + const [supplierSelectInputValue, setSupplierSelectInputValue] = useState(''); + const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ search: supplierSelectInputValue ?? '' }).toString()}`; + const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR(suppliersUrl, SupplierApi.getAllFetcher); + const supplierOptions = isResponseSuccess(suppliers) + ? suppliers?.data + .filter((sup) => sup.category === 'SAPRONAK') + .map((sup) => ({ value: sup.id, label: sup.name })) + : []; + const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { + const arr = Array.isArray(val) ? val : val ? [val] : []; + formik.setFieldTouched('supplier_ids', true); + formik.setFieldValue('supplier_ids', arr.map((v) => (v as OptionType).value)); + }; + + const deleteProductClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + await ProductApi.delete(initialValues?.id as number); + deleteModal.closeModal(); + toast.success('Successfully delete Product!'); + setIsDeleteLoading(false); + router.push('/master-data/product'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + +

    + {type === 'add' && 'Tambah Produk'} + {type === 'edit' && 'Edit Produk'} + {type === 'detail' && 'Detail Produk'} +

    +
    +
    +
    + + + + + + + + + + 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' && ( +
    + + {type !== 'edit' && ( + + )} +
    + )} + {type !== 'detail' && ( +
    + + +
    + )} +
    + {productFormErrorMessage && ( +
    + + {productFormErrorMessage} +
    + )} +
    +
    + {type !== 'add' && ( + + )} + + ); +}; + +export default ProductForm; \ No newline at end of file From f5952f5a3629d5263bbd1cd34a65870af580cfeb Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 8 Oct 2025 09:12:49 +0700 Subject: [PATCH 134/327] feat(FE-43): add Supplier API and data types for supplier management --- src/services/api/master-data.ts | 11 ++++++++ src/types/api/master-data/supplier.d.ts | 34 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/types/api/master-data/supplier.d.ts diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index e1a4db17..7429b8ef 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -34,6 +34,11 @@ import { Product, UpdateProductPayload, } from '@/types/api/master-data/product'; +import { + CreateSupplierPayload, + Supplier, + UpdateSupplierPayload, +} from '@/types/api/master-data/supplier'; export const UomApi = new BaseApiService< Uom, @@ -76,3 +81,9 @@ export const ProductApi = new BaseApiService< CreateProductPayload, UpdateProductPayload >('/master-data/products'); + +export const SupplierApi = new BaseApiService< + Supplier, + CreateSupplierPayload, + UpdateSupplierPayload +>('/master-data/suppliers'); \ No newline at end of file diff --git a/src/types/api/master-data/supplier.d.ts b/src/types/api/master-data/supplier.d.ts new file mode 100644 index 00000000..f2cfdb11 --- /dev/null +++ b/src/types/api/master-data/supplier.d.ts @@ -0,0 +1,34 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type BaseSupplier = { + id: number; + name: string; + alias: string; + category: string; + pic: string; + type: string; + phone: string; + email: string; + address: string; + account_number: string; + balance: number; + due_date: number; +}; + +export type Supplier = BaseMetadata & BaseSupplier; + +export type CreateSupplierPayload = { + name: string; + alias: string; + category: string; + pic: string; + type: string; + phone: string; + email: string; + address: string; + account_number: string; + balance: number; + due_date: number; +}; + +export type UpdateSupplierPayload = CreateSupplierPayload; \ No newline at end of file From 396ebe50014eb20fd0fc3900ff832b348af35ed0 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 8 Oct 2025 09:55:19 +0700 Subject: [PATCH 135/327] feat(FE-43): add 'Code' column to Product Category table --- .../master-data/product-category/ProductCategoryTable.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/pages/master-data/product-category/ProductCategoryTable.tsx b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx index f5226387..f8413ab6 100644 --- a/src/components/pages/master-data/product-category/ProductCategoryTable.tsx +++ b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx @@ -109,6 +109,10 @@ const ProductCategoryTable = () => { props.row.index + 1, }, + { + accessorKey: 'code', + header: 'Code', + }, { accessorKey: 'name', header: 'Nama', From 3e7da624aa3d045b1a76e4740dceb4bc0ee6287a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 13:47:56 +0700 Subject: [PATCH 136/327] feat: add .prettierrc.json config --- .prettierrc.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..250df482 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,15 @@ +{ + "singleQuote": true, + "jsxSingleQuote": true, + "endOfLine": "lf", + "arrowParens": "always", + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "printWidth": 80, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "semi": true, + "tabWidth": 2, + "trailingComma": "es5" +} From 8461667ca216f7d1d23ab8878912966b046db214 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 14:56:52 +0700 Subject: [PATCH 137/327] chore(FE-41): delete nonstock api helper function file --- src/services/api/master-data/nonstock.ts | 87 ------------------------ 1 file changed, 87 deletions(-) delete mode 100644 src/services/api/master-data/nonstock.ts diff --git a/src/services/api/master-data/nonstock.ts b/src/services/api/master-data/nonstock.ts deleted file mode 100644 index 7340e37b..00000000 --- a/src/services/api/master-data/nonstock.ts +++ /dev/null @@ -1,87 +0,0 @@ -import axios from 'axios'; -import { httpClient } from '@/services/http/client'; - -import { - CreateNonstockPayload, - DeleteNonstockResponse, - NonstockResponse, - UpdateNonstockPayload, -} from '@/types/api/master-data/nonstock'; - -export const getNonstock = async (nonstockId: number) => { - try { - const getNonstockRes = await httpClient( - `/master-data/nonstocks/${nonstockId}` - ); - - return getNonstockRes; - } catch (error: unknown) { - if (axios.isAxiosError(error)) { - return error.response?.data; - } - - return undefined; - } -}; - -export const createNonstock = async (payload: CreateNonstockPayload) => { - try { - const createNonstockRes = await httpClient( - '/master-data/nonstocks', - { - method: 'POST', - body: payload, - } - ); - - return createNonstockRes; - } catch (error: unknown) { - if (axios.isAxiosError(error)) { - return error.response?.data; - } - - return undefined; - } -}; - -export const updateNonstock = async ( - nonstockId: number, - payload: UpdateNonstockPayload -) => { - try { - const updateNonstockRes = await httpClient( - `/master-data/nonstocks/${nonstockId}`, - { - method: 'PATCH', - body: payload, - } - ); - - return updateNonstockRes; - } catch (error: unknown) { - if (axios.isAxiosError(error)) { - return error.response?.data; - } - - return undefined; - } -}; - -export const deleteNonstock = async (nonstockId: number) => { - try { - const deleteNonstockRes = await httpClient( - `/master-data/nonstocks/${nonstockId}`, - { - method: 'DELETE', - } - ); - - return deleteNonstockRes; - } catch (error) { - if (axios.isAxiosError(error)) { - return error.response?.data; - } - - return undefined; - } -}; From 0e49e29002c4947ffb4edef52438d949219e7124 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 14:58:21 +0700 Subject: [PATCH 138/327] feat(FE-42): create SUPPLIER_FLAG_OPTIONS constant --- src/config/constant.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/config/constant.ts b/src/config/constant.ts index 1fbef81f..ab58df5b 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -120,3 +120,6 @@ export const PRODUCT_FLAG_OPTIONS = [ { label: 'KIMIA', value: 'KIMIA' }, ]; +export const SUPPLIER_FLAG_OPTIONS = [ + { label: 'EKSPEDISI', value: 'EKSPEDISI' }, +]; From 143d640a1e029e097f66ad83fe6a6dc47034aaaf Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 14:58:54 +0700 Subject: [PATCH 139/327] chore(FE-41): refactor nonstock type --- src/types/api/master-data/nonstock.d.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/types/api/master-data/nonstock.d.ts b/src/types/api/master-data/nonstock.d.ts index 682f7852..e4e79d8e 100644 --- a/src/types/api/master-data/nonstock.d.ts +++ b/src/types/api/master-data/nonstock.d.ts @@ -1,18 +1,23 @@ -import { BaseApiResponse } from '@/types/api/api-general'; +import { BaseApiResponse, BaseMetadata, flags } from '@/types/api/api-general'; +import { BaseUom } from '@/types/api/master-data/uom'; +import { BaseSupplier } from '@/types/api/master-data/supplier'; -export type Nonstock = { +export type BaseNonstock = { id: number; name: string; + uom_id: number; + uom: BaseUom; + suppliers: BaseSupplier[]; + flags: flags[]; }; +export type Nonstock = BaseMetadata & BaseNonstock; + export type CreateNonstockPayload = { name: string; + uom_id: number; + supplier_ids: number[]; + flags: flags[]; }; export type UpdateNonstockPayload = CreateNonstockPayload; - -export type NonstockResponse = BaseApiResponse; - -export type NonstocksResponse = BaseApiResponse; - -export type DeleteNonstockResponse = BaseApiResponse; From f3d0e12bcded069380bcdc34c59f17b8b73defdf Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 14:59:14 +0700 Subject: [PATCH 140/327] feat(FE-42): create flags type --- src/types/api/api-general.d.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/types/api/api-general.d.ts b/src/types/api/api-general.d.ts index 8a4c4de7..6a3fc6be 100644 --- a/src/types/api/api-general.d.ts +++ b/src/types/api/api-general.d.ts @@ -53,3 +53,16 @@ export type BaseMetadata = { export type Override = Omit & Overrides; + +export type flags = + | 'PAKAN' + | 'OBAT' + | 'VITAMIN' + | 'KIMIA' + | 'EKSPEDISI' + | 'IS_ACTIVE' + | 'DOC' + | 'PRE-STARTER' + | 'STARTER' + | 'FINISHER' + | 'OVK'; From d24d50474d1ab4590e7ce7607091ad7cc0b23a1e Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 14:59:39 +0700 Subject: [PATCH 141/327] feat(FE-41): create Nonstock API service --- src/services/api/master-data.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 7429b8ef..41975bd8 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -39,6 +39,11 @@ import { Supplier, UpdateSupplierPayload, } from '@/types/api/master-data/supplier'; +import { + CreateNonstockPayload, + Nonstock, + UpdateNonstockPayload, +} from '@/types/api/master-data/nonstock'; export const UomApi = new BaseApiService< Uom, @@ -86,4 +91,10 @@ export const SupplierApi = new BaseApiService< Supplier, CreateSupplierPayload, UpdateSupplierPayload ->('/master-data/suppliers'); \ No newline at end of file +>('/master-data/suppliers'); + +export const NonstockApi = new BaseApiService< + Nonstock, + CreateNonstockPayload, + UpdateNonstockPayload +>('/master-data/nonstocks'); From 96fea80f6258c38b149c83d2d49c593d88156b4b Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:00:06 +0700 Subject: [PATCH 142/327] feat(FE-40,41): create NonstockForm component --- .../nonstock/form/NonstockForm.tsx | 361 ++++++++++++++---- 1 file changed, 287 insertions(+), 74 deletions(-) diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx index 33dcba54..7a67c9a7 100644 --- a/src/components/pages/master-data/nonstock/form/NonstockForm.tsx +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.tsx @@ -3,26 +3,31 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; +import useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { NonstockFormSchema, NonstockFormValues, UpdateNonstockFormSchema, } from '@/components/pages/master-data/nonstock/form/NonstockForm.schema'; -import { isResponseError } from '@/lib/api-helper'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { - CreateNonstockPayload, Nonstock, + CreateNonstockPayload, UpdateNonstockPayload, } from '@/types/api/master-data/nonstock'; -import { - createNonstock, - updateNonstock, -} from '@/services/api/master-data/nonstock'; +import { NonstockApi, SupplierApi, UomApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { flags } from '@/types/api/api-general'; +import { SUPPLIER_FLAG_OPTIONS } from '@/config/constant'; interface NonstockFormProps { type?: 'add' | 'edit' | 'detail'; @@ -31,19 +36,21 @@ interface NonstockFormProps { const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const router = useRouter(); + const deleteModal = useModal(); const [nonstockFormErrorMessage, setNonstockFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); const createNonstockHandler = useCallback( async (payload: CreateNonstockPayload) => { - const createNonstockRes = await createNonstock(payload); + const createNonstockRes = await NonstockApi.create(payload); if (isResponseError(createNonstockRes)) { setNonstockFormErrorMessage(createNonstockRes.message); return; } - alert(createNonstockRes?.message); + toast.success(createNonstockRes?.message as string); router.push('/master-data/nonstock'); }, [router] @@ -51,14 +58,14 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const updateNonstockHandler = useCallback( async (nonstockId: number, payload: UpdateNonstockPayload) => { - const updateNonstockRes = await updateNonstock(nonstockId, payload); + const updateNonstockRes = await NonstockApi.update(nonstockId, payload); if (updateNonstockRes?.status === 'error') { setNonstockFormErrorMessage(updateNonstockRes.message); return; } - alert(updateNonstockRes?.message); + toast.success(updateNonstockRes?.message as string); router.refresh(); router.push('/master-data/nonstock'); }, @@ -68,6 +75,22 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const formikInitialValues = useMemo(() => { return { name: initialValues?.name ?? '', + uomId: initialValues?.uom_id ?? 0, + uom: initialValues?.uom + ? { + value: initialValues?.uom.id, + label: initialValues?.uom.name, + } + : null, + supplierIds: + initialValues?.suppliers.map((supplier) => supplier.id) ?? [], + suppliers: + initialValues?.suppliers.map((supplier) => ({ + value: supplier.id, + label: supplier.name, + })) ?? [], + + flags: initialValues?.flags ?? [], }; }, [initialValues]); @@ -80,6 +103,9 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const nonstockPayload: CreateNonstockPayload = { name: values.name, + uom_id: values.uomId, + supplier_ids: values.supplierIds as number[], + flags: values.flags as flags[], }; switch (type) { @@ -97,81 +123,268 @@ const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { }, }); + const { setValues: formikSetValues } = formik; + + // UOM + const [uomSelectInputValue, setUomSelectInputValue] = useState(''); + + const uomsUrl = `${UomApi.basePath}?${new URLSearchParams({ + search: uomSelectInputValue ?? '', + }).toString()}`; + + const { data: uoms, isLoading: isLoadingUoms } = useSWR( + uomsUrl, + UomApi.getAllFetcher + ); + + const uomOptions = isResponseSuccess(uoms) + ? uoms?.data.map((uom) => ({ + value: uom.id, + label: uom.name, + })) + : []; + + const uomChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('uom', true); + formik.setFieldValue('uom', val); + + formik.setFieldTouched('uomId', true); + formik.setFieldValue('uomId', (val as OptionType)?.value); + }; + + // supplier + const [supplierSelectInputValue, setSupplierSelectInputValue] = useState(''); + + const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ + search: supplierSelectInputValue ?? '', + }).toString()}`; + + const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR( + suppliersUrl, + SupplierApi.getAllFetcher + ); + + const supplierOptions = isResponseSuccess(suppliers) + ? suppliers?.data + .filter((sup) => sup.category === 'BOP') + .map((supplier) => ({ + value: supplier.id, + label: supplier.name, + })) + : []; + + const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('suppliers', true); + formik.setFieldValue('suppliers', val); + + const supplierIds = (val as OptionType[]).map( + (supplier) => supplier.value as number + ); + + formik.setFieldTouched('supplierIds', true); + formik.setFieldValue('supplierIds', supplierIds); + }; + + const deleteNonstockClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await NonstockApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Nonstock!'); + setIsDeleteLoading(false); + router.push('/master-data/nonstock'); + }; + + const flagsChangeHandler = (val: OptionType | OptionType[] | null) => { + const formattedFlags = (val as OptionType[]).map( + (flag) => flag.value as string + ); + + formik.setFieldValue('flags', formattedFlags); + }; + useEffect(() => { - formik.setValues(formikInitialValues); - }, [formikInitialValues]); + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); return ( -
    -
    - + +

    + {type === 'add' && 'Tambah Nonstock'} + {type === 'edit' && 'Edit Nonstock'} + {type === 'detail' && 'Detail Nonstock'} +

    +
    + +
    - - Kembali - +
    + -

    - {type === 'add' && 'Tambah Non Stock'} - {type === 'edit' && 'Edit Non Stock'} - {type === 'detail' && 'Detail Non Stock'} -

    - + - -
    - -
    + - {type !== 'detail' && ( - <> -
    - + + formik.values.flags?.includes(opt.value) + )} + onChange={flagsChangeHandler} + options={SUPPLIER_FLAG_OPTIONS} + isError={formik.touched.flags && Boolean(formik.errors.flags)} + errorMessage={formik.errors.flags as string} + isDisabled={type === 'detail'} + isClearable + /> +
    - -
    +
    + {type !== 'add' && ( +
    + - {nonstockFormErrorMessage && ( -
    - - {nonstockFormErrorMessage} + {type !== 'edit' && ( + + )}
    )} - - )} - -
    + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {nonstockFormErrorMessage && ( +
    + + {nonstockFormErrorMessage} +
    + )} + + + + {type !== 'add' && ( + + )} + ); }; From c53f91ec3f282469a869b4d1557d3e1943da3cac Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:00:30 +0700 Subject: [PATCH 143/327] feat(FE-43): create NonstocksTable component --- .../master-data/nonstock/NonstocksTable.tsx | 330 +++++++++++------- 1 file changed, 208 insertions(+), 122 deletions(-) diff --git a/src/components/pages/master-data/nonstock/NonstocksTable.tsx b/src/components/pages/master-data/nonstock/NonstocksTable.tsx index 4a2dbc5b..462b3488 100644 --- a/src/components/pages/master-data/nonstock/NonstocksTable.tsx +++ b/src/components/pages/master-data/nonstock/NonstocksTable.tsx @@ -1,20 +1,31 @@ 'use client'; -import { ChangeEventHandler, useState } from 'react'; +import { ChangeEventHandler, useCallback, useEffect, useState } from 'react'; import useSWR from 'swr'; -import { CellContext, ColumnDef } from '@tanstack/react-table'; +import { + CellContext, + ColumnDef, + ColumnSort, + SortingState, +} from '@tanstack/react-table'; +import toast from 'react-hot-toast'; import { Icon } from '@iconify/react'; import Table from '@/components/Table'; -import TextInput from '@/components/input/TextInput'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import Button from '@/components/Button'; -import Collapse from '@/components/Collapse'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; -import { httpClientFetcher } from '@/services/http/client'; -import { Nonstock, NonstocksResponse } from '@/types/api/master-data/nonstock'; +import { Nonstock } from '@/types/api/master-data/nonstock'; +import { NonstockApi } from '@/services/api/master-data'; import { cn } from '@/lib/helper'; -import { deleteNonstock } from '@/services/api/master-data/nonstock'; import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; const RowOptionsMenu = ({ type = 'dropdown', @@ -23,7 +34,7 @@ const RowOptionsMenu = ({ }: { type: 'dropdown' | 'collapse'; props: CellContext; - deleteClickHandler: () => Promise; + deleteClickHandler: () => void; }) => { return (
    ; - isLast2Rows: boolean; - deleteClickHandler: () => Promise; -}) => { - return ( -
    - - - -
    - ); -}; - -const RowCollapseOptions = ({ - props, - deleteClickHandler, -}: { - props: CellContext; - deleteClickHandler: () => Promise; -}) => { - return ( - - - - } - className='w-fit' - titleClassName='p-0! justify-self-end' - > - - - ); -}; - const NonstocksTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '', locationSort: '', picSort: '' }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + locationSort: 'sort_location', + picSort: ' sort_pic', + }, + }); + const { data: nonstocks, isLoading, mutate: refreshNonstocks, - } = useSWR('/master-data/nonstocks', httpClientFetcher); + } = useSWR( + `${NonstockApi.basePath}${getTableFilterQueryString()}`, + NonstockApi.getAllFetcher + ); - const [searchValue, setSearchValue] = useState(''); + const deleteModal = useModal(); + + const [selectedNonstock, setSelectedNonstock] = useState< + Nonstock | undefined + >(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); const nonstocksColumns: ColumnDef[] = [ { header: '#', - cell: (props) => props.row.index + 1, + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, }, { - header: 'Nama', accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'uom', + header: 'UOM', + cell: (props) => props.row.original.uom.name, + }, + { + accessorKey: 'suppliers', + header: 'Supplier', + cell: (props) => { + const supplierNames = props.row.original.suppliers.map( + (supplier) => supplier.name + ); + + return supplierNames.join(', ') || '-'; + }, + }, + { + accessorKey: 'flags', + header: 'Flag', + cell: (props) => props.row.original.flags?.join(', ') || '-', }, { header: 'Aksi', @@ -157,33 +164,31 @@ const NonstocksTable = () => { const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; - const deleteClickHandler = async () => { - const confirmation = confirm( - 'Apakah anda yakin untuk menghapus non stock ini?' - ); - - if (confirmation) { - await deleteNonstock(props.row.original.id); - refreshNonstocks(); - alert('Nonstock berhasil dihapus!'); - } + const deleteClickHandler = () => { + setSelectedNonstock(props.row.original); + deleteModal.openModal(); }; return ( <> {currentPageSize > 2 && ( - + + + )} {currentPageSize <= 2 && ( - + + + )} ); @@ -191,52 +196,133 @@ const NonstocksTable = () => { }, ]; - const searchChangeHandler: ChangeEventHandler = (e) => { - setSearchValue(e.target.value); + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await NonstockApi.delete(selectedNonstock?.id as number); + refreshNonstocks(); + + deleteModal.closeModal(); + toast.success('Successfully delete Nonstock!'); + setIsDeleteLoading(false); }; + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + const updateSortingFilter = useCallback( + ( + sortName: Exclude, + sortFilter: ColumnSort | undefined + ) => { + if (!sortFilter) { + updateFilter(sortName, ''); + } else { + updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc'); + } + }, + [updateFilter] + ); + + // track sorting + useEffect(() => { + const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name'); + const locationSortFilter = sorting.find( + (sortItem) => sortItem.id === 'location' + ); + const picSortFilter = sorting.find((sortItem) => sortItem.id === 'pic'); + + updateSortingFilter('nameSort', nameSortFilter); + updateSortingFilter('locationSort', locationSortFilter); + updateSortingFilter('picSort', picSortFilter); + }, [sorting]); + return ( -
    -
    -
    - + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    - + data={isResponseSuccess(nonstocks) ? nonstocks?.data : []} + columns={nonstocksColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(nonstocks) ? nonstocks?.meta?.page : 0} + totalItems={ + isResponseSuccess(nonstocks) ? nonstocks?.meta?.total_results : 0 + } + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': + isResponseSuccess(nonstocks) && nonstocks?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} />
    - - data={isResponseSuccess(nonstocks) ? nonstocks?.data : []} - columns={nonstocksColumns} - pageSize={10} - fuzzySearchValue={searchValue} - onFuzzySearchValueChange={setSearchValue} - isLoading={isLoading} - className={{ - containerClassName: cn({ - 'mb-20': - isResponseSuccess(nonstocks) && nonstocks?.data?.length === 0, - }), - tableWrapperClassName: 'overflow-x-auto min-h-full!', - tableClassName: 'font-inter w-full table-auto min-h-full!', - headerRowClassName: 'border-b border-b-gray-200', - headerColumnClassName: - 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', - bodyRowClassName: 'border-b border-b-gray-200', - bodyColumnClassName: - 'px-6 py-3 last:flex last:flex-row last:justify-end', + -
    + ); }; From b8548b72c95f668eadc64f16bb80571486e1e7b8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:00:41 +0700 Subject: [PATCH 144/327] feat(FE-40,41): create Nonstock form validation schema --- .../nonstock/form/NonstockForm.schema.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts b/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts index 50f69c7d..8039ef76 100644 --- a/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts +++ b/src/components/pages/master-data/nonstock/form/NonstockForm.schema.ts @@ -2,6 +2,22 @@ import * as Yup from 'yup'; export const NonstockFormSchema = Yup.object({ name: Yup.string().required('Nama wajib diisi!'), + + uomId: Yup.number().min(1, 'UOM wajib diisi!').required('UOM wajib diisi!'), + uom: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + + supplierIds: Yup.array().of(Yup.number().min(0, 'Supplier wajib diisi!')), + suppliers: Yup.array().of( + Yup.object({ + value: Yup.number().min(0).required(), + label: Yup.string().required(), + }) + ), + + flags: Yup.array().of(Yup.string()).notRequired(), }); export const UpdateNonstockFormSchema = NonstockFormSchema; From 780c0bb9d0d0d341be8aa4227ad05250f565e3db Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:01:45 +0700 Subject: [PATCH 145/327] chore(FE-41): use Nonstock API service --- src/app/master-data/nonstock/detail/edit/page.tsx | 8 ++++---- src/app/master-data/nonstock/detail/page.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/app/master-data/nonstock/detail/edit/page.tsx b/src/app/master-data/nonstock/detail/edit/page.tsx index a0fbb6b3..3b3db5f5 100644 --- a/src/app/master-data/nonstock/detail/edit/page.tsx +++ b/src/app/master-data/nonstock/detail/edit/page.tsx @@ -5,8 +5,8 @@ import useSWR from 'swr'; import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm'; -import { getNonstock } from '@/services/api/master-data/nonstock'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { NonstockApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const NonstockEdit = () => { const router = useRouter(); @@ -16,7 +16,7 @@ const NonstockEdit = () => { const { data: nonstock, isLoading: isLoadingNonstock } = useSWR( nonstockId, - getNonstock + (id: number) => NonstockApi.getSingle(id) ); if (!nonstockId) { @@ -29,7 +29,7 @@ const NonstockEdit = () => { ); } - if (!isLoadingNonstock && !nonstock) { + if (!isLoadingNonstock && (!nonstock || isResponseError(nonstock))) { router.replace('/404'); return; } diff --git a/src/app/master-data/nonstock/detail/page.tsx b/src/app/master-data/nonstock/detail/page.tsx index 375ec999..798a843e 100644 --- a/src/app/master-data/nonstock/detail/page.tsx +++ b/src/app/master-data/nonstock/detail/page.tsx @@ -5,8 +5,8 @@ import useSWR from 'swr'; import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm'; -import { getNonstock } from '@/services/api/master-data/nonstock'; -import { isResponseSuccess } from '@/lib/api-helper'; +import { NonstockApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; const NonstockDetail = () => { const router = useRouter(); @@ -16,7 +16,7 @@ const NonstockDetail = () => { const { data: nonstock, isLoading: isLoadingNonstock } = useSWR( nonstockId, - getNonstock + (id: number) => NonstockApi.getSingle(id) ); if (!nonstockId) { @@ -29,7 +29,7 @@ const NonstockDetail = () => { ); } - if (!isLoadingNonstock && !nonstock) { + if (!isLoadingNonstock && (!nonstock || isResponseError(nonstock))) { router.replace('/404'); return; } From 7ceb25ea71dc421b68bcc24a7d006a16e23c52ee Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 8 Oct 2025 15:26:45 +0700 Subject: [PATCH 146/327] feat(FE-62,65): add inventory movement management with API and form validation --- .../movement/form/MovementForm.schema.ts | 67 +++++ src/config/constant.ts | 241 ++++++++++-------- src/services/api/inventory.ts | 12 + src/types/api/inventory/movement.d.ts | 51 ++++ 4 files changed, 262 insertions(+), 109 deletions(-) create mode 100644 src/components/pages/inventory/movement/form/MovementForm.schema.ts create mode 100644 src/services/api/inventory.ts create mode 100644 src/types/api/inventory/movement.d.ts diff --git a/src/components/pages/inventory/movement/form/MovementForm.schema.ts b/src/components/pages/inventory/movement/form/MovementForm.schema.ts new file mode 100644 index 00000000..cdabe355 --- /dev/null +++ b/src/components/pages/inventory/movement/form/MovementForm.schema.ts @@ -0,0 +1,67 @@ +import * as Yup from 'yup'; + +export const MovementFormSchema = Yup.object({ + alasan_transfer: Yup.string() + .required('Alasan Transfer wajib diisi!'), + tanggal_transfer: Yup.date() + .required('Tanggal Transfer wajib diisi!') + .typeError('Tanggal Transfer tidak valid!'), + warehouse_asal: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + warehouse_asal_id: Yup.number() + .required('Gudang Asal wajib diisi!'), + warehouse_tujuan: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + warehouse_tujuan_id: Yup.number() + .required('Gudang Tujuan wajib diisi!'), + alasan: Yup.string() + .required('Alasan wajib diisi!'), + product: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + product_id: Yup.array() + .of(Yup.number()).min(1, 'Pilih minimal 1 produk') + .required('Produk wajib diisi!'), + qty_product: Yup.array() + .of(Yup.number().min(1, 'Kuantitas minimal 1')) + .min(1, 'Pilih minimal 1 produk') + .required('Kuantitas wajib diisi!'), + ekspedisi: Yup.array().of( + Yup.object({ + product: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + product_id: Yup.number() + .required('Produk wajib diisi!'), + qty: Yup.number().min(1, 'Kuantitas minimal 1') + .required('Kuantitas wajib diisi!'), + supplier: Yup.object({ + value: Yup.number().min(1).required(), + label: Yup.string().required(), + }).nullable(), + supplier_id: Yup.number() + .required('Supplier wajib diisi!'), + plat_nomor: Yup.string() + .required('Plat Nomor wajib diisi!'), + no_surat_jalan: Yup.string() + .required('No Surat Jalan wajib diisi!'), + dokumen: Yup.mixed() + .required('Dokumen wajib diisi!'), + biaya_ekspedisi: Yup.number() + .min(0, 'Biaya Ekspedisi minimal 0') + .required('Biaya Ekspedisi wajib diisi!'), + nama_sopir: Yup.string() + .required('Nama Sopir wajib diisi!'), + }) + ).min(1, 'Pilih minimal 1 ekspedisi').required('Ekspedisi wajib diisi!'), +}); + +export const UpdateMovementFormSchema = MovementFormSchema; + +export type MovementFormValues = Yup.InferType; \ No newline at end of file diff --git a/src/config/constant.ts b/src/config/constant.ts index 1fbef81f..870002bf 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -1,122 +1,145 @@ export const MAIN_DRAWER_LINKS = [ - { - title: 'Dashboard', - link: '/dashboard', - icon: 'gg:chart', - }, + { + title: 'Dashboard', + link: '/dashboard', + icon: 'gg:chart', + }, - { - title: 'Master Data', - link: '/master-data', - icon: 'majesticons:data-line', - submenu: [ - { - title: 'Product', - link: '/master-data/product', - icon: 'fluent-mdl2:product-variant', - }, - { - title: 'Product Category', - link: '/master-data/product-category', - icon: 'carbon:categories', - }, - { - title: 'Bank', - link: '/master-data/bank', - icon: 'mdi:bank-outline', - }, - { - title: 'Area', - link: '/master-data/area', - icon: 'majesticons:map-marker-area-line', - }, - { - title: 'Location', - link: '/master-data/location', - icon: 'mingcute:location-line', - }, - { - title: 'Kandang', - link: '/master-data/kandang', - icon: 'mdi:farm-home-outline', - }, - { - title: 'Warehouse', - link: '/master-data/warehouse', - icon: 'hugeicons:warehouse', - }, - { - title: 'Customer', - link: '/master-data/customer', - icon: 'ix:customer', - }, - { - title: 'UOM', - link: '/master-data/uom', - icon: 'lsicon:measure-outline', - }, - { - title: 'Non-Stock', - link: '/master-data/nonstock', - icon: 'fluent:box-32-regular', - }, - { - title: 'FCR', - link: '/master-data/FCR', - icon: 'fluent:food-chicken-leg-16-regular', - }, - { - title: 'Supplier', - link: '/master-data/supplier', - icon: 'material-symbols:add-business-outline-rounded', - }, - ], - }, + { + title: 'Persediaan', + link: '/inventory', + icon: 'mdi:warehouse', + submenu: [ + { + title: 'Product', + link: '/inventory/product', + icon: 'mdi:package-variant-closed', + }, + { + title: 'Penyesuaian Stok', + link: '/inventory/adjustment', + icon: 'mdi:database-edit', + }, + { + title: 'Transfer Stok', + link: '/inventory/movement', + icon: 'mdi:swap-horizontal', + }, + ], + }, + + { + title: 'Master Data', + link: '/master-data', + icon: 'majesticons:data-line', + submenu: [ + { + title: 'Product', + link: '/master-data/product', + icon: 'fluent-mdl2:product-variant', + }, + { + title: 'Product Category', + link: '/master-data/product-category', + icon: 'carbon:categories', + }, + { + title: 'Bank', + link: '/master-data/bank', + icon: 'mdi:bank-outline', + }, + { + title: 'Area', + link: '/master-data/area', + icon: 'majesticons:map-marker-area-line', + }, + { + title: 'Location', + link: '/master-data/location', + icon: 'mingcute:location-line', + }, + { + title: 'Kandang', + link: '/master-data/kandang', + icon: 'mdi:farm-home-outline', + }, + { + title: 'Warehouse', + link: '/master-data/warehouse', + icon: 'hugeicons:warehouse', + }, + { + title: 'Customer', + link: '/master-data/customer', + icon: 'ix:customer', + }, + { + title: 'UOM', + link: '/master-data/uom', + icon: 'lsicon:measure-outline', + }, + { + title: 'Non-Stock', + link: '/master-data/nonstock', + icon: 'fluent:box-32-regular', + }, + { + title: 'FCR', + link: '/master-data/FCR', + icon: 'fluent:food-chicken-leg-16-regular', + }, + { + title: 'Supplier', + link: '/master-data/supplier', + icon: 'material-symbols:add-business-outline-rounded', + }, + ], + }, ] as const; export const ROWS_OPTIONS = [ - { - label: '10', - value: 10, - }, - { - label: '20', - value: 20, - }, - { - label: '50', - value: 50, - }, - { - label: '100', - value: 100, - }, + { + label: '10', + value: 10, + }, + { + label: '20', + value: 20, + }, + { + label: '50', + value: 50, + }, + { + label: '100', + value: 100, + }, ]; export const WAREHOUSE_TYPE_OPTIONS = [ - { - label: 'AREA', - value: 'AREA', - }, - { - label: 'LOKASI', - value: 'LOKASI', - }, - { - label: 'KANDANG', - value: 'KANDANG', - }, + { + label: 'AREA', + value: 'AREA', + }, + { + label: 'LOKASI', + value: 'LOKASI', + }, + { + label: 'KANDANG', + value: 'KANDANG', + }, ]; export const PRODUCT_FLAG_OPTIONS = [ - { label: 'DOC', value: 'DOC' }, - { label: 'PAKAN', value: 'PAKAN' }, - { label: 'PRE-STARTER', value: 'PRE-STARTER' }, - { label: 'STARTER', value: 'STARTER' }, - { label: 'FINISHER', value: 'FINISHER' }, - { label: 'OVK', value: 'OVK' }, - { label: 'OBAT', value: 'OBAT' }, - { label: 'VITAMIN', value: 'VITAMIN' }, - { label: 'KIMIA', value: 'KIMIA' }, + {label: 'DOC', value: 'DOC'}, + {label: 'PAKAN', value: 'PAKAN'}, + {label: 'PRE-STARTER', value: 'PRE-STARTER'}, + {label: 'STARTER', value: 'STARTER'}, + {label: 'FINISHER', value: 'FINISHER'}, + {label: 'OVK', value: 'OVK'}, + {label: 'OBAT', value: 'OBAT'}, + {label: 'VITAMIN', value: 'VITAMIN'}, + {label: 'KIMIA', value: 'KIMIA'}, ]; diff --git a/src/services/api/inventory.ts b/src/services/api/inventory.ts new file mode 100644 index 00000000..3e3115e2 --- /dev/null +++ b/src/services/api/inventory.ts @@ -0,0 +1,12 @@ +import { + CreateMovementPayload, + Movement, + UpdateMovementPayload, +} from "@/types/api/inventory/movement"; +import {BaseApiService} from "@/services/api/base"; + +export const MovementApi = new BaseApiService< + Movement, + CreateMovementPayload, + UpdateMovementPayload +>('/inventory/movements'); \ No newline at end of file diff --git a/src/types/api/inventory/movement.d.ts b/src/types/api/inventory/movement.d.ts new file mode 100644 index 00000000..fe2996ba --- /dev/null +++ b/src/types/api/inventory/movement.d.ts @@ -0,0 +1,51 @@ +import {BaseMetadata} from '@/types/api/api-general'; +import {Product} from "@/types/api/master-data/product"; +import {Supplier} from "@/types/api/master-data/supplier"; +import {Warehouse} from "@/types/api/master-data/warehouse"; + +export type BaseMovement = { + id: number; + alasan_transfer: string; + tanggal_transfer: string; + warehouse_asal: Warehouse; + warehouse_tujuan: Warehouse; + product: Array<{ + product: Product; + qty_product: number; + }>; + ekspedisi: Array<{ + product_id: number; + qty: number; + supplier: Supplier; + plat_nomor: string; + no_surat_jalan: string; + dokumen: string; + biaya_ekspedisi: number; + nama_sopir: string; + }>; + name: string; +}; + +export type Movement = BaseMetadata & BaseMovement; + +export type CreateMovementPayload = { + alasan: string; + warehouse_asal_id: number; + warehouse_tujuan_id: number; + product: Array<{ + product_id: number; + qty_product: number; + }>; + ekspedisi: Array<{ + product_id: number; + qty: number; + supplier_id: number; + plat_nomor: string; + no_surat_jalan: string; + dokumen: string; + biaya_ekspedisi: number; + nama_sopir: string; + }>; +} + +export type UpdateMovementPayload = CreateMovementPayload; \ No newline at end of file From 293f457ecbdfbacba08b724e42b20a2c3eb160b1 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:35:00 +0700 Subject: [PATCH 147/327] feat(FE-41): create Bank type --- src/types/api/master-data/bank.d.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/types/api/master-data/bank.d.ts diff --git a/src/types/api/master-data/bank.d.ts b/src/types/api/master-data/bank.d.ts new file mode 100644 index 00000000..0b23b446 --- /dev/null +++ b/src/types/api/master-data/bank.d.ts @@ -0,0 +1,20 @@ +import { BaseMetadata } from '@/types/api/api-general'; + +export type BaseBank = { + id: number; + name: string; + alias: string; + owner?: string; + account_number: string; +}; + +export type Bank = BaseMetadata & BaseBank; + +export type CreateBankPayload = { + name: string; + alias: string; + account_number: string; + owner?: string; +}; + +export type UpdateBankPayload = CreateBankPayload; From 10749f06da103124d5b5df6a5f417c612696e6fb Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:35:15 +0700 Subject: [PATCH 148/327] feat(FE-41): create Bank API service --- src/services/api/master-data.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/api/master-data.ts b/src/services/api/master-data.ts index 41975bd8..8a57e6e6 100644 --- a/src/services/api/master-data.ts +++ b/src/services/api/master-data.ts @@ -44,6 +44,11 @@ import { Nonstock, UpdateNonstockPayload, } from '@/types/api/master-data/nonstock'; +import { + Bank, + CreateBankPayload, + UpdateBankPayload, +} from '@/types/api/master-data/bank'; export const UomApi = new BaseApiService< Uom, @@ -98,3 +103,9 @@ export const NonstockApi = new BaseApiService< CreateNonstockPayload, UpdateNonstockPayload >('/master-data/nonstocks'); + +export const BankApi = new BaseApiService< + Bank, + CreateBankPayload, + UpdateBankPayload +>('/master-data/banks'); From 8c507aa410f494436daab22fb7e7bac306ff6ac1 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:35:34 +0700 Subject: [PATCH 149/327] feat(FE-40,41): create BankForm component --- .../pages/master-data/bank/form/BankForm.tsx | 301 ++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 src/components/pages/master-data/bank/form/BankForm.tsx diff --git a/src/components/pages/master-data/bank/form/BankForm.tsx b/src/components/pages/master-data/bank/form/BankForm.tsx new file mode 100644 index 00000000..442d5c76 --- /dev/null +++ b/src/components/pages/master-data/bank/form/BankForm.tsx @@ -0,0 +1,301 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + BankFormSchema, + BankFormValues, + UpdateBankFormSchema, +} from '@/components/pages/master-data/bank/form/BankForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + CreateBankPayload, + Bank, + UpdateBankPayload, +} from '@/types/api/master-data/bank'; +import { BankApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; + +interface BankFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Bank; +} + +const BankForm = ({ type = 'add', initialValues }: BankFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [bankFormErrorMessage, setBankFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createBankHandler = useCallback( + async (payload: CreateBankPayload) => { + const createBankRes = await BankApi.create(payload); + + if (isResponseError(createBankRes)) { + setBankFormErrorMessage(createBankRes.message); + return; + } + + toast.success(createBankRes?.message as string); + router.push('/master-data/bank'); + }, + [router] + ); + + const updateBankHandler = useCallback( + async (bankId: number, payload: UpdateBankPayload) => { + const updateBankRes = await BankApi.update(bankId, payload); + + if (updateBankRes?.status === 'error') { + setBankFormErrorMessage(updateBankRes.message); + return; + } + + toast.success(updateBankRes?.message as string); + router.refresh(); + router.push('/master-data/bank'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + alias: initialValues?.alias ?? '', + account_number: initialValues?.account_number ?? '', + owner: initialValues?.owner, + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateBankFormSchema : BankFormSchema, + onSubmit: async (values) => { + setBankFormErrorMessage(''); + + const bankPayload: CreateBankPayload = { + name: values.name, + alias: values.alias, + account_number: values.account_number.toString(), + owner: values.owner ? values.owner : '', + }; + + switch (type) { + case 'add': + await createBankHandler(bankPayload); + break; + + case 'edit': + await updateBankHandler(initialValues?.id as number, bankPayload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + const deleteBankClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await BankApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Bank!'); + setIsDeleteLoading(false); + router.push('/master-data/bank'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
    +
    + + +

    + {type === 'add' && 'Tambah Bank'} + {type === 'edit' && 'Edit Bank'} + {type === 'detail' && 'Detail Bank'} +

    +
    + +
    +
    + + + + + + + +
    + +
    + {type !== 'add' && ( +
    + + + {type !== 'edit' && ( + + )} +
    + )} + + {type !== 'detail' && ( +
    + + + +
    + )} +
    + + {bankFormErrorMessage && ( +
    + + {bankFormErrorMessage} +
    + )} +
    +
    + + {type !== 'add' && ( + + )} + + ); +}; + +export default BankForm; From 16a15fce66c6369099c1d4a4bc6be7976b496de1 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:35:56 +0700 Subject: [PATCH 150/327] feat(FE-42): create Bank form validation schema --- .../pages/master-data/bank/form/BankForm.schema.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/components/pages/master-data/bank/form/BankForm.schema.ts diff --git a/src/components/pages/master-data/bank/form/BankForm.schema.ts b/src/components/pages/master-data/bank/form/BankForm.schema.ts new file mode 100644 index 00000000..0bf48c76 --- /dev/null +++ b/src/components/pages/master-data/bank/form/BankForm.schema.ts @@ -0,0 +1,14 @@ +import * as Yup from 'yup'; + +export const BankFormSchema = Yup.object({ + name: Yup.string().required('Nama wajib diisi!'), + alias: Yup.string() + .max(5, 'Maksimal 5 karakter!') + .required('Alias wajib diisi!'), + account_number: Yup.string().required('Rekening wajib diisi!'), + owner: Yup.string(), +}); + +export const UpdateBankFormSchema = BankFormSchema; + +export type BankFormValues = Yup.InferType; From ca42570a4086e349b21a50e0a4b991d08d2e11f1 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:36:13 +0700 Subject: [PATCH 151/327] feat(FE-43): create BanksTable component --- .../pages/master-data/bank/BanksTable.tsx | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 src/components/pages/master-data/bank/BanksTable.tsx diff --git a/src/components/pages/master-data/bank/BanksTable.tsx b/src/components/pages/master-data/bank/BanksTable.tsx new file mode 100644 index 00000000..0d084491 --- /dev/null +++ b/src/components/pages/master-data/bank/BanksTable.tsx @@ -0,0 +1,289 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; + +import { Bank } from '@/types/api/master-data/bank'; +import { BankApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ROWS_OPTIONS } from '@/config/constant'; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => { + return ( +
    + + + + + +
    + ); +}; + +const BanksTable = () => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { search: '', nameSort: '' }, + paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' }, + }); + + const { + data: banks, + isLoading, + mutate: refreshBanks, + } = useSWR( + `${BankApi.basePath}${getTableFilterQueryString()}`, + BankApi.getAllFetcher + ); + + const deleteModal = useModal(); + + const [selectedBank, setSelectedBank] = useState(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const [sorting, setSorting] = useState([]); + + const banksColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => + tableFilterState.pageSize * (tableFilterState.page - 1) + + props.row.index + + 1, + }, + { + accessorKey: 'name', + header: 'Nama', + }, + { + accessorKey: 'alias', + header: 'Alias', + }, + { + accessorKey: 'account_number', + header: 'No. Rekening', + }, + { + accessorKey: 'owner', + header: 'Pemilik', + cell: (props) => (props.getValue() ? props.getValue() : '-'), + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedBank(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await BankApi.delete(selectedBank?.id as number); + refreshBanks(); + + deleteModal.closeModal(); + toast.success('Successfully delete Bank!'); + setIsDeleteLoading(false); + }; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + + setPageSize(newVal.value as number); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting]); + + return ( + <> +
    +
    +
    +
    + +
    + + +
    + +
    + +
    +
    + + + data={isResponseSuccess(banks) ? banks?.data : []} + columns={banksColumns} + pageSize={tableFilterState.pageSize} + page={isResponseSuccess(banks) ? banks?.meta?.page : 0} + totalItems={isResponseSuccess(banks) ? banks?.meta?.total_results : 0} + onPageChange={setPage} + isLoading={isLoading} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': isResponseSuccess(banks) && banks?.data?.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + + ); +}; + +export default BanksTable; From b9015ed673f4c160a5dd2cafd485d9dcc212134f Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:37:01 +0700 Subject: [PATCH 152/327] feat(FE-43): create Master Data Bank page --- src/app/master-data/bank/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/bank/page.tsx diff --git a/src/app/master-data/bank/page.tsx b/src/app/master-data/bank/page.tsx new file mode 100644 index 00000000..3f913c55 --- /dev/null +++ b/src/app/master-data/bank/page.tsx @@ -0,0 +1,11 @@ +import BanksTable from '@/components/pages/master-data/bank/BanksTable'; + +const Bank = () => { + return ( +
    + +
    + ); +}; + +export default Bank; From 0d5e8383fda172d7d3852501d8d2c2db952fc68a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:37:26 +0700 Subject: [PATCH 153/327] feat(FE-40,41): create Master Data Add Bank page --- src/app/master-data/bank/add/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/master-data/bank/add/page.tsx diff --git a/src/app/master-data/bank/add/page.tsx b/src/app/master-data/bank/add/page.tsx new file mode 100644 index 00000000..0bb6e532 --- /dev/null +++ b/src/app/master-data/bank/add/page.tsx @@ -0,0 +1,11 @@ +import BankForm from '@/components/pages/master-data/bank/form/BankForm'; + +const AddBank = () => { + return ( +
    + +
    + ); +}; + +export default AddBank; From 372f1698ca45c2f123d613836ec91e2e165c3440 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:38:01 +0700 Subject: [PATCH 154/327] feat(FE-40,41): create Master Data Detail Bank page --- src/app/master-data/bank/detail/page.tsx | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/app/master-data/bank/detail/page.tsx diff --git a/src/app/master-data/bank/detail/page.tsx b/src/app/master-data/bank/detail/page.tsx new file mode 100644 index 00000000..bd1661d8 --- /dev/null +++ b/src/app/master-data/bank/detail/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import BankForm from '@/components/pages/master-data/bank/form/BankForm'; + +import { BankApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const BankDetail = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const bankId = searchParams.get('bankId'); + + const { data: bank, isLoading: isLoadingBank } = useSWR( + bankId, + (id: number) => BankApi.getSingle(id) + ); + + if (!bankId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingBank && (!bank || isResponseError(bank))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingBank && } + {!isLoadingBank && isResponseSuccess(bank) && ( + + )} +
    + ); +}; + +export default BankDetail; From 1d7f10050756a7bfee025a8cc7430a5eff21f7b8 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 8 Oct 2025 15:38:10 +0700 Subject: [PATCH 155/327] feat(FE-40,41): create Master Data Edit Bank page --- src/app/master-data/bank/detail/edit/page.tsx | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/app/master-data/bank/detail/edit/page.tsx diff --git a/src/app/master-data/bank/detail/edit/page.tsx b/src/app/master-data/bank/detail/edit/page.tsx new file mode 100644 index 00000000..a0939af9 --- /dev/null +++ b/src/app/master-data/bank/detail/edit/page.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; + +import BankForm from '@/components/pages/master-data/bank/form/BankForm'; + +import { BankApi } from '@/services/api/master-data'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; + +const BankEdit = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const bankId = searchParams.get('bankId'); + + const { data: bank, isLoading: isLoadingBank } = useSWR( + bankId, + (id: number) => BankApi.getSingle(id) + ); + + if (!bankId) { + router.back(); + + return ( +
    + +
    + ); + } + + if (!isLoadingBank && (!bank || isResponseError(bank))) { + router.replace('/404'); + return; + } + + return ( +
    + {isLoadingBank && } + {!isLoadingBank && isResponseSuccess(bank) && ( + + )} +
    + ); +}; + +export default BankEdit; From 3f97ec45f8b14d8c77347ad5104540c647b4d926 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 8 Oct 2025 16:02:52 +0700 Subject: [PATCH 156/327] feat(FE-64): add MovementTable component for inventory movement management --- src/app/inventory/movement/page.tsx | 11 + .../inventory/movement/MovementTable.tsx | 651 ++++++++++++++++++ 2 files changed, 662 insertions(+) create mode 100644 src/app/inventory/movement/page.tsx create mode 100644 src/components/pages/inventory/movement/MovementTable.tsx diff --git a/src/app/inventory/movement/page.tsx b/src/app/inventory/movement/page.tsx new file mode 100644 index 00000000..12fe795b --- /dev/null +++ b/src/app/inventory/movement/page.tsx @@ -0,0 +1,11 @@ +import MovementTable from '@/components/pages/inventory/movement/MovementTable'; + +const Product = () => { + return ( +
    + +
    + ); +}; + +export default Product; diff --git a/src/components/pages/inventory/movement/MovementTable.tsx b/src/components/pages/inventory/movement/MovementTable.tsx new file mode 100644 index 00000000..288cb2a6 --- /dev/null +++ b/src/components/pages/inventory/movement/MovementTable.tsx @@ -0,0 +1,651 @@ +'use client'; + +import { useState, useMemo } from 'react'; +import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import DebouncedTextInput from '@/components/input/DebouncedTextInput'; +import Button from '@/components/Button'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; +import SelectInput, { OptionType } from '@/components/input/SelectInput'; +import RowDropdownOptions from '@/components/table/RowDropdownOptions'; +import RowCollapseOptions from '@/components/table/RowCollapseOptions'; +import { cn } from '@/lib/helper'; +import { ROWS_OPTIONS } from '@/config/constant'; +import { Movement } from '@/types/api/inventory/movement'; +import { BaseMetadata } from '@/types/api/api-general'; + +// Dummy data +const baseMetadata: BaseMetadata = { + created_user: { + id: 1, + id_user: 1, + email: 'user@example.com', + name: 'User', + }, + created_at: '2024-06-01T00:00:00Z', + updated_at: '2024-06-01T00:00:00Z', +}; + +const dummyMovements: Movement[] = [ + { + ...baseMetadata, + id: 1, + alasan_transfer: 'Restock', + tanggal_transfer: '2024-06-01', + warehouse_asal: { + ...baseMetadata, + id: 1, + name: 'Warehouse A', + type: 'AREA', + area: { id: 1, name: 'Area 1' }, + }, + warehouse_tujuan: { + ...baseMetadata, + id: 2, + name: 'Warehouse B', + type: 'AREA', + area: { id: 2, name: 'Area 2' }, + }, + product: [ + { + product: { + ...baseMetadata, + id: 1, + name: 'Product X', + brand: 'Brand X', + sku: 'SKU-X', + product_price: 10000, + selling_price: 12000, + tax: 10, + expiry_period: 365, + uom: { + ...baseMetadata, + id: 1, + name: 'PCS', + }, + product_category: { + ...baseMetadata, + id: 1, + code: 'CAT-1', + name: 'Category 1', + }, + suppliers: [], + flags: [], + }, + qty_product: 10, + }, + ], + ekspedisi: [ + { + product_id: 1, + qty: 10, + supplier: { + ...baseMetadata, + id: 1, + name: 'Supplier 1', + alias: 'S1', + category: 'General', + pic: 'PIC 1', + type: 'Type 1', + phone: '08123456789', + email: 'supplier1@example.com', + address: 'Address 1', + account_number: '1234567890', + balance: 0, + due_date: 30, + }, + plat_nomor: 'B 1234 CD', + no_surat_jalan: 'SJ-001', + dokumen: 'doc1.pdf', + biaya_ekspedisi: 50000, + nama_sopir: 'Andi', + }, + ], + name: 'Movement 1', + }, + { + ...baseMetadata, + id: 2, + alasan_transfer: 'Mutasi Stok', + tanggal_transfer: '2024-06-02', + warehouse_asal: { + ...baseMetadata, + id: 2, + name: 'Warehouse B', + type: 'AREA', + area: { id: 2, name: 'Area 2' }, + }, + warehouse_tujuan: { + ...baseMetadata, + id: 3, + name: 'Warehouse C', + type: 'AREA', + area: { id: 3, name: 'Area 3' }, + }, + product: [ + { + product: { + ...baseMetadata, + id: 2, + name: 'Product Y', + brand: 'Brand Y', + sku: 'SKU-Y', + product_price: 20000, + selling_price: 25000, + tax: 5, + expiry_period: 180, + uom: { + ...baseMetadata, + id: 2, + name: 'BOX', + }, + product_category: { + ...baseMetadata, + id: 2, + code: 'CAT-2', + name: 'Category 2', + }, + suppliers: [], + flags: [], + }, + qty_product: 5, + }, + ], + ekspedisi: [ + { + product_id: 2, + qty: 5, + supplier: { + ...baseMetadata, + id: 2, + name: 'Supplier 2', + alias: 'S2', + category: 'Special', + pic: 'PIC 2', + type: 'Type 2', + phone: '08123456780', + email: 'supplier2@example.com', + address: 'Address 2', + account_number: '1234567891', + balance: 1000, + due_date: 15, + }, + plat_nomor: 'D 5678 EF', + no_surat_jalan: 'SJ-002', + dokumen: 'doc2.pdf', + biaya_ekspedisi: 60000, + nama_sopir: 'Budi', + }, + ], + name: 'Movement 2', + }, + { + ...baseMetadata, + id: 3, + alasan_transfer: 'Pengembalian', + tanggal_transfer: '2024-06-03', + warehouse_asal: { + ...baseMetadata, + id: 3, + name: 'Warehouse C', + type: 'AREA', + area: { id: 3, name: 'Area 3' }, + }, + warehouse_tujuan: { + ...baseMetadata, + id: 1, + name: 'Warehouse A', + type: 'AREA', + area: { id: 1, name: 'Area 1' }, + }, + product: [ + { + product: { + ...baseMetadata, + id: 3, + name: 'Product Z', + brand: 'Brand Z', + sku: 'SKU-Z', + product_price: 15000, + selling_price: 18000, + tax: 8, + expiry_period: 90, + uom: { + ...baseMetadata, + id: 3, + name: 'KG', + }, + product_category: { + ...baseMetadata, + id: 3, + code: 'CAT-3', + name: 'Category 3', + }, + suppliers: [], + flags: [], + }, + qty_product: 8, + }, + ], + ekspedisi: [ + { + product_id: 3, + qty: 8, + supplier: { + ...baseMetadata, + id: 3, + name: 'Supplier 3', + alias: 'S3', + category: 'Return', + pic: 'PIC 3', + type: 'Type 3', + phone: '08123456781', + email: 'supplier3@example.com', + address: 'Address 3', + account_number: '1234567892', + balance: 500, + due_date: 10, + }, + plat_nomor: 'F 9101 GH', + no_surat_jalan: 'SJ-003', + dokumen: 'doc3.pdf', + biaya_ekspedisi: 40000, + nama_sopir: 'Cici', + }, + ], + name: 'Movement 3', + }, + { + ...baseMetadata, + id: 4, + alasan_transfer: 'Transfer Internal', + tanggal_transfer: '2024-06-04', + warehouse_asal: { + ...baseMetadata, + id: 4, + name: 'Warehouse D', + type: 'AREA', + area: { id: 4, name: 'Area 4' }, + }, + warehouse_tujuan: { + ...baseMetadata, + id: 5, + name: 'Warehouse E', + type: 'AREA', + area: { id: 5, name: 'Area 5' }, + }, + product: [ + { + product: { + ...baseMetadata, + id: 4, + name: 'Product A', + brand: 'Brand A', + sku: 'SKU-A', + product_price: 5000, + selling_price: 7000, + tax: 0, + expiry_period: 60, + uom: { + ...baseMetadata, + id: 4, + name: 'LITER', + }, + product_category: { + ...baseMetadata, + id: 4, + code: 'CAT-4', + name: 'Category 4', + }, + suppliers: [], + flags: [], + }, + qty_product: 20, + }, + ], + ekspedisi: [ + { + product_id: 4, + qty: 20, + supplier: { + ...baseMetadata, + id: 4, + name: 'Supplier 4', + alias: 'S4', + category: 'Internal', + pic: 'PIC 4', + type: 'Type 4', + phone: '08123456782', + email: 'supplier4@example.com', + address: 'Address 4', + account_number: '1234567893', + balance: 200, + due_date: 20, + }, + plat_nomor: 'H 2345 IJ', + no_surat_jalan: 'SJ-004', + dokumen: 'doc4.pdf', + biaya_ekspedisi: 30000, + nama_sopir: 'Dedi', + }, + ], + name: 'Movement 4', + }, + { + ...baseMetadata, + id: 5, + alasan_transfer: 'Distribusi', + tanggal_transfer: '2024-06-05', + warehouse_asal: { + ...baseMetadata, + id: 5, + name: 'Warehouse E', + type: 'AREA', + area: { id: 5, name: 'Area 5' }, + }, + warehouse_tujuan: { + ...baseMetadata, + id: 1, + name: 'Warehouse A', + type: 'AREA', + area: { id: 1, name: 'Area 1' }, + }, + product: [ + { + product: { + ...baseMetadata, + id: 5, + name: 'Product B', + brand: 'Brand B', + sku: 'SKU-B', + product_price: 8000, + selling_price: 9500, + tax: 2, + expiry_period: 120, + uom: { + ...baseMetadata, + id: 5, + name: 'PAK', + }, + product_category: { + ...baseMetadata, + id: 5, + code: 'CAT-5', + name: 'Category 5', + }, + suppliers: [], + flags: [], + }, + qty_product: 15, + }, + ], + ekspedisi: [ + { + product_id: 5, + qty: 15, + supplier: { + ...baseMetadata, + id: 5, + name: 'Supplier 5', + alias: 'S5', + category: 'Distribusi', + pic: 'PIC 5', + type: 'Type 5', + phone: '08123456783', + email: 'supplier5@example.com', + address: 'Address 5', + account_number: '1234567894', + balance: 300, + due_date: 25, + }, + plat_nomor: 'K 6789 KL', + no_surat_jalan: 'SJ-005', + dokumen: 'doc5.pdf', + biaya_ekspedisi: 70000, + nama_sopir: 'Eka', + }, + ], + name: 'Movement 5', + }, +]; + +const RowOptionsMenu = ({ + type = 'dropdown', + props, + deleteClickHandler, +}: { + type: 'dropdown' | 'collapse'; + props: CellContext; + deleteClickHandler: () => void; +}) => ( +
    + + + +
    +); + +const MovementTable = () => { + const [search, setSearch] = useState(''); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + const [sorting, setSorting] = useState([]); + const [selectedMovement, setSelectedMovement] = useState< + Movement | undefined + >(undefined); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const paginatedData = useMemo(() => { + const start = (page - 1) * pageSize; + return dummyMovements.slice(start, start + pageSize); + }, [page, pageSize]); + + const movementsColumns: ColumnDef[] = [ + { + header: '#', + cell: (props) => pageSize * (page - 1) + props.row.index + 1, + }, + { + accessorKey: 'warehouse_asal', + header: 'Gudang Asal', + cell: (props) => props.row.original.warehouse_asal.name, + }, + { + accessorKey: 'warehouse_tujuan', + header: 'Gudang Tujuan', + cell: (props) => props.row.original.warehouse_tujuan.name, + }, + { + accessorKey: 'product', + header: 'Nama Produk', + cell: (props) => props.row.original.product.map((p) => p.product.name), + }, + { + accessorKey: 'alasan_transfer', + header: 'Catatan', + }, + { + accessorKey: 'biaya_ekspedisi', + header: 'Biaya Ekspedisi', + cell: (props) => + props.row.original.ekspedisi.map((e) => e.biaya_ekspedisi), + }, + { + header: 'Aksi', + cell: (props) => { + const currentPageSize = props.table.getPaginationRowModel().rows.length; + const currentPageRows = props.table.getPaginationRowModel().flatRows; + const currentRowRelativeIndex = + currentPageRows.findIndex((r) => r.id === props.row.id) + 1; + + const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; + + const deleteClickHandler = () => { + setSelectedMovement(props.row.original); + deleteModal.openModal(); + }; + + return ( + <> + {currentPageSize > 2 && ( + + + + )} + {currentPageSize <= 2 && ( + + + + )} + + ); + }, + }, + ]; + + const deleteModal = useModal(); + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + setTimeout(() => { + setIsDeleteLoading(false); + deleteModal.closeModal(); + }, 1000); + }; + + const searchChangeHandler: React.ChangeEventHandler = ( + e + ) => { + setSearch(e.target.value); + setPage(1); + }; + + const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => { + const newVal = val as OptionType; + setPageSize(newVal.value as number); + setPage(1); + }; + + return ( + <> +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    + + data={paginatedData} + columns={movementsColumns} + pageSize={pageSize} + page={page} + totalItems={dummyMovements.length} + onPageChange={setPage} + isLoading={false} + sorting={sorting} + setSorting={setSorting} + className={{ + containerClassName: cn({ + 'mb-20': paginatedData.length === 0, + }), + tableWrapperClassName: 'overflow-x-auto min-h-full!', + tableClassName: 'font-inter w-full table-auto min-h-full!', + headerRowClassName: 'border-b border-b-gray-200', + headerColumnClassName: + 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end', + bodyRowClassName: 'border-b border-b-gray-200', + bodyColumnClassName: + 'px-6 py-3 last:flex last:flex-row last:justify-end', + }} + /> +
    + + + ); +}; + +export default MovementTable; From ddbf8b0896618e5810108f4dde360ceaa69f7707 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 8 Oct 2025 16:16:12 +0700 Subject: [PATCH 157/327] refactor(FE-62): rename Product component to Movement for clarity --- src/app/inventory/movement/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/inventory/movement/page.tsx b/src/app/inventory/movement/page.tsx index 12fe795b..a2c25612 100644 --- a/src/app/inventory/movement/page.tsx +++ b/src/app/inventory/movement/page.tsx @@ -1,6 +1,6 @@ import MovementTable from '@/components/pages/inventory/movement/MovementTable'; -const Product = () => { +const Movement = () => { return (
    @@ -8,4 +8,4 @@ const Product = () => { ); }; -export default Product; +export default Movement; From 21b93963230ae90e5a8b489e465951152aead512 Mon Sep 17 00:00:00 2001 From: sweetpotet Date: Wed, 8 Oct 2025 16:40:30 +0700 Subject: [PATCH 158/327] feat(FE-33): create customers forms --- src/app/master-data/customer/add/page.tsx | 11 + .../master-data/customer/detail/edit/page.tsx | 0 src/app/master-data/customer/detail/page.tsx | 0 src/app/master-data/customer/page.tsx | 11 + src/components/helper/RequireAuth.tsx | 160 +++++++- src/components/input/TextArea.tsx | 124 ++++++ .../master-data/customer/CustomersTable.tsx | 245 ++++++++++++ .../customer/form/CustomerForm.schema.ts | 40 ++ .../customer/form/CustomerForm.tsx | 377 ++++++++++++++++++ src/config/constant.ts | 11 + src/services/api/master-data.ts | 11 + src/types/api/master-data/customer.d.ts | 27 ++ 12 files changed, 1008 insertions(+), 9 deletions(-) create mode 100644 src/app/master-data/customer/add/page.tsx create mode 100644 src/app/master-data/customer/detail/edit/page.tsx create mode 100644 src/app/master-data/customer/detail/page.tsx create mode 100644 src/app/master-data/customer/page.tsx create mode 100644 src/components/input/TextArea.tsx create mode 100644 src/components/pages/master-data/customer/CustomersTable.tsx create mode 100644 src/components/pages/master-data/customer/form/CustomerForm.schema.ts create mode 100644 src/components/pages/master-data/customer/form/CustomerForm.tsx create mode 100644 src/types/api/master-data/customer.d.ts diff --git a/src/app/master-data/customer/add/page.tsx b/src/app/master-data/customer/add/page.tsx new file mode 100644 index 00000000..274b7d90 --- /dev/null +++ b/src/app/master-data/customer/add/page.tsx @@ -0,0 +1,11 @@ +import CustomerForm from "@/components/pages/master-data/customer/form/CustomerForm"; + +const AddNonstock = () => { + return ( +
    + +
    + ); +} + +export default AddNonstock; \ No newline at end of file diff --git a/src/app/master-data/customer/detail/edit/page.tsx b/src/app/master-data/customer/detail/edit/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/master-data/customer/detail/page.tsx b/src/app/master-data/customer/detail/page.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/master-data/customer/page.tsx b/src/app/master-data/customer/page.tsx new file mode 100644 index 00000000..56281702 --- /dev/null +++ b/src/app/master-data/customer/page.tsx @@ -0,0 +1,11 @@ +import CustomersTable from "@/components/pages/master-data/customer/CustomersTable"; + +const Nonstock = () => { + return ( +
    + +
    + ) +}; + +export default Nonstock; \ No newline at end of file diff --git a/src/components/helper/RequireAuth.tsx b/src/components/helper/RequireAuth.tsx index 9bc199f9..1d9d86b4 100644 --- a/src/components/helper/RequireAuth.tsx +++ b/src/components/helper/RequireAuth.tsx @@ -9,6 +9,145 @@ import { httpClientFetcher, SWRHttpKey } from '@/services/http/client'; import { isResponseSuccess } from '@/lib/api-helper'; import { GetMeResponse } from '@/types/api/api-general'; +// TODO: delete this later, DONT HARDCODE USER DATA +const DUMMY_USER = { + id: 1, + email: 'admin@mbugroup.id', + npk: '0001', + name: 'Super Admin', + image: null, + created_at: '2025-09-30T03:24:20.899229Z', + updated_at: '2025-09-30T03:24:20.899229Z', + roles: [ + { + id: 1, + key: 'mbu.super_admin', + name: 'MBU Administrator', + client: { + id: 1, + name: 'PT Mitra Berlian Unggas', + alias: 'MBU', + }, + permissions: [ + { + id: 1, + name: 'mbu:purchase:read', + action: 'read', + client: { + id: 1, + name: 'PT Mitra Berlian Unggas', + alias: 'MBU', + }, + }, + { + id: 2, + name: 'mbu:purchase:create', + action: 'create', + client: { + id: 1, + name: 'PT Mitra Berlian Unggas', + alias: 'MBU', + }, + }, + { + id: 3, + name: 'mbu:purchase:approve', + action: 'approve', + client: { + id: 1, + name: 'PT Mitra Berlian Unggas', + alias: 'MBU', + }, + }, + ], + }, + { + id: 2, + key: 'lti.super_admin', + name: 'LTI Administrator', + client: { + id: 2, + name: 'PT Lumbung Telur Indonesia', + alias: 'LTI', + }, + permissions: [ + { + id: 4, + name: 'lti:purchase:read', + action: 'read', + client: { + id: 2, + name: 'PT Lumbung Telur Indonesia', + alias: 'LTI', + }, + }, + { + id: 5, + name: 'lti:purchase:create', + action: 'create', + client: { + id: 2, + name: 'PT Lumbung Telur Indonesia', + alias: 'LTI', + }, + }, + { + id: 6, + name: 'lti:purchase:approve', + action: 'approve', + client: { + id: 2, + name: 'PT Lumbung Telur Indonesia', + alias: 'LTI', + }, + }, + ], + }, + { + id: 3, + key: 'manbu.super_admin', + name: 'MANBU Administrator', + client: { + id: 3, + name: 'PT Mandiri Berlian Unggas', + alias: 'MANBU', + }, + permissions: [ + { + id: 7, + name: 'manbu:purchase:read', + action: 'read', + client: { + id: 3, + name: 'PT Mandiri Berlian Unggas', + alias: 'MANBU', + }, + }, + { + id: 8, + name: 'manbu:purchase:create', + action: 'create', + client: { + id: 3, + name: 'PT Mandiri Berlian Unggas', + alias: 'MANBU', + }, + }, + { + id: 9, + name: 'manbu:purchase:approve', + action: 'approve', + client: { + id: 3, + name: 'PT Mandiri Berlian Unggas', + alias: 'MANBU', + }, + }, + ], + }, + ], +}; + interface RequireAuthProps { children?: ReactNode; } @@ -37,19 +176,22 @@ const RequireAuth = ({ children }: RequireAuthProps) => { if (isResponseSuccess(userResponse)) { setUser(userResponse.data); } else { - router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string); + // router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string); + // TODO: remove this later, DONT HARDCODE USER DATA + setUser(DUMMY_USER); } }, [userResponse, setIsLoadingUser, setUser]); - if (isLoadingUserResponse && !userResponse) { - return ( -
    - -
    - ); - } + // TODO: uncomment this later + // if (isLoadingUserResponse && !userResponse) { + // return ( + //
    + // + //
    + // ); + // } return <>{children}; }; -export default RequireAuth; +export default RequireAuth; \ No newline at end of file diff --git a/src/components/input/TextArea.tsx b/src/components/input/TextArea.tsx new file mode 100644 index 00000000..b4a6c9f5 --- /dev/null +++ b/src/components/input/TextArea.tsx @@ -0,0 +1,124 @@ +'use client'; + +import { + ChangeEventHandler, + FocusEventHandler, + ReactNode, +} from 'react'; + +import { cn } from '@/lib/helper'; + +export interface TextAreaProps { + label?: string; + bottomLabel?: string; + name: string; + value?: string | number; + placeholder?: string; + className?: { + wrapper?: string; + label?: string; + inputWrapper?: string; + input?: string; + }; + isError?: boolean; + isValid?: boolean; + disabled?: boolean; + readOnly?: boolean; + required?: boolean; + isLoading?: boolean; + errorMessage?: string; + startAdornment?: ReactNode; + endAdornment?: ReactNode; + onChange?: ChangeEventHandler; + onBlur?: FocusEventHandler; + cols?: number; +} + +const TextArea = ({ + label, + bottomLabel, + name, + value, + placeholder, + className, + isError, + isValid, + errorMessage, + startAdornment, + endAdornment, + disabled = false, + required = false, + onChange, + onBlur, + readOnly = false, + isLoading = false, + cols = 3 +}: TextAreaProps) => { + return ( +
    + {label && ( + + )} + {startAdornment && startAdornment} + +