[
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\n.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing to Shadcn-Admin\n\nThank you for considering contributing to **shadcn-admin**! Every contribution is valuable, whether it's reporting bugs, suggesting improvements, adding features, or refining README.\n\n## Table of Contents\n\n1. [Getting Started](#getting-started)\n2. [How to Contribute](#how-to-contribute)\n3. [Code Standards](#code-standards)\n4. [Pull Request Guidelines](#pull-request-guidelines)\n5. [Reporting Issues](#reporting-issues)\n6. [Community Guidelines](#community-guidelines)\n\n---\n\n## Getting Started\n\n1. **Fork** the repository.\n2. **Clone** your fork:\n\n   ```bash\n   git clone https://github.com/your-username/shadcn-admin.git\n   ```\n\n3. **Install dependencies:**\n\n   ```bash\n   pnpm install\n   ```\n\n4. **Run the project locally:**\n\n   ```bash\n   pnpm dev\n   ```\n\n5. Create a new branch for your contribution:\n\n   ```bash\n   git checkout -b feature/your-feature\n   ```\n\n---\n\n## How to Contribute\n\n- **Feature Requests:** Open an issue or start a discussion to discuss the feature before implementation.\n- **Bug Fixes:** Provide clear reproduction steps in your issue.\n- **Documentation:** Improvements to the documentation (README) are always appreciated.\n\n> **Note:** Pull Requests adding new features without a prior issue or discussion will **not be accepted**.\n\n---\n\n## Code Standards\n\n- Follow the existing **ESLint** and **Prettier** configurations.\n- Ensure your code is **type-safe** with **TypeScript**.\n- Maintain consistency with the existing code structure.\n\n> **Tips!** Before submitting your changes, run the following commands:\n\n```bash\npnpm lint && pnpm format && pnpm knip && pnpm build\n```\n\n---\n\n## Pull Request Guidelines\n\n- **Follow the [PR Template](./PULL_REQUEST_TEMPLATE.md):**\n  - Description\n  - Types of changes\n  - Checklist\n  - Further comments\n  - Related Issue\n- Ensure your changes pass **CI checks**.\n- Keep PRs **focused** and **concise**.\n- Reference related issues in your PR description.\n\n---\n\n## Reporting Issues\n\n- Clearly describe the issue.\n- Provide reproduction steps if applicable.\n- Include screenshots or code examples if relevant.\n\n---\n\n## Community Guidelines\n\n- Be respectful and constructive.\n- Follow the [Code of Conduct](./CODE_OF_CONDUCT.md).\n- Stay on topic in discussions.\n\n---\n\nThank you for helping make **shadcn-admin** better! 🚀\n\nIf you have any questions, feel free to reach out via [Discussions](https://github.com/satnaing/shadcn-admin/discussions).\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [satnaing]\nbuy_me_a_coffee: satnaing\n\n# patreon: # Replace with a single Patreon username\n# open_collective: # Replace with a single Open Collective username\n# ko_fi: # Replace with a single Ko-fi username\n# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\n# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\n# liberapay: # Replace with a single Liberapay username\n# issuehunt: # Replace with a single IssueHunt username\n# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\n# polar: # Replace with a single Polar username\n# thanks_dev: # Replace with a single thanks.dev username\n# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Shadcn-Admin Discussions\n    url: https://github.com/satnaing/shadcn-admin/discussions\n    about: Please ask and answer questions here."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/✨-feature-request.md",
    "content": "---\nname: \"✨ Feature Request\"\nabout: Suggest an idea for improving Shadcn-Admin\ntitle: \"[Feature Request]: \"\nlabels: enhancement\nassignees: \"\"\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/🐞-bug-report.md",
    "content": "---\nname: \"\\U0001F41E Bug report\"\nabout: Report a bug or unexpected behavior in Shadcn-Admin\ntitle: \"[BUG]: \"\nlabels: bug\nassignees: \"\"\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Description\n\n<!-- A clear and concise description of what the pull request does. Include any relevant motivation and background. -->\n\n## Types of changes\n\n<!-- What types of changes does your code introduce to AstroPaper? Put an `x` in the boxes that apply -->\n\n- [ ] Bug Fix (non-breaking change which fixes an issue)\n- [ ] New Feature (non-breaking change which adds functionality)\n- [ ] Others (any other types not listed above)\n\n## Checklist\n\n<!-- Please follow this checklist and put an x in each of the boxes, like this: [x]. You can also fill these out after creating the PR. This is simply a reminder of what we are going to look for before merging your code. -->\n\n- [ ] I have read the [Contributing Guide](https://github.com/satnaing/shadcn-admin/blob/main/.github/CONTRIBUTING.md)\n\n## Further comments\n\n<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->\n\n## Related Issue\n\n<!-- If this PR is related to an existing issue, link to it here. -->\n\nCloses: #<!-- Issue number, if applicable -->"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: Continuous Integration\n\non:\n  push:\n    branches:\n      - main\n\n  pull_request:\n    branches:\n      - main\n\njobs:\n  install-lint-build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Install pnpm\n        run: npm install -g pnpm\n\n      - name: Install dependencies\n        run: pnpm install --frozen-lockfile\n\n      - name: Lint the code\n        run: pnpm lint\n\n      # - name: Analyze unused files and dependencies\n      #   run: pnpm knip\n\n      - name: Run Prettier check\n        run: pnpm format:check\n\n      - name: Build the project\n        run: pnpm build\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: Close inactive issues/PR\n\non:\n  schedule:\n  - cron: '38 18 * * *'\n\njobs:\n  stale:\n\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n\n    steps:\n    - uses: actions/stale@v5\n      with:\n        repo-token: ${{ secrets.GITHUB_TOKEN }}\n        days-before-issue-stale: 120\n        days-before-issue-close: 120\n        stale-issue-label: \"stale\"\n        stale-issue-message: \"This issue is stale because it has been open for 120 days with no activity.\"\n        close-issue-message: \"This issue was closed because it has been inactive for 120 days since being marked as stale.\"\n        days-before-pr-stale: 120\n        days-before-pr-close: 120\n        stale-pr-label: \"stale\"\n        stale-pr-message: \"This PR is stale because it has been open for 120 days with no activity.\"\n        close-pr-message: \"This PR was closed because it has been inactive for 120 days since being marked as stale.\"\n        operations-per-run: 0\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n.env\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": ".prettierignore",
    "content": "# Ignore everything\n/*\n\n# Except these files & folders\n!/src\n!index.html\n!package.json\n!tailwind.config.js\n!tsconfig.json\n!tsconfig.node.json\n!vite.config.ts\n!.prettierrc\n!README.md\n!eslint.config.js\n!postcss.config.js\n\n# Ignore auto generated routeTree.gen.ts\n/src/routeTree.gen.ts"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"arrowParens\": \"always\",\n  \"semi\": false,\n  \"tabWidth\": 2,\n  \"printWidth\": 80,\n  \"singleQuote\": true,\n  \"jsxSingleQuote\": true,\n  \"trailingComma\": \"es5\",\n  \"bracketSpacing\": true,\n  \"endOfLine\": \"lf\",\n  \"plugins\": [\n    \"@trivago/prettier-plugin-sort-imports\",\n    \"prettier-plugin-tailwindcss\"\n  ],\n  \"tailwindStylesheet\": \"./src/styles/index.css\",\n  \"importOrder\": [\n    \"^path$\",\n    \"^vite$\",\n    \"^@vitejs/(.*)$\",\n    \"^react$\",\n    \"^react-dom/client$\",\n    \"^react/(.*)$\",\n    \"^globals$\",\n    \"^zod$\",\n    \"^axios$\",\n    \"^date-fns$\",\n    \"^react-hook-form$\",\n    \"^use-intl$\",\n    \"^@radix-ui/(.*)$\",\n    \"^@hookform/resolvers/zod$\",\n    \"^@tanstack/react-query$\",\n    \"^@tanstack/react-router$\",\n    \"^@tanstack/react-table$\",\n    \"<THIRD_PARTY_MODULES>\",\n    \"^@/assets/(.*)\",\n    \"^@/api/(.*)$\",\n    \"^@/stores/(.*)$\",\n    \"^@/lib/(.*)$\",\n    \"^@/utils/(.*)$\",\n    \"^@/constants/(.*)$\",\n    \"^@/context/(.*)$\",\n    \"^@/hooks/(.*)$\",\n    \"^@/components/layouts/(.*)$\",\n    \"^@/components/ui/(.*)$\",\n    \"^@/components/errors/(.*)$\",\n    \"^@/components/(.*)$\",\n    \"^@/features/(.*)$\",\n    \"^[./]\"\n  ]\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## v2.2.1 (2025-11-06)\n\n### Fix\n\n- **style**: update data attribute class in authenticated layout (#249)\n- prevent navigation to 500 page during development (#240)\n- **style**: apply variant 'destructive' to sign-out buttons (#236)\n- add missing space in profile form (#235)\n\n### Refactor\n\n- enhance tables and update table layout (#234)\n\n## v2.2.0 (2025-10-09)\n\n### Feat\n\n- add analytics tab in dashboard page (#220)\n- add extra AppTitle component for sidebar header (#216)\n- update 2-column sign in page (#213)\n\n### Fix\n\n- update sidebar menu chevron direction in RTL mode (#229)\n- pagination button spacing (#215)\n- upgrade lucide-react to solve antivirus warning (#211)\n\n### Refactor\n\n- move sidebar related components into app-sidebar\n- change SidebarInset component from 'main' to 'div'\n- replace extra main container query with content container query\n- replace inline svg logo with logo component (#214)\n\n## v2.1.0 (2025-08-23)\n\n### Feat\n\n- enhance data table pagination with page numbers (#207)\n- enhance auth flow with sign-out dialogs and redirect functionality (#206)\n\n### Refactor\n\n- reorganize utility files into `lib/` folder (#209)\n- extract data-table components and reorganize structure (#208)\n\n## v2.0.0 (2025-08-16)\n\n### BREAKING CHANGE\n\n- CSS file structure has been reorganized\n\n### Feat\n\n- add search param sync in apps route (#200)\n- improve tables and sync table states with search param (#199)\n- add data table bulk action toolbar (#196)\n- add config drawer and update overall layout (#186)\n- RTL support (#179)\n\n### Fix\n\n- adjust layout styles in search and top nav in dashboard page\n- update spacing and layout styles\n- update faceted icon color\n- improve user table hover & selected styles (#195)\n- add max-width for large screens to improve responsiveness (#194)\n- adjust chat border radius for better responsiveness (#193)\n- update hard-coded or inconsistent colors (#191)\n- use variable for inset layout height calculation\n- faded-bottom overflow issue in inset layout\n- hide unnecessary configs on mobile (#189)\n- adjust file input text vertical alignment (#188)\n\n### Refactor\n\n- enforce consistency and code quality (#198)\n- improve code quality and consistency (#197)\n- update error routes (#192)\n- remove DirSwitch component and its usage in Tasks (#190)\n- standardize using cookie as persist state (#187)\n- separate CSS into modular theme and base styles (#185)\n- replace tabler icons with lucide icons (#183)\n\n## v1.4.2 (2025-07-23)\n\n### Fix\n\n- remove unnecessary transitions in table (#176)\n- overflow background in tables (#175)\n\n## v1.4.1 (2025-06-25)\n\n### Fix\n\n- user list overflow in chat (#160)\n- prevent showing collapsed menu on mobile (#155)\n- white background select dropdown in dark mode (#149)\n\n### Refactor\n\n- update font config guide in fonts.ts (#164)\n\n## v1.4.0 (2025-05-25)\n\n### Feat\n\n- **clerk**: add Clerk for auth and protected route (#146)\n\n### Fix\n\n- add an indicator for nested pages in search (#147)\n- update faded-bottom color with css variable (#139)\n\n## v1.3.0 (2025-04-16)\n\n### Fix\n\n- replace custom otp with input-otp component (#131)\n- disable layout animation on mobile (#130)\n- upgrade react-day-picker and update calendar component (#129)\n\n### Others\n\n- upgrade Tailwind CSS to v4 (#125)\n- upgrade dependencies (#128)\n- configure automatic code-splitting (#127)\n\n## v1.2.0 (2025-04-12)\n\n### Feat\n\n- add loading indicator during page transitions (#119)\n- add light favicons and theme-based switching (#112)\n- add new chat dialog in chats page (#90)\n\n### Fix\n\n- add fallback font for fontFamily (#110)\n- broken focus behavior in add user dialog (#113)\n\n## v1.1.0 (2025-01-30)\n\n### Feat\n\n- allow changing font family in setting\n\n### Fix\n\n- update sidebar color in dark mode for consistent look (#87)\n- use overflow-clip in table paginations (#86)\n- **style**: update global scrollbar style (#82)\n- toolbar filter placeholder typo in user table (#76)\n\n## v1.0.3 (2024-12-28)\n\n### Fix\n\n- add gap between buttons in import task dialog (#70)\n- hide button sort if column cannot be hidden & update filterFn (#69)\n- nav links added in profile dropdown (#68)\n\n### Refactor\n\n- optimize states in users/tasks context (#71)\n\n## v1.0.2 (2024-12-25)\n\n### Fix\n\n- update overall layout due to scroll-lock bug (#66)\n\n### Refactor\n\n- analyze and remove unused files/exports with knip (#67)\n\n## v1.0.1 (2024-12-14)\n\n### Fix\n\n- merge two button components into one (#60)\n- loading all tabler-icon chunks in dev mode (#59)\n- display menu dropdown when sidebar collapsed (#58)\n- update spacing & alignment in dialogs/drawers\n- update border & transition of sticky columns in user table\n- update heading alignment to left in user dialogs\n- add height and scroll area in user mutation dialogs\n- update `/dashboard` route to just `/`\n- **build**: replace require with import in tailwind.config.js\n\n### Refactor\n\n- remove unnecessary layout-backup file\n\n## v1.0.0 (2024-12-09)\n\n### BREAKING CHANGE\n\n- Restructured the entire folder\nhierarchy to adopt a feature-based structure. This\nchange improves code modularity and maintainability\nbut introduces breaking changes.\n\n### Feat\n\n- implement task dialogs\n- implement user invite dialog\n- implement users CRUD\n- implement global command/search\n- implement custom sidebar trigger\n- implement coming-soon page\n\n### Fix\n\n- uncontrolled issue in account setting\n- card layout issue in app integrations page\n- remove form reset logic from useEffect in task import\n- update JSX types due to react 19\n- prevent card stretch in filtered app layout\n- layout wrap issue in tasks page on mobile\n- update user column hover and selected colors\n- add setTimeout in user dialog closing\n- layout shift issue in dropdown modal\n- z-axis overflow issue in header\n- stretch search bar only in mobile\n- language dropdown issue in account setting\n- update overflow contents with scroll area\n\n### Refactor\n\n- update layouts and extract common layout\n- reorganize project to feature-based structure\n\n## v1.0.0-beta.5 (2024-11-11)\n\n### Feat\n\n- add multiple language support (#37)\n\n### Fix\n\n- ensure site syncs with system theme changes (#49)\n- recent sales responsive on ipad view (#40)\n\n## v1.0.0-beta.4 (2024-09-22)\n\n### Feat\n\n- upgrade theme button to theme dropdown (#33)\n- **a11y**: add \"Skip to Main\" button to improve keyboard navigation (#27)\n\n### Fix\n\n- optimize onComplete/onIncomplete invocation (#32)\n- solve asChild attribute issue in custom button (#31)\n- improve custom Button component (#28)\n\n## v1.0.0-beta.3 (2024-08-25)\n\n### Feat\n\n- implement chat page (#21)\n- add 401 error page (#12)\n- implement apps page\n- add otp page\n\n### Fix\n\n- prevent focus zoom on mobile devices (#20)\n- resolve eslint script issue (#18)\n- **a11y**: update default aria-label of each pin-input\n- resolve OTP paste issue in multi-digit pin-input\n- update layouts and solve overflow issues (#11)\n- sync pin inputs programmatically\n\n## v1.0.0-beta.2 (2024-03-18)\n\n### Feat\n\n- implement custom pin-input component (#2)\n\n## v1.0.0-beta.1 (2024-02-08)\n\n### Feat\n\n- update theme-color meta tag when theme is updated\n- add coming soon page in broken pages\n- implement tasks table and page\n- add remaining settings pages\n- add example error page for settings\n- update general error page to be more flexible\n- implement settings layout and settings profile page\n- add error pages\n- add password-input custom component\n- add sign-up page\n- add forgot-password page\n- add box sign in page\n- add email + password sign in page\n- make sidebar responsive and accessible\n- add tailwind prettier plugin\n- make sidebar collapsed state in local storage\n- add check current active nav hook\n- add loader component ui\n- update dropdown nav by default if child is active\n- add main-panel in dashboard\n- **ui**: add dark mode\n- **ui**: implement side nav ui\n\n### Fix\n\n- update incorrect overflow side nav height\n- exclude shadcn components from linting and remove unused props\n- solve text overflow issue when nav text is long\n- replace nav with dropdown in mobile topnav\n- make sidebar scrollable when overflow\n- update nav link keys\n- **ui**: update label style\n\n### Refactor\n\n- move password-input component into custom component dir\n- add custom button component\n- extract redundant codes into layout component\n- update react-router to use new api for routing\n- update main panel layout\n- update major layouts and styling\n- update main panel to be responsive\n- update sidebar collapsed state to false in mobile\n- update sidebar logo and title\n- **ui**: remove unnecessary spacing\n- remove unused files\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 Sat Naing\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Shadcn Admin Dashboard\n\nAdmin Dashboard UI crafted with Shadcn and Vite. Built with responsiveness and accessibility in mind.\n\n![alt text](public/images/shadcn-admin.png)\n\n[![Sponsored by Clerk](https://img.shields.io/badge/Sponsored%20by-Clerk-5b6ee1?logo=clerk)](https://go.clerk.com/GttUAaK)\n\nI've been creating dashboard UIs at work and for my personal projects. I always wanted to make a reusable collection of dashboard UI for future projects; and here it is now. While I've created a few custom components, some of the code is directly adapted from ShadcnUI examples.\n\n> This is not a starter project (template) though. I'll probably make one in the future.\n\n## Features\n\n- Light/dark mode\n- Responsive\n- Accessible\n- With built-in Sidebar component\n- Global search command\n- 10+ pages\n- Extra custom components\n- RTL support\n\n<details>\n<summary>Customized Components (click to expand)</summary>\n\nThis project uses Shadcn UI components, but some have been slightly modified for better RTL (Right-to-Left) support and other improvements. These customized components differ from the original Shadcn UI versions.\n\nIf you want to update components using the Shadcn CLI (e.g., `npx shadcn@latest add <component>`), it's generally safe for non-customized components. For the listed customized ones, you may need to manually merge changes to preserve the project's modifications and avoid overwriting RTL support or other updates.\n\n> If you don't require RTL support, you can safely update the 'RTL Updated Components' via the Shadcn CLI, as these changes are primarily for RTL compatibility. The 'Modified Components' may have other customizations to consider.\n\n### Modified Components\n\n- scroll-area\n- sonner\n- separator\n\n### RTL Updated Components\n\n- alert-dialog\n- calendar\n- command\n- dialog\n- dropdown-menu\n- select\n- table\n- sheet\n- sidebar\n- switch\n\n**Notes:**\n\n- **Modified Components**: These have general updates, potentially including RTL adjustments.\n- **RTL Updated Components**: These have specific changes for RTL language support (e.g., layout, positioning).\n- For implementation details, check the source files in `src/components/ui/`.\n- All other Shadcn UI components in the project are standard and can be safely updated via the CLI.\n\n</details>\n\n## Tech Stack\n\n**UI:** [ShadcnUI](https://ui.shadcn.com) (TailwindCSS + RadixUI)\n\n**Build Tool:** [Vite](https://vitejs.dev/)\n\n**Routing:** [TanStack Router](https://tanstack.com/router/latest)\n\n**Type Checking:** [TypeScript](https://www.typescriptlang.org/)\n\n**Linting/Formatting:** [ESLint](https://eslint.org/) & [Prettier](https://prettier.io/)\n\n**Icons:** [Lucide Icons](https://lucide.dev/icons/), [Tabler Icons](https://tabler.io/icons) (Brand icons only)\n\n**Auth (partial):** [Clerk](https://go.clerk.com/GttUAaK)\n\n## Run Locally\n\nClone the project\n\n```bash\n  git clone https://github.com/satnaing/shadcn-admin.git\n```\n\nGo to the project directory\n\n```bash\n  cd shadcn-admin\n```\n\nInstall dependencies\n\n```bash\n  pnpm install\n```\n\nStart the server\n\n```bash\n  pnpm run dev\n```\n\n## Sponsoring this project ❤️\n\nIf you find this project helpful or use this in your own work, consider [sponsoring me](https://github.com/sponsors/satnaing) to support development and maintenance. You can [buy me a coffee](https://buymeacoffee.com/satnaing) as well. Don’t worry, every penny helps. Thank you! 🙏\n\nFor questions or sponsorship inquiries, feel free to reach out at [satnaingdev@gmail.com](mailto:satnaingdev@gmail.com).\n\n### Current Sponsor\n\n- [Clerk](https://go.clerk.com/GttUAaK) - authentication and user management for the modern web\n\n## Author\n\nCrafted with 🤍 by [@satnaing](https://github.com/satnaing)\n\n## License\n\nLicensed under the [MIT License](https://choosealicense.com/licenses/mit/)\n"
  },
  {
    "path": "components.json",
    "content": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"new-york\",\n  \"rsc\": false,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"src/styles/index.css\",\n    \"baseColor\": \"slate\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@/lib/utils\",\n    \"ui\": \"@/components/ui\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"iconLibrary\": \"lucide\"\n}\n"
  },
  {
    "path": "cz.yaml",
    "content": "---\ncommitizen:\n  name: cz_conventional_commits\n  tag_format: v$version\n  update_changelog_on_bump: true\n  version_provider: npm\n  version_scheme: semver\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import globals from 'globals'\nimport js from '@eslint/js'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport reactRefresh from 'eslint-plugin-react-refresh'\nimport { defineConfig } from 'eslint/config'\nimport tseslint from 'typescript-eslint'\n\nexport default defineConfig(\n  { ignores: ['dist', 'src/components/ui'] },\n  {\n    extends: [\n      js.configs.recommended,\n      ...tseslint.configs.recommended,\n      ...pluginQuery.configs['flat/recommended'],\n    ],\n    files: ['**/*.{ts,tsx}'],\n    languageOptions: {\n      ecmaVersion: 2020,\n      globals: globals.browser,\n    },\n    plugins: {\n      'react-hooks': reactHooks,\n      'react-refresh': reactRefresh,\n    },\n    rules: {\n      ...reactHooks.configs.recommended.rules,\n      'react-refresh/only-export-components': [\n        'warn',\n        { allowConstantExport: true },\n      ],\n      'no-console': 'error',\n      'no-unused-vars': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          args: 'all',\n          argsIgnorePattern: '^_',\n          caughtErrors: 'all',\n          caughtErrorsIgnorePattern: '^_',\n          destructuredArrayIgnorePattern: '^_',\n          varsIgnorePattern: '^_',\n          ignoreRestSiblings: true,\n        },\n      ],\n      // Enforce type-only imports for TypeScript types\n      '@typescript-eslint/consistent-type-imports': [\n        'error',\n        {\n          prefer: 'type-imports',\n          fixStyle: 'inline-type-imports',\n          disallowTypeAnnotations: false,\n        },\n      ],\n      // Prevent duplicate imports from the same module\n      'no-duplicate-imports': 'error',\n    },\n  }\n)\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link\n      rel=\"icon\"\n      type=\"image/svg+xml\"\n      href=\"/images/favicon.svg\"\n      media=\"(prefers-color-scheme: light)\"\n    />\n    <link\n      rel=\"icon\"\n      type=\"image/svg+xml\"\n      href=\"/images/favicon_light.svg\"\n      media=\"(prefers-color-scheme: dark)\"\n    />\n    <link\n      rel=\"icon\"\n      type=\"image/png\"\n      href=\"/images/favicon.png\"\n      media=\"(prefers-color-scheme: light)\"\n    />\n    <link\n      rel=\"icon\"\n      type=\"image/png\"\n      href=\"/images/favicon_light.png\"\n      media=\"(prefers-color-scheme: dark)\"\n    />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\n    <!-- Primary Meta Tags -->\n    <title>Shadcn Admin</title>\n    <meta name=\"title\" content=\"Shadcn Admin\" />\n    <meta\n      name=\"description\"\n      content=\"Admin Dashboard UI built with Shadcn and Vite.\"\n    />\n\n    <!-- Open Graph / Facebook -->\n    <meta property=\"og:type\" content=\"website\" />\n    <meta property=\"og:url\" content=\"https://shadcn-admin.netlify.app\" />\n    <meta property=\"og:title\" content=\"Shadcn Admin\" />\n    <meta\n      property=\"og:description\"\n      content=\"Admin Dashboard UI built with Shadcn and Vite.\"\n    />\n    <meta\n      property=\"og:image\"\n      content=\"https://shadcn-admin.netlify.app/images/shadcn-admin.png\"\n    />\n\n    <!-- Twitter -->\n    <meta property=\"twitter:card\" content=\"summary_large_image\" />\n    <meta property=\"twitter:url\" content=\"https://shadcn-admin.netlify.app\" />\n    <meta property=\"twitter:title\" content=\"Shadcn Admin\" />\n    <meta\n      property=\"twitter:description\"\n      content=\"Admin Dashboard UI built with Shadcn and Vite.\"\n    />\n    <meta\n      property=\"twitter:image\"\n      content=\"https://shadcn-admin.netlify.app/images/shadcn-admin.png\"\n    />\n\n    <!-- font family -->\n    <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n    <link\n      href=\"https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Manrope:wght@200..800&display=swap\"\n      rel=\"stylesheet\"\n    />\n\n    <meta name=\"theme-color\" content=\"#fff\" />\n  </head>\n\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "knip.config.ts",
    "content": "import type { KnipConfig } from 'knip';\n\nconst config: KnipConfig = {\n  ignore: ['src/components/ui/**', 'src/routeTree.gen.ts'],\n  ignoreDependencies: [\"tailwindcss\", \"tw-animate-css\"]\n};\n\nexport default config;"
  },
  {
    "path": "netlify.toml",
    "content": "[[redirects]]\n  from = \"/*\"\n  to = \"/index.html\"\n  status = 200"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"shadcn-admin\",\n  \"private\": false,\n  \"version\": \"2.2.1\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"lint\": \"eslint .\",\n    \"preview\": \"vite preview\",\n    \"format:check\": \"prettier --check .\",\n    \"format\": \"prettier --write .\",\n    \"knip\": \"knip\"\n  },\n  \"dependencies\": {\n    \"@clerk/clerk-react\": \"^5.58.1\",\n    \"@hookform/resolvers\": \"^5.2.2\",\n    \"@radix-ui/react-alert-dialog\": \"^1.1.15\",\n    \"@radix-ui/react-avatar\": \"^1.1.11\",\n    \"@radix-ui/react-checkbox\": \"^1.3.3\",\n    \"@radix-ui/react-collapsible\": \"^1.1.12\",\n    \"@radix-ui/react-dialog\": \"^1.1.15\",\n    \"@radix-ui/react-direction\": \"^1.1.1\",\n    \"@radix-ui/react-dropdown-menu\": \"^2.1.16\",\n    \"@radix-ui/react-icons\": \"^1.3.2\",\n    \"@radix-ui/react-label\": \"^2.1.8\",\n    \"@radix-ui/react-popover\": \"^1.1.15\",\n    \"@radix-ui/react-radio-group\": \"^1.3.8\",\n    \"@radix-ui/react-scroll-area\": \"^1.2.10\",\n    \"@radix-ui/react-select\": \"^2.2.6\",\n    \"@radix-ui/react-separator\": \"^1.1.8\",\n    \"@radix-ui/react-slot\": \"^1.2.4\",\n    \"@radix-ui/react-switch\": \"^1.2.6\",\n    \"@radix-ui/react-tabs\": \"^1.1.13\",\n    \"@radix-ui/react-tooltip\": \"^1.2.8\",\n    \"@tailwindcss/vite\": \"^4.1.18\",\n    \"@tanstack/react-query\": \"^5.90.12\",\n    \"@tanstack/react-router\": \"^1.141.2\",\n    \"@tanstack/react-table\": \"^8.21.3\",\n    \"axios\": \"^1.13.5\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"1.1.1\",\n    \"date-fns\": \"^4.1.0\",\n    \"input-otp\": \"^1.4.2\",\n    \"lucide-react\": \"^0.561.0\",\n    \"react\": \"^19.2.3\",\n    \"react-day-picker\": \"9.12.0\",\n    \"react-dom\": \"^19.2.3\",\n    \"react-hook-form\": \"^7.68.0\",\n    \"react-top-loading-bar\": \"^3.0.2\",\n    \"recharts\": \"^3.6.0\",\n    \"sonner\": \"^2.0.7\",\n    \"tailwind-merge\": \"^3.4.0\",\n    \"tailwindcss\": \"^4.1.18\",\n    \"tw-animate-css\": \"^1.4.0\",\n    \"zod\": \"^4.2.0\",\n    \"zustand\": \"^5.0.9\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.39.2\",\n    \"@faker-js/faker\": \"^10.1.0\",\n    \"@tanstack/eslint-plugin-query\": \"^5.91.2\",\n    \"@tanstack/react-query-devtools\": \"^5.91.1\",\n    \"@tanstack/react-router-devtools\": \"^1.141.2\",\n    \"@tanstack/router-plugin\": \"^1.141.2\",\n    \"@trivago/prettier-plugin-sort-imports\": \"^6.0.0\",\n    \"@types/node\": \"^25.0.2\",\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitejs/plugin-react-swc\": \"^4.2.2\",\n    \"eslint\": \"^9.39.2\",\n    \"eslint-plugin-react-hooks\": \"^7.0.1\",\n    \"eslint-plugin-react-refresh\": \"^0.4.25\",\n    \"globals\": \"^16.5.0\",\n    \"knip\": \"^5.73.4\",\n    \"prettier\": \"^3.7.4\",\n    \"prettier-plugin-tailwindcss\": \"^0.7.2\",\n    \"typescript\": \"~5.9.3\",\n    \"typescript-eslint\": \"^8.49.0\",\n    \"vite\": \"^7.3.0\"\n  }\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-discord.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconDiscord({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Discord</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M8 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0' />\n      <path d='M14 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0' />\n      <path d='M15.5 17c0 1 1.5 3 2 3c1.5 0 2.833 -1.667 3.5 -3c.667 -1.667 .5 -5.833 -1.5 -11.5c-1.457 -1.015 -3 -1.34 -4.5 -1.5l-.972 1.923a11.913 11.913 0 0 0 -4.053 0l-.975 -1.923c-1.5 .16 -3.043 .485 -4.5 1.5c-2 5.667 -2.167 9.833 -1.5 11.5c.667 1.333 2 3 3.5 3c.5 0 2 -2 2 -3' />\n      <path d='M7 16.5c3.5 1 6.5 1 10 0' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-docker.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconDocker({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Docker</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M22 12.54c-1.804 -.345 -2.701 -1.08 -3.523 -2.94c-.487 .696 -1.102 1.568 -.92 2.4c.028 .238 -.32 1 -.557 1h-14c0 5.208 3.164 7 6.196 7c4.124 .022 7.828 -1.376 9.854 -5c1.146 -.101 2.296 -1.505 2.95 -2.46z' />\n      <path d='M5 10h3v3h-3z' />\n      <path d='M8 10h3v3h-3z' />\n      <path d='M11 10h3v3h-3z' />\n      <path d='M8 7h3v3h-3z' />\n      <path d='M11 7h3v3h-3z' />\n      <path d='M11 4h3v3h-3z' />\n      <path d='M4.571 18c1.5 0 2.047 -.074 2.958 -.78' />\n      <path d='M10 16l0 .01' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-facebook.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconFacebook({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Facebook</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M7 10v4h3v7h4v-7h3l1 -4h-4v-2a1 1 0 0 1 1 -1h3v-4h-3a5 5 0 0 0 -5 5v2h-3' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-figma.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconFigma({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Figma</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M15 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0' />\n      <path d='M6 3m0 3a3 3 0 0 1 3 -3h6a3 3 0 0 1 3 3v0a3 3 0 0 1 -3 3h-6a3 3 0 0 1 -3 -3z' />\n      <path d='M9 9a3 3 0 0 0 0 6h3m-3 0a3 3 0 1 0 3 3v-15' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-github.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGithub({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>GitHub</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-gitlab.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGitlab({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>GitLab</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M21 14l-9 7l-9 -7l3 -11l3 7h6l3 -7z' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-gmail.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGmail({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Gmail</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M16 20h3a1 1 0 0 0 1 -1v-14a1 1 0 0 0 -1 -1h-3v16z' />\n      <path d='M5 20h3v-16h-3a1 1 0 0 0 -1 1v14a1 1 0 0 0 1 1z' />\n      <path d='M16 4l-4 4l-4 -4' />\n      <path d='M4 6.5l8 7.5l8 -7.5' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-medium.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconMedium({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Medium</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' />\n      <path d='M8 9h1l3 3l3 -3h1' />\n      <path d='M8 15l2 0' />\n      <path d='M14 15l2 0' />\n      <path d='M9 9l0 6' />\n      <path d='M15 9l0 6' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-notion.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconNotion({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Notion</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M11 17.5v-6.5h.5l4 6h.5v-6.5' />\n      <path d='M19.077 20.071l-11.53 .887a1 1 0 0 1 -.876 -.397l-2.471 -3.294a1 1 0 0 1 -.2 -.6v-10.741a1 1 0 0 1 .923 -.997l11.389 -.876a2 2 0 0 1 1.262 .33l1.535 1.023a2 2 0 0 1 .891 1.664v12.004a1 1 0 0 1 -.923 .997z' />\n      <path d='M4.5 5.5l2.5 2.5' />\n      <path d='M20 7l-13 1v12.5' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-skype.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconSkype({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Skype</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M12 3a9 9 0 0 1 8.603 11.65a4.5 4.5 0 0 1 -5.953 5.953a9 9 0 0 1 -11.253 -11.253a4.5 4.5 0 0 1 5.953 -5.954a8.987 8.987 0 0 1 2.65 -.396z' />\n      <path d='M8 14.5c.5 2 2.358 2.5 4 2.5c2.905 0 4 -1.187 4 -2.5c0 -1.503 -1.927 -2.5 -4 -2.5s-4 -1 -4 -2.5c0 -1.313 1.095 -2.5 4 -2.5c1.642 0 3.5 .5 4 2.5' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-slack.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconSlack({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Slack</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M12 12v-6a2 2 0 0 1 4 0v6m0 -2a2 2 0 1 1 2 2h-6' />\n      <path d='M12 12h6a2 2 0 0 1 0 4h-6m2 0a2 2 0 1 1 -2 2v-6' />\n      <path d='M12 12v6a2 2 0 0 1 -4 0v-6m0 2a2 2 0 1 1 -2 -2h6' />\n      <path d='M12 12h-6a2 2 0 0 1 0 -4h6m-2 0a2 2 0 1 1 2 -2v6' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-stripe.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconStripe({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Stripe</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M11.453 8.056c0 -.623 .518 -.979 1.442 -.979c1.69 0 3.41 .343 4.605 .923l.5 -4c-.948 -.449 -2.82 -1 -5.5 -1c-1.895 0 -3.373 .087 -4.5 1c-1.172 .956 -2 2.33 -2 4c0 3.03 1.958 4.906 5 6c1.961 .69 3 .743 3 1.5c0 .735 -.851 1.5 -2 1.5c-1.423 0 -3.963 -.609 -5.5 -1.5l-.5 4c1.321 .734 3.474 1.5 6 1.5c2 0 3.957 -.468 5.084 -1.36c1.263 -.979 1.916 -2.268 1.916 -4.14c0 -3.096 -1.915 -4.547 -5 -5.637c-1.646 -.605 -2.544 -1.07 -2.544 -1.807z' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-telegram.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconTelegram({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Telegram</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M15 10l-4 4l6 6l4 -16l-18 7l4 2l2 6l3 -4' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-trello.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconTrello({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Trello</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' />\n      <path d='M7 7h3v10h-3z' />\n      <path d='M14 7h3v6h-3z' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-whatsapp.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconWhatsapp({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>WhatsApp</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M3 21l1.65 -3.8a9 9 0 1 1 3.4 2.9l-5.05 .9' />\n      <path d='M9 10a.5 .5 0 0 0 1 0v-1a.5 .5 0 0 0 -1 0v1a5 5 0 0 0 5 5h1a.5 .5 0 0 0 0 -1h-1a.5 .5 0 0 0 0 1' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/icon-zoom.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconZoom({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      width='24'\n      height='24'\n      className={cn('[&>path]:stroke-current', className)}\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      {...props}\n    >\n      <title>Zoom</title>\n      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />\n      <path d='M17.011 9.385v5.128l3.989 3.487v-12z' />\n      <path d='M3.887 6h10.08c1.468 0 3.033 1.203 3.033 2.803v8.196a.991 .991 0 0 1 -.975 1h-10.373c-1.667 0 -2.652 -1.5 -2.652 -3l.01 -8a.882 .882 0 0 1 .208 -.71a.841 .841 0 0 1 .67 -.287z' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/brand-icons/index.ts",
    "content": "export { IconDiscord } from './icon-discord'\nexport { IconDocker } from './icon-docker'\nexport { IconFacebook } from './icon-facebook'\nexport { IconFigma } from './icon-figma'\nexport { IconGithub } from './icon-github'\nexport { IconGitlab } from './icon-gitlab'\nexport { IconGmail } from './icon-gmail'\nexport { IconMedium } from './icon-medium'\nexport { IconNotion } from './icon-notion'\nexport { IconSkype } from './icon-skype'\nexport { IconSlack } from './icon-slack'\nexport { IconStripe } from './icon-stripe'\nexport { IconTelegram } from './icon-telegram'\nexport { IconTrello } from './icon-trello'\nexport { IconWhatsapp } from './icon-whatsapp'\nexport { IconZoom } from './icon-zoom'\n"
  },
  {
    "path": "src/assets/clerk-full-logo.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function ClerkFullLogo(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      width={77}\n      height={24}\n      viewBox='0 0 77 24'\n      fill='none'\n      xmlns='http://www.w3.org/2000/svg'\n      {...props}\n    >\n      <path\n        d='M35.148 16.738a4.198 4.198 0 01-3.06 1.283 3.53 3.53 0 01-2.604-1.034c-.619-.645-.975-1.566-.975-2.665 0-2.199 1.432-3.703 3.58-3.703a3.914 3.914 0 013.034 1.377l1.859-1.644c-1.211-1.47-3.176-2.229-5.042-2.229-3.652 0-6.24 2.517-6.24 6.22 0 1.831.643 3.374 1.728 4.463s2.631 1.728 4.415 1.728c2.317 0 4.166-.94 5.203-2.122l-1.898-1.674zM38.727 3.428h2.766V20.34h-2.766V3.428zM54.818 15.283c.046-.368.07-.74.076-1.11 0-3.507-2.296-6.047-5.847-6.047a5.738 5.738 0 00-4.215 1.725c-1.038 1.089-1.66 2.631-1.66 4.47 0 3.749 2.642 6.216 6.146 6.216 2.35 0 4.043-.951 5.058-2.242l-1.812-1.605-.09-.076a3.749 3.749 0 01-3.008 1.406c-1.778 0-3.061-1.037-3.427-2.737h8.779zm-8.733-2.22a3.365 3.365 0 01.737-1.449 3.082 3.082 0 012.368-.996c1.58 0 2.57.988 2.911 2.445h-6.016zM63.445 8.09v3.084a13.36 13.36 0 00-.838-.05c-2.094 0-3.282 1.505-3.282 3.479v5.736h-2.763V8.261h2.763v1.83h.025c.938-1.283 2.284-1.997 3.75-1.997l.345-.004zM69.887 15.281l-1.998 2.222v2.837h-2.764V3.428h2.764v10.374L72.822 8.3h3.283l-4.341 4.86 4.417 7.18h-3.11l-3.133-5.059h-.051z'\n        fill='#1F0256'\n      />\n      <path\n        d='M19.116 3.16l-2.88 2.881a.571.571 0 01-.701.084 6.854 6.854 0 00-10.39 5.647 6.867 6.867 0 00.979 3.764.571.571 0 01-.084.699l-2.88 2.88a.57.57 0 01-.865-.063A11.994 11.994 0 0119.051 2.295a.57.57 0 01.065.866z'\n        fill='url(#paint0_linear_26568_214324)'\n      />\n      <path\n        d='M19.113 20.829l-2.88-2.88a.571.571 0 00-.7-.085 6.854 6.854 0 01-7.081 0 .571.571 0 00-.7.084l-2.881 2.88a.57.57 0 00.062.877 11.994 11.994 0 0014.114 0 .571.571 0 00.066-.876zM11.997 15.422a3.427 3.427 0 100-6.854 3.427 3.427 0 000 6.854z'\n        fill='#1F0256'\n      />\n      <defs>\n        <linearGradient\n          id='paint0_linear_26568_214324'\n          x1={16.4087}\n          y1={-1.75881}\n          x2={-7.88473}\n          y2={22.5365}\n          gradientUnits='userSpaceOnUse'\n        >\n          <stop stopColor='#17CCFC' />\n          <stop offset={0.5} stopColor='#5D31FF' />\n          <stop offset={1} stopColor='#F35AFF' />\n        </linearGradient>\n      </defs>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/clerk-logo.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function ClerkLogo({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      role='img'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      id='clerk'\n      height='24'\n      width='24'\n      className={cn('[&>path]:fill-foreground', className)}\n      {...props}\n    >\n      <title>Clerk</title>\n      <path\n        d='m21.47 20.829 -2.881 -2.881a0.572 0.572 0 0 0 -0.7 -0.084 6.854 6.854 0 0 1 -7.081 0 0.576 0.576 0 0 0 -0.7 0.084l-2.881 2.881a0.576 0.576 0 0 0 -0.103 0.69 0.57 0.57 0 0 0 0.166 0.186 12 12 0 0 0 14.113 0 0.58 0.58 0 0 0 0.239 -0.423 0.576 0.576 0 0 0 -0.172 -0.453Zm0.002 -17.668 -2.88 2.88a0.569 0.569 0 0 1 -0.701 0.084A6.857 6.857 0 0 0 8.724 8.08a6.862 6.862 0 0 0 -1.222 3.692 6.86 6.86 0 0 0 0.978 3.764 0.573 0.573 0 0 1 -0.083 0.699l-2.881 2.88a0.567 0.567 0 0 1 -0.864 -0.063A11.993 11.993 0 0 1 6.771 2.7a11.99 11.99 0 0 1 14.637 -0.405 0.566 0.566 0 0 1 0.232 0.418 0.57 0.57 0 0 1 -0.168 0.448Zm-7.118 12.261a3.427 3.427 0 1 0 0 -6.854 3.427 3.427 0 0 0 0 6.854Z'\n        strokeWidth='1'\n      ></path>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-dir.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\nimport { type Direction } from '@/context/direction-provider'\n\ntype IconDirProps = SVGProps<SVGSVGElement> & {\n  dir: Direction\n}\n\nexport function IconDir({ dir, className, ...props }: IconDirProps) {\n  return (\n    <svg\n      data-name={`icon-dir-${dir}`}\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      className={cn(dir === 'rtl' && 'rotate-y-180', className)}\n      {...props}\n    >\n      <path\n        d='M23.42.51h51.92c2.21 0 4 1.79 4 4v42.18c0 2.21-1.79 4-4 4H23.42s-.04-.02-.04-.04V.55s.02-.04.04-.04z'\n        opacity={0.15}\n      />\n      <path\n        fill='none'\n        opacity={0.72}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 14.88L17.78 14.88'\n      />\n      <path\n        fill='none'\n        opacity={0.48}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 22.09L16.08 22.09'\n      />\n      <path\n        fill='none'\n        opacity={0.55}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 18.38L14.93 18.38'\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <circle cx={7.51} cy={7.4} r={2.54} opacity={0.8} />\n        <path\n          fill='none'\n          opacity={0.8}\n          strokeWidth='2px'\n          d='M12.06 6.14L17.78 6.14'\n        />\n        <path fill='none' opacity={0.6} d='M11.85 8.79L16.91 8.79' />\n      </g>\n      <path\n        fill='none'\n        opacity={0.62}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='3px'\n        d='M29.41 7.4L34.67 7.4'\n      />\n      <rect\n        x={28.76}\n        y={11.21}\n        width={26.03}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.44}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={28.76}\n        y={17.01}\n        width={44.25}\n        height={13.48}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.3}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={28.76}\n        y={33.57}\n        width={44.25}\n        height={4.67}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.21}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={28.76}\n        y={41.32}\n        width={36.21}\n        height={4.67}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.3}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-layout-compact.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconLayoutCompact(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-layout-compact'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <rect\n        x={5.84}\n        y={5.2}\n        width={4}\n        height={40}\n        rx={2}\n        ry={2}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <g stroke='#fff' strokeLinecap='round' strokeMiterlimit={10}>\n        <path\n          fill='none'\n          opacity={0.66}\n          strokeWidth='2px'\n          d='M7.26 11.56L8.37 11.56'\n        />\n        <path\n          fill='none'\n          opacity={0.51}\n          strokeWidth='2px'\n          d='M7.26 14.49L8.37 14.49'\n        />\n        <path\n          fill='none'\n          opacity={0.52}\n          strokeWidth='2px'\n          d='M7.26 17.39L8.37 17.39'\n        />\n        <circle cx={7.81} cy={7.25} r={1.16} fill='#fff' opacity={0.8} />\n      </g>\n      <path\n        fill='none'\n        opacity={0.75}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='3px'\n        d='M15.81 14.49L22.89 14.49'\n      />\n      <rect\n        x={14.93}\n        y={18.39}\n        width={22.19}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.5}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={14.93}\n        y={5.89}\n        width={59.16}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.9}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={14.93}\n        y={24.22}\n        width={32.68}\n        height={19.95}\n        rx={2.11}\n        ry={2.11}\n        opacity={0.4}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <rect\n          x={59.05}\n          y={38.15}\n          width={2.01}\n          height={3.42}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.32}\n        />\n        <rect\n          x={54.78}\n          y={34.99}\n          width={2.01}\n          height={6.58}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.44}\n        />\n        <rect\n          x={63.17}\n          y={32.86}\n          width={2.01}\n          height={8.7}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n        <rect\n          x={67.54}\n          y={29.17}\n          width={2.01}\n          height={12.4}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.66}\n        />\n      </g>\n      <g opacity={0.5}>\n        <circle cx={62.16} cy={18.63} r={7.5} />\n        <path d='M62.16 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />\n      </g>\n      <g opacity={0.74}>\n        <path d='M63.04 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />\n        <path d='M66.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-layout-default.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconLayoutDefault(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='con-layout-default'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <path\n        d='M39.22 15.99h-8.16c-.79 0-1.43-.67-1.43-1.5s.64-1.5 1.43-1.5h8.16c.79 0 1.43.67 1.43 1.5s-.64 1.5-1.43 1.5z'\n        opacity={0.75}\n      />\n      <rect\n        x={29.63}\n        y={18.39}\n        width={16.72}\n        height={2.73}\n        rx={1.36}\n        ry={1.36}\n        opacity={0.5}\n      />\n      <path\n        d='M75.1 6.68v1.45c0 .63-.49 1.14-1.09 1.14H30.72c-.6 0-1.09-.51-1.09-1.14V6.68c0-.62.49-1.14 1.09-1.14h43.29c.6 0 1.09.52 1.09 1.14z'\n        opacity={0.9}\n      />\n      <rect\n        x={29.63}\n        y={24.22}\n        width={21.8}\n        height={19.95}\n        rx={2.11}\n        ry={2.11}\n        opacity={0.4}\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <rect\n          x={61.06}\n          y={38.15}\n          width={2.01}\n          height={3.42}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.32}\n        />\n        <rect\n          x={56.78}\n          y={34.99}\n          width={2.01}\n          height={6.58}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.44}\n        />\n        <rect\n          x={65.17}\n          y={32.86}\n          width={2.01}\n          height={8.7}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n        <rect\n          x={69.55}\n          y={29.17}\n          width={2.01}\n          height={12.4}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.66}\n        />\n      </g>\n      <g opacity={0.5}>\n        <circle cx={63.17} cy={18.63} r={7.5} />\n        <path d='M63.17 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />\n      </g>\n      <g opacity={0.74}>\n        <path d='M64.05 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />\n        <path d='M67.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />\n      </g>\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <rect\n          x={5.84}\n          y={5.02}\n          width={19.14}\n          height={40}\n          rx={2}\n          ry={2}\n          opacity={0.8}\n        />\n        <g stroke='#fff'>\n          <path\n            fill='none'\n            opacity={0.72}\n            strokeWidth='2px'\n            d='M9.02 17.39L21.25 17.39'\n          />\n          <path\n            fill='none'\n            opacity={0.48}\n            strokeWidth='2px'\n            d='M9.02 24.6L19.54 24.6'\n          />\n          <path\n            fill='none'\n            opacity={0.55}\n            strokeWidth='2px'\n            d='M9.02 20.88L18.4 20.88'\n          />\n          <circle cx={10.98} cy={9.91} r={2.54} fill='#fff' opacity={0.8} />\n          <path\n            fill='none'\n            opacity={0.8}\n            strokeWidth='2px'\n            d='M15.53 8.65L21.25 8.65'\n          />\n          <path fill='none' opacity={0.6} d='M15.32 11.3L20.38 11.3' />\n        </g>\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-layout-full.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconLayoutFull(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-layout-full'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <path\n        fill='none'\n        opacity={0.75}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='3px'\n        d='M6.85 14.49L15.02 14.49'\n      />\n      <rect\n        x={5.84}\n        y={18.39}\n        width={25.6}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.5}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={5.84}\n        y={5.89}\n        width={68.26}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.9}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={5.84}\n        y={24.22}\n        width={37.71}\n        height={19.95}\n        rx={2.11}\n        ry={2.11}\n        opacity={0.4}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <rect\n          x={59.05}\n          y={38.15}\n          width={2.01}\n          height={3.42}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.32}\n        />\n        <rect\n          x={54.78}\n          y={34.99}\n          width={2.01}\n          height={6.58}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.44}\n        />\n        <rect\n          x={63.17}\n          y={32.86}\n          width={2.01}\n          height={8.7}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n        <rect\n          x={67.54}\n          y={29.17}\n          width={2.01}\n          height={12.4}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.66}\n        />\n      </g>\n      <g opacity={0.5}>\n        <circle cx={62.16} cy={18.63} r={7.5} />\n        <path d='M62.16 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />\n      </g>\n      <g opacity={0.74}>\n        <path d='M63.04 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />\n        <path d='M66.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-sidebar-floating.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconSidebarFloating(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-sidebar-floating'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <rect\n        x={5.89}\n        y={5.15}\n        width={19.74}\n        height={40}\n        rx={2}\n        ry={2}\n        opacity={0.8}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <g stroke='#fff' strokeLinecap='round' strokeMiterlimit={10}>\n        <path\n          fill='none'\n          opacity={0.72}\n          strokeWidth='2px'\n          d='M9.81 18.36L22.04 18.36'\n        />\n        <path\n          fill='none'\n          opacity={0.48}\n          strokeWidth='2px'\n          d='M9.81 25.57L20.33 25.57'\n        />\n        <path\n          fill='none'\n          opacity={0.55}\n          strokeWidth='2px'\n          d='M9.81 21.85L19.18 21.85'\n        />\n        <circle cx={11.76} cy={10.88} r={2.54} fill='#fff' opacity={0.8} />\n        <path\n          fill='none'\n          opacity={0.8}\n          strokeWidth='2px'\n          d='M16.31 9.62L22.04 9.62'\n        />\n        <path fill='none' opacity={0.6} d='M16.1 12.27L21.16 12.27' />\n      </g>\n      <path\n        fill='none'\n        opacity={0.62}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='3px'\n        d='M30.59 9.62L35.85 9.62'\n      />\n      <rect\n        x={29.94}\n        y={13.42}\n        width={26.03}\n        height={2.73}\n        rx={0.64}\n        ry={0.64}\n        opacity={0.44}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <rect\n        x={29.94}\n        y={19.28}\n        width={43.11}\n        height={25.87}\n        rx={2}\n        ry={2}\n        opacity={0.3}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-sidebar-inset.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconSidebarInset(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-sidebar-inset'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <rect\n        x={23.39}\n        y={5.57}\n        width={50.22}\n        height={40}\n        rx={2}\n        ry={2}\n        opacity={0.2}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <path\n        fill='none'\n        opacity={0.72}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.08 17.05L17.31 17.05'\n      />\n      <path\n        fill='none'\n        opacity={0.48}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.08 24.25L15.6 24.25'\n      />\n      <path\n        fill='none'\n        opacity={0.55}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.08 20.54L14.46 20.54'\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <circle cx={7.04} cy={9.57} r={2.54} opacity={0.8} />\n        <path\n          fill='none'\n          opacity={0.8}\n          strokeWidth='2px'\n          d='M11.59 8.3L17.31 8.3'\n        />\n        <path fill='none' opacity={0.6} d='M11.38 10.95L16.44 10.95' />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-sidebar-sidebar.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconSidebarSidebar(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-sidebar-sidebar'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <path\n        d='M23.42.51h51.99c2.21 0 4 1.79 4 4v42.18c0 2.21-1.79 4-4 4H23.42s-.04-.02-.04-.04V.55s.02-.04.04-.04z'\n        opacity={0.2}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <path\n        fill='none'\n        opacity={0.72}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 14.88L17.78 14.88'\n      />\n      <path\n        fill='none'\n        opacity={0.48}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 22.09L16.08 22.09'\n      />\n      <path\n        fill='none'\n        opacity={0.55}\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n        strokeWidth='2px'\n        d='M5.56 18.38L14.93 18.38'\n      />\n      <g strokeLinecap='round' strokeMiterlimit={10}>\n        <circle cx={7.51} cy={7.4} r={2.54} opacity={0.8} />\n        <path\n          fill='none'\n          opacity={0.8}\n          strokeWidth='2px'\n          d='M12.06 6.14L17.78 6.14'\n        />\n        <path fill='none' opacity={0.6} d='M11.85 8.79L16.91 8.79' />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-theme-dark.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconThemeDark(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-theme-dark'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <g fill='#1d2b3f'>\n        <rect x={0.53} y={0.5} width={78.83} height={50.14} rx={3.5} ry={3.5} />\n        <path d='M75.86 1c1.65 0 3 1.35 3 3v43.14c0 1.65-1.35 3-3 3H4.03c-1.65 0-3-1.35-3-3V4c0-1.65 1.35-3 3-3h71.83m0-1H4.03c-2.21 0-4 1.79-4 4v43.14c0 2.21 1.79 4 4 4h71.83c2.21 0 4-1.79 4-4V4c0-2.21-1.79-4-4-4z' />\n      </g>\n      <path\n        d='M22.88 0h52.97c2.21 0 4 1.79 4 4v43.14c0 2.21-1.79 4-4 4H22.88V0z'\n        fill='#0d1628'\n      />\n      <circle cx={6.7} cy={7.04} r={3.54} fill='#426187' />\n      <path\n        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1zM18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05zM15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91zM16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'\n        fill='#426187'\n      />\n      <g fill='#2a62bc'>\n        <rect\n          x={33.36}\n          y={19.73}\n          width={2.75}\n          height={3.42}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.32}\n        />\n        <rect\n          x={29.64}\n          y={16.57}\n          width={2.75}\n          height={6.58}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.44}\n        />\n        <rect\n          x={37.16}\n          y={14.44}\n          width={2.75}\n          height={8.7}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n        <rect\n          x={41.19}\n          y={10.75}\n          width={2.75}\n          height={12.4}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n      </g>\n      <circle cx={62.74} cy={16.32} r={8} fill='#2f5491' opacity={0.5} />\n      <path\n        d='M62.74 16.32l4.1-6.87c1.19.71 2.18 1.72 2.86 2.92s1.04 2.57 1.04 3.95h-8z'\n        fill='#2f5491'\n        opacity={0.74}\n      />\n      <rect\n        x={29.64}\n        y={27.75}\n        width={41.62}\n        height={18.62}\n        rx={1.69}\n        ry={1.69}\n        fill='#17273f'\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-theme-light.tsx",
    "content": "import { type SVGProps } from 'react'\n\nexport function IconThemeLight(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-theme-light'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      {...props}\n    >\n      <g fill='#d9d9d9'>\n        <rect x={0.53} y={0.5} width={78.83} height={50.14} rx={3.5} ry={3.5} />\n        <path d='M75.86 1c1.65 0 3 1.35 3 3v43.14c0 1.65-1.35 3-3 3H4.03c-1.65 0-3-1.35-3-3V4c0-1.65 1.35-3 3-3h71.83m0-1H4.03c-2.21 0-4 1.79-4 4v43.14c0 2.21 1.79 4 4 4h71.83c2.21 0 4-1.79 4-4V4c0-2.21-1.79-4-4-4z' />\n      </g>\n      <path\n        d='M22.88 0h52.97c2.21 0 4 1.79 4 4v43.14c0 2.21-1.79 4-4 4H22.88V0z'\n        fill='#ecedef'\n      />\n      <circle cx={6.7} cy={7.04} r={3.54} fill='#fff' />\n      <path\n        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1zM18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05zM15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91zM16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'\n        fill='#fff'\n      />\n      <g fill='#c0c4c4'>\n        <rect\n          x={33.36}\n          y={19.73}\n          width={2.75}\n          height={3.42}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.32}\n        />\n        <rect\n          x={29.64}\n          y={16.57}\n          width={2.75}\n          height={6.58}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.44}\n        />\n        <rect\n          x={37.16}\n          y={14.44}\n          width={2.75}\n          height={8.7}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n        <rect\n          x={41.19}\n          y={10.75}\n          width={2.75}\n          height={12.4}\n          rx={0.33}\n          ry={0.33}\n          opacity={0.53}\n        />\n      </g>\n      <circle cx={62.74} cy={16.32} r={8} fill='#fff' />\n      <g fill='#d9d9d9'>\n        <path d='M63.62 15.82L67 10.15c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />\n        <path d='M67.14 10.88a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95s-1.67-2.21-2.86-2.92z' />\n      </g>\n      <rect\n        x={29.64}\n        y={27.75}\n        width={41.62}\n        height={18.62}\n        rx={1.69}\n        ry={1.69}\n        fill='#fff'\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/custom/icon-theme-system.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconThemeSystem({\n  className,\n  ...props\n}: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      data-name='icon-theme-system'\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 79.86 51.14'\n      className={cn(\n        'overflow-hidden rounded-[6px]',\n        'fill-primary stroke-primary group-data-[state=unchecked]:fill-muted-foreground group-data-[state=unchecked]:stroke-muted-foreground',\n        className\n      )}\n      {...props}\n    >\n      <path opacity={0.2} d='M0 0.03H22.88V51.17H0z' />\n      <circle\n        cx={6.7}\n        cy={7.04}\n        r={3.54}\n        fill='#fff'\n        opacity={0.8}\n        stroke='#fff'\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n      <path\n        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1z'\n        fill='#fff'\n        stroke='none'\n        opacity={0.75}\n      />\n      <path\n        d='M18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05z'\n        fill='#fff'\n        stroke='none'\n        opacity={0.72}\n      />\n      <path\n        d='M15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91z'\n        fill='#fff'\n        stroke='none'\n        opacity={0.55}\n      />\n      <path\n        d='M16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'\n        fill='#fff'\n        stroke='none'\n        opacity={0.67}\n      />\n      <rect\n        x={33.36}\n        y={19.73}\n        width={2.75}\n        height={3.42}\n        rx={0.33}\n        ry={0.33}\n        opacity={0.31}\n        stroke='none'\n      />\n      <rect\n        x={29.64}\n        y={16.57}\n        width={2.75}\n        height={6.58}\n        rx={0.33}\n        ry={0.33}\n        opacity={0.4}\n        stroke='none'\n      />\n      <rect\n        x={37.16}\n        y={14.44}\n        width={2.75}\n        height={8.7}\n        rx={0.33}\n        ry={0.33}\n        opacity={0.26}\n        stroke='none'\n      />\n      <rect\n        x={41.19}\n        y={10.75}\n        width={2.75}\n        height={12.4}\n        rx={0.33}\n        ry={0.33}\n        opacity={0.37}\n        stroke='none'\n      />\n      <g>\n        <circle cx={62.74} cy={16.32} r={8} opacity={0.25} />\n        <path\n          d='M62.74 16.32l4.1-6.87c1.19.71 2.18 1.72 2.86 2.92s1.04 2.57 1.04 3.95h-8z'\n          opacity={0.45}\n        />\n      </g>\n      <rect\n        x={29.64}\n        y={27.75}\n        width={41.62}\n        height={18.62}\n        rx={1.69}\n        ry={1.69}\n        opacity={0.3}\n        stroke='none'\n        strokeLinecap='round'\n        strokeMiterlimit={10}\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/assets/logo.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function Logo({ className, ...props }: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      id='shadcn-admin-logo'\n      viewBox='0 0 24 24'\n      xmlns='http://www.w3.org/2000/svg'\n      height='24'\n      width='24'\n      fill='none'\n      stroke='currentColor'\n      strokeWidth='2'\n      strokeLinecap='round'\n      strokeLinejoin='round'\n      className={cn('size-6', className)}\n      {...props}\n    >\n      <title>Shadcn-Admin</title>\n      <path d='M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3' />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "src/components/coming-soon.tsx",
    "content": "import { Telescope } from 'lucide-react'\n\nexport function ComingSoon() {\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <Telescope size={72} />\n        <h1 className='text-4xl leading-tight font-bold'>Coming Soon!</h1>\n        <p className='text-center text-muted-foreground'>\n          This page has not been created yet. <br />\n          Stay tuned though!\n        </p>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/command-menu.tsx",
    "content": "import React from 'react'\nimport { useNavigate } from '@tanstack/react-router'\nimport { ArrowRight, ChevronRight, Laptop, Moon, Sun } from 'lucide-react'\nimport { useSearch } from '@/context/search-provider'\nimport { useTheme } from '@/context/theme-provider'\nimport {\n  CommandDialog,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n  CommandSeparator,\n} from '@/components/ui/command'\nimport { sidebarData } from './layout/data/sidebar-data'\nimport { ScrollArea } from './ui/scroll-area'\n\nexport function CommandMenu() {\n  const navigate = useNavigate()\n  const { setTheme } = useTheme()\n  const { open, setOpen } = useSearch()\n\n  const runCommand = React.useCallback(\n    (command: () => unknown) => {\n      setOpen(false)\n      command()\n    },\n    [setOpen]\n  )\n\n  return (\n    <CommandDialog modal open={open} onOpenChange={setOpen}>\n      <CommandInput placeholder='Type a command or search...' />\n      <CommandList>\n        <ScrollArea type='hover' className='h-72 pe-1'>\n          <CommandEmpty>No results found.</CommandEmpty>\n          {sidebarData.navGroups.map((group) => (\n            <CommandGroup key={group.title} heading={group.title}>\n              {group.items.map((navItem, i) => {\n                if (navItem.url)\n                  return (\n                    <CommandItem\n                      key={`${navItem.url}-${i}`}\n                      value={navItem.title}\n                      onSelect={() => {\n                        runCommand(() => navigate({ to: navItem.url }))\n                      }}\n                    >\n                      <div className='flex size-4 items-center justify-center'>\n                        <ArrowRight className='size-2 text-muted-foreground/80' />\n                      </div>\n                      {navItem.title}\n                    </CommandItem>\n                  )\n\n                return navItem.items?.map((subItem, i) => (\n                  <CommandItem\n                    key={`${navItem.title}-${subItem.url}-${i}`}\n                    value={`${navItem.title}-${subItem.url}`}\n                    onSelect={() => {\n                      runCommand(() => navigate({ to: subItem.url }))\n                    }}\n                  >\n                    <div className='flex size-4 items-center justify-center'>\n                      <ArrowRight className='size-2 text-muted-foreground/80' />\n                    </div>\n                    {navItem.title} <ChevronRight /> {subItem.title}\n                  </CommandItem>\n                ))\n              })}\n            </CommandGroup>\n          ))}\n          <CommandSeparator />\n          <CommandGroup heading='Theme'>\n            <CommandItem onSelect={() => runCommand(() => setTheme('light'))}>\n              <Sun /> <span>Light</span>\n            </CommandItem>\n            <CommandItem onSelect={() => runCommand(() => setTheme('dark'))}>\n              <Moon className='scale-90' />\n              <span>Dark</span>\n            </CommandItem>\n            <CommandItem onSelect={() => runCommand(() => setTheme('system'))}>\n              <Laptop />\n              <span>System</span>\n            </CommandItem>\n          </CommandGroup>\n        </ScrollArea>\n      </CommandList>\n    </CommandDialog>\n  )\n}\n"
  },
  {
    "path": "src/components/config-drawer.tsx",
    "content": "import { type SVGProps } from 'react'\nimport { Root as Radio, Item } from '@radix-ui/react-radio-group'\nimport { CircleCheck, RotateCcw, Settings } from 'lucide-react'\nimport { IconDir } from '@/assets/custom/icon-dir'\nimport { IconLayoutCompact } from '@/assets/custom/icon-layout-compact'\nimport { IconLayoutDefault } from '@/assets/custom/icon-layout-default'\nimport { IconLayoutFull } from '@/assets/custom/icon-layout-full'\nimport { IconSidebarFloating } from '@/assets/custom/icon-sidebar-floating'\nimport { IconSidebarInset } from '@/assets/custom/icon-sidebar-inset'\nimport { IconSidebarSidebar } from '@/assets/custom/icon-sidebar-sidebar'\nimport { IconThemeDark } from '@/assets/custom/icon-theme-dark'\nimport { IconThemeLight } from '@/assets/custom/icon-theme-light'\nimport { IconThemeSystem } from '@/assets/custom/icon-theme-system'\nimport { cn } from '@/lib/utils'\nimport { useDirection } from '@/context/direction-provider'\nimport { type Collapsible, useLayout } from '@/context/layout-provider'\nimport { useTheme } from '@/context/theme-provider'\nimport { Button } from '@/components/ui/button'\nimport {\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n  SheetTrigger,\n} from '@/components/ui/sheet'\nimport { useSidebar } from './ui/sidebar'\n\nexport function ConfigDrawer() {\n  const { setOpen } = useSidebar()\n  const { resetDir } = useDirection()\n  const { resetTheme } = useTheme()\n  const { resetLayout } = useLayout()\n\n  const handleReset = () => {\n    setOpen(true)\n    resetDir()\n    resetTheme()\n    resetLayout()\n  }\n\n  return (\n    <Sheet>\n      <SheetTrigger asChild>\n        <Button\n          size='icon'\n          variant='ghost'\n          aria-label='Open theme settings'\n          aria-describedby='config-drawer-description'\n          className='rounded-full'\n        >\n          <Settings aria-hidden='true' />\n        </Button>\n      </SheetTrigger>\n      <SheetContent className='flex flex-col'>\n        <SheetHeader className='pb-0 text-start'>\n          <SheetTitle>Theme Settings</SheetTitle>\n          <SheetDescription id='config-drawer-description'>\n            Adjust the appearance and layout to suit your preferences.\n          </SheetDescription>\n        </SheetHeader>\n        <div className='space-y-6 overflow-y-auto px-4'>\n          <ThemeConfig />\n          <SidebarConfig />\n          <LayoutConfig />\n          <DirConfig />\n        </div>\n        <SheetFooter className='gap-2'>\n          <Button\n            variant='destructive'\n            onClick={handleReset}\n            aria-label='Reset all settings to default values'\n          >\n            Reset\n          </Button>\n        </SheetFooter>\n      </SheetContent>\n    </Sheet>\n  )\n}\n\nfunction SectionTitle({\n  title,\n  showReset = false,\n  onReset,\n  className,\n}: {\n  title: string\n  showReset?: boolean\n  onReset?: () => void\n  className?: string\n}) {\n  return (\n    <div\n      className={cn(\n        'mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground',\n        className\n      )}\n    >\n      {title}\n      {showReset && onReset && (\n        <Button\n          size='icon'\n          variant='secondary'\n          className='size-4 rounded-full'\n          onClick={onReset}\n        >\n          <RotateCcw className='size-3' />\n        </Button>\n      )}\n    </div>\n  )\n}\n\nfunction RadioGroupItem({\n  item,\n  isTheme = false,\n}: {\n  item: {\n    value: string\n    label: string\n    icon: (props: SVGProps<SVGSVGElement>) => React.ReactElement\n  }\n  isTheme?: boolean\n}) {\n  return (\n    <Item\n      value={item.value}\n      className={cn('group outline-none', 'transition duration-200 ease-in')}\n      aria-label={`Select ${item.label.toLowerCase()}`}\n      aria-describedby={`${item.value}-description`}\n    >\n      <div\n        className={cn(\n          'relative rounded-[6px] ring-[1px] ring-border',\n          'group-data-[state=checked]:shadow-2xl group-data-[state=checked]:ring-primary',\n          'group-focus-visible:ring-2'\n        )}\n        role='img'\n        aria-hidden='false'\n        aria-label={`${item.label} option preview`}\n      >\n        <CircleCheck\n          className={cn(\n            'size-6 fill-primary stroke-white',\n            'group-data-[state=unchecked]:hidden',\n            'absolute top-0 right-0 translate-x-1/2 -translate-y-1/2'\n          )}\n          aria-hidden='true'\n        />\n        <item.icon\n          className={cn(\n            !isTheme &&\n              'fill-primary stroke-primary group-data-[state=unchecked]:fill-muted-foreground group-data-[state=unchecked]:stroke-muted-foreground'\n          )}\n          aria-hidden='true'\n        />\n      </div>\n      <div\n        className='mt-1 text-xs'\n        id={`${item.value}-description`}\n        aria-live='polite'\n      >\n        {item.label}\n      </div>\n    </Item>\n  )\n}\n\nfunction ThemeConfig() {\n  const { defaultTheme, theme, setTheme } = useTheme()\n  return (\n    <div>\n      <SectionTitle\n        title='Theme'\n        showReset={theme !== defaultTheme}\n        onReset={() => setTheme(defaultTheme)}\n      />\n      <Radio\n        value={theme}\n        onValueChange={setTheme}\n        className='grid w-full max-w-md grid-cols-3 gap-4'\n        aria-label='Select theme preference'\n        aria-describedby='theme-description'\n      >\n        {[\n          {\n            value: 'system',\n            label: 'System',\n            icon: IconThemeSystem,\n          },\n          {\n            value: 'light',\n            label: 'Light',\n            icon: IconThemeLight,\n          },\n          {\n            value: 'dark',\n            label: 'Dark',\n            icon: IconThemeDark,\n          },\n        ].map((item) => (\n          <RadioGroupItem key={item.value} item={item} isTheme />\n        ))}\n      </Radio>\n      <div id='theme-description' className='sr-only'>\n        Choose between system preference, light mode, or dark mode\n      </div>\n    </div>\n  )\n}\n\nfunction SidebarConfig() {\n  const { defaultVariant, variant, setVariant } = useLayout()\n  return (\n    <div className='max-md:hidden'>\n      <SectionTitle\n        title='Sidebar'\n        showReset={defaultVariant !== variant}\n        onReset={() => setVariant(defaultVariant)}\n      />\n      <Radio\n        value={variant}\n        onValueChange={setVariant}\n        className='grid w-full max-w-md grid-cols-3 gap-4'\n        aria-label='Select sidebar style'\n        aria-describedby='sidebar-description'\n      >\n        {[\n          {\n            value: 'inset',\n            label: 'Inset',\n            icon: IconSidebarInset,\n          },\n          {\n            value: 'floating',\n            label: 'Floating',\n            icon: IconSidebarFloating,\n          },\n          {\n            value: 'sidebar',\n            label: 'Sidebar',\n            icon: IconSidebarSidebar,\n          },\n        ].map((item) => (\n          <RadioGroupItem key={item.value} item={item} />\n        ))}\n      </Radio>\n      <div id='sidebar-description' className='sr-only'>\n        Choose between inset, floating, or standard sidebar layout\n      </div>\n    </div>\n  )\n}\n\nfunction LayoutConfig() {\n  const { open, setOpen } = useSidebar()\n  const { defaultCollapsible, collapsible, setCollapsible } = useLayout()\n\n  const radioState = open ? 'default' : collapsible\n\n  return (\n    <div className='max-md:hidden'>\n      <SectionTitle\n        title='Layout'\n        showReset={radioState !== 'default'}\n        onReset={() => {\n          setOpen(true)\n          setCollapsible(defaultCollapsible)\n        }}\n      />\n      <Radio\n        value={radioState}\n        onValueChange={(v) => {\n          if (v === 'default') {\n            setOpen(true)\n            return\n          }\n          setOpen(false)\n          setCollapsible(v as Collapsible)\n        }}\n        className='grid w-full max-w-md grid-cols-3 gap-4'\n        aria-label='Select layout style'\n        aria-describedby='layout-description'\n      >\n        {[\n          {\n            value: 'default',\n            label: 'Default',\n            icon: IconLayoutDefault,\n          },\n          {\n            value: 'icon',\n            label: 'Compact',\n            icon: IconLayoutCompact,\n          },\n          {\n            value: 'offcanvas',\n            label: 'Full layout',\n            icon: IconLayoutFull,\n          },\n        ].map((item) => (\n          <RadioGroupItem key={item.value} item={item} />\n        ))}\n      </Radio>\n      <div id='layout-description' className='sr-only'>\n        Choose between default expanded, compact icon-only, or full layout mode\n      </div>\n    </div>\n  )\n}\n\nfunction DirConfig() {\n  const { defaultDir, dir, setDir } = useDirection()\n  return (\n    <div>\n      <SectionTitle\n        title='Direction'\n        showReset={defaultDir !== dir}\n        onReset={() => setDir(defaultDir)}\n      />\n      <Radio\n        value={dir}\n        onValueChange={setDir}\n        className='grid w-full max-w-md grid-cols-3 gap-4'\n        aria-label='Select site direction'\n        aria-describedby='direction-description'\n      >\n        {[\n          {\n            value: 'ltr',\n            label: 'Left to Right',\n            icon: (props: SVGProps<SVGSVGElement>) => (\n              <IconDir dir='ltr' {...props} />\n            ),\n          },\n          {\n            value: 'rtl',\n            label: 'Right to Left',\n            icon: (props: SVGProps<SVGSVGElement>) => (\n              <IconDir dir='rtl' {...props} />\n            ),\n          },\n        ].map((item) => (\n          <RadioGroupItem key={item.value} item={item} />\n        ))}\n      </Radio>\n      <div id='direction-description' className='sr-only'>\n        Choose between left-to-right or right-to-left site direction\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/confirm-dialog.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n} from '@/components/ui/alert-dialog'\nimport { Button } from '@/components/ui/button'\n\ntype ConfirmDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  title: React.ReactNode\n  disabled?: boolean\n  desc: React.JSX.Element | string\n  cancelBtnText?: string\n  confirmText?: React.ReactNode\n  destructive?: boolean\n  handleConfirm: () => void\n  isLoading?: boolean\n  className?: string\n  children?: React.ReactNode\n}\n\nexport function ConfirmDialog(props: ConfirmDialogProps) {\n  const {\n    title,\n    desc,\n    children,\n    className,\n    confirmText,\n    cancelBtnText,\n    destructive,\n    isLoading,\n    disabled = false,\n    handleConfirm,\n    ...actions\n  } = props\n  return (\n    <AlertDialog {...actions}>\n      <AlertDialogContent className={cn(className && className)}>\n        <AlertDialogHeader className='text-start'>\n          <AlertDialogTitle>{title}</AlertDialogTitle>\n          <AlertDialogDescription asChild>\n            <div>{desc}</div>\n          </AlertDialogDescription>\n        </AlertDialogHeader>\n        {children}\n        <AlertDialogFooter>\n          <AlertDialogCancel disabled={isLoading}>\n            {cancelBtnText ?? 'Cancel'}\n          </AlertDialogCancel>\n          <Button\n            variant={destructive ? 'destructive' : 'default'}\n            onClick={handleConfirm}\n            disabled={disabled || isLoading}\n          >\n            {confirmText ?? 'Continue'}\n          </Button>\n        </AlertDialogFooter>\n      </AlertDialogContent>\n    </AlertDialog>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/bulk-actions.tsx",
    "content": "import { useState, useEffect, useRef } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Separator } from '@/components/ui/separator'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\n\ntype DataTableBulkActionsProps<TData> = {\n  table: Table<TData>\n  entityName: string\n  children: React.ReactNode\n}\n\n/**\n * A modular toolbar for displaying bulk actions when table rows are selected.\n *\n * @template TData The type of data in the table.\n * @param {object} props The component props.\n * @param {Table<TData>} props.table The react-table instance.\n * @param {string} props.entityName The name of the entity being acted upon (e.g., \"task\", \"user\").\n * @param {React.ReactNode} props.children The action buttons to be rendered inside the toolbar.\n * @returns {React.ReactNode | null} The rendered component or null if no rows are selected.\n */\nexport function DataTableBulkActions<TData>({\n  table,\n  entityName,\n  children,\n}: DataTableBulkActionsProps<TData>): React.ReactNode | null {\n  const selectedRows = table.getFilteredSelectedRowModel().rows\n  const selectedCount = selectedRows.length\n  const toolbarRef = useRef<HTMLDivElement>(null)\n  const [announcement, setAnnouncement] = useState('')\n\n  // Announce selection changes to screen readers\n  useEffect(() => {\n    if (selectedCount > 0) {\n      const message = `${selectedCount} ${entityName}${selectedCount > 1 ? 's' : ''} selected. Bulk actions toolbar is available.`\n\n      // Use queueMicrotask to defer state update and avoid cascading renders\n      queueMicrotask(() => {\n        setAnnouncement(message)\n      })\n\n      // Clear announcement after a delay\n      const timer = setTimeout(() => setAnnouncement(''), 3000)\n      return () => clearTimeout(timer)\n    }\n  }, [selectedCount, entityName])\n\n  const handleClearSelection = () => {\n    table.resetRowSelection()\n  }\n\n  const handleKeyDown = (event: React.KeyboardEvent) => {\n    const buttons = toolbarRef.current?.querySelectorAll('button')\n    if (!buttons) return\n\n    const currentIndex = Array.from(buttons).findIndex(\n      (button) => button === document.activeElement\n    )\n\n    switch (event.key) {\n      case 'ArrowRight': {\n        event.preventDefault()\n        const nextIndex = (currentIndex + 1) % buttons.length\n        buttons[nextIndex]?.focus()\n        break\n      }\n      case 'ArrowLeft': {\n        event.preventDefault()\n        const prevIndex =\n          currentIndex === 0 ? buttons.length - 1 : currentIndex - 1\n        buttons[prevIndex]?.focus()\n        break\n      }\n      case 'Home':\n        event.preventDefault()\n        buttons[0]?.focus()\n        break\n      case 'End':\n        event.preventDefault()\n        buttons[buttons.length - 1]?.focus()\n        break\n      case 'Escape': {\n        // Check if the Escape key came from a dropdown trigger or content\n        // We can't check dropdown state because Radix UI closes it before our handler runs\n        const target = event.target as HTMLElement\n        const activeElement = document.activeElement as HTMLElement\n\n        // Check if the event target or currently focused element is a dropdown trigger\n        const isFromDropdownTrigger =\n          target?.getAttribute('data-slot') === 'dropdown-menu-trigger' ||\n          activeElement?.getAttribute('data-slot') ===\n            'dropdown-menu-trigger' ||\n          target?.closest('[data-slot=\"dropdown-menu-trigger\"]') ||\n          activeElement?.closest('[data-slot=\"dropdown-menu-trigger\"]')\n\n        // Check if the focused element is inside dropdown content (which is portaled)\n        const isFromDropdownContent =\n          activeElement?.closest('[data-slot=\"dropdown-menu-content\"]') ||\n          target?.closest('[data-slot=\"dropdown-menu-content\"]')\n\n        if (isFromDropdownTrigger || isFromDropdownContent) {\n          // Escape was meant for the dropdown - don't clear selection\n          return\n        }\n\n        // Escape was meant for the toolbar - clear selection\n        event.preventDefault()\n        handleClearSelection()\n        break\n      }\n    }\n  }\n\n  if (selectedCount === 0) {\n    return null\n  }\n\n  return (\n    <>\n      {/* Live region for screen reader announcements */}\n      <div\n        aria-live='polite'\n        aria-atomic='true'\n        className='sr-only'\n        role='status'\n      >\n        {announcement}\n      </div>\n\n      <div\n        ref={toolbarRef}\n        role='toolbar'\n        aria-label={`Bulk actions for ${selectedCount} selected ${entityName}${selectedCount > 1 ? 's' : ''}`}\n        aria-describedby='bulk-actions-description'\n        tabIndex={-1}\n        onKeyDown={handleKeyDown}\n        className={cn(\n          'fixed bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-xl',\n          'transition-all delay-100 duration-300 ease-out hover:scale-105',\n          'focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none'\n        )}\n      >\n        <div\n          className={cn(\n            'p-2 shadow-xl',\n            'rounded-xl border',\n            'bg-background/95 backdrop-blur-lg supports-backdrop-filter:bg-background/60',\n            'flex items-center gap-x-2'\n          )}\n        >\n          <Tooltip>\n            <TooltipTrigger asChild>\n              <Button\n                variant='outline'\n                size='icon'\n                onClick={handleClearSelection}\n                className='size-6 rounded-full'\n                aria-label='Clear selection'\n                title='Clear selection (Escape)'\n              >\n                <X />\n                <span className='sr-only'>Clear selection</span>\n              </Button>\n            </TooltipTrigger>\n            <TooltipContent>\n              <p>Clear selection (Escape)</p>\n            </TooltipContent>\n          </Tooltip>\n\n          <Separator\n            className='h-5'\n            orientation='vertical'\n            aria-hidden='true'\n          />\n\n          <div\n            className='flex items-center gap-x-1 text-sm'\n            id='bulk-actions-description'\n          >\n            <Badge\n              variant='default'\n              className='min-w-8 rounded-lg'\n              aria-label={`${selectedCount} selected`}\n            >\n              {selectedCount}\n            </Badge>{' '}\n            <span className='hidden sm:inline'>\n              {entityName}\n              {selectedCount > 1 ? 's' : ''}\n            </span>{' '}\n            selected\n          </div>\n\n          <Separator\n            className='h-5'\n            orientation='vertical'\n            aria-hidden='true'\n          />\n\n          {children}\n        </div>\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/column-header.tsx",
    "content": "import {\n  ArrowDownIcon,\n  ArrowUpIcon,\n  CaretSortIcon,\n  EyeNoneIcon,\n} from '@radix-ui/react-icons'\nimport { type Column } from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\n\ntype DataTableColumnHeaderProps<TData, TValue> =\n  React.HTMLAttributes<HTMLDivElement> & {\n    column: Column<TData, TValue>\n    title: string\n  }\n\nexport function DataTableColumnHeader<TData, TValue>({\n  column,\n  title,\n  className,\n}: DataTableColumnHeaderProps<TData, TValue>) {\n  if (!column.getCanSort()) {\n    return <div className={cn(className)}>{title}</div>\n  }\n\n  return (\n    <div className={cn('flex items-center space-x-2', className)}>\n      <DropdownMenu>\n        <DropdownMenuTrigger asChild>\n          <Button\n            variant='ghost'\n            size='sm'\n            className='h-8 data-[state=open]:bg-accent'\n          >\n            <span>{title}</span>\n            {column.getIsSorted() === 'desc' ? (\n              <ArrowDownIcon className='ms-2 h-4 w-4' />\n            ) : column.getIsSorted() === 'asc' ? (\n              <ArrowUpIcon className='ms-2 h-4 w-4' />\n            ) : (\n              <CaretSortIcon className='ms-2 h-4 w-4' />\n            )}\n          </Button>\n        </DropdownMenuTrigger>\n        <DropdownMenuContent align='start'>\n          <DropdownMenuItem onClick={() => column.toggleSorting(false)}>\n            <ArrowUpIcon className='size-3.5 text-muted-foreground/70' />\n            Asc\n          </DropdownMenuItem>\n          <DropdownMenuItem onClick={() => column.toggleSorting(true)}>\n            <ArrowDownIcon className='size-3.5 text-muted-foreground/70' />\n            Desc\n          </DropdownMenuItem>\n          {column.getCanHide() && (\n            <>\n              <DropdownMenuSeparator />\n              <DropdownMenuItem onClick={() => column.toggleVisibility(false)}>\n                <EyeNoneIcon className='size-3.5 text-muted-foreground/70' />\n                Hide\n              </DropdownMenuItem>\n            </>\n          )}\n        </DropdownMenuContent>\n      </DropdownMenu>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/faceted-filter.tsx",
    "content": "import * as React from 'react'\nimport { CheckIcon, PlusCircledIcon } from '@radix-ui/react-icons'\nimport { type Column } from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n  CommandSeparator,\n} from '@/components/ui/command'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\nimport { Separator } from '@/components/ui/separator'\n\ntype DataTableFacetedFilterProps<TData, TValue> = {\n  column?: Column<TData, TValue>\n  title?: string\n  options: {\n    label: string\n    value: string\n    icon?: React.ComponentType<{ className?: string }>\n  }[]\n}\n\nexport function DataTableFacetedFilter<TData, TValue>({\n  column,\n  title,\n  options,\n}: DataTableFacetedFilterProps<TData, TValue>) {\n  const facets = column?.getFacetedUniqueValues()\n  const selectedValues = new Set(column?.getFilterValue() as string[])\n\n  return (\n    <Popover>\n      <PopoverTrigger asChild>\n        <Button variant='outline' size='sm' className='h-8 border-dashed'>\n          <PlusCircledIcon className='size-4' />\n          {title}\n          {selectedValues?.size > 0 && (\n            <>\n              <Separator orientation='vertical' className='mx-2 h-4' />\n              <Badge\n                variant='secondary'\n                className='rounded-sm px-1 font-normal lg:hidden'\n              >\n                {selectedValues.size}\n              </Badge>\n              <div className='hidden space-x-1 lg:flex'>\n                {selectedValues.size > 2 ? (\n                  <Badge\n                    variant='secondary'\n                    className='rounded-sm px-1 font-normal'\n                  >\n                    {selectedValues.size} selected\n                  </Badge>\n                ) : (\n                  options\n                    .filter((option) => selectedValues.has(option.value))\n                    .map((option) => (\n                      <Badge\n                        variant='secondary'\n                        key={option.value}\n                        className='rounded-sm px-1 font-normal'\n                      >\n                        {option.label}\n                      </Badge>\n                    ))\n                )}\n              </div>\n            </>\n          )}\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent className='w-[200px] p-0' align='start'>\n        <Command>\n          <CommandInput placeholder={title} />\n          <CommandList>\n            <CommandEmpty>No results found.</CommandEmpty>\n            <CommandGroup>\n              {options.map((option) => {\n                const isSelected = selectedValues.has(option.value)\n                return (\n                  <CommandItem\n                    key={option.value}\n                    onSelect={() => {\n                      if (isSelected) {\n                        selectedValues.delete(option.value)\n                      } else {\n                        selectedValues.add(option.value)\n                      }\n                      const filterValues = Array.from(selectedValues)\n                      column?.setFilterValue(\n                        filterValues.length ? filterValues : undefined\n                      )\n                    }}\n                  >\n                    <div\n                      className={cn(\n                        'flex size-4 items-center justify-center rounded-sm border border-primary',\n                        isSelected\n                          ? 'bg-primary text-primary-foreground'\n                          : 'opacity-50 [&_svg]:invisible'\n                      )}\n                    >\n                      <CheckIcon className={cn('h-4 w-4 text-background')} />\n                    </div>\n                    {option.icon && (\n                      <option.icon className='size-4 text-muted-foreground' />\n                    )}\n                    <span>{option.label}</span>\n                    {facets?.get(option.value) && (\n                      <span className='ms-auto flex h-4 w-4 items-center justify-center font-mono text-xs'>\n                        {facets.get(option.value)}\n                      </span>\n                    )}\n                  </CommandItem>\n                )\n              })}\n            </CommandGroup>\n            {selectedValues.size > 0 && (\n              <>\n                <CommandSeparator />\n                <CommandGroup>\n                  <CommandItem\n                    onSelect={() => column?.setFilterValue(undefined)}\n                    className='justify-center text-center'\n                  >\n                    Clear filters\n                  </CommandItem>\n                </CommandGroup>\n              </>\n            )}\n          </CommandList>\n        </Command>\n      </PopoverContent>\n    </Popover>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/index.ts",
    "content": "export { DataTablePagination } from './pagination'\nexport { DataTableColumnHeader } from './column-header'\nexport { DataTableFacetedFilter } from './faceted-filter'\nexport { DataTableViewOptions } from './view-options'\nexport { DataTableToolbar } from './toolbar'\nexport { DataTableBulkActions } from './bulk-actions'\n"
  },
  {
    "path": "src/components/data-table/pagination.tsx",
    "content": "import {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  DoubleArrowLeftIcon,\n  DoubleArrowRightIcon,\n} from '@radix-ui/react-icons'\nimport { type Table } from '@tanstack/react-table'\nimport { cn, getPageNumbers } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\n\ntype DataTablePaginationProps<TData> = {\n  table: Table<TData>\n  className?: string\n}\n\nexport function DataTablePagination<TData>({\n  table,\n  className,\n}: DataTablePaginationProps<TData>) {\n  const currentPage = table.getState().pagination.pageIndex + 1\n  const totalPages = table.getPageCount()\n  const pageNumbers = getPageNumbers(currentPage, totalPages)\n\n  return (\n    <div\n      className={cn(\n        'flex items-center justify-between overflow-clip px-2',\n        '@max-2xl/content:flex-col-reverse @max-2xl/content:gap-4',\n        className\n      )}\n      style={{ overflowClipMargin: 1 }}\n    >\n      <div className='flex w-full items-center justify-between'>\n        <div className='flex w-[100px] items-center justify-center text-sm font-medium @2xl/content:hidden'>\n          Page {currentPage} of {totalPages}\n        </div>\n        <div className='flex items-center gap-2 @max-2xl/content:flex-row-reverse'>\n          <Select\n            value={`${table.getState().pagination.pageSize}`}\n            onValueChange={(value) => {\n              table.setPageSize(Number(value))\n            }}\n          >\n            <SelectTrigger className='h-8 w-[70px]'>\n              <SelectValue placeholder={table.getState().pagination.pageSize} />\n            </SelectTrigger>\n            <SelectContent side='top'>\n              {[10, 20, 30, 40, 50].map((pageSize) => (\n                <SelectItem key={pageSize} value={`${pageSize}`}>\n                  {pageSize}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n          <p className='hidden text-sm font-medium sm:block'>Rows per page</p>\n        </div>\n      </div>\n\n      <div className='flex items-center sm:space-x-6 lg:space-x-8'>\n        <div className='flex w-[100px] items-center justify-center text-sm font-medium @max-3xl/content:hidden'>\n          Page {currentPage} of {totalPages}\n        </div>\n        <div className='flex items-center space-x-2'>\n          <Button\n            variant='outline'\n            className='size-8 p-0 @max-md/content:hidden'\n            onClick={() => table.setPageIndex(0)}\n            disabled={!table.getCanPreviousPage()}\n          >\n            <span className='sr-only'>Go to first page</span>\n            <DoubleArrowLeftIcon className='h-4 w-4' />\n          </Button>\n          <Button\n            variant='outline'\n            className='size-8 p-0'\n            onClick={() => table.previousPage()}\n            disabled={!table.getCanPreviousPage()}\n          >\n            <span className='sr-only'>Go to previous page</span>\n            <ChevronLeftIcon className='h-4 w-4' />\n          </Button>\n\n          {/* Page number buttons */}\n          {pageNumbers.map((pageNumber, index) => (\n            <div key={`${pageNumber}-${index}`} className='flex items-center'>\n              {pageNumber === '...' ? (\n                <span className='px-1 text-sm text-muted-foreground'>...</span>\n              ) : (\n                <Button\n                  variant={currentPage === pageNumber ? 'default' : 'outline'}\n                  className='h-8 min-w-8 px-2'\n                  onClick={() => table.setPageIndex((pageNumber as number) - 1)}\n                >\n                  <span className='sr-only'>Go to page {pageNumber}</span>\n                  {pageNumber}\n                </Button>\n              )}\n            </div>\n          ))}\n\n          <Button\n            variant='outline'\n            className='size-8 p-0'\n            onClick={() => table.nextPage()}\n            disabled={!table.getCanNextPage()}\n          >\n            <span className='sr-only'>Go to next page</span>\n            <ChevronRightIcon className='h-4 w-4' />\n          </Button>\n          <Button\n            variant='outline'\n            className='size-8 p-0 @max-md/content:hidden'\n            onClick={() => table.setPageIndex(table.getPageCount() - 1)}\n            disabled={!table.getCanNextPage()}\n          >\n            <span className='sr-only'>Go to last page</span>\n            <DoubleArrowRightIcon className='h-4 w-4' />\n          </Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/toolbar.tsx",
    "content": "import { Cross2Icon } from '@radix-ui/react-icons'\nimport { type Table } from '@tanstack/react-table'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { DataTableFacetedFilter } from './faceted-filter'\nimport { DataTableViewOptions } from './view-options'\n\ntype DataTableToolbarProps<TData> = {\n  table: Table<TData>\n  searchPlaceholder?: string\n  searchKey?: string\n  filters?: {\n    columnId: string\n    title: string\n    options: {\n      label: string\n      value: string\n      icon?: React.ComponentType<{ className?: string }>\n    }[]\n  }[]\n}\n\nexport function DataTableToolbar<TData>({\n  table,\n  searchPlaceholder = 'Filter...',\n  searchKey,\n  filters = [],\n}: DataTableToolbarProps<TData>) {\n  const isFiltered =\n    table.getState().columnFilters.length > 0 || table.getState().globalFilter\n\n  return (\n    <div className='flex items-center justify-between'>\n      <div className='flex flex-1 flex-col-reverse items-start gap-y-2 sm:flex-row sm:items-center sm:space-x-2'>\n        {searchKey ? (\n          <Input\n            placeholder={searchPlaceholder}\n            value={\n              (table.getColumn(searchKey)?.getFilterValue() as string) ?? ''\n            }\n            onChange={(event) =>\n              table.getColumn(searchKey)?.setFilterValue(event.target.value)\n            }\n            className='h-8 w-[150px] lg:w-[250px]'\n          />\n        ) : (\n          <Input\n            placeholder={searchPlaceholder}\n            value={table.getState().globalFilter ?? ''}\n            onChange={(event) => table.setGlobalFilter(event.target.value)}\n            className='h-8 w-[150px] lg:w-[250px]'\n          />\n        )}\n        <div className='flex gap-x-2'>\n          {filters.map((filter) => {\n            const column = table.getColumn(filter.columnId)\n            if (!column) return null\n            return (\n              <DataTableFacetedFilter\n                key={filter.columnId}\n                column={column}\n                title={filter.title}\n                options={filter.options}\n              />\n            )\n          })}\n        </div>\n        {isFiltered && (\n          <Button\n            variant='ghost'\n            onClick={() => {\n              table.resetColumnFilters()\n              table.setGlobalFilter('')\n            }}\n            className='h-8 px-2 lg:px-3'\n          >\n            Reset\n            <Cross2Icon className='ms-2 h-4 w-4' />\n          </Button>\n        )}\n      </div>\n      <DataTableViewOptions table={table} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/data-table/view-options.tsx",
    "content": "import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu'\nimport { MixerHorizontalIcon } from '@radix-ui/react-icons'\nimport { type Table } from '@tanstack/react-table'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuCheckboxItem,\n  DropdownMenuContent,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n} from '@/components/ui/dropdown-menu'\n\ntype DataTableViewOptionsProps<TData> = {\n  table: Table<TData>\n}\n\nexport function DataTableViewOptions<TData>({\n  table,\n}: DataTableViewOptionsProps<TData>) {\n  return (\n    <DropdownMenu modal={false}>\n      <DropdownMenuTrigger asChild>\n        <Button\n          variant='outline'\n          size='sm'\n          className='ms-auto hidden h-8 lg:flex'\n        >\n          <MixerHorizontalIcon className='size-4' />\n          View\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align='end' className='w-[150px]'>\n        <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>\n        <DropdownMenuSeparator />\n        {table\n          .getAllColumns()\n          .filter(\n            (column) =>\n              typeof column.accessorFn !== 'undefined' && column.getCanHide()\n          )\n          .map((column) => {\n            return (\n              <DropdownMenuCheckboxItem\n                key={column.id}\n                className='capitalize'\n                checked={column.getIsVisible()}\n                onCheckedChange={(value) => column.toggleVisibility(!!value)}\n              >\n                {column.id}\n              </DropdownMenuCheckboxItem>\n            )\n          })}\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n"
  },
  {
    "path": "src/components/date-picker.tsx",
    "content": "import { format } from 'date-fns'\nimport { Calendar as CalendarIcon } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { Calendar } from '@/components/ui/calendar'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\n\ntype DatePickerProps = {\n  selected: Date | undefined\n  onSelect: (date: Date | undefined) => void\n  placeholder?: string\n}\n\nexport function DatePicker({\n  selected,\n  onSelect,\n  placeholder = 'Pick a date',\n}: DatePickerProps) {\n  return (\n    <Popover>\n      <PopoverTrigger asChild>\n        <Button\n          variant='outline'\n          data-empty={!selected}\n          className='w-[240px] justify-start text-start font-normal data-[empty=true]:text-muted-foreground'\n        >\n          {selected ? (\n            format(selected, 'MMM d, yyyy')\n          ) : (\n            <span>{placeholder}</span>\n          )}\n          <CalendarIcon className='ms-auto h-4 w-4 opacity-50' />\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent className='w-auto p-0'>\n        <Calendar\n          mode='single'\n          captionLayout='dropdown'\n          selected={selected}\n          onSelect={onSelect}\n          disabled={(date: Date) =>\n            date > new Date() || date < new Date('1900-01-01')\n          }\n        />\n      </PopoverContent>\n    </Popover>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/app-sidebar.tsx",
    "content": "import { useLayout } from '@/context/layout-provider'\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarHeader,\n  SidebarRail,\n} from '@/components/ui/sidebar'\n// import { AppTitle } from './app-title'\nimport { sidebarData } from './data/sidebar-data'\nimport { NavGroup } from './nav-group'\nimport { NavUser } from './nav-user'\nimport { TeamSwitcher } from './team-switcher'\n\nexport function AppSidebar() {\n  const { collapsible, variant } = useLayout()\n  return (\n    <Sidebar collapsible={collapsible} variant={variant}>\n      <SidebarHeader>\n        <TeamSwitcher teams={sidebarData.teams} />\n\n        {/* Replace <TeamSwitch /> with the following <AppTitle />\n         /* if you want to use the normal app title instead of TeamSwitch dropdown */}\n        {/* <AppTitle /> */}\n      </SidebarHeader>\n      <SidebarContent>\n        {sidebarData.navGroups.map((props) => (\n          <NavGroup key={props.title} {...props} />\n        ))}\n      </SidebarContent>\n      <SidebarFooter>\n        <NavUser user={sidebarData.user} />\n      </SidebarFooter>\n      <SidebarRail />\n    </Sidebar>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/app-title.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport { Menu, X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar'\nimport { Button } from '../ui/button'\n\nexport function AppTitle() {\n  const { setOpenMobile } = useSidebar()\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <SidebarMenuButton\n          size='lg'\n          className='gap-0 py-0 hover:bg-transparent active:bg-transparent'\n          asChild\n        >\n          <div>\n            <Link\n              to='/'\n              onClick={() => setOpenMobile(false)}\n              className='grid flex-1 text-start text-sm leading-tight'\n            >\n              <span className='truncate font-bold'>Shadcn-Admin</span>\n              <span className='truncate text-xs'>Vite + ShadcnUI</span>\n            </Link>\n            <ToggleSidebar />\n          </div>\n        </SidebarMenuButton>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  )\n}\n\nfunction ToggleSidebar({\n  className,\n  onClick,\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  const { toggleSidebar } = useSidebar()\n\n  return (\n    <Button\n      data-sidebar='trigger'\n      data-slot='sidebar-trigger'\n      variant='ghost'\n      size='icon'\n      className={cn('aspect-square size-8 max-md:scale-125', className)}\n      onClick={(event) => {\n        onClick?.(event)\n        toggleSidebar()\n      }}\n      {...props}\n    >\n      <X className='md:hidden' />\n      <Menu className='max-md:hidden' />\n      <span className='sr-only'>Toggle Sidebar</span>\n    </Button>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/authenticated-layout.tsx",
    "content": "import { Outlet } from '@tanstack/react-router'\nimport { getCookie } from '@/lib/cookies'\nimport { cn } from '@/lib/utils'\nimport { LayoutProvider } from '@/context/layout-provider'\nimport { SearchProvider } from '@/context/search-provider'\nimport { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'\nimport { AppSidebar } from '@/components/layout/app-sidebar'\nimport { SkipToMain } from '@/components/skip-to-main'\n\ntype AuthenticatedLayoutProps = {\n  children?: React.ReactNode\n}\n\nexport function AuthenticatedLayout({ children }: AuthenticatedLayoutProps) {\n  const defaultOpen = getCookie('sidebar_state') !== 'false'\n  return (\n    <SearchProvider>\n      <LayoutProvider>\n        <SidebarProvider defaultOpen={defaultOpen}>\n          <SkipToMain />\n          <AppSidebar />\n          <SidebarInset\n            className={cn(\n              // Set content container, so we can use container queries\n              '@container/content',\n\n              // If layout is fixed, set the height\n              // to 100svh to prevent overflow\n              'has-data-[layout=fixed]:h-svh',\n\n              // If layout is fixed and sidebar is inset,\n              // set the height to 100svh - spacing (total margins) to prevent overflow\n              'peer-data-[variant=inset]:has-data-[layout=fixed]:h-[calc(100svh-(var(--spacing)*4))]'\n            )}\n          >\n            {children ?? <Outlet />}\n          </SidebarInset>\n        </SidebarProvider>\n      </LayoutProvider>\n    </SearchProvider>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/data/sidebar-data.ts",
    "content": "import {\n  Construction,\n  LayoutDashboard,\n  Monitor,\n  Bug,\n  ListTodo,\n  FileX,\n  HelpCircle,\n  Lock,\n  Bell,\n  Package,\n  Palette,\n  ServerOff,\n  Settings,\n  Wrench,\n  UserCog,\n  UserX,\n  Users,\n  MessagesSquare,\n  ShieldCheck,\n  AudioWaveform,\n  Command,\n  GalleryVerticalEnd,\n} from 'lucide-react'\nimport { ClerkLogo } from '@/assets/clerk-logo'\nimport { type SidebarData } from '../types'\n\nexport const sidebarData: SidebarData = {\n  user: {\n    name: 'satnaing',\n    email: 'satnaingdev@gmail.com',\n    avatar: '/avatars/shadcn.jpg',\n  },\n  teams: [\n    {\n      name: 'Shadcn Admin',\n      logo: Command,\n      plan: 'Vite + ShadcnUI',\n    },\n    {\n      name: 'Acme Inc',\n      logo: GalleryVerticalEnd,\n      plan: 'Enterprise',\n    },\n    {\n      name: 'Acme Corp.',\n      logo: AudioWaveform,\n      plan: 'Startup',\n    },\n  ],\n  navGroups: [\n    {\n      title: 'General',\n      items: [\n        {\n          title: 'Dashboard',\n          url: '/',\n          icon: LayoutDashboard,\n        },\n        {\n          title: 'Tasks',\n          url: '/tasks',\n          icon: ListTodo,\n        },\n        {\n          title: 'Apps',\n          url: '/apps',\n          icon: Package,\n        },\n        {\n          title: 'Chats',\n          url: '/chats',\n          badge: '3',\n          icon: MessagesSquare,\n        },\n        {\n          title: 'Users',\n          url: '/users',\n          icon: Users,\n        },\n        {\n          title: 'Secured by Clerk',\n          icon: ClerkLogo,\n          items: [\n            {\n              title: 'Sign In',\n              url: '/clerk/sign-in',\n            },\n            {\n              title: 'Sign Up',\n              url: '/clerk/sign-up',\n            },\n            {\n              title: 'User Management',\n              url: '/clerk/user-management',\n            },\n          ],\n        },\n      ],\n    },\n    {\n      title: 'Pages',\n      items: [\n        {\n          title: 'Auth',\n          icon: ShieldCheck,\n          items: [\n            {\n              title: 'Sign In',\n              url: '/sign-in',\n            },\n            {\n              title: 'Sign In (2 Col)',\n              url: '/sign-in-2',\n            },\n            {\n              title: 'Sign Up',\n              url: '/sign-up',\n            },\n            {\n              title: 'Forgot Password',\n              url: '/forgot-password',\n            },\n            {\n              title: 'OTP',\n              url: '/otp',\n            },\n          ],\n        },\n        {\n          title: 'Errors',\n          icon: Bug,\n          items: [\n            {\n              title: 'Unauthorized',\n              url: '/errors/unauthorized',\n              icon: Lock,\n            },\n            {\n              title: 'Forbidden',\n              url: '/errors/forbidden',\n              icon: UserX,\n            },\n            {\n              title: 'Not Found',\n              url: '/errors/not-found',\n              icon: FileX,\n            },\n            {\n              title: 'Internal Server Error',\n              url: '/errors/internal-server-error',\n              icon: ServerOff,\n            },\n            {\n              title: 'Maintenance Error',\n              url: '/errors/maintenance-error',\n              icon: Construction,\n            },\n          ],\n        },\n      ],\n    },\n    {\n      title: 'Other',\n      items: [\n        {\n          title: 'Settings',\n          icon: Settings,\n          items: [\n            {\n              title: 'Profile',\n              url: '/settings',\n              icon: UserCog,\n            },\n            {\n              title: 'Account',\n              url: '/settings/account',\n              icon: Wrench,\n            },\n            {\n              title: 'Appearance',\n              url: '/settings/appearance',\n              icon: Palette,\n            },\n            {\n              title: 'Notifications',\n              url: '/settings/notifications',\n              icon: Bell,\n            },\n            {\n              title: 'Display',\n              url: '/settings/display',\n              icon: Monitor,\n            },\n          ],\n        },\n        {\n          title: 'Help Center',\n          url: '/help-center',\n          icon: HelpCircle,\n        },\n      ],\n    },\n  ],\n}\n"
  },
  {
    "path": "src/components/layout/header.tsx",
    "content": "import { useEffect, useState } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Separator } from '@/components/ui/separator'\nimport { SidebarTrigger } from '@/components/ui/sidebar'\n\ntype HeaderProps = React.HTMLAttributes<HTMLElement> & {\n  fixed?: boolean\n  ref?: React.Ref<HTMLElement>\n}\n\nexport function Header({ className, fixed, children, ...props }: HeaderProps) {\n  const [offset, setOffset] = useState(0)\n\n  useEffect(() => {\n    const onScroll = () => {\n      setOffset(document.body.scrollTop || document.documentElement.scrollTop)\n    }\n\n    // Add scroll listener to the body\n    document.addEventListener('scroll', onScroll, { passive: true })\n\n    // Clean up the event listener on unmount\n    return () => document.removeEventListener('scroll', onScroll)\n  }, [])\n\n  return (\n    <header\n      className={cn(\n        'z-50 h-16',\n        fixed && 'header-fixed peer/header sticky top-0 w-[inherit]',\n        offset > 10 && fixed ? 'shadow' : 'shadow-none',\n        className\n      )}\n      {...props}\n    >\n      <div\n        className={cn(\n          'relative flex h-full items-center gap-3 p-4 sm:gap-4',\n          offset > 10 &&\n            fixed &&\n            'after:absolute after:inset-0 after:-z-10 after:bg-background/20 after:backdrop-blur-lg'\n        )}\n      >\n        <SidebarTrigger variant='outline' className='max-md:scale-125' />\n        <Separator orientation='vertical' className='h-6' />\n        {children}\n      </div>\n    </header>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/main.tsx",
    "content": "import { cn } from '@/lib/utils'\n\ntype MainProps = React.HTMLAttributes<HTMLElement> & {\n  fixed?: boolean\n  fluid?: boolean\n  ref?: React.Ref<HTMLElement>\n}\n\nexport function Main({ fixed, className, fluid, ...props }: MainProps) {\n  return (\n    <main\n      data-layout={fixed ? 'fixed' : 'auto'}\n      className={cn(\n        'px-4 py-6',\n\n        // If layout is fixed, make the main container flex and grow\n        fixed && 'flex grow flex-col overflow-hidden',\n\n        // If layout is not fluid, set the max-width\n        !fluid &&\n          '@7xl/content:mx-auto @7xl/content:w-full @7xl/content:max-w-7xl',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n"
  },
  {
    "path": "src/components/layout/nav-group.tsx",
    "content": "import { type ReactNode } from 'react'\nimport { Link, useLocation } from '@tanstack/react-router'\nimport { ChevronRight } from 'lucide-react'\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from '@/components/ui/collapsible'\nimport {\n  SidebarGroup,\n  SidebarGroupLabel,\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  SidebarMenuSub,\n  SidebarMenuSubButton,\n  SidebarMenuSubItem,\n  useSidebar,\n} from '@/components/ui/sidebar'\nimport { Badge } from '../ui/badge'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport {\n  type NavCollapsible,\n  type NavItem,\n  type NavLink,\n  type NavGroup as NavGroupProps,\n} from './types'\n\nexport function NavGroup({ title, items }: NavGroupProps) {\n  const { state, isMobile } = useSidebar()\n  const href = useLocation({ select: (location) => location.href })\n  return (\n    <SidebarGroup>\n      <SidebarGroupLabel>{title}</SidebarGroupLabel>\n      <SidebarMenu>\n        {items.map((item) => {\n          const key = `${item.title}-${item.url}`\n\n          if (!item.items)\n            return <SidebarMenuLink key={key} item={item} href={href} />\n\n          if (state === 'collapsed' && !isMobile)\n            return (\n              <SidebarMenuCollapsedDropdown key={key} item={item} href={href} />\n            )\n\n          return <SidebarMenuCollapsible key={key} item={item} href={href} />\n        })}\n      </SidebarMenu>\n    </SidebarGroup>\n  )\n}\n\nfunction NavBadge({ children }: { children: ReactNode }) {\n  return <Badge className='rounded-full px-1 py-0 text-xs'>{children}</Badge>\n}\n\nfunction SidebarMenuLink({ item, href }: { item: NavLink; href: string }) {\n  const { setOpenMobile } = useSidebar()\n  return (\n    <SidebarMenuItem>\n      <SidebarMenuButton\n        asChild\n        isActive={checkIsActive(href, item)}\n        tooltip={item.title}\n      >\n        <Link to={item.url} onClick={() => setOpenMobile(false)}>\n          {item.icon && <item.icon />}\n          <span>{item.title}</span>\n          {item.badge && <NavBadge>{item.badge}</NavBadge>}\n        </Link>\n      </SidebarMenuButton>\n    </SidebarMenuItem>\n  )\n}\n\nfunction SidebarMenuCollapsible({\n  item,\n  href,\n}: {\n  item: NavCollapsible\n  href: string\n}) {\n  const { setOpenMobile } = useSidebar()\n  return (\n    <Collapsible\n      asChild\n      defaultOpen={checkIsActive(href, item, true)}\n      className='group/collapsible'\n    >\n      <SidebarMenuItem>\n        <CollapsibleTrigger asChild>\n          <SidebarMenuButton tooltip={item.title}>\n            {item.icon && <item.icon />}\n            <span>{item.title}</span>\n            {item.badge && <NavBadge>{item.badge}</NavBadge>}\n            <ChevronRight className='ms-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90 rtl:rotate-180' />\n          </SidebarMenuButton>\n        </CollapsibleTrigger>\n        <CollapsibleContent className='CollapsibleContent'>\n          <SidebarMenuSub>\n            {item.items.map((subItem) => (\n              <SidebarMenuSubItem key={subItem.title}>\n                <SidebarMenuSubButton\n                  asChild\n                  isActive={checkIsActive(href, subItem)}\n                >\n                  <Link to={subItem.url} onClick={() => setOpenMobile(false)}>\n                    {subItem.icon && <subItem.icon />}\n                    <span>{subItem.title}</span>\n                    {subItem.badge && <NavBadge>{subItem.badge}</NavBadge>}\n                  </Link>\n                </SidebarMenuSubButton>\n              </SidebarMenuSubItem>\n            ))}\n          </SidebarMenuSub>\n        </CollapsibleContent>\n      </SidebarMenuItem>\n    </Collapsible>\n  )\n}\n\nfunction SidebarMenuCollapsedDropdown({\n  item,\n  href,\n}: {\n  item: NavCollapsible\n  href: string\n}) {\n  return (\n    <SidebarMenuItem>\n      <DropdownMenu>\n        <DropdownMenuTrigger asChild>\n          <SidebarMenuButton\n            tooltip={item.title}\n            isActive={checkIsActive(href, item)}\n          >\n            {item.icon && <item.icon />}\n            <span>{item.title}</span>\n            {item.badge && <NavBadge>{item.badge}</NavBadge>}\n            <ChevronRight className='ms-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90' />\n          </SidebarMenuButton>\n        </DropdownMenuTrigger>\n        <DropdownMenuContent side='right' align='start' sideOffset={4}>\n          <DropdownMenuLabel>\n            {item.title} {item.badge ? `(${item.badge})` : ''}\n          </DropdownMenuLabel>\n          <DropdownMenuSeparator />\n          {item.items.map((sub) => (\n            <DropdownMenuItem key={`${sub.title}-${sub.url}`} asChild>\n              <Link\n                to={sub.url}\n                className={`${checkIsActive(href, sub) ? 'bg-secondary' : ''}`}\n              >\n                {sub.icon && <sub.icon />}\n                <span className='max-w-52 text-wrap'>{sub.title}</span>\n                {sub.badge && (\n                  <span className='ms-auto text-xs'>{sub.badge}</span>\n                )}\n              </Link>\n            </DropdownMenuItem>\n          ))}\n        </DropdownMenuContent>\n      </DropdownMenu>\n    </SidebarMenuItem>\n  )\n}\n\nfunction checkIsActive(href: string, item: NavItem, mainNav = false) {\n  return (\n    href === item.url || // /endpint?search=param\n    href.split('?')[0] === item.url || // endpoint\n    !!item?.items?.filter((i) => i.url === href).length || // if child nav is active\n    (mainNav &&\n      href.split('/')[1] !== '' &&\n      href.split('/')[1] === item?.url?.split('/')[1])\n  )\n}\n"
  },
  {
    "path": "src/components/layout/nav-user.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport {\n  BadgeCheck,\n  Bell,\n  ChevronsUpDown,\n  CreditCard,\n  LogOut,\n  Sparkles,\n} from 'lucide-react'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar'\nimport { SignOutDialog } from '@/components/sign-out-dialog'\n\ntype NavUserProps = {\n  user: {\n    name: string\n    email: string\n    avatar: string\n  }\n}\n\nexport function NavUser({ user }: NavUserProps) {\n  const { isMobile } = useSidebar()\n  const [open, setOpen] = useDialogState()\n\n  return (\n    <>\n      <SidebarMenu>\n        <SidebarMenuItem>\n          <DropdownMenu>\n            <DropdownMenuTrigger asChild>\n              <SidebarMenuButton\n                size='lg'\n                className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground'\n              >\n                <Avatar className='h-8 w-8 rounded-lg'>\n                  <AvatarImage src={user.avatar} alt={user.name} />\n                  <AvatarFallback className='rounded-lg'>SN</AvatarFallback>\n                </Avatar>\n                <div className='grid flex-1 text-start text-sm leading-tight'>\n                  <span className='truncate font-semibold'>{user.name}</span>\n                  <span className='truncate text-xs'>{user.email}</span>\n                </div>\n                <ChevronsUpDown className='ms-auto size-4' />\n              </SidebarMenuButton>\n            </DropdownMenuTrigger>\n            <DropdownMenuContent\n              className='w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg'\n              side={isMobile ? 'bottom' : 'right'}\n              align='end'\n              sideOffset={4}\n            >\n              <DropdownMenuLabel className='p-0 font-normal'>\n                <div className='flex items-center gap-2 px-1 py-1.5 text-start text-sm'>\n                  <Avatar className='h-8 w-8 rounded-lg'>\n                    <AvatarImage src={user.avatar} alt={user.name} />\n                    <AvatarFallback className='rounded-lg'>SN</AvatarFallback>\n                  </Avatar>\n                  <div className='grid flex-1 text-start text-sm leading-tight'>\n                    <span className='truncate font-semibold'>{user.name}</span>\n                    <span className='truncate text-xs'>{user.email}</span>\n                  </div>\n                </div>\n              </DropdownMenuLabel>\n              <DropdownMenuSeparator />\n              <DropdownMenuGroup>\n                <DropdownMenuItem>\n                  <Sparkles />\n                  Upgrade to Pro\n                </DropdownMenuItem>\n              </DropdownMenuGroup>\n              <DropdownMenuSeparator />\n              <DropdownMenuGroup>\n                <DropdownMenuItem asChild>\n                  <Link to='/settings/account'>\n                    <BadgeCheck />\n                    Account\n                  </Link>\n                </DropdownMenuItem>\n                <DropdownMenuItem asChild>\n                  <Link to='/settings'>\n                    <CreditCard />\n                    Billing\n                  </Link>\n                </DropdownMenuItem>\n                <DropdownMenuItem asChild>\n                  <Link to='/settings/notifications'>\n                    <Bell />\n                    Notifications\n                  </Link>\n                </DropdownMenuItem>\n              </DropdownMenuGroup>\n              <DropdownMenuSeparator />\n              <DropdownMenuItem\n                variant='destructive'\n                onClick={() => setOpen(true)}\n              >\n                <LogOut />\n                Sign out\n              </DropdownMenuItem>\n            </DropdownMenuContent>\n          </DropdownMenu>\n        </SidebarMenuItem>\n      </SidebarMenu>\n\n      <SignOutDialog open={!!open} onOpenChange={setOpen} />\n    </>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/team-switcher.tsx",
    "content": "import * as React from 'react'\nimport { ChevronsUpDown, Plus } from 'lucide-react'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar'\n\ntype TeamSwitcherProps = {\n  teams: {\n    name: string\n    logo: React.ElementType\n    plan: string\n  }[]\n}\n\nexport function TeamSwitcher({ teams }: TeamSwitcherProps) {\n  const { isMobile } = useSidebar()\n  const [activeTeam, setActiveTeam] = React.useState(teams[0])\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger asChild>\n            <SidebarMenuButton\n              size='lg'\n              className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground'\n            >\n              <div className='flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground'>\n                <activeTeam.logo className='size-4' />\n              </div>\n              <div className='grid flex-1 text-start text-sm leading-tight'>\n                <span className='truncate font-semibold'>\n                  {activeTeam.name}\n                </span>\n                <span className='truncate text-xs'>{activeTeam.plan}</span>\n              </div>\n              <ChevronsUpDown className='ms-auto' />\n            </SidebarMenuButton>\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            className='w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg'\n            align='start'\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className='text-xs text-muted-foreground'>\n              Teams\n            </DropdownMenuLabel>\n            {teams.map((team, index) => (\n              <DropdownMenuItem\n                key={team.name}\n                onClick={() => setActiveTeam(team)}\n                className='gap-2 p-2'\n              >\n                <div className='flex size-6 items-center justify-center rounded-sm border'>\n                  <team.logo className='size-4 shrink-0' />\n                </div>\n                {team.name}\n                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n              </DropdownMenuItem>\n            ))}\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className='gap-2 p-2'>\n              <div className='flex size-6 items-center justify-center rounded-md border bg-background'>\n                <Plus className='size-4' />\n              </div>\n              <div className='font-medium text-muted-foreground'>Add team</div>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/top-nav.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport { Menu } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\n\ntype TopNavProps = React.HTMLAttributes<HTMLElement> & {\n  links: {\n    title: string\n    href: string\n    isActive: boolean\n    disabled?: boolean\n  }[]\n}\n\nexport function TopNav({ className, links, ...props }: TopNavProps) {\n  return (\n    <>\n      <div className='lg:hidden'>\n        <DropdownMenu modal={false}>\n          <DropdownMenuTrigger asChild>\n            <Button size='icon' variant='outline' className='md:size-7'>\n              <Menu />\n            </Button>\n          </DropdownMenuTrigger>\n          <DropdownMenuContent side='bottom' align='start'>\n            {links.map(({ title, href, isActive, disabled }) => (\n              <DropdownMenuItem key={`${title}-${href}`} asChild>\n                <Link\n                  to={href}\n                  className={!isActive ? 'text-muted-foreground' : ''}\n                  disabled={disabled}\n                >\n                  {title}\n                </Link>\n              </DropdownMenuItem>\n            ))}\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </div>\n\n      <nav\n        className={cn(\n          'hidden items-center space-x-4 lg:flex lg:space-x-4 xl:space-x-6',\n          className\n        )}\n        {...props}\n      >\n        {links.map(({ title, href, isActive, disabled }) => (\n          <Link\n            key={`${title}-${href}`}\n            to={href}\n            disabled={disabled}\n            className={`text-sm font-medium transition-colors hover:text-primary ${isActive ? '' : 'text-muted-foreground'}`}\n          >\n            {title}\n          </Link>\n        ))}\n      </nav>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/components/layout/types.ts",
    "content": "import { type LinkProps } from '@tanstack/react-router'\n\ntype User = {\n  name: string\n  email: string\n  avatar: string\n}\n\ntype Team = {\n  name: string\n  logo: React.ElementType\n  plan: string\n}\n\ntype BaseNavItem = {\n  title: string\n  badge?: string\n  icon?: React.ElementType\n}\n\ntype NavLink = BaseNavItem & {\n  url: LinkProps['to'] | (string & {})\n  items?: never\n}\n\ntype NavCollapsible = BaseNavItem & {\n  items: (BaseNavItem & { url: LinkProps['to'] | (string & {}) })[]\n  url?: never\n}\n\ntype NavItem = NavCollapsible | NavLink\n\ntype NavGroup = {\n  title: string\n  items: NavItem[]\n}\n\ntype SidebarData = {\n  user: User\n  teams: Team[]\n  navGroups: NavGroup[]\n}\n\nexport type { SidebarData, NavGroup, NavItem, NavCollapsible, NavLink }\n"
  },
  {
    "path": "src/components/learn-more.tsx",
    "content": "import { type Root, type Content, type Trigger } from '@radix-ui/react-popover'\nimport { CircleQuestionMark } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\n\ntype LearnMoreProps = React.ComponentProps<typeof Root> & {\n  contentProps?: React.ComponentProps<typeof Content>\n  triggerProps?: React.ComponentProps<typeof Trigger>\n}\n\nexport function LearnMore({\n  children,\n  contentProps,\n  triggerProps,\n  ...props\n}: LearnMoreProps) {\n  return (\n    <Popover {...props}>\n      <PopoverTrigger\n        asChild\n        {...triggerProps}\n        className={cn('size-5 rounded-full', triggerProps?.className)}\n      >\n        <Button variant='outline' size='icon'>\n          <span className='sr-only'>Learn more</span>\n          <CircleQuestionMark className='size-4 [&>circle]:hidden' />\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent\n        side='top'\n        align='start'\n        {...contentProps}\n        className={cn('text-sm text-muted-foreground', contentProps?.className)}\n      >\n        {children}\n      </PopoverContent>\n    </Popover>\n  )\n}\n"
  },
  {
    "path": "src/components/long-text.tsx",
    "content": "import { useRef, useState } from 'react'\nimport { cn } from '@/lib/utils'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\n\ntype LongTextProps = {\n  children: React.ReactNode\n  className?: string\n  contentClassName?: string\n}\n\nexport function LongText({\n  children,\n  className = '',\n  contentClassName = '',\n}: LongTextProps) {\n  const ref = useRef<HTMLDivElement>(null)\n  const [isOverflown, setIsOverflown] = useState(false)\n\n  // Use ref callback to check overflow when element is mounted\n  const refCallback = (node: HTMLDivElement | null) => {\n    ref.current = node\n    if (node && checkOverflow(node)) {\n      queueMicrotask(() => setIsOverflown(true))\n    }\n  }\n\n  if (!isOverflown)\n    return (\n      <div ref={refCallback} className={cn('truncate', className)}>\n        {children}\n      </div>\n    )\n\n  return (\n    <>\n      <div className='hidden sm:block'>\n        <TooltipProvider delayDuration={0}>\n          <Tooltip>\n            <TooltipTrigger asChild>\n              <div ref={refCallback} className={cn('truncate', className)}>\n                {children}\n              </div>\n            </TooltipTrigger>\n            <TooltipContent>\n              <p className={contentClassName}>{children}</p>\n            </TooltipContent>\n          </Tooltip>\n        </TooltipProvider>\n      </div>\n      <div className='sm:hidden'>\n        <Popover>\n          <PopoverTrigger asChild>\n            <div ref={refCallback} className={cn('truncate', className)}>\n              {children}\n            </div>\n          </PopoverTrigger>\n          <PopoverContent className={cn('w-fit', contentClassName)}>\n            <p>{children}</p>\n          </PopoverContent>\n        </Popover>\n      </div>\n    </>\n  )\n}\n\nconst checkOverflow = (textContainer: HTMLDivElement | null) => {\n  if (textContainer) {\n    return (\n      textContainer.offsetHeight < textContainer.scrollHeight ||\n      textContainer.offsetWidth < textContainer.scrollWidth\n    )\n  }\n  return false\n}\n"
  },
  {
    "path": "src/components/navigation-progress.tsx",
    "content": "import { useEffect, useRef } from 'react'\nimport { useRouterState } from '@tanstack/react-router'\nimport LoadingBar, { type LoadingBarRef } from 'react-top-loading-bar'\n\nexport function NavigationProgress() {\n  const ref = useRef<LoadingBarRef>(null)\n  const state = useRouterState()\n\n  useEffect(() => {\n    if (state.status === 'pending') {\n      ref.current?.continuousStart()\n    } else {\n      ref.current?.complete()\n    }\n  }, [state.status])\n\n  return (\n    <LoadingBar\n      color='var(--muted-foreground)'\n      ref={ref}\n      shadow={true}\n      height={2}\n    />\n  )\n}\n"
  },
  {
    "path": "src/components/password-input.tsx",
    "content": "import * as React from 'react'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from './ui/button'\n\ntype PasswordInputProps = Omit<\n  React.InputHTMLAttributes<HTMLInputElement>,\n  'type'\n> & {\n  ref?: React.Ref<HTMLInputElement>\n}\n\nexport function PasswordInput({\n  className,\n  disabled,\n  ref,\n  ...props\n}: PasswordInputProps) {\n  const [showPassword, setShowPassword] = React.useState(false)\n\n  return (\n    <div className={cn('relative rounded-md', className)}>\n      <input\n        type={showPassword ? 'text' : 'password'}\n        className='flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50'\n        ref={ref}\n        disabled={disabled}\n        {...props}\n      />\n      <Button\n        type='button'\n        size='icon'\n        variant='ghost'\n        disabled={disabled}\n        className='absolute end-1 top-1/2 h-6 w-6 -translate-y-1/2 rounded-md text-muted-foreground'\n        onClick={() => setShowPassword((prev) => !prev)}\n      >\n        {showPassword ? <Eye size={18} /> : <EyeOff size={18} />}\n      </Button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/profile-dropdown.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { SignOutDialog } from '@/components/sign-out-dialog'\n\nexport function ProfileDropdown() {\n  const [open, setOpen] = useDialogState()\n\n  return (\n    <>\n      <DropdownMenu modal={false}>\n        <DropdownMenuTrigger asChild>\n          <Button variant='ghost' className='relative h-8 w-8 rounded-full'>\n            <Avatar className='h-8 w-8'>\n              <AvatarImage src='/avatars/01.png' alt='@shadcn' />\n              <AvatarFallback>SN</AvatarFallback>\n            </Avatar>\n          </Button>\n        </DropdownMenuTrigger>\n        <DropdownMenuContent className='w-56' align='end' forceMount>\n          <DropdownMenuLabel className='font-normal'>\n            <div className='flex flex-col gap-1.5'>\n              <p className='text-sm leading-none font-medium'>satnaing</p>\n              <p className='text-xs leading-none text-muted-foreground'>\n                satnaingdev@gmail.com\n              </p>\n            </div>\n          </DropdownMenuLabel>\n          <DropdownMenuSeparator />\n          <DropdownMenuGroup>\n            <DropdownMenuItem asChild>\n              <Link to='/settings'>\n                Profile\n                <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>\n              </Link>\n            </DropdownMenuItem>\n            <DropdownMenuItem asChild>\n              <Link to='/settings'>\n                Billing\n                <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>\n              </Link>\n            </DropdownMenuItem>\n            <DropdownMenuItem asChild>\n              <Link to='/settings'>\n                Settings\n                <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>\n              </Link>\n            </DropdownMenuItem>\n            <DropdownMenuItem>New Team</DropdownMenuItem>\n          </DropdownMenuGroup>\n          <DropdownMenuSeparator />\n          <DropdownMenuItem variant='destructive' onClick={() => setOpen(true)}>\n            Sign out\n            <DropdownMenuShortcut className='text-current'>\n              ⇧⌘Q\n            </DropdownMenuShortcut>\n          </DropdownMenuItem>\n        </DropdownMenuContent>\n      </DropdownMenu>\n\n      <SignOutDialog open={!!open} onOpenChange={setOpen} />\n    </>\n  )\n}\n"
  },
  {
    "path": "src/components/search.tsx",
    "content": "import { SearchIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useSearch } from '@/context/search-provider'\nimport { Button } from './ui/button'\n\ntype SearchProps = {\n  className?: string\n  type?: React.HTMLInputTypeAttribute\n  placeholder?: string\n}\n\nexport function Search({\n  className = '',\n  placeholder = 'Search',\n}: SearchProps) {\n  const { setOpen } = useSearch()\n  return (\n    <Button\n      variant='outline'\n      className={cn(\n        'group relative h-8 w-full flex-1 justify-start rounded-md bg-muted/25 text-sm font-normal text-muted-foreground shadow-none hover:bg-accent sm:w-40 sm:pe-12 md:flex-none lg:w-52 xl:w-64',\n        className\n      )}\n      onClick={() => setOpen(true)}\n    >\n      <SearchIcon\n        aria-hidden='true'\n        className='absolute start-1.5 top-1/2 -translate-y-1/2'\n        size={16}\n      />\n      <span className='ms-4'>{placeholder}</span>\n      <kbd className='pointer-events-none absolute end-[0.3rem] top-[0.3rem] hidden h-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 select-none group-hover:bg-accent sm:flex'>\n        <span className='text-xs'>⌘</span>K\n      </kbd>\n    </Button>\n  )\n}\n"
  },
  {
    "path": "src/components/select-dropdown.tsx",
    "content": "import { Loader } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { FormControl } from '@/components/ui/form'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\n\ntype SelectDropdownProps = {\n  onValueChange?: (value: string) => void\n  defaultValue: string | undefined\n  placeholder?: string\n  isPending?: boolean\n  items: { label: string; value: string }[] | undefined\n  disabled?: boolean\n  className?: string\n  isControlled?: boolean\n}\n\nexport function SelectDropdown({\n  defaultValue,\n  onValueChange,\n  isPending,\n  items,\n  placeholder,\n  disabled,\n  className = '',\n  isControlled = false,\n}: SelectDropdownProps) {\n  const defaultState = isControlled\n    ? { value: defaultValue, onValueChange }\n    : { defaultValue, onValueChange }\n  return (\n    <Select {...defaultState}>\n      <FormControl>\n        <SelectTrigger disabled={disabled} className={cn(className)}>\n          <SelectValue placeholder={placeholder ?? 'Select'} />\n        </SelectTrigger>\n      </FormControl>\n      <SelectContent>\n        {isPending ? (\n          <SelectItem disabled value='loading' className='h-14'>\n            <div className='flex items-center justify-center gap-2'>\n              <Loader className='h-5 w-5 animate-spin' />\n              {'  '}\n              Loading...\n            </div>\n          </SelectItem>\n        ) : (\n          items?.map(({ label, value }) => (\n            <SelectItem key={value} value={value}>\n              {label}\n            </SelectItem>\n          ))\n        )}\n      </SelectContent>\n    </Select>\n  )\n}\n"
  },
  {
    "path": "src/components/sign-out-dialog.tsx",
    "content": "import { useNavigate, useLocation } from '@tanstack/react-router'\nimport { useAuthStore } from '@/stores/auth-store'\nimport { ConfirmDialog } from '@/components/confirm-dialog'\n\ninterface SignOutDialogProps {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nexport function SignOutDialog({ open, onOpenChange }: SignOutDialogProps) {\n  const navigate = useNavigate()\n  const location = useLocation()\n  const { auth } = useAuthStore()\n\n  const handleSignOut = () => {\n    auth.reset()\n    // Preserve current location for redirect after sign-in\n    const currentPath = location.href\n    navigate({\n      to: '/sign-in',\n      search: { redirect: currentPath },\n      replace: true,\n    })\n  }\n\n  return (\n    <ConfirmDialog\n      open={open}\n      onOpenChange={onOpenChange}\n      title='Sign out'\n      desc='Are you sure you want to sign out? You will need to sign in again to access your account.'\n      confirmText='Sign out'\n      destructive\n      handleConfirm={handleSignOut}\n      className='sm:max-w-sm'\n    />\n  )\n}\n"
  },
  {
    "path": "src/components/skip-to-main.tsx",
    "content": "export function SkipToMain() {\n  return (\n    <a\n      className={`fixed start-44 z-999 -translate-y-52 bg-primary px-4 py-2 text-sm font-medium whitespace-nowrap text-primary-foreground opacity-95 shadow-sm transition hover:bg-primary/90 focus:translate-y-3 focus:transform focus-visible:ring-1 focus-visible:ring-ring`}\n      href='#content'\n    >\n      Skip to Main\n    </a>\n  )\n}\n"
  },
  {
    "path": "src/components/theme-switch.tsx",
    "content": "import { useEffect } from 'react'\nimport { Check, Moon, Sun } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useTheme } from '@/context/theme-provider'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\n\nexport function ThemeSwitch() {\n  const { theme, setTheme } = useTheme()\n\n  /* Update theme-color meta tag\n   * when theme is updated */\n  useEffect(() => {\n    const themeColor = theme === 'dark' ? '#020817' : '#fff'\n    const metaThemeColor = document.querySelector(\"meta[name='theme-color']\")\n    if (metaThemeColor) metaThemeColor.setAttribute('content', themeColor)\n  }, [theme])\n\n  return (\n    <DropdownMenu modal={false}>\n      <DropdownMenuTrigger asChild>\n        <Button variant='ghost' size='icon' className='scale-95 rounded-full'>\n          <Sun className='size-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90' />\n          <Moon className='absolute size-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0' />\n          <span className='sr-only'>Toggle theme</span>\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align='end'>\n        <DropdownMenuItem onClick={() => setTheme('light')}>\n          Light{' '}\n          <Check\n            size={14}\n            className={cn('ms-auto', theme !== 'light' && 'hidden')}\n          />\n        </DropdownMenuItem>\n        <DropdownMenuItem onClick={() => setTheme('dark')}>\n          Dark\n          <Check\n            size={14}\n            className={cn('ms-auto', theme !== 'dark' && 'hidden')}\n          />\n        </DropdownMenuItem>\n        <DropdownMenuItem onClick={() => setTheme('system')}>\n          System\n          <Check\n            size={14}\n            className={cn('ms-auto', theme !== 'system' && 'hidden')}\n          />\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n"
  },
  {
    "path": "src/components/ui/alert-dialog.tsx",
    "content": "import * as React from 'react'\nimport * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'\nimport { cn } from '@/lib/utils'\nimport { buttonVariants } from '@/components/ui/button'\n\nfunction AlertDialog({\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {\n  return <AlertDialogPrimitive.Root data-slot='alert-dialog' {...props} />\n}\n\nfunction AlertDialogTrigger({\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\n  return (\n    <AlertDialogPrimitive.Trigger data-slot='alert-dialog-trigger' {...props} />\n  )\n}\n\nfunction AlertDialogPortal({\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\n  return (\n    <AlertDialogPrimitive.Portal data-slot='alert-dialog-portal' {...props} />\n  )\n}\n\nfunction AlertDialogOverlay({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n  return (\n    <AlertDialogPrimitive.Overlay\n      data-slot='alert-dialog-overlay'\n      className={cn(\n        'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogContent({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {\n  return (\n    <AlertDialogPortal>\n      <AlertDialogOverlay />\n      <AlertDialogPrimitive.Content\n        data-slot='alert-dialog-content'\n        className={cn(\n          'fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg',\n          className\n        )}\n        {...props}\n      />\n    </AlertDialogPortal>\n  )\n}\n\nfunction AlertDialogHeader({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='alert-dialog-header'\n      className={cn('flex flex-col gap-2 text-center sm:text-start', className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogFooter({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='alert-dialog-footer'\n      className={cn(\n        'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogTitle({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n  return (\n    <AlertDialogPrimitive.Title\n      data-slot='alert-dialog-title'\n      className={cn('text-lg font-semibold', className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n  return (\n    <AlertDialogPrimitive.Description\n      data-slot='alert-dialog-description'\n      className={cn('text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogAction({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n  return (\n    <AlertDialogPrimitive.Action\n      className={cn(buttonVariants(), className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogCancel({\n  className,\n  ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n  return (\n    <AlertDialogPrimitive.Cancel\n      className={cn(buttonVariants({ variant: 'outline' }), className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  AlertDialog,\n  AlertDialogPortal,\n  AlertDialogOverlay,\n  AlertDialogTrigger,\n  AlertDialogContent,\n  AlertDialogHeader,\n  AlertDialogFooter,\n  AlertDialogTitle,\n  AlertDialogDescription,\n  AlertDialogAction,\n  AlertDialogCancel,\n}\n"
  },
  {
    "path": "src/components/ui/alert.tsx",
    "content": "import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\nconst alertVariants = cva(\n  'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',\n  {\n    variants: {\n      variant: {\n        default: 'bg-card text-card-foreground',\n        destructive:\n          'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n    },\n  }\n)\n\nfunction Alert({\n  className,\n  variant,\n  ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {\n  return (\n    <div\n      data-slot='alert'\n      role='alert'\n      className={cn(alertVariants({ variant }), className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='alert-title'\n      className={cn(\n        'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDescription({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='alert-description'\n      className={cn(\n        'col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Alert, AlertTitle, AlertDescription }\n"
  },
  {
    "path": "src/components/ui/avatar.tsx",
    "content": "import * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\nimport { cn } from '@/lib/utils'\n\nfunction Avatar({\n  className,\n  ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n  return (\n    <AvatarPrimitive.Root\n      data-slot='avatar'\n      className={cn(\n        'relative flex size-8 shrink-0 overflow-hidden rounded-full',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction AvatarImage({\n  className,\n  ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n  return (\n    <AvatarPrimitive.Image\n      data-slot='avatar-image'\n      className={cn('aspect-square size-full', className)}\n      {...props}\n    />\n  )\n}\n\nfunction AvatarFallback({\n  className,\n  ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n  return (\n    <AvatarPrimitive.Fallback\n      data-slot='avatar-fallback'\n      className={cn(\n        'flex size-full items-center justify-center rounded-full bg-muted',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n"
  },
  {
    "path": "src/components/ui/badge.tsx",
    "content": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\nconst badgeVariants = cva(\n  'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',\n  {\n    variants: {\n      variant: {\n        default:\n          'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',\n        secondary:\n          'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',\n        destructive:\n          'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n        outline:\n          'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n    },\n  }\n)\n\nfunction Badge({\n  className,\n  variant,\n  asChild = false,\n  ...props\n}: React.ComponentProps<'span'> &\n  VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot : 'span'\n\n  return (\n    <Comp\n      data-slot='badge'\n      className={cn(badgeVariants({ variant }), className)}\n      {...props}\n    />\n  )\n}\n\nexport { Badge, badgeVariants }\n"
  },
  {
    "path": "src/components/ui/button.tsx",
    "content": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\nconst buttonVariants = cva(\n  \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n  {\n    variants: {\n      variant: {\n        default:\n          'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',\n        destructive:\n          'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n        outline:\n          'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n        secondary:\n          'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',\n        ghost:\n          'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n        link: 'text-primary underline-offset-4 hover:underline',\n      },\n      size: {\n        default: 'h-9 px-4 py-2 has-[>svg]:px-3',\n        sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n        lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n        icon: 'size-9',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  }\n)\n\nfunction Button({\n  className,\n  variant,\n  size,\n  asChild = false,\n  ...props\n}: React.ComponentProps<'button'> &\n  VariantProps<typeof buttonVariants> & {\n    asChild?: boolean\n  }) {\n  const Comp = asChild ? Slot : 'button'\n\n  return (\n    <Comp\n      data-slot='button'\n      className={cn(buttonVariants({ variant, size, className }))}\n      {...props}\n    />\n  )\n}\n\nexport { Button, buttonVariants }\n"
  },
  {
    "path": "src/components/ui/calendar.tsx",
    "content": "import * as React from 'react'\nimport {\n  ChevronDownIcon,\n  ChevronLeftIcon,\n  ChevronRightIcon,\n} from 'lucide-react'\nimport { DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker'\nimport { cn } from '@/lib/utils'\nimport { Button, buttonVariants } from '@/components/ui/button'\n\nfunction Calendar({\n  className,\n  classNames,\n  showOutsideDays = true,\n  captionLayout = 'label',\n  buttonVariant = 'ghost',\n  formatters,\n  components,\n  ...props\n}: React.ComponentProps<typeof DayPicker> & {\n  buttonVariant?: React.ComponentProps<typeof Button>['variant']\n}) {\n  const defaultClassNames = getDefaultClassNames()\n\n  return (\n    <DayPicker\n      showOutsideDays={showOutsideDays}\n      className={cn(\n        'group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',\n        String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n        String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n        className\n      )}\n      captionLayout={captionLayout}\n      formatters={{\n        formatMonthDropdown: (date) =>\n          date.toLocaleString('default', { month: 'short' }),\n        ...formatters,\n      }}\n      classNames={{\n        root: cn('w-fit', defaultClassNames.root),\n        months: cn(\n          'flex gap-4 flex-col md:flex-row relative',\n          defaultClassNames.months\n        ),\n        month: cn('flex flex-col w-full gap-4', defaultClassNames.month),\n        nav: cn(\n          'flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between',\n          defaultClassNames.nav\n        ),\n        button_previous: cn(\n          buttonVariants({ variant: buttonVariant }),\n          'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',\n          defaultClassNames.button_previous\n        ),\n        button_next: cn(\n          buttonVariants({ variant: buttonVariant }),\n          'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',\n          defaultClassNames.button_next\n        ),\n        month_caption: cn(\n          'flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)',\n          defaultClassNames.month_caption\n        ),\n        dropdowns: cn(\n          'w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5',\n          defaultClassNames.dropdowns\n        ),\n        dropdown_root: cn(\n          'relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md',\n          defaultClassNames.dropdown_root\n        ),\n        dropdown: cn(\n          'absolute bg-popover inset-0 opacity-0',\n          defaultClassNames.dropdown\n        ),\n        caption_label: cn(\n          'select-none font-medium',\n          captionLayout === 'label'\n            ? 'text-sm'\n            : 'rounded-md ps-2 pe-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5',\n          defaultClassNames.caption_label\n        ),\n        table: 'w-full border-collapse',\n        weekdays: cn('flex', defaultClassNames.weekdays),\n        weekday: cn(\n          'text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none',\n          defaultClassNames.weekday\n        ),\n        week: cn('flex w-full mt-2', defaultClassNames.week),\n        week_number_header: cn(\n          'select-none w-(--cell-size)',\n          defaultClassNames.week_number_header\n        ),\n        week_number: cn(\n          'text-[0.8rem] select-none text-muted-foreground',\n          defaultClassNames.week_number\n        ),\n        day: cn(\n          'relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none',\n          defaultClassNames.day\n        ),\n        range_start: cn(\n          'rounded-l-md bg-accent',\n          defaultClassNames.range_start\n        ),\n        range_middle: cn('rounded-none', defaultClassNames.range_middle),\n        range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end),\n        today: cn(\n          'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',\n          defaultClassNames.today\n        ),\n        outside: cn(\n          'text-muted-foreground aria-selected:text-muted-foreground',\n          defaultClassNames.outside\n        ),\n        disabled: cn(\n          'text-muted-foreground opacity-50',\n          defaultClassNames.disabled\n        ),\n        hidden: cn('invisible', defaultClassNames.hidden),\n        ...classNames,\n      }}\n      components={{\n        Root: ({ className, rootRef, ...props }) => {\n          return (\n            <div\n              data-slot='calendar'\n              ref={rootRef}\n              className={cn(className)}\n              {...props}\n            />\n          )\n        },\n        Chevron: ({ className, orientation, ...props }) => {\n          if (orientation === 'left') {\n            return (\n              <ChevronLeftIcon className={cn('size-4', className)} {...props} />\n            )\n          }\n\n          if (orientation === 'right') {\n            return (\n              <ChevronRightIcon\n                className={cn('size-4', className)}\n                {...props}\n              />\n            )\n          }\n\n          return (\n            <ChevronDownIcon className={cn('size-4', className)} {...props} />\n          )\n        },\n        DayButton: CalendarDayButton,\n        WeekNumber: ({ children, ...props }) => {\n          return (\n            <td {...props}>\n              <div className='flex size-(--cell-size) items-center justify-center text-center'>\n                {children}\n              </div>\n            </td>\n          )\n        },\n        ...components,\n      }}\n      {...props}\n    />\n  )\n}\n\nfunction CalendarDayButton({\n  className,\n  day,\n  modifiers,\n  ...props\n}: React.ComponentProps<typeof DayButton>) {\n  const defaultClassNames = getDefaultClassNames()\n\n  const ref = React.useRef<HTMLButtonElement>(null)\n  React.useEffect(() => {\n    if (modifiers.focused) ref.current?.focus()\n  }, [modifiers.focused])\n\n  return (\n    <Button\n      ref={ref}\n      variant='ghost'\n      size='icon'\n      data-day={day.date.toLocaleDateString()}\n      data-selected-single={\n        modifiers.selected &&\n        !modifiers.range_start &&\n        !modifiers.range_end &&\n        !modifiers.range_middle\n      }\n      data-range-start={modifiers.range_start}\n      data-range-end={modifiers.range_end}\n      data-range-middle={modifiers.range_middle}\n      className={cn(\n        'flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70',\n        defaultClassNames.day,\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Calendar, CalendarDayButton }\n"
  },
  {
    "path": "src/components/ui/card.tsx",
    "content": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Card({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card'\n      className={cn(\n        'flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-header'\n      className={cn(\n        '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-title'\n      className={cn('leading-none font-semibold', className)}\n      {...props}\n    />\n  )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-description'\n      className={cn('text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-action'\n      className={cn(\n        'col-start-2 row-span-2 row-start-1 self-start justify-self-end',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-content'\n      className={cn('px-6', className)}\n      {...props}\n    />\n  )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='card-footer'\n      className={cn('flex items-center px-6 [.border-t]:pt-6', className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Card,\n  CardHeader,\n  CardFooter,\n  CardTitle,\n  CardAction,\n  CardDescription,\n  CardContent,\n}\n"
  },
  {
    "path": "src/components/ui/checkbox.tsx",
    "content": "import * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { CheckIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction Checkbox({\n  className,\n  ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n  return (\n    <CheckboxPrimitive.Root\n      data-slot='checkbox'\n      className={cn(\n        'peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary',\n        className\n      )}\n      {...props}\n    >\n      <CheckboxPrimitive.Indicator\n        data-slot='checkbox-indicator'\n        className='flex items-center justify-center text-current transition-none'\n      >\n        <CheckIcon className='size-3.5' />\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  )\n}\n\nexport { Checkbox }\n"
  },
  {
    "path": "src/components/ui/collapsible.tsx",
    "content": "import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\n\nfunction Collapsible({\n  ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n  return <CollapsiblePrimitive.Root data-slot='collapsible' {...props} />\n}\n\nfunction CollapsibleTrigger({\n  ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n  return (\n    <CollapsiblePrimitive.CollapsibleTrigger\n      data-slot='collapsible-trigger'\n      {...props}\n    />\n  )\n}\n\nfunction CollapsibleContent({\n  ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n  return (\n    <CollapsiblePrimitive.CollapsibleContent\n      data-slot='collapsible-content'\n      {...props}\n    />\n  )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n"
  },
  {
    "path": "src/components/ui/command.tsx",
    "content": "import * as React from 'react'\nimport { Command as CommandPrimitive } from 'cmdk'\nimport { SearchIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\n\nfunction Command({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n  return (\n    <CommandPrimitive\n      data-slot='command'\n      className={cn(\n        'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandDialog({\n  title = 'Command Palette',\n  description = 'Search for a command to run...',\n  children,\n  className,\n  showCloseButton = true,\n  ...props\n}: React.ComponentProps<typeof Dialog> & {\n  title?: string\n  description?: string\n  className?: string\n  showCloseButton?: boolean\n}) {\n  return (\n    <Dialog {...props}>\n      <DialogHeader className='sr-only'>\n        <DialogTitle>{title}</DialogTitle>\n        <DialogDescription>{description}</DialogDescription>\n      </DialogHeader>\n      <DialogContent\n        className={cn('overflow-hidden p-0', className)}\n        showCloseButton={showCloseButton}\n      >\n        <Command className='**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5'>\n          {children}\n        </Command>\n      </DialogContent>\n    </Dialog>\n  )\n}\n\nfunction CommandInput({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n  return (\n    <div\n      data-slot='command-input-wrapper'\n      className='flex h-9 items-center gap-2 border-b px-3'\n    >\n      <SearchIcon className='size-4 shrink-0 opacity-50' />\n      <CommandPrimitive.Input\n        data-slot='command-input'\n        className={cn(\n          'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',\n          className\n        )}\n        {...props}\n      />\n    </div>\n  )\n}\n\nfunction CommandList({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n  return (\n    <CommandPrimitive.List\n      data-slot='command-list'\n      className={cn(\n        'max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandEmpty({\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n  return (\n    <CommandPrimitive.Empty\n      data-slot='command-empty'\n      className='py-6 text-center text-sm'\n      {...props}\n    />\n  )\n}\n\nfunction CommandGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n  return (\n    <CommandPrimitive.Group\n      data-slot='command-group'\n      className={cn(\n        'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n  return (\n    <CommandPrimitive.Separator\n      data-slot='command-separator'\n      className={cn('-mx-1 h-px bg-border', className)}\n      {...props}\n    />\n  )\n}\n\nfunction CommandItem({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n  return (\n    <CommandPrimitive.Item\n      data-slot='command-item'\n      className={cn(\n        \"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandShortcut({\n  className,\n  ...props\n}: React.ComponentProps<'span'>) {\n  return (\n    <span\n      data-slot='command-shortcut'\n      className={cn(\n        'ms-auto text-xs tracking-widest text-muted-foreground',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Command,\n  CommandDialog,\n  CommandInput,\n  CommandList,\n  CommandEmpty,\n  CommandGroup,\n  CommandItem,\n  CommandShortcut,\n  CommandSeparator,\n}\n"
  },
  {
    "path": "src/components/ui/dialog.tsx",
    "content": "'use client'\n\nimport * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { XIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction Dialog({\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n  return <DialogPrimitive.Root data-slot='dialog' {...props} />\n}\n\nfunction DialogTrigger({\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n  return <DialogPrimitive.Trigger data-slot='dialog-trigger' {...props} />\n}\n\nfunction DialogPortal({\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n  return <DialogPrimitive.Portal data-slot='dialog-portal' {...props} />\n}\n\nfunction DialogClose({\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n  return <DialogPrimitive.Close data-slot='dialog-close' {...props} />\n}\n\nfunction DialogOverlay({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n  return (\n    <DialogPrimitive.Overlay\n      data-slot='dialog-overlay'\n      className={cn(\n        'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction DialogContent({\n  className,\n  children,\n  showCloseButton = true,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n  showCloseButton?: boolean\n}) {\n  return (\n    <DialogPortal data-slot='dialog-portal'>\n      <DialogOverlay />\n      <DialogPrimitive.Content\n        data-slot='dialog-content'\n        className={cn(\n          'fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg',\n          className\n        )}\n        {...props}\n      >\n        {children}\n        {showCloseButton && (\n          <DialogPrimitive.Close\n            data-slot='dialog-close'\n            className=\"absolute end-4 top-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n          >\n            <XIcon />\n            <span className='sr-only'>Close</span>\n          </DialogPrimitive.Close>\n        )}\n      </DialogPrimitive.Content>\n    </DialogPortal>\n  )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='dialog-header'\n      className={cn('flex flex-col gap-2 text-center sm:text-start', className)}\n      {...props}\n    />\n  )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='dialog-footer'\n      className={cn(\n        'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction DialogTitle({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n  return (\n    <DialogPrimitive.Title\n      data-slot='dialog-title'\n      className={cn('text-lg leading-none font-semibold', className)}\n      {...props}\n    />\n  )\n}\n\nfunction DialogDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n  return (\n    <DialogPrimitive.Description\n      data-slot='dialog-description'\n      className={cn('text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogOverlay,\n  DialogPortal,\n  DialogTitle,\n  DialogTrigger,\n}\n"
  },
  {
    "path": "src/components/ui/dropdown-menu.tsx",
    "content": "import * as React from 'react'\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction DropdownMenu({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n  return <DropdownMenuPrimitive.Root data-slot='dropdown-menu' {...props} />\n}\n\nfunction DropdownMenuPortal({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n  return (\n    <DropdownMenuPrimitive.Portal data-slot='dropdown-menu-portal' {...props} />\n  )\n}\n\nfunction DropdownMenuTrigger({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n  return (\n    <DropdownMenuPrimitive.Trigger\n      data-slot='dropdown-menu-trigger'\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuContent({\n  className,\n  sideOffset = 4,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n  return (\n    <DropdownMenuPrimitive.Portal>\n      <DropdownMenuPrimitive.Content\n        data-slot='dropdown-menu-content'\n        sideOffset={sideOffset}\n        className={cn(\n          'z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n          className\n        )}\n        {...props}\n      />\n    </DropdownMenuPrimitive.Portal>\n  )\n}\n\nfunction DropdownMenuGroup({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n  return (\n    <DropdownMenuPrimitive.Group data-slot='dropdown-menu-group' {...props} />\n  )\n}\n\nfunction DropdownMenuItem({\n  className,\n  inset,\n  variant = 'default',\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n  inset?: boolean\n  variant?: 'default' | 'destructive'\n}) {\n  return (\n    <DropdownMenuPrimitive.Item\n      data-slot='dropdown-menu-item'\n      data-inset={inset}\n      data-variant={variant}\n      className={cn(\n        \"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:ps-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:!text-destructive\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuCheckboxItem({\n  className,\n  children,\n  checked,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n  return (\n    <DropdownMenuPrimitive.CheckboxItem\n      data-slot='dropdown-menu-checkbox-item'\n      className={cn(\n        \"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className\n      )}\n      checked={checked}\n      {...props}\n    >\n      <span className='pointer-events-none absolute start-2 flex size-3.5 items-center justify-center'>\n        <DropdownMenuPrimitive.ItemIndicator>\n          <CheckIcon className='size-4' />\n        </DropdownMenuPrimitive.ItemIndicator>\n      </span>\n      {children}\n    </DropdownMenuPrimitive.CheckboxItem>\n  )\n}\n\nfunction DropdownMenuRadioGroup({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n  return (\n    <DropdownMenuPrimitive.RadioGroup\n      data-slot='dropdown-menu-radio-group'\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuRadioItem({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n  return (\n    <DropdownMenuPrimitive.RadioItem\n      data-slot='dropdown-menu-radio-item'\n      className={cn(\n        \"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className\n      )}\n      {...props}\n    >\n      <span className='pointer-events-none absolute start-2 flex size-3.5 items-center justify-center'>\n        <DropdownMenuPrimitive.ItemIndicator>\n          <CircleIcon className='size-2 fill-current' />\n        </DropdownMenuPrimitive.ItemIndicator>\n      </span>\n      {children}\n    </DropdownMenuPrimitive.RadioItem>\n  )\n}\n\nfunction DropdownMenuLabel({\n  className,\n  inset,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n  inset?: boolean\n}) {\n  return (\n    <DropdownMenuPrimitive.Label\n      data-slot='dropdown-menu-label'\n      data-inset={inset}\n      className={cn(\n        'px-2 py-1.5 text-sm font-medium data-[inset]:ps-8',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n  return (\n    <DropdownMenuPrimitive.Separator\n      data-slot='dropdown-menu-separator'\n      className={cn('-mx-1 my-1 h-px bg-border', className)}\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuShortcut({\n  className,\n  ...props\n}: React.ComponentProps<'span'>) {\n  return (\n    <span\n      data-slot='dropdown-menu-shortcut'\n      className={cn(\n        'ms-auto text-xs tracking-widest text-muted-foreground',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction DropdownMenuSub({\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n  return <DropdownMenuPrimitive.Sub data-slot='dropdown-menu-sub' {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n  className,\n  inset,\n  children,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n  inset?: boolean\n}) {\n  return (\n    <DropdownMenuPrimitive.SubTrigger\n      data-slot='dropdown-menu-sub-trigger'\n      data-inset={inset}\n      className={cn(\n        'flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[inset]:ps-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <ChevronRightIcon className='ms-auto size-4' />\n    </DropdownMenuPrimitive.SubTrigger>\n  )\n}\n\nfunction DropdownMenuSubContent({\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n  return (\n    <DropdownMenuPrimitive.SubContent\n      data-slot='dropdown-menu-sub-content'\n      className={cn(\n        'z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  DropdownMenu,\n  DropdownMenuPortal,\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuLabel,\n  DropdownMenuItem,\n  DropdownMenuCheckboxItem,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubTrigger,\n  DropdownMenuSubContent,\n}\n"
  },
  {
    "path": "src/components/ui/form.tsx",
    "content": "import * as React from 'react'\nimport {\n  Controller,\n  FormProvider,\n  useFormContext,\n  useFormState,\n  type ControllerProps,\n  type FieldPath,\n  type FieldValues,\n} from 'react-hook-form'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cn } from '@/lib/utils'\nimport { Label } from '@/components/ui/label'\n\nconst Form = FormProvider\n\ntype FormFieldContextValue<\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n  name: TName\n}\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>(\n  {} as FormFieldContextValue\n)\n\nconst FormField = <\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n  ...props\n}: ControllerProps<TFieldValues, TName>) => {\n  return (\n    <FormFieldContext.Provider value={{ name: props.name }}>\n      <Controller {...props} />\n    </FormFieldContext.Provider>\n  )\n}\n\nconst useFormField = () => {\n  const fieldContext = React.useContext(FormFieldContext)\n  const itemContext = React.useContext(FormItemContext)\n  const { getFieldState } = useFormContext()\n  const formState = useFormState({ name: fieldContext.name })\n  const fieldState = getFieldState(fieldContext.name, formState)\n\n  if (!fieldContext) {\n    throw new Error('useFormField should be used within <FormField>')\n  }\n\n  const { id } = itemContext\n\n  return {\n    id,\n    name: fieldContext.name,\n    formItemId: `${id}-form-item`,\n    formDescriptionId: `${id}-form-item-description`,\n    formMessageId: `${id}-form-item-message`,\n    ...fieldState,\n  }\n}\n\ntype FormItemContextValue = {\n  id: string\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n  {} as FormItemContextValue\n)\n\nfunction FormItem({ className, ...props }: React.ComponentProps<'div'>) {\n  const id = React.useId()\n\n  return (\n    <FormItemContext.Provider value={{ id }}>\n      <div\n        data-slot='form-item'\n        className={cn('grid gap-2', className)}\n        {...props}\n      />\n    </FormItemContext.Provider>\n  )\n}\n\nfunction FormLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n  const { error, formItemId } = useFormField()\n\n  return (\n    <Label\n      data-slot='form-label'\n      data-error={!!error}\n      className={cn('data-[error=true]:text-destructive', className)}\n      htmlFor={formItemId}\n      {...props}\n    />\n  )\n}\n\nfunction FormControl({ ...props }: React.ComponentProps<typeof Slot>) {\n  const { error, formItemId, formDescriptionId, formMessageId } = useFormField()\n\n  return (\n    <Slot\n      data-slot='form-control'\n      id={formItemId}\n      aria-describedby={\n        !error\n          ? `${formDescriptionId}`\n          : `${formDescriptionId} ${formMessageId}`\n      }\n      aria-invalid={!!error}\n      {...props}\n    />\n  )\n}\n\nfunction FormDescription({ className, ...props }: React.ComponentProps<'p'>) {\n  const { formDescriptionId } = useFormField()\n\n  return (\n    <p\n      data-slot='form-description'\n      id={formDescriptionId}\n      className={cn('text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nfunction FormMessage({ className, ...props }: React.ComponentProps<'p'>) {\n  const { error, formMessageId } = useFormField()\n  const body = error ? String(error?.message ?? '') : props.children\n\n  if (!body) {\n    return null\n  }\n\n  return (\n    <p\n      data-slot='form-message'\n      id={formMessageId}\n      className={cn('text-sm text-destructive', className)}\n      {...props}\n    >\n      {body}\n    </p>\n  )\n}\n\nexport {\n  useFormField,\n  Form,\n  FormItem,\n  FormLabel,\n  FormControl,\n  FormDescription,\n  FormMessage,\n  FormField,\n}\n"
  },
  {
    "path": "src/components/ui/input-otp.tsx",
    "content": "import * as React from 'react'\nimport { OTPInput, OTPInputContext } from 'input-otp'\nimport { MinusIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction InputOTP({\n  className,\n  containerClassName,\n  ...props\n}: React.ComponentProps<typeof OTPInput> & {\n  containerClassName?: string\n}) {\n  return (\n    <OTPInput\n      data-slot='input-otp'\n      containerClassName={cn(\n        'flex items-center gap-2 has-disabled:opacity-50',\n        containerClassName\n      )}\n      className={cn('disabled:cursor-not-allowed', className)}\n      {...props}\n    />\n  )\n}\n\nfunction InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='input-otp-group'\n      className={cn('flex items-center', className)}\n      {...props}\n    />\n  )\n}\n\nfunction InputOTPSlot({\n  index,\n  className,\n  ...props\n}: React.ComponentProps<'div'> & {\n  index: number\n}) {\n  const inputOTPContext = React.useContext(OTPInputContext)\n  const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}\n\n  return (\n    <div\n      data-slot='input-otp-slot'\n      data-active={isActive}\n      className={cn(\n        'relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-[3px] data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40',\n        className\n      )}\n      {...props}\n    >\n      {char}\n      {hasFakeCaret && (\n        <div className='pointer-events-none absolute inset-0 flex items-center justify-center'>\n          <div className='h-4 w-px animate-caret-blink bg-foreground duration-1000' />\n        </div>\n      )}\n    </div>\n  )\n}\n\nfunction InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div data-slot='input-otp-separator' role='separator' {...props}>\n      <MinusIcon />\n    </div>\n  )\n}\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n"
  },
  {
    "path": "src/components/ui/input.tsx",
    "content": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Input({ className, type, ...props }: React.ComponentProps<'input'>) {\n  return (\n    <input\n      type={type}\n      data-slot='input'\n      className={cn(\n        'flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30',\n        'focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',\n        'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Input }\n"
  },
  {
    "path": "src/components/ui/label.tsx",
    "content": "'use client'\n\nimport * as React from 'react'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { cn } from '@/lib/utils'\n\nfunction Label({\n  className,\n  ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n  return (\n    <LabelPrimitive.Root\n      data-slot='label'\n      className={cn(\n        'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Label }\n"
  },
  {
    "path": "src/components/ui/popover.tsx",
    "content": "import * as React from 'react'\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport { cn } from '@/lib/utils'\n\nfunction Popover({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n  return <PopoverPrimitive.Root data-slot='popover' {...props} />\n}\n\nfunction PopoverTrigger({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n  return <PopoverPrimitive.Trigger data-slot='popover-trigger' {...props} />\n}\n\nfunction PopoverContent({\n  className,\n  align = 'center',\n  sideOffset = 4,\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n  return (\n    <PopoverPrimitive.Portal>\n      <PopoverPrimitive.Content\n        data-slot='popover-content'\n        align={align}\n        sideOffset={sideOffset}\n        className={cn(\n          'z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n          className\n        )}\n        {...props}\n      />\n    </PopoverPrimitive.Portal>\n  )\n}\n\nfunction PopoverAnchor({\n  ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n  return <PopoverPrimitive.Anchor data-slot='popover-anchor' {...props} />\n}\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }\n"
  },
  {
    "path": "src/components/ui/radio-group.tsx",
    "content": "import * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { CircleIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction RadioGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {\n  return (\n    <RadioGroupPrimitive.Root\n      data-slot='radio-group'\n      className={cn('grid gap-3', className)}\n      {...props}\n    />\n  )\n}\n\nfunction RadioGroupItem({\n  className,\n  ...props\n}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {\n  return (\n    <RadioGroupPrimitive.Item\n      data-slot='radio-group-item'\n      className={cn(\n        'aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40',\n        className\n      )}\n      {...props}\n    >\n      <RadioGroupPrimitive.Indicator\n        data-slot='radio-group-indicator'\n        className='relative flex items-center justify-center'\n      >\n        <CircleIcon className='absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary' />\n      </RadioGroupPrimitive.Indicator>\n    </RadioGroupPrimitive.Item>\n  )\n}\n\nexport { RadioGroup, RadioGroupItem }\n"
  },
  {
    "path": "src/components/ui/scroll-area.tsx",
    "content": "import * as React from 'react'\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'\nimport { cn } from '@/lib/utils'\n\ninterface ScrollAreaProps extends React.ComponentProps<\n  typeof ScrollAreaPrimitive.Root\n> {\n  orientation?: 'vertical' | 'horizontal'\n}\n\nfunction ScrollArea({\n  className,\n  children,\n  orientation = 'vertical',\n  ...props\n}: ScrollAreaProps) {\n  return (\n    <ScrollAreaPrimitive.Root\n      data-slot='scroll-area'\n      className={cn('relative', className)}\n      {...props}\n    >\n      <ScrollAreaPrimitive.Viewport\n        data-slot='scroll-area-viewport'\n        className={cn(\n          'size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1',\n          orientation === 'horizontal' && 'overflow-x-auto!'\n        )}\n      >\n        {children}\n      </ScrollAreaPrimitive.Viewport>\n      <ScrollBar orientation={orientation} />\n      <ScrollAreaPrimitive.Corner />\n    </ScrollAreaPrimitive.Root>\n  )\n}\n\nfunction ScrollBar({\n  className,\n  orientation = 'vertical',\n  ...props\n}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {\n  return (\n    <ScrollAreaPrimitive.ScrollAreaScrollbar\n      data-slot='scroll-area-scrollbar'\n      orientation={orientation}\n      className={cn(\n        'flex touch-none p-px transition-colors select-none',\n        orientation === 'vertical' &&\n          'h-full w-2.5 border-l border-l-transparent',\n        orientation === 'horizontal' &&\n          'h-2.5 flex-col border-t border-t-transparent',\n        className\n      )}\n      {...props}\n    >\n      <ScrollAreaPrimitive.ScrollAreaThumb\n        data-slot='scroll-area-thumb'\n        className='relative flex-1 rounded-full bg-border'\n      />\n    </ScrollAreaPrimitive.ScrollAreaScrollbar>\n  )\n}\n\nexport { ScrollArea, ScrollBar }\n"
  },
  {
    "path": "src/components/ui/select.tsx",
    "content": "import * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction Select({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n  return <SelectPrimitive.Root data-slot='select' {...props} />\n}\n\nfunction SelectGroup({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n  return <SelectPrimitive.Group data-slot='select-group' {...props} />\n}\n\nfunction SelectValue({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n  return <SelectPrimitive.Value data-slot='select-value' {...props} />\n}\n\nfunction SelectTrigger({\n  className,\n  size = 'default',\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n  size?: 'sm' | 'default'\n}) {\n  return (\n    <SelectPrimitive.Trigger\n      data-slot='select-trigger'\n      data-size={size}\n      className={cn(\n        \"flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <SelectPrimitive.Icon asChild>\n        <ChevronDownIcon className='size-4 opacity-50' />\n      </SelectPrimitive.Icon>\n    </SelectPrimitive.Trigger>\n  )\n}\n\nfunction SelectContent({\n  className,\n  children,\n  position = 'popper',\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n  return (\n    <SelectPrimitive.Portal>\n      <SelectPrimitive.Content\n        data-slot='select-content'\n        className={cn(\n          'relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n          position === 'popper' &&\n            'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n          className\n        )}\n        position={position}\n        {...props}\n      >\n        <SelectScrollUpButton />\n        <SelectPrimitive.Viewport\n          className={cn(\n            'p-1',\n            position === 'popper' &&\n              'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1'\n          )}\n        >\n          {children}\n        </SelectPrimitive.Viewport>\n        <SelectScrollDownButton />\n      </SelectPrimitive.Content>\n    </SelectPrimitive.Portal>\n  )\n}\n\nfunction SelectLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n  return (\n    <SelectPrimitive.Label\n      data-slot='select-label'\n      className={cn('px-2 py-1.5 text-xs text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectItem({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n  return (\n    <SelectPrimitive.Item\n      data-slot='select-item'\n      className={cn(\n        \"relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 ps-2 pe-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n        className\n      )}\n      {...props}\n    >\n      <span className='absolute end-2 flex size-3.5 items-center justify-center'>\n        <SelectPrimitive.ItemIndicator>\n          <CheckIcon className='size-4' />\n        </SelectPrimitive.ItemIndicator>\n      </span>\n      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n    </SelectPrimitive.Item>\n  )\n}\n\nfunction SelectSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n  return (\n    <SelectPrimitive.Separator\n      data-slot='select-separator'\n      className={cn('pointer-events-none -mx-1 my-1 h-px bg-border', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectScrollUpButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n  return (\n    <SelectPrimitive.ScrollUpButton\n      data-slot='select-scroll-up-button'\n      className={cn(\n        'flex cursor-default items-center justify-center py-1',\n        className\n      )}\n      {...props}\n    >\n      <ChevronUpIcon className='size-4' />\n    </SelectPrimitive.ScrollUpButton>\n  )\n}\n\nfunction SelectScrollDownButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n  return (\n    <SelectPrimitive.ScrollDownButton\n      data-slot='select-scroll-down-button'\n      className={cn(\n        'flex cursor-default items-center justify-center py-1',\n        className\n      )}\n      {...props}\n    >\n      <ChevronDownIcon className='size-4' />\n    </SelectPrimitive.ScrollDownButton>\n  )\n}\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectScrollDownButton,\n  SelectScrollUpButton,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n}\n"
  },
  {
    "path": "src/components/ui/separator.tsx",
    "content": "import * as React from 'react'\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\nimport { cn } from '@/lib/utils'\n\nfunction Separator({\n  className,\n  orientation = 'horizontal',\n  decorative = true,\n  ...props\n}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {\n  return (\n    <SeparatorPrimitive.Root\n      data-slot='separator'\n      decorative={decorative}\n      orientation={orientation}\n      className={cn(\n        'shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Separator }\n"
  },
  {
    "path": "src/components/ui/sheet.tsx",
    "content": "import * as React from 'react'\nimport * as SheetPrimitive from '@radix-ui/react-dialog'\nimport { XIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nfunction Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {\n  return <SheetPrimitive.Root data-slot='sheet' {...props} />\n}\n\nfunction SheetTrigger({\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {\n  return <SheetPrimitive.Trigger data-slot='sheet-trigger' {...props} />\n}\n\nfunction SheetClose({\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Close>) {\n  return <SheetPrimitive.Close data-slot='sheet-close' {...props} />\n}\n\nfunction SheetPortal({\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Portal>) {\n  return <SheetPrimitive.Portal data-slot='sheet-portal' {...props} />\n}\n\nfunction SheetOverlay({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {\n  return (\n    <SheetPrimitive.Overlay\n      data-slot='sheet-overlay'\n      className={cn(\n        'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SheetContent({\n  className,\n  children,\n  side = 'right',\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & {\n  side?: 'top' | 'right' | 'bottom' | 'left'\n}) {\n  return (\n    <SheetPortal>\n      <SheetOverlay />\n      <SheetPrimitive.Content\n        data-slot='sheet-content'\n        className={cn(\n          'fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500',\n          side === 'right' &&\n            'inset-y-0 end-0 h-full w-3/4 border-s data-[state=closed]:slide-out-to-end data-[state=open]:slide-in-from-end sm:max-w-sm',\n          side === 'left' &&\n            'inset-y-0 start-0 h-full w-3/4 border-e data-[state=closed]:slide-out-to-start data-[state=open]:slide-in-from-start sm:max-w-sm',\n          side === 'top' &&\n            'inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',\n          side === 'bottom' &&\n            'inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',\n          className\n        )}\n        {...props}\n      >\n        {children}\n        <SheetPrimitive.Close className='absolute end-4 top-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary'>\n          <XIcon className='size-4' />\n          <span className='sr-only'>Close</span>\n        </SheetPrimitive.Close>\n      </SheetPrimitive.Content>\n    </SheetPortal>\n  )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sheet-header'\n      className={cn('flex flex-col gap-1.5 p-4', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sheet-footer'\n      className={cn('mt-auto flex flex-col gap-2 p-4', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetTitle({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Title>) {\n  return (\n    <SheetPrimitive.Title\n      data-slot='sheet-title'\n      className={cn('font-semibold text-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Description>) {\n  return (\n    <SheetPrimitive.Description\n      data-slot='sheet-description'\n      className={cn('text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Sheet,\n  SheetTrigger,\n  SheetClose,\n  SheetContent,\n  SheetHeader,\n  SheetFooter,\n  SheetTitle,\n  SheetDescription,\n}\n"
  },
  {
    "path": "src/components/ui/sidebar.tsx",
    "content": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { VariantProps, cva } from 'class-variance-authority'\nimport { PanelLeftIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useIsMobile } from '@/hooks/use-mobile'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Separator } from '@/components/ui/separator'\nimport {\n  Sheet,\n  SheetContent,\n  SheetDescription,\n  SheetHeader,\n  SheetTitle,\n} from '@/components/ui/sheet'\nimport { Skeleton } from '@/components/ui/skeleton'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\n\nconst SIDEBAR_COOKIE_NAME = 'sidebar_state'\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = '16rem'\nconst SIDEBAR_WIDTH_MOBILE = '18rem'\nconst SIDEBAR_WIDTH_ICON = '3rem'\nconst SIDEBAR_KEYBOARD_SHORTCUT = 'b'\n\ntype SidebarContextProps = {\n  state: 'expanded' | 'collapsed'\n  open: boolean\n  setOpen: (open: boolean) => void\n  openMobile: boolean\n  setOpenMobile: (open: boolean) => void\n  isMobile: boolean\n  toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\n\nfunction useSidebar() {\n  const context = React.useContext(SidebarContext)\n  if (!context) {\n    throw new Error('useSidebar must be used within a SidebarProvider.')\n  }\n\n  return context\n}\n\nfunction SidebarProvider({\n  defaultOpen = true,\n  open: openProp,\n  onOpenChange: setOpenProp,\n  className,\n  style,\n  children,\n  ...props\n}: React.ComponentProps<'div'> & {\n  defaultOpen?: boolean\n  open?: boolean\n  onOpenChange?: (open: boolean) => void\n}) {\n  const isMobile = useIsMobile()\n  const [openMobile, setOpenMobile] = React.useState(false)\n\n  // This is the internal state of the sidebar.\n  // We use openProp and setOpenProp for control from outside the component.\n  const [_open, _setOpen] = React.useState(defaultOpen)\n  const open = openProp ?? _open\n  const setOpen = React.useCallback(\n    (value: boolean | ((value: boolean) => boolean)) => {\n      const openState = typeof value === 'function' ? value(open) : value\n      if (setOpenProp) {\n        setOpenProp(openState)\n      } else {\n        _setOpen(openState)\n      }\n\n      // This sets the cookie to keep the sidebar state.\n      document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n    },\n    [setOpenProp, open]\n  )\n\n  // Helper to toggle the sidebar.\n  const toggleSidebar = React.useCallback(() => {\n    return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\n  }, [isMobile, setOpen, setOpenMobile])\n\n  // Adds a keyboard shortcut to toggle the sidebar.\n  React.useEffect(() => {\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (\n        event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n        (event.metaKey || event.ctrlKey)\n      ) {\n        event.preventDefault()\n        toggleSidebar()\n      }\n    }\n\n    window.addEventListener('keydown', handleKeyDown)\n    return () => window.removeEventListener('keydown', handleKeyDown)\n  }, [toggleSidebar])\n\n  // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n  // This makes it easier to style the sidebar with Tailwind classes.\n  const state = open ? 'expanded' : 'collapsed'\n\n  const contextValue = React.useMemo<SidebarContextProps>(\n    () => ({\n      state,\n      open,\n      setOpen,\n      isMobile,\n      openMobile,\n      setOpenMobile,\n      toggleSidebar,\n    }),\n    [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\n  )\n\n  return (\n    <SidebarContext.Provider value={contextValue}>\n      <TooltipProvider delayDuration={0}>\n        <div\n          data-slot='sidebar-wrapper'\n          style={\n            {\n              '--sidebar-width': SIDEBAR_WIDTH,\n              '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,\n              ...style,\n            } as React.CSSProperties\n          }\n          className={cn(\n            'group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar',\n            className\n          )}\n          {...props}\n        >\n          {children}\n        </div>\n      </TooltipProvider>\n    </SidebarContext.Provider>\n  )\n}\n\nfunction Sidebar({\n  side = 'left',\n  variant = 'sidebar',\n  collapsible = 'offcanvas',\n  className,\n  children,\n  ...props\n}: React.ComponentProps<'div'> & {\n  side?: 'left' | 'right'\n  variant?: 'sidebar' | 'floating' | 'inset'\n  collapsible?: 'offcanvas' | 'icon' | 'none'\n}) {\n  const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n  if (collapsible === 'none') {\n    return (\n      <div\n        data-slot='sidebar'\n        className={cn(\n          'flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground',\n          className\n        )}\n        {...props}\n      >\n        {children}\n      </div>\n    )\n  }\n\n  if (isMobile) {\n    return (\n      <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n        <SheetContent\n          data-sidebar='sidebar'\n          data-slot='sidebar'\n          data-mobile='true'\n          className='w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden'\n          style={\n            {\n              '--sidebar-width': SIDEBAR_WIDTH_MOBILE,\n            } as React.CSSProperties\n          }\n          side={side}\n        >\n          <SheetHeader className='sr-only'>\n            <SheetTitle>Sidebar</SheetTitle>\n            <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n          </SheetHeader>\n          <div className='flex h-full w-full flex-col'>{children}</div>\n        </SheetContent>\n      </Sheet>\n    )\n  }\n\n  return (\n    <div\n      className='group peer hidden text-sidebar-foreground md:block'\n      data-state={state}\n      data-collapsible={state === 'collapsed' ? collapsible : ''}\n      data-variant={variant}\n      data-side={side}\n      data-slot='sidebar'\n    >\n      {/* This is what handles the sidebar gap on desktop */}\n      <div\n        data-slot='sidebar-gap'\n        className={cn(\n          'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',\n          'group-data-[collapsible=offcanvas]:w-0',\n          'group-data-[side=right]:rotate-180',\n          variant === 'floating' || variant === 'inset'\n            ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'\n            : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)'\n        )}\n      />\n      <div\n        data-slot='sidebar-container'\n        className={cn(\n          'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[inset-inline,width] duration-200 ease-linear md:flex',\n          side === 'left'\n            ? 'start-0 group-data-[collapsible=offcanvas]:-start-[calc(var(--sidebar-width))]'\n            : 'end-0 group-data-[collapsible=offcanvas]:-end-[calc(var(--sidebar-width))]',\n          // Adjust the padding for floating and inset variants.\n          variant === 'floating' || variant === 'inset'\n            ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'\n            : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-e group-data-[side=right]:border-s',\n          className\n        )}\n        {...props}\n      >\n        <div\n          data-sidebar='sidebar'\n          data-slot='sidebar-inner'\n          className='flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm'\n        >\n          {children}\n        </div>\n      </div>\n    </div>\n  )\n}\n\nfunction SidebarTrigger({\n  className,\n  onClick,\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  const { toggleSidebar } = useSidebar()\n\n  return (\n    <Button\n      data-sidebar='trigger'\n      data-slot='sidebar-trigger'\n      variant='ghost'\n      size='icon'\n      className={cn('size-7', className)}\n      onClick={(event) => {\n        onClick?.(event)\n        toggleSidebar()\n      }}\n      {...props}\n    >\n      <PanelLeftIcon />\n      <span className='sr-only'>Toggle Sidebar</span>\n    </Button>\n  )\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<'button'>) {\n  const { toggleSidebar } = useSidebar()\n\n  return (\n    <button\n      data-sidebar='rail'\n      data-slot='sidebar-rail'\n      aria-label='Toggle Sidebar'\n      tabIndex={-1}\n      onClick={toggleSidebar}\n      title='Toggle Sidebar'\n      className={cn(\n        'absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-end-4 group-data-[side=right]:start-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex',\n        'in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize',\n        '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',\n        'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:start-full hover:group-data-[collapsible=offcanvas]:bg-sidebar',\n        '[[data-side=left][data-collapsible=offcanvas]_&]:-end-2',\n        '[[data-side=right][data-collapsible=offcanvas]_&]:-start-2',\n\n        // RTL support\n        'rtl:translate-x-1/2',\n        'rtl:in-data-[side=left]:cursor-e-resize rtl:in-data-[side=right]:cursor-w-resize',\n        'rtl:[[data-side=left][data-state=collapsed]_&]:cursor-w-resize rtl:[[data-side=right][data-state=collapsed]_&]:cursor-e-resize',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-inset'\n      className={cn(\n        'relative flex w-full flex-1 flex-col bg-background',\n        'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarInput({\n  className,\n  ...props\n}: React.ComponentProps<typeof Input>) {\n  return (\n    <Input\n      data-slot='sidebar-input'\n      data-sidebar='input'\n      className={cn('h-8 w-full bg-background shadow-none', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-header'\n      data-sidebar='header'\n      className={cn('flex flex-col gap-2 p-2', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-footer'\n      data-sidebar='footer'\n      className={cn('flex flex-col gap-2 p-2', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof Separator>) {\n  return (\n    <Separator\n      data-slot='sidebar-separator'\n      data-sidebar='separator'\n      className={cn('mx-2 w-auto bg-sidebar-border', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-content'\n      data-sidebar='content'\n      className={cn(\n        'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-group'\n      data-sidebar='group'\n      className={cn('relative flex w-full min-w-0 flex-col p-2', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarGroupLabel({\n  className,\n  asChild = false,\n  ...props\n}: React.ComponentProps<'div'> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot : 'div'\n\n  return (\n    <Comp\n      data-slot='sidebar-group-label'\n      data-sidebar='group-label'\n      className={cn(\n        'flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarGroupAction({\n  className,\n  asChild = false,\n  ...props\n}: React.ComponentProps<'button'> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot : 'button'\n\n  return (\n    <Comp\n      data-slot='sidebar-group-action'\n      data-sidebar='group-action'\n      className={cn(\n        'absolute end-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        // Increases the hit area of the button on mobile.\n        'after:absolute after:-inset-2 md:after:hidden',\n        'group-data-[collapsible=icon]:hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarGroupContent({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-group-content'\n      data-sidebar='group-content'\n      className={cn('w-full text-sm', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {\n  return (\n    <ul\n      data-slot='sidebar-menu'\n      data-sidebar='menu'\n      className={cn('flex w-full min-w-0 flex-col gap-1', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>) {\n  return (\n    <li\n      data-slot='sidebar-menu-item'\n      data-sidebar='menu-item'\n      className={cn('group/menu-item relative', className)}\n      {...props}\n    />\n  )\n}\n\nconst sidebarMenuButtonVariants = cva(\n  'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-start text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pe-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',\n  {\n    variants: {\n      variant: {\n        default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',\n        outline:\n          'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',\n      },\n      size: {\n        default: 'h-8 text-sm',\n        sm: 'h-7 text-xs',\n        lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  }\n)\n\nfunction SidebarMenuButton({\n  asChild = false,\n  isActive = false,\n  variant = 'default',\n  size = 'default',\n  tooltip,\n  className,\n  ...props\n}: React.ComponentProps<'button'> & {\n  asChild?: boolean\n  isActive?: boolean\n  tooltip?: string | React.ComponentProps<typeof TooltipContent>\n} & VariantProps<typeof sidebarMenuButtonVariants>) {\n  const Comp = asChild ? Slot : 'button'\n  const { isMobile, state } = useSidebar()\n\n  const button = (\n    <Comp\n      data-slot='sidebar-menu-button'\n      data-sidebar='menu-button'\n      data-size={size}\n      data-active={isActive}\n      className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\n      {...props}\n    />\n  )\n\n  if (!tooltip) {\n    return button\n  }\n\n  if (typeof tooltip === 'string') {\n    tooltip = {\n      children: tooltip,\n    }\n  }\n\n  return (\n    <Tooltip>\n      <TooltipTrigger asChild>{button}</TooltipTrigger>\n      <TooltipContent\n        side='right'\n        align='center'\n        hidden={state !== 'collapsed' || isMobile}\n        {...tooltip}\n      />\n    </Tooltip>\n  )\n}\n\nfunction SidebarMenuAction({\n  className,\n  asChild = false,\n  showOnHover = false,\n  ...props\n}: React.ComponentProps<'button'> & {\n  asChild?: boolean\n  showOnHover?: boolean\n}) {\n  const Comp = asChild ? Slot : 'button'\n\n  return (\n    <Comp\n      data-slot='sidebar-menu-action'\n      data-sidebar='menu-action'\n      className={cn(\n        'absolute end-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\n        // Increases the hit area of the button on mobile.\n        'after:absolute after:-inset-2 md:after:hidden',\n        'peer-data-[size=sm]/menu-button:top-1',\n        'peer-data-[size=default]/menu-button:top-1.5',\n        'peer-data-[size=lg]/menu-button:top-2.5',\n        'group-data-[collapsible=icon]:hidden',\n        showOnHover &&\n          'group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground data-[state=open]:opacity-100 md:opacity-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenuBadge({\n  className,\n  ...props\n}: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='sidebar-menu-badge'\n      data-sidebar='menu-badge'\n      className={cn(\n        'pointer-events-none absolute end-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none',\n        'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',\n        'peer-data-[size=sm]/menu-button:top-1',\n        'peer-data-[size=default]/menu-button:top-1.5',\n        'peer-data-[size=lg]/menu-button:top-2.5',\n        'group-data-[collapsible=icon]:hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenuSkeleton({\n  className,\n  showIcon = false,\n  ...props\n}: React.ComponentProps<'div'> & {\n  showIcon?: boolean\n}) {\n  // Random width between 50 to 90%.\n  const width = React.useMemo(() => {\n    return `${Math.floor(Math.random() * 40) + 50}%`\n  }, [])\n\n  return (\n    <div\n      data-slot='sidebar-menu-skeleton'\n      data-sidebar='menu-skeleton'\n      className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}\n      {...props}\n    >\n      {showIcon && (\n        <Skeleton\n          className='size-4 rounded-md'\n          data-sidebar='menu-skeleton-icon'\n        />\n      )}\n      <Skeleton\n        className='h-4 max-w-(--skeleton-width) flex-1'\n        data-sidebar='menu-skeleton-text'\n        style={\n          {\n            '--skeleton-width': width,\n          } as React.CSSProperties\n        }\n      />\n    </div>\n  )\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>) {\n  return (\n    <ul\n      data-slot='sidebar-menu-sub'\n      data-sidebar='menu-sub'\n      className={cn(\n        'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-s border-sidebar-border px-2.5 py-0.5',\n        'group-data-[collapsible=icon]:hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenuSubItem({\n  className,\n  ...props\n}: React.ComponentProps<'li'>) {\n  return (\n    <li\n      data-slot='sidebar-menu-sub-item'\n      data-sidebar='menu-sub-item'\n      className={cn('group/menu-sub-item relative', className)}\n      {...props}\n    />\n  )\n}\n\nfunction SidebarMenuSubButton({\n  asChild = false,\n  size = 'md',\n  isActive = false,\n  className,\n  ...props\n}: React.ComponentProps<'a'> & {\n  asChild?: boolean\n  size?: 'sm' | 'md'\n  isActive?: boolean\n}) {\n  const Comp = asChild ? Slot : 'a'\n\n  return (\n    <Comp\n      data-slot='sidebar-menu-sub-button'\n      data-sidebar='menu-sub-button'\n      data-size={size}\n      data-active={isActive}\n      className={cn(\n        'flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-inherit',\n        'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',\n        size === 'sm' && 'text-xs',\n        size === 'md' && 'text-sm',\n        'group-data-[collapsible=icon]:hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupAction,\n  SidebarGroupContent,\n  SidebarGroupLabel,\n  SidebarHeader,\n  SidebarInput,\n  SidebarInset,\n  SidebarMenu,\n  SidebarMenuAction,\n  SidebarMenuBadge,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  SidebarMenuSkeleton,\n  SidebarMenuSub,\n  SidebarMenuSubButton,\n  SidebarMenuSubItem,\n  SidebarProvider,\n  SidebarRail,\n  SidebarSeparator,\n  SidebarTrigger,\n  useSidebar,\n}\n"
  },
  {
    "path": "src/components/ui/skeleton.tsx",
    "content": "import { cn } from '@/lib/utils'\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='skeleton'\n      className={cn('animate-pulse rounded-md bg-accent', className)}\n      {...props}\n    />\n  )\n}\n\nexport { Skeleton }\n"
  },
  {
    "path": "src/components/ui/sonner.tsx",
    "content": "import { Toaster as Sonner, ToasterProps } from 'sonner'\nimport { useTheme } from '@/context/theme-provider'\n\nexport function Toaster({ ...props }: ToasterProps) {\n  const { theme = 'system' } = useTheme()\n\n  return (\n    <Sonner\n      theme={theme as ToasterProps['theme']}\n      className='toaster group [&_div[data-content]]:w-full'\n      style={\n        {\n          '--normal-bg': 'var(--popover)',\n          '--normal-text': 'var(--popover-foreground)',\n          '--normal-border': 'var(--border)',\n        } as React.CSSProperties\n      }\n      {...props}\n    />\n  )\n}\n"
  },
  {
    "path": "src/components/ui/switch.tsx",
    "content": "import * as React from 'react'\nimport * as SwitchPrimitive from '@radix-ui/react-switch'\nimport { cn } from '@/lib/utils'\n\nfunction Switch({\n  className,\n  ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n  return (\n    <SwitchPrimitive.Root\n      data-slot='switch'\n      className={cn(\n        'peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80',\n        className\n      )}\n      {...props}\n    >\n      <SwitchPrimitive.Thumb\n        data-slot='switch-thumb'\n        className={cn(\n          'pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0 rtl:data-[state=checked]:-translate-x-[calc(100%-2px)] dark:data-[state=checked]:bg-primary-foreground dark:data-[state=unchecked]:bg-foreground'\n        )}\n      />\n    </SwitchPrimitive.Root>\n  )\n}\n\nexport { Switch }\n"
  },
  {
    "path": "src/components/ui/table.tsx",
    "content": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Table({ className, ...props }: React.ComponentProps<'table'>) {\n  return (\n    <div\n      data-slot='table-container'\n      className='relative w-full overflow-x-auto'\n    >\n      <table\n        data-slot='table'\n        className={cn('w-full caption-bottom text-sm', className)}\n        {...props}\n      />\n    </div>\n  )\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n  return (\n    <thead\n      data-slot='table-header'\n      className={cn('[&_tr]:border-b', className)}\n      {...props}\n    />\n  )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n  return (\n    <tbody\n      data-slot='table-body'\n      className={cn('[&_tr:last-child]:border-0', className)}\n      {...props}\n    />\n  )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n  return (\n    <tfoot\n      data-slot='table-footer'\n      className={cn(\n        'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<'tr'>) {\n  return (\n    <tr\n      data-slot='table-row'\n      className={cn(\n        'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<'th'>) {\n  return (\n    <th\n      data-slot='table-head'\n      className={cn(\n        'h-10 px-2 text-start align-middle font-medium whitespace-nowrap text-foreground [&>[role=checkbox]]:translate-y-[2px]',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<'td'>) {\n  return (\n    <td\n      data-slot='table-cell'\n      className={cn(\n        'p-2 align-middle whitespace-nowrap [&>[role=checkbox]]:translate-y-[2px]',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TableCaption({\n  className,\n  ...props\n}: React.ComponentProps<'caption'>) {\n  return (\n    <caption\n      data-slot='table-caption'\n      className={cn('mt-4 text-sm text-muted-foreground', className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Table,\n  TableHeader,\n  TableBody,\n  TableFooter,\n  TableHead,\n  TableRow,\n  TableCell,\n  TableCaption,\n}\n"
  },
  {
    "path": "src/components/ui/tabs.tsx",
    "content": "import * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\nimport { cn } from '@/lib/utils'\n\nfunction Tabs({\n  className,\n  ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>) {\n  return (\n    <TabsPrimitive.Root\n      data-slot='tabs'\n      className={cn('flex flex-col gap-2', className)}\n      {...props}\n    />\n  )\n}\n\nfunction TabsList({\n  className,\n  ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>) {\n  return (\n    <TabsPrimitive.List\n      data-slot='tabs-list'\n      className={cn(\n        'inline-flex h-9 w-fit items-center justify-center rounded-lg bg-muted p-[3px] text-muted-foreground',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TabsTrigger({\n  className,\n  ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n  return (\n    <TabsPrimitive.Trigger\n      data-slot='tabs-trigger'\n      className={cn(\n        \"inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:shadow-sm dark:text-muted-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TabsContent({\n  className,\n  ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>) {\n  return (\n    <TabsPrimitive.Content\n      data-slot='tabs-content'\n      className={cn('flex-1 outline-none', className)}\n      {...props}\n    />\n  )\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n"
  },
  {
    "path": "src/components/ui/textarea.tsx",
    "content": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {\n  return (\n    <textarea\n      data-slot='textarea'\n      className={cn(\n        'flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { Textarea }\n"
  },
  {
    "path": "src/components/ui/tooltip.tsx",
    "content": "'use client'\n\nimport * as React from 'react'\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport { cn } from '@/lib/utils'\n\nfunction TooltipProvider({\n  delayDuration = 0,\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n  return (\n    <TooltipPrimitive.Provider\n      data-slot='tooltip-provider'\n      delayDuration={delayDuration}\n      {...props}\n    />\n  )\n}\n\nfunction Tooltip({\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n  return (\n    <TooltipProvider>\n      <TooltipPrimitive.Root data-slot='tooltip' {...props} />\n    </TooltipProvider>\n  )\n}\n\nfunction TooltipTrigger({\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n  return <TooltipPrimitive.Trigger data-slot='tooltip-trigger' {...props} />\n}\n\nfunction TooltipContent({\n  className,\n  sideOffset = 0,\n  children,\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n  return (\n    <TooltipPrimitive.Portal>\n      <TooltipPrimitive.Content\n        data-slot='tooltip-content'\n        sideOffset={sideOffset}\n        className={cn(\n          'z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in rounded-md bg-primary px-3 py-1.5 text-xs text-balance text-primary-foreground fade-in-0 zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',\n          className\n        )}\n        {...props}\n      >\n        {children}\n        <TooltipPrimitive.Arrow className='z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary' />\n      </TooltipPrimitive.Content>\n    </TooltipPrimitive.Portal>\n  )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n"
  },
  {
    "path": "src/config/fonts.ts",
    "content": "/**\n * List of available font names (visit the url `/settings/appearance`).\n * This array is used to generate dynamic font classes (e.g., `font-inter`, `font-manrope`).\n *\n * 📝 How to Add a New Font (Tailwind v4+):\n * 1. Add the font name here.\n * 2. Update the `<link>` tag in 'index.html' to include the new font from Google Fonts (or any other source).\n * 3. Add the new font family to 'index.css' using the `@theme inline` and `font-family` CSS variable.\n *\n * Example:\n * fonts.ts           → Add 'roboto' to this array.\n * index.html         → Add Google Fonts link for Roboto.\n * index.css          → Add the new font in the CSS, e.g.:\n *   @theme inline {\n *      // ... other font families\n *      --font-roboto: 'Roboto', var(--font-sans);\n *   }\n */\nexport const fonts = ['inter', 'manrope', 'system'] as const\n"
  },
  {
    "path": "src/context/direction-provider.tsx",
    "content": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { DirectionProvider as RdxDirProvider } from '@radix-ui/react-direction'\nimport { getCookie, setCookie, removeCookie } from '@/lib/cookies'\n\nexport type Direction = 'ltr' | 'rtl'\n\nconst DEFAULT_DIRECTION = 'ltr'\nconst DIRECTION_COOKIE_NAME = 'dir'\nconst DIRECTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year\n\ntype DirectionContextType = {\n  defaultDir: Direction\n  dir: Direction\n  setDir: (dir: Direction) => void\n  resetDir: () => void\n}\n\nconst DirectionContext = createContext<DirectionContextType | null>(null)\n\nexport function DirectionProvider({ children }: { children: React.ReactNode }) {\n  const [dir, _setDir] = useState<Direction>(\n    () => (getCookie(DIRECTION_COOKIE_NAME) as Direction) || DEFAULT_DIRECTION\n  )\n\n  useEffect(() => {\n    const htmlElement = document.documentElement\n    htmlElement.setAttribute('dir', dir)\n  }, [dir])\n\n  const setDir = (dir: Direction) => {\n    _setDir(dir)\n    setCookie(DIRECTION_COOKIE_NAME, dir, DIRECTION_COOKIE_MAX_AGE)\n  }\n\n  const resetDir = () => {\n    _setDir(DEFAULT_DIRECTION)\n    removeCookie(DIRECTION_COOKIE_NAME)\n  }\n\n  return (\n    <DirectionContext\n      value={{\n        defaultDir: DEFAULT_DIRECTION,\n        dir,\n        setDir,\n        resetDir,\n      }}\n    >\n      <RdxDirProvider dir={dir}>{children}</RdxDirProvider>\n    </DirectionContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useDirection() {\n  const context = useContext(DirectionContext)\n  if (!context) {\n    throw new Error('useDirection must be used within a DirectionProvider')\n  }\n  return context\n}\n"
  },
  {
    "path": "src/context/font-provider.tsx",
    "content": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { fonts } from '@/config/fonts'\nimport { getCookie, setCookie, removeCookie } from '@/lib/cookies'\n\ntype Font = (typeof fonts)[number]\n\nconst FONT_COOKIE_NAME = 'font'\nconst FONT_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year\n\ntype FontContextType = {\n  font: Font\n  setFont: (font: Font) => void\n  resetFont: () => void\n}\n\nconst FontContext = createContext<FontContextType | null>(null)\n\nexport function FontProvider({ children }: { children: React.ReactNode }) {\n  const [font, _setFont] = useState<Font>(() => {\n    const savedFont = getCookie(FONT_COOKIE_NAME)\n    return fonts.includes(savedFont as Font) ? (savedFont as Font) : fonts[0]\n  })\n\n  useEffect(() => {\n    const applyFont = (font: string) => {\n      const root = document.documentElement\n      root.classList.forEach((cls) => {\n        if (cls.startsWith('font-')) root.classList.remove(cls)\n      })\n      root.classList.add(`font-${font}`)\n    }\n\n    applyFont(font)\n  }, [font])\n\n  const setFont = (font: Font) => {\n    setCookie(FONT_COOKIE_NAME, font, FONT_COOKIE_MAX_AGE)\n    _setFont(font)\n  }\n\n  const resetFont = () => {\n    removeCookie(FONT_COOKIE_NAME)\n    _setFont(fonts[0])\n  }\n\n  return (\n    <FontContext value={{ font, setFont, resetFont }}>{children}</FontContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const useFont = () => {\n  const context = useContext(FontContext)\n  if (!context) {\n    throw new Error('useFont must be used within a FontProvider')\n  }\n  return context\n}\n"
  },
  {
    "path": "src/context/layout-provider.tsx",
    "content": "import { createContext, useContext, useState } from 'react'\nimport { getCookie, setCookie } from '@/lib/cookies'\n\nexport type Collapsible = 'offcanvas' | 'icon' | 'none'\nexport type Variant = 'inset' | 'sidebar' | 'floating'\n\n// Cookie constants following the pattern from sidebar.tsx\nconst LAYOUT_COLLAPSIBLE_COOKIE_NAME = 'layout_collapsible'\nconst LAYOUT_VARIANT_COOKIE_NAME = 'layout_variant'\nconst LAYOUT_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 // 7 days\n\n// Default values\nconst DEFAULT_VARIANT = 'inset'\nconst DEFAULT_COLLAPSIBLE = 'icon'\n\ntype LayoutContextType = {\n  resetLayout: () => void\n\n  defaultCollapsible: Collapsible\n  collapsible: Collapsible\n  setCollapsible: (collapsible: Collapsible) => void\n\n  defaultVariant: Variant\n  variant: Variant\n  setVariant: (variant: Variant) => void\n}\n\nconst LayoutContext = createContext<LayoutContextType | null>(null)\n\ntype LayoutProviderProps = {\n  children: React.ReactNode\n}\n\nexport function LayoutProvider({ children }: LayoutProviderProps) {\n  const [collapsible, _setCollapsible] = useState<Collapsible>(() => {\n    const saved = getCookie(LAYOUT_COLLAPSIBLE_COOKIE_NAME)\n    return (saved as Collapsible) || DEFAULT_COLLAPSIBLE\n  })\n\n  const [variant, _setVariant] = useState<Variant>(() => {\n    const saved = getCookie(LAYOUT_VARIANT_COOKIE_NAME)\n    return (saved as Variant) || DEFAULT_VARIANT\n  })\n\n  const setCollapsible = (newCollapsible: Collapsible) => {\n    _setCollapsible(newCollapsible)\n    setCookie(\n      LAYOUT_COLLAPSIBLE_COOKIE_NAME,\n      newCollapsible,\n      LAYOUT_COOKIE_MAX_AGE\n    )\n  }\n\n  const setVariant = (newVariant: Variant) => {\n    _setVariant(newVariant)\n    setCookie(LAYOUT_VARIANT_COOKIE_NAME, newVariant, LAYOUT_COOKIE_MAX_AGE)\n  }\n\n  const resetLayout = () => {\n    setCollapsible(DEFAULT_COLLAPSIBLE)\n    setVariant(DEFAULT_VARIANT)\n  }\n\n  const contextValue: LayoutContextType = {\n    resetLayout,\n    defaultCollapsible: DEFAULT_COLLAPSIBLE,\n    collapsible,\n    setCollapsible,\n    defaultVariant: DEFAULT_VARIANT,\n    variant,\n    setVariant,\n  }\n\n  return <LayoutContext value={contextValue}>{children}</LayoutContext>\n}\n\n// Define the hook for the provider\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useLayout() {\n  const context = useContext(LayoutContext)\n  if (!context) {\n    throw new Error('useLayout must be used within a LayoutProvider')\n  }\n  return context\n}\n"
  },
  {
    "path": "src/context/search-provider.tsx",
    "content": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { CommandMenu } from '@/components/command-menu'\n\ntype SearchContextType = {\n  open: boolean\n  setOpen: React.Dispatch<React.SetStateAction<boolean>>\n}\n\nconst SearchContext = createContext<SearchContextType | null>(null)\n\ntype SearchProviderProps = {\n  children: React.ReactNode\n}\n\nexport function SearchProvider({ children }: SearchProviderProps) {\n  const [open, setOpen] = useState(false)\n\n  useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n        e.preventDefault()\n        setOpen((open) => !open)\n      }\n    }\n    document.addEventListener('keydown', down)\n    return () => document.removeEventListener('keydown', down)\n  }, [])\n\n  return (\n    <SearchContext value={{ open, setOpen }}>\n      {children}\n      <CommandMenu />\n    </SearchContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const useSearch = () => {\n  const searchContext = useContext(SearchContext)\n\n  if (!searchContext) {\n    throw new Error('useSearch has to be used within SearchProvider')\n  }\n\n  return searchContext\n}\n"
  },
  {
    "path": "src/context/theme-provider.tsx",
    "content": "import { createContext, useContext, useEffect, useState, useMemo } from 'react'\nimport { getCookie, setCookie, removeCookie } from '@/lib/cookies'\n\ntype Theme = 'dark' | 'light' | 'system'\ntype ResolvedTheme = Exclude<Theme, 'system'>\n\nconst DEFAULT_THEME = 'system'\nconst THEME_COOKIE_NAME = 'vite-ui-theme'\nconst THEME_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year\n\ntype ThemeProviderProps = {\n  children: React.ReactNode\n  defaultTheme?: Theme\n  storageKey?: string\n}\n\ntype ThemeProviderState = {\n  defaultTheme: Theme\n  resolvedTheme: ResolvedTheme\n  theme: Theme\n  setTheme: (theme: Theme) => void\n  resetTheme: () => void\n}\n\nconst initialState: ThemeProviderState = {\n  defaultTheme: DEFAULT_THEME,\n  resolvedTheme: 'light',\n  theme: DEFAULT_THEME,\n  setTheme: () => null,\n  resetTheme: () => null,\n}\n\nconst ThemeContext = createContext<ThemeProviderState>(initialState)\n\nexport function ThemeProvider({\n  children,\n  defaultTheme = DEFAULT_THEME,\n  storageKey = THEME_COOKIE_NAME,\n  ...props\n}: ThemeProviderProps) {\n  const [theme, _setTheme] = useState<Theme>(\n    () => (getCookie(storageKey) as Theme) || defaultTheme\n  )\n\n  // Optimized: Memoize the resolved theme calculation to prevent unnecessary re-computations\n  const resolvedTheme = useMemo((): ResolvedTheme => {\n    if (theme === 'system') {\n      return window.matchMedia('(prefers-color-scheme: dark)').matches\n        ? 'dark'\n        : 'light'\n    }\n    return theme as ResolvedTheme\n  }, [theme])\n\n  useEffect(() => {\n    const root = window.document.documentElement\n    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n\n    const applyTheme = (currentResolvedTheme: ResolvedTheme) => {\n      root.classList.remove('light', 'dark') // Remove existing theme classes\n      root.classList.add(currentResolvedTheme) // Add the new theme class\n    }\n\n    const handleChange = () => {\n      if (theme === 'system') {\n        const systemTheme = mediaQuery.matches ? 'dark' : 'light'\n        applyTheme(systemTheme)\n      }\n    }\n\n    applyTheme(resolvedTheme)\n\n    mediaQuery.addEventListener('change', handleChange)\n\n    return () => mediaQuery.removeEventListener('change', handleChange)\n  }, [theme, resolvedTheme])\n\n  const setTheme = (theme: Theme) => {\n    setCookie(storageKey, theme, THEME_COOKIE_MAX_AGE)\n    _setTheme(theme)\n  }\n\n  const resetTheme = () => {\n    removeCookie(storageKey)\n    _setTheme(DEFAULT_THEME)\n  }\n\n  const contextValue = {\n    defaultTheme,\n    resolvedTheme,\n    resetTheme,\n    theme,\n    setTheme,\n  }\n\n  return (\n    <ThemeContext value={contextValue} {...props}>\n      {children}\n    </ThemeContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const useTheme = () => {\n  const context = useContext(ThemeContext)\n\n  if (!context) throw new Error('useTheme must be used within a ThemeProvider')\n\n  return context\n}\n"
  },
  {
    "path": "src/features/apps/data/apps.tsx",
    "content": "import {\n  IconTelegram,\n  IconNotion,\n  IconFigma,\n  IconTrello,\n  IconSlack,\n  IconZoom,\n  IconStripe,\n  IconGmail,\n  IconMedium,\n  IconSkype,\n  IconDocker,\n  IconGithub,\n  IconGitlab,\n  IconDiscord,\n  IconWhatsapp,\n} from '@/assets/brand-icons'\n\nexport const apps = [\n  {\n    name: 'Telegram',\n    logo: <IconTelegram />,\n    connected: false,\n    desc: 'Connect with Telegram for real-time communication.',\n  },\n  {\n    name: 'Notion',\n    logo: <IconNotion />,\n    connected: true,\n    desc: 'Effortlessly sync Notion pages for seamless collaboration.',\n  },\n  {\n    name: 'Figma',\n    logo: <IconFigma />,\n    connected: true,\n    desc: 'View and collaborate on Figma designs in one place.',\n  },\n  {\n    name: 'Trello',\n    logo: <IconTrello />,\n    connected: false,\n    desc: 'Sync Trello cards for streamlined project management.',\n  },\n  {\n    name: 'Slack',\n    logo: <IconSlack />,\n    connected: false,\n    desc: 'Integrate Slack for efficient team communication',\n  },\n  {\n    name: 'Zoom',\n    logo: <IconZoom />,\n    connected: true,\n    desc: 'Host Zoom meetings directly from the dashboard.',\n  },\n  {\n    name: 'Stripe',\n    logo: <IconStripe />,\n    connected: false,\n    desc: 'Easily manage Stripe transactions and payments.',\n  },\n  {\n    name: 'Gmail',\n    logo: <IconGmail />,\n    connected: true,\n    desc: 'Access and manage Gmail messages effortlessly.',\n  },\n  {\n    name: 'Medium',\n    logo: <IconMedium />,\n    connected: false,\n    desc: 'Explore and share Medium stories on your dashboard.',\n  },\n  {\n    name: 'Skype',\n    logo: <IconSkype />,\n    connected: false,\n    desc: 'Connect with Skype contacts seamlessly.',\n  },\n  {\n    name: 'Docker',\n    logo: <IconDocker />,\n    connected: false,\n    desc: 'Effortlessly manage Docker containers on your dashboard.',\n  },\n  {\n    name: 'GitHub',\n    logo: <IconGithub />,\n    connected: false,\n    desc: 'Streamline code management with GitHub integration.',\n  },\n  {\n    name: 'GitLab',\n    logo: <IconGitlab />,\n    connected: false,\n    desc: 'Efficiently manage code projects with GitLab integration.',\n  },\n  {\n    name: 'Discord',\n    logo: <IconDiscord />,\n    connected: false,\n    desc: 'Connect with Discord for seamless team communication.',\n  },\n  {\n    name: 'WhatsApp',\n    logo: <IconWhatsapp />,\n    connected: false,\n    desc: 'Easily integrate WhatsApp for direct messaging.',\n  },\n]\n"
  },
  {
    "path": "src/features/apps/index.tsx",
    "content": "import { type ChangeEvent, useState } from 'react'\nimport { getRouteApi } from '@tanstack/react-router'\nimport { SlidersHorizontal, ArrowUpAZ, ArrowDownAZ } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\nimport { Separator } from '@/components/ui/separator'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { apps } from './data/apps'\n\nconst route = getRouteApi('/_authenticated/apps/')\n\ntype AppType = 'all' | 'connected' | 'notConnected'\n\nconst appText = new Map<AppType, string>([\n  ['all', 'All Apps'],\n  ['connected', 'Connected'],\n  ['notConnected', 'Not Connected'],\n])\n\nexport function Apps() {\n  const {\n    filter = '',\n    type = 'all',\n    sort: initSort = 'asc',\n  } = route.useSearch()\n  const navigate = route.useNavigate()\n\n  const [sort, setSort] = useState(initSort)\n  const [appType, setAppType] = useState(type)\n  const [searchTerm, setSearchTerm] = useState(filter)\n\n  const filteredApps = apps\n    .sort((a, b) =>\n      sort === 'asc'\n        ? a.name.localeCompare(b.name)\n        : b.name.localeCompare(a.name)\n    )\n    .filter((app) =>\n      appType === 'connected'\n        ? app.connected\n        : appType === 'notConnected'\n          ? !app.connected\n          : true\n    )\n    .filter((app) => app.name.toLowerCase().includes(searchTerm.toLowerCase()))\n\n  const handleSearch = (e: ChangeEvent<HTMLInputElement>) => {\n    setSearchTerm(e.target.value)\n    navigate({\n      search: (prev) => ({\n        ...prev,\n        filter: e.target.value || undefined,\n      }),\n    })\n  }\n\n  const handleTypeChange = (value: AppType) => {\n    setAppType(value)\n    navigate({\n      search: (prev) => ({\n        ...prev,\n        type: value === 'all' ? undefined : value,\n      }),\n    })\n  }\n\n  const handleSortChange = (sort: 'asc' | 'desc') => {\n    setSort(sort)\n    navigate({ search: (prev) => ({ ...prev, sort }) })\n  }\n\n  return (\n    <>\n      {/* ===== Top Heading ===== */}\n      <Header>\n        <Search />\n        <div className='ms-auto flex items-center gap-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      {/* ===== Content ===== */}\n      <Main fixed>\n        <div>\n          <h1 className='text-2xl font-bold tracking-tight'>\n            App Integrations\n          </h1>\n          <p className='text-muted-foreground'>\n            Here&apos;s a list of your apps for the integration!\n          </p>\n        </div>\n        <div className='my-4 flex items-end justify-between sm:my-0 sm:items-center'>\n          <div className='flex flex-col gap-4 sm:my-4 sm:flex-row'>\n            <Input\n              placeholder='Filter apps...'\n              className='h-9 w-40 lg:w-[250px]'\n              value={searchTerm}\n              onChange={handleSearch}\n            />\n            <Select value={appType} onValueChange={handleTypeChange}>\n              <SelectTrigger className='w-36'>\n                <SelectValue>{appText.get(appType)}</SelectValue>\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value='all'>All Apps</SelectItem>\n                <SelectItem value='connected'>Connected</SelectItem>\n                <SelectItem value='notConnected'>Not Connected</SelectItem>\n              </SelectContent>\n            </Select>\n          </div>\n\n          <Select value={sort} onValueChange={handleSortChange}>\n            <SelectTrigger className='w-16'>\n              <SelectValue>\n                <SlidersHorizontal size={18} />\n              </SelectValue>\n            </SelectTrigger>\n            <SelectContent align='end'>\n              <SelectItem value='asc'>\n                <div className='flex items-center gap-4'>\n                  <ArrowUpAZ size={16} />\n                  <span>Ascending</span>\n                </div>\n              </SelectItem>\n              <SelectItem value='desc'>\n                <div className='flex items-center gap-4'>\n                  <ArrowDownAZ size={16} />\n                  <span>Descending</span>\n                </div>\n              </SelectItem>\n            </SelectContent>\n          </Select>\n        </div>\n        <Separator className='shadow-sm' />\n        <ul className='faded-bottom no-scrollbar grid gap-4 overflow-auto pt-4 pb-16 md:grid-cols-2 lg:grid-cols-3'>\n          {filteredApps.map((app) => (\n            <li\n              key={app.name}\n              className='rounded-lg border p-4 hover:shadow-md'\n            >\n              <div className='mb-8 flex items-center justify-between'>\n                <div\n                  className={`flex size-10 items-center justify-center rounded-lg bg-muted p-2`}\n                >\n                  {app.logo}\n                </div>\n                <Button\n                  variant='outline'\n                  size='sm'\n                  className={`${app.connected ? 'border border-blue-300 bg-blue-50 hover:bg-blue-100 dark:border-blue-700 dark:bg-blue-950 dark:hover:bg-blue-900' : ''}`}\n                >\n                  {app.connected ? 'Connected' : 'Connect'}\n                </Button>\n              </div>\n              <div>\n                <h2 className='mb-1 font-semibold'>{app.name}</h2>\n                <p className='line-clamp-2 text-gray-500'>{app.desc}</p>\n              </div>\n            </li>\n          ))}\n        </ul>\n      </Main>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/auth-layout.tsx",
    "content": "import { Logo } from '@/assets/logo'\n\ntype AuthLayoutProps = {\n  children: React.ReactNode\n}\n\nexport function AuthLayout({ children }: AuthLayoutProps) {\n  return (\n    <div className='container grid h-svh max-w-none items-center justify-center'>\n      <div className='mx-auto flex w-full flex-col justify-center space-y-2 py-8 sm:w-[480px] sm:p-8'>\n        <div className='mb-4 flex items-center justify-center'>\n          <Logo className='me-2' />\n          <h1 className='text-xl font-medium'>Shadcn Admin</h1>\n        </div>\n        {children}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/forgot-password/components/forgot-password-form.tsx",
    "content": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useNavigate } from '@tanstack/react-router'\nimport { ArrowRight, Loader2 } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { sleep, cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\n\nconst formSchema = z.object({\n  email: z.email({\n    error: (iss) => (iss.input === '' ? 'Please enter your email' : undefined),\n  }),\n})\n\nexport function ForgotPasswordForm({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLFormElement>) {\n  const navigate = useNavigate()\n  const [isLoading, setIsLoading] = useState(false)\n\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { email: '' },\n  })\n\n  function onSubmit(data: z.infer<typeof formSchema>) {\n    setIsLoading(true)\n    // eslint-disable-next-line no-console\n    console.log(data)\n\n    toast.promise(sleep(2000), {\n      loading: 'Sending email...',\n      success: () => {\n        setIsLoading(false)\n        form.reset()\n        navigate({ to: '/otp' })\n        return `Email sent to ${data.email}`\n      },\n      error: 'Error',\n    })\n  }\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit(onSubmit)}\n        className={cn('grid gap-2', className)}\n        {...props}\n      >\n        <FormField\n          control={form.control}\n          name='email'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input placeholder='name@example.com' {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button className='mt-2' disabled={isLoading}>\n          Continue\n          {isLoading ? <Loader2 className='animate-spin' /> : <ArrowRight />}\n        </Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/forgot-password/index.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { AuthLayout } from '../auth-layout'\nimport { ForgotPasswordForm } from './components/forgot-password-form'\n\nexport function ForgotPassword() {\n  return (\n    <AuthLayout>\n      <Card className='gap-4'>\n        <CardHeader>\n          <CardTitle className='text-lg tracking-tight'>\n            Forgot Password\n          </CardTitle>\n          <CardDescription>\n            Enter your registered email and <br /> we will send you a link to\n            reset your password.\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <ForgotPasswordForm />\n        </CardContent>\n        <CardFooter>\n          <p className='mx-auto px-8 text-center text-sm text-balance text-muted-foreground'>\n            Don't have an account?{' '}\n            <Link\n              to='/sign-up'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Sign up\n            </Link>\n            .\n          </p>\n        </CardFooter>\n      </Card>\n    </AuthLayout>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/otp/components/otp-form.tsx",
    "content": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { useNavigate } from '@tanstack/react-router'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport {\n  InputOTP,\n  InputOTPGroup,\n  InputOTPSlot,\n  InputOTPSeparator,\n} from '@/components/ui/input-otp'\n\nconst formSchema = z.object({\n  otp: z\n    .string()\n    .min(6, 'Please enter the 6-digit code.')\n    .max(6, 'Please enter the 6-digit code.'),\n})\n\ntype OtpFormProps = React.HTMLAttributes<HTMLFormElement>\n\nexport function OtpForm({ className, ...props }: OtpFormProps) {\n  const navigate = useNavigate()\n  const [isLoading, setIsLoading] = useState(false)\n\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { otp: '' },\n  })\n\n  // eslint-disable-next-line react-hooks/incompatible-library\n  const otp = form.watch('otp')\n\n  function onSubmit(data: z.infer<typeof formSchema>) {\n    setIsLoading(true)\n    showSubmittedData(data)\n\n    setTimeout(() => {\n      setIsLoading(false)\n      navigate({ to: '/' })\n    }, 1000)\n  }\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit(onSubmit)}\n        className={cn('grid gap-2', className)}\n        {...props}\n      >\n        <FormField\n          control={form.control}\n          name='otp'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel className='sr-only'>One-Time Password</FormLabel>\n              <FormControl>\n                <InputOTP\n                  maxLength={6}\n                  {...field}\n                  containerClassName='justify-between sm:[&>[data-slot=\"input-otp-group\"]>div]:w-12'\n                >\n                  <InputOTPGroup>\n                    <InputOTPSlot index={0} />\n                    <InputOTPSlot index={1} />\n                  </InputOTPGroup>\n                  <InputOTPSeparator />\n                  <InputOTPGroup>\n                    <InputOTPSlot index={2} />\n                    <InputOTPSlot index={3} />\n                  </InputOTPGroup>\n                  <InputOTPSeparator />\n                  <InputOTPGroup>\n                    <InputOTPSlot index={4} />\n                    <InputOTPSlot index={5} />\n                  </InputOTPGroup>\n                </InputOTP>\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button className='mt-2' disabled={otp.length < 6 || isLoading}>\n          Verify\n        </Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/otp/index.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { AuthLayout } from '../auth-layout'\nimport { OtpForm } from './components/otp-form'\n\nexport function Otp() {\n  return (\n    <AuthLayout>\n      <Card className='gap-4'>\n        <CardHeader>\n          <CardTitle className='text-base tracking-tight'>\n            Two-factor Authentication\n          </CardTitle>\n          <CardDescription>\n            Please enter the authentication code. <br /> We have sent the\n            authentication code to your email.\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <OtpForm />\n        </CardContent>\n        <CardFooter>\n          <p className='px-8 text-center text-sm text-muted-foreground'>\n            Haven't received it?{' '}\n            <Link\n              to='/sign-in'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Resend a new code.\n            </Link>\n            .\n          </p>\n        </CardFooter>\n      </Card>\n    </AuthLayout>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/sign-in/components/user-auth-form.tsx",
    "content": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { Link, useNavigate } from '@tanstack/react-router'\nimport { Loader2, LogIn } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { IconFacebook, IconGithub } from '@/assets/brand-icons'\nimport { useAuthStore } from '@/stores/auth-store'\nimport { sleep, cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport { PasswordInput } from '@/components/password-input'\n\nconst formSchema = z.object({\n  email: z.email({\n    error: (iss) => (iss.input === '' ? 'Please enter your email' : undefined),\n  }),\n  password: z\n    .string()\n    .min(1, 'Please enter your password')\n    .min(7, 'Password must be at least 7 characters long'),\n})\n\ninterface UserAuthFormProps extends React.HTMLAttributes<HTMLFormElement> {\n  redirectTo?: string\n}\n\nexport function UserAuthForm({\n  className,\n  redirectTo,\n  ...props\n}: UserAuthFormProps) {\n  const [isLoading, setIsLoading] = useState(false)\n  const navigate = useNavigate()\n  const { auth } = useAuthStore()\n\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: {\n      email: '',\n      password: '',\n    },\n  })\n\n  function onSubmit(data: z.infer<typeof formSchema>) {\n    setIsLoading(true)\n\n    toast.promise(sleep(2000), {\n      loading: 'Signing in...',\n      success: () => {\n        setIsLoading(false)\n\n        // Mock successful authentication with expiry computed at success time\n        const mockUser = {\n          accountNo: 'ACC001',\n          email: data.email,\n          role: ['user'],\n          exp: Date.now() + 24 * 60 * 60 * 1000, // 24 hours from now\n        }\n\n        // Set user and access token\n        auth.setUser(mockUser)\n        auth.setAccessToken('mock-access-token')\n\n        // Redirect to the stored location or default to dashboard\n        const targetPath = redirectTo || '/'\n        navigate({ to: targetPath, replace: true })\n\n        return `Welcome back, ${data.email}!`\n      },\n      error: 'Error',\n    })\n  }\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit(onSubmit)}\n        className={cn('grid gap-3', className)}\n        {...props}\n      >\n        <FormField\n          control={form.control}\n          name='email'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input placeholder='name@example.com' {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='password'\n          render={({ field }) => (\n            <FormItem className='relative'>\n              <FormLabel>Password</FormLabel>\n              <FormControl>\n                <PasswordInput placeholder='********' {...field} />\n              </FormControl>\n              <FormMessage />\n              <Link\n                to='/forgot-password'\n                className='absolute end-0 -top-0.5 text-sm font-medium text-muted-foreground hover:opacity-75'\n              >\n                Forgot password?\n              </Link>\n            </FormItem>\n          )}\n        />\n        <Button className='mt-2' disabled={isLoading}>\n          {isLoading ? <Loader2 className='animate-spin' /> : <LogIn />}\n          Sign in\n        </Button>\n\n        <div className='relative my-2'>\n          <div className='absolute inset-0 flex items-center'>\n            <span className='w-full border-t' />\n          </div>\n          <div className='relative flex justify-center text-xs uppercase'>\n            <span className='bg-background px-2 text-muted-foreground'>\n              Or continue with\n            </span>\n          </div>\n        </div>\n\n        <div className='grid grid-cols-2 gap-2'>\n          <Button variant='outline' type='button' disabled={isLoading}>\n            <IconGithub className='h-4 w-4' /> GitHub\n          </Button>\n          <Button variant='outline' type='button' disabled={isLoading}>\n            <IconFacebook className='h-4 w-4' /> Facebook\n          </Button>\n        </div>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/sign-in/index.tsx",
    "content": "import { useSearch } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { AuthLayout } from '../auth-layout'\nimport { UserAuthForm } from './components/user-auth-form'\n\nexport function SignIn() {\n  const { redirect } = useSearch({ from: '/(auth)/sign-in' })\n\n  return (\n    <AuthLayout>\n      <Card className='gap-4'>\n        <CardHeader>\n          <CardTitle className='text-lg tracking-tight'>Sign in</CardTitle>\n          <CardDescription>\n            Enter your email and password below to <br />\n            log into your account\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <UserAuthForm redirectTo={redirect} />\n        </CardContent>\n        <CardFooter>\n          <p className='px-8 text-center text-sm text-muted-foreground'>\n            By clicking sign in, you agree to our{' '}\n            <a\n              href='/terms'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Terms of Service\n            </a>{' '}\n            and{' '}\n            <a\n              href='/privacy'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Privacy Policy\n            </a>\n            .\n          </p>\n        </CardFooter>\n      </Card>\n    </AuthLayout>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/sign-in/sign-in-2.tsx",
    "content": "import { Logo } from '@/assets/logo'\nimport { cn } from '@/lib/utils'\nimport dashboardDark from './assets/dashboard-dark.png'\nimport dashboardLight from './assets/dashboard-light.png'\nimport { UserAuthForm } from './components/user-auth-form'\n\nexport function SignIn2() {\n  return (\n    <div className='relative container grid h-svh flex-col items-center justify-center lg:max-w-none lg:grid-cols-2 lg:px-0'>\n      <div className='lg:p-8'>\n        <div className='mx-auto flex w-full flex-col justify-center space-y-2 py-8 sm:w-[480px] sm:p-8'>\n          <div className='mb-4 flex items-center justify-center'>\n            <Logo className='me-2' />\n            <h1 className='text-xl font-medium'>Shadcn Admin</h1>\n          </div>\n        </div>\n        <div className='mx-auto flex w-full max-w-sm flex-col justify-center space-y-2'>\n          <div className='flex flex-col space-y-2 text-start'>\n            <h2 className='text-lg font-semibold tracking-tight'>Sign in</h2>\n            <p className='text-sm text-muted-foreground'>\n              Enter your email and password below <br />\n              to log into your account\n            </p>\n          </div>\n          <UserAuthForm />\n          <p className='px-8 text-center text-sm text-muted-foreground'>\n            By clicking sign in, you agree to our{' '}\n            <a\n              href='/terms'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Terms of Service\n            </a>{' '}\n            and{' '}\n            <a\n              href='/privacy'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Privacy Policy\n            </a>\n            .\n          </p>\n        </div>\n      </div>\n\n      <div\n        className={cn(\n          'relative h-full overflow-hidden bg-muted max-lg:hidden',\n          '[&>img]:absolute [&>img]:top-[15%] [&>img]:left-20 [&>img]:h-full [&>img]:w-full [&>img]:object-cover [&>img]:object-top-left [&>img]:select-none'\n        )}\n      >\n        <img\n          src={dashboardLight}\n          className='dark:hidden'\n          width={1024}\n          height={1151}\n          alt='Shadcn-Admin'\n        />\n        <img\n          src={dashboardDark}\n          className='hidden dark:block'\n          width={1024}\n          height={1138}\n          alt='Shadcn-Admin'\n        />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/sign-up/components/sign-up-form.tsx",
    "content": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { IconFacebook, IconGithub } from '@/assets/brand-icons'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport { PasswordInput } from '@/components/password-input'\n\nconst formSchema = z\n  .object({\n    email: z.email({\n      error: (iss) =>\n        iss.input === '' ? 'Please enter your email' : undefined,\n    }),\n    password: z\n      .string()\n      .min(1, 'Please enter your password')\n      .min(7, 'Password must be at least 7 characters long'),\n    confirmPassword: z.string().min(1, 'Please confirm your password'),\n  })\n  .refine((data) => data.password === data.confirmPassword, {\n    message: \"Passwords don't match.\",\n    path: ['confirmPassword'],\n  })\n\nexport function SignUpForm({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLFormElement>) {\n  const [isLoading, setIsLoading] = useState(false)\n\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: {\n      email: '',\n      password: '',\n      confirmPassword: '',\n    },\n  })\n\n  function onSubmit(data: z.infer<typeof formSchema>) {\n    setIsLoading(true)\n    // eslint-disable-next-line no-console\n    console.log(data)\n\n    setTimeout(() => {\n      setIsLoading(false)\n    }, 3000)\n  }\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit(onSubmit)}\n        className={cn('grid gap-3', className)}\n        {...props}\n      >\n        <FormField\n          control={form.control}\n          name='email'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <FormControl>\n                <Input placeholder='name@example.com' {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='password'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Password</FormLabel>\n              <FormControl>\n                <PasswordInput placeholder='********' {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='confirmPassword'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Confirm Password</FormLabel>\n              <FormControl>\n                <PasswordInput placeholder='********' {...field} />\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button className='mt-2' disabled={isLoading}>\n          Create Account\n        </Button>\n\n        <div className='relative my-2'>\n          <div className='absolute inset-0 flex items-center'>\n            <span className='w-full border-t' />\n          </div>\n          <div className='relative flex justify-center text-xs uppercase'>\n            <span className='bg-background px-2 text-muted-foreground'>\n              Or continue with\n            </span>\n          </div>\n        </div>\n\n        <div className='grid grid-cols-2 gap-2'>\n          <Button\n            variant='outline'\n            className='w-full'\n            type='button'\n            disabled={isLoading}\n          >\n            <IconGithub className='h-4 w-4' /> GitHub\n          </Button>\n          <Button\n            variant='outline'\n            className='w-full'\n            type='button'\n            disabled={isLoading}\n          >\n            <IconFacebook className='h-4 w-4' /> Facebook\n          </Button>\n        </div>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/auth/sign-up/index.tsx",
    "content": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { AuthLayout } from '../auth-layout'\nimport { SignUpForm } from './components/sign-up-form'\n\nexport function SignUp() {\n  return (\n    <AuthLayout>\n      <Card className='gap-4'>\n        <CardHeader>\n          <CardTitle className='text-lg tracking-tight'>\n            Create an account\n          </CardTitle>\n          <CardDescription>\n            Enter your email and password to create an account. <br />\n            Already have an account?{' '}\n            <Link\n              to='/sign-in'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Sign In\n            </Link>\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <SignUpForm />\n        </CardContent>\n        <CardFooter>\n          <p className='px-8 text-center text-sm text-muted-foreground'>\n            By creating an account, you agree to our{' '}\n            <a\n              href='/terms'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Terms of Service\n            </a>{' '}\n            and{' '}\n            <a\n              href='/privacy'\n              className='underline underline-offset-4 hover:text-primary'\n            >\n              Privacy Policy\n            </a>\n            .\n          </p>\n        </CardFooter>\n      </Card>\n    </AuthLayout>\n  )\n}\n"
  },
  {
    "path": "src/features/chats/components/new-chat.tsx",
    "content": "import { useState } from 'react'\nimport { Check, X } from 'lucide-react'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command'\nimport {\n  Dialog,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport { type ChatUser } from '../data/chat-types'\n\ntype User = Omit<ChatUser, 'messages'>\n\ntype NewChatProps = {\n  users: User[]\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\nexport function NewChat({ users, onOpenChange, open }: NewChatProps) {\n  const [selectedUsers, setSelectedUsers] = useState<User[]>([])\n\n  const handleSelectUser = (user: User) => {\n    if (!selectedUsers.find((u) => u.id === user.id)) {\n      setSelectedUsers([...selectedUsers, user])\n    } else {\n      handleRemoveUser(user.id)\n    }\n  }\n\n  const handleRemoveUser = (userId: string) => {\n    setSelectedUsers(selectedUsers.filter((user) => user.id !== userId))\n  }\n\n  const handleOpenChange = (newOpen: boolean) => {\n    onOpenChange(newOpen)\n    // Reset selected users when dialog closes\n    if (!newOpen) {\n      setSelectedUsers([])\n    }\n  }\n\n  return (\n    <Dialog open={open} onOpenChange={handleOpenChange}>\n      <DialogContent className='sm:max-w-[600px]'>\n        <DialogHeader>\n          <DialogTitle>New message</DialogTitle>\n        </DialogHeader>\n        <div className='flex flex-col gap-4'>\n          <div className='flex flex-wrap items-baseline-last gap-2'>\n            <span className='min-h-6 text-sm text-muted-foreground'>To:</span>\n            {selectedUsers.map((user) => (\n              <Badge key={user.id} variant='default'>\n                {user.fullName}\n                <button\n                  className='ms-1 rounded-full ring-offset-background outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2'\n                  onKeyDown={(e) => {\n                    if (e.key === 'Enter') {\n                      handleRemoveUser(user.id)\n                    }\n                  }}\n                  onClick={() => handleRemoveUser(user.id)}\n                >\n                  <X className='h-3 w-3 text-muted-foreground hover:text-foreground' />\n                </button>\n              </Badge>\n            ))}\n          </div>\n          <Command className='rounded-lg border'>\n            <CommandInput\n              placeholder='Search people...'\n              className='text-foreground'\n            />\n            <CommandList>\n              <CommandEmpty>No people found.</CommandEmpty>\n              <CommandGroup>\n                {users.map((user) => (\n                  <CommandItem\n                    key={user.id}\n                    onSelect={() => handleSelectUser(user)}\n                    className='flex items-center justify-between gap-2 hover:bg-accent hover:text-accent-foreground'\n                  >\n                    <div className='flex items-center gap-2'>\n                      <img\n                        src={user.profile || '/placeholder.svg'}\n                        alt={user.fullName}\n                        className='h-8 w-8 rounded-full'\n                      />\n                      <div className='flex flex-col'>\n                        <span className='text-sm font-medium'>\n                          {user.fullName}\n                        </span>\n                        <span className='text-xs text-accent-foreground/70'>\n                          {user.username}\n                        </span>\n                      </div>\n                    </div>\n\n                    {selectedUsers.find((u) => u.id === user.id) && (\n                      <Check className='h-4 w-4' />\n                    )}\n                  </CommandItem>\n                ))}\n              </CommandGroup>\n            </CommandList>\n          </Command>\n          <Button\n            variant={'default'}\n            onClick={() => showSubmittedData(selectedUsers)}\n            disabled={selectedUsers.length === 0}\n          >\n            Chat\n          </Button>\n        </div>\n      </DialogContent>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "src/features/chats/data/chat-types.ts",
    "content": "import { type conversations } from './convo.json'\n\nexport type ChatUser = (typeof conversations)[number]\nexport type Convo = ChatUser['messages'][number]\n"
  },
  {
    "path": "src/features/chats/data/convo.json",
    "content": "{\n  \"conversations\": [\n    {\n      \"id\": \"conv1\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/32.jpg\",\n      \"username\": \"alex_dev\",\n      \"fullName\": \"Alex John\",\n      \"title\": \"Senior Backend Dev\",\n      \"messages\": [\n        {\n          \"sender\": \"You\",\n          \"message\": \"See you later, Alex!\",\n          \"timestamp\": \"2024-08-24T11:15:15\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"Alright, talk to you later!\",\n          \"timestamp\": \"2024-08-24T11:11:30\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"For sure. Anyway, I should get back to reviewing the project.\",\n          \"timestamp\": \"2024-08-23T09:26:50\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"Yeah, let me know what you think.\",\n          \"timestamp\": \"2024-08-23T09:25:15\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Oh, nice! I've been waiting for that. I'll check it out later.\",\n          \"timestamp\": \"2024-08-23T09:24:30\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"They've added a dark mode option! It looks really sleek.\",\n          \"timestamp\": \"2024-08-23T09:23:10\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"No, not yet. What's new?\",\n          \"timestamp\": \"2024-08-23T09:22:00\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"By the way, have you seen the new feature update?\",\n          \"timestamp\": \"2024-08-23T09:21:05\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Will do! Thanks, Alex.\",\n          \"timestamp\": \"2024-08-23T09:20:10\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"Great! Let me know if you need any help.\",\n          \"timestamp\": \"2024-08-23T09:19:20\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Almost done. Just need to review a few things.\",\n          \"timestamp\": \"2024-08-23T09:18:45\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"I'm good, thanks! Did you finish the project?\",\n          \"timestamp\": \"2024-08-23T09:17:10\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Hey Alex, I'm doing well! How about you?\",\n          \"timestamp\": \"2024-08-23T09:16:30\"\n        },\n        {\n          \"sender\": \"Alex\",\n          \"message\": \"Hey Bob, how are you doing?\",\n          \"timestamp\": \"2024-08-23T09:15:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv2\",\n      \"profile\": \"https://randomuser.me/api/portraits/women/45.jpg\",\n      \"username\": \"taylor.codes\",\n      \"fullName\": \"Taylor Grande\",\n      \"title\": \"Tech Lead\",\n      \"messages\": [\n        {\n          \"sender\": \"Taylor\",\n          \"message\": \"Yeah, it's really well-explained. You should give it a try.\",\n          \"timestamp\": \"2024-08-23T10:35:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Not yet, is it good?\",\n          \"timestamp\": \"2024-08-23T10:32:00\"\n        },\n        {\n          \"sender\": \"Taylor\",\n          \"message\": \"Hey, did you check out that new tutorial?\",\n          \"timestamp\": \"2024-08-23T10:30:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv3\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/54.jpg\",\n      \"username\": \"john_stack\",\n      \"fullName\": \"John Doe\",\n      \"title\": \"QA\",\n      \"messages\": [\n        {\n          \"sender\": \"You\",\n          \"message\": \"Yep, see ya. 👋🏼\",\n          \"timestamp\": \"2024-08-22T18:59:00\"\n        },\n        {\n          \"sender\": \"John\",\n          \"message\": \"Great, see you then!\",\n          \"timestamp\": \"2024-08-22T18:55:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Yes, same time as usual. I'll send the invite shortly.\",\n          \"timestamp\": \"2024-08-22T18:50:00\"\n        },\n        {\n          \"sender\": \"John\",\n          \"message\": \"Are we still on for the meeting tomorrow?\",\n          \"timestamp\": \"2024-08-22T18:45:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv4\",\n      \"profile\": \"https://randomuser.me/api/portraits/women/29.jpg\",\n      \"username\": \"megan_frontend\",\n      \"fullName\": \"Megan Flux\",\n      \"title\": \"Jr Developer\",\n      \"messages\": [\n        {\n          \"sender\": \"You\",\n          \"message\": \"Sure ✌🏼\",\n          \"timestamp\": \"2024-08-23T11:30:00\"\n        },\n        {\n          \"sender\": \"Megan\",\n          \"message\": \"Thanks, appreciate it!\",\n          \"timestamp\": \"2024-08-23T11:30:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Sure thing! I'll take a look in the next hour.\",\n          \"timestamp\": \"2024-08-23T11:25:00\"\n        },\n        {\n          \"sender\": \"Megan\",\n          \"message\": \"Hey! Do you have time to review my PR today?\",\n          \"timestamp\": \"2024-08-23T11:20:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv5\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/72.jpg\",\n      \"username\": \"dev_david\",\n      \"fullName\": \"David Brown\",\n      \"title\": \"Senior UI/UX Designer\",\n      \"messages\": [\n        {\n          \"sender\": \"You\",\n          \"message\": \"Great, I'll review them now!\",\n          \"timestamp\": \"2024-08-23T12:00:00\"\n        },\n        {\n          \"sender\": \"David\",\n          \"message\": \"Just sent you the files. Let me know if you need any changes.\",\n          \"timestamp\": \"2024-08-23T11:58:00\"\n        },\n        {\n          \"sender\": \"David\",\n          \"message\": \"I finished the design for the dashboard. Thoughts?\",\n          \"timestamp\": \"2024-08-23T11:55:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv6\",\n      \"profile\": \"https://randomuser.me/api/portraits/women/68.jpg\",\n      \"username\": \"julia.design\",\n      \"fullName\": \"Julia Carter\",\n      \"title\": \"Product Designer\",\n      \"messages\": [\n        {\n          \"sender\": \"Julia\",\n          \"message\": \"Same here! It's coming together nicely.\",\n          \"timestamp\": \"2024-08-22T14:10:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"I'm really excited to see the final product!\",\n          \"timestamp\": \"2024-08-22T14:15:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"How's the project looking on your end?\",\n          \"timestamp\": \"2024-08-22T14:05:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv7\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/24.jpg\",\n      \"username\": \"brad_dev\",\n      \"fullName\": \"Brad Wilson\",\n      \"title\": \"CEO\",\n      \"messages\": [\n        {\n          \"sender\": \"Brad\",\n          \"message\": \"Got it! Thanks for the update.\",\n          \"timestamp\": \"2024-08-23T15:45:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"The release has been delayed to next week.\",\n          \"timestamp\": \"2024-08-23T15:40:00\"\n        },\n        {\n          \"sender\": \"Brad\",\n          \"message\": \"Hey, any news on the release?\",\n          \"timestamp\": \"2024-08-23T15:35:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv8\",\n      \"profile\": \"https://randomuser.me/api/portraits/women/34.jpg\",\n      \"username\": \"katie_ui\",\n      \"fullName\": \"Katie Lee\",\n      \"title\": \"QA\",\n      \"messages\": [\n        {\n          \"sender\": \"Katie\",\n          \"message\": \"I'll join the call in a few minutes.\",\n          \"timestamp\": \"2024-08-23T09:50:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Perfect! We'll start as soon as you're in.\",\n          \"timestamp\": \"2024-08-23T09:48:00\"\n        },\n        {\n          \"sender\": \"Katie\",\n          \"message\": \"Is the meeting still on?\",\n          \"timestamp\": \"2024-08-23T09:45:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv9\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/67.jpg\",\n      \"username\": \"matt_fullstack\",\n      \"fullName\": \"Matt Green\",\n      \"title\": \"Full-stack Dev\",\n      \"messages\": [\n        {\n          \"sender\": \"Matt\",\n          \"message\": \"Sure thing, I'll send over the updates shortly.\",\n          \"timestamp\": \"2024-08-23T10:25:00\"\n        },\n        {\n          \"sender\": \"You\",\n          \"message\": \"Could you update the backend as well?\",\n          \"timestamp\": \"2024-08-23T10:23:00\"\n        },\n        {\n          \"sender\": \"Matt\",\n          \"message\": \"The frontend updates are done. How does it look?\",\n          \"timestamp\": \"2024-08-23T10:20:00\"\n        }\n      ]\n    },\n    {\n      \"id\": \"conv10\",\n      \"profile\": \"https://randomuser.me/api/portraits/women/56.jpg\",\n      \"username\": \"sophie_dev\",\n      \"fullName\": \"Sophie Alex\",\n      \"title\": \"Jr. Frontend Dev\",\n      \"messages\": [\n        {\n          \"sender\": \"You\",\n          \"message\": \"Thanks! I'll review your code and get back to you.\",\n          \"timestamp\": \"2024-08-23T16:10:00\"\n        },\n        {\n          \"sender\": \"Sophie\",\n          \"message\": \"Let me know if you need anything else.\",\n          \"timestamp\": \"2024-08-23T16:05:00\"\n        },\n        {\n          \"sender\": \"Sophie\",\n          \"message\": \"The feature is implemented. Can you review it?\",\n          \"timestamp\": \"2024-08-23T16:00:00\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "src/features/chats/index.tsx",
    "content": "import { useState } from 'react'\nimport { Fragment } from 'react/jsx-runtime'\nimport { format } from 'date-fns'\nimport {\n  ArrowLeft,\n  MoreVertical,\n  Edit,\n  Paperclip,\n  Phone,\n  ImagePlus,\n  Plus,\n  Search as SearchIcon,\n  Send,\n  Video,\n  MessagesSquare,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Separator } from '@/components/ui/separator'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { NewChat } from './components/new-chat'\nimport { type ChatUser, type Convo } from './data/chat-types'\n// Fake Data\nimport { conversations } from './data/convo.json'\n\nexport function Chats() {\n  const [search, setSearch] = useState('')\n  const [selectedUser, setSelectedUser] = useState<ChatUser | null>(null)\n  const [mobileSelectedUser, setMobileSelectedUser] = useState<ChatUser | null>(\n    null\n  )\n  const [createConversationDialogOpened, setCreateConversationDialog] =\n    useState(false)\n\n  // Filtered data based on the search query\n  const filteredChatList = conversations.filter(({ fullName }) =>\n    fullName.toLowerCase().includes(search.trim().toLowerCase())\n  )\n\n  const currentMessage = selectedUser?.messages.reduce(\n    (acc: Record<string, Convo[]>, obj) => {\n      const key = format(obj.timestamp, 'd MMM, yyyy')\n\n      // Create an array for the category if it doesn't exist\n      if (!acc[key]) {\n        acc[key] = []\n      }\n\n      // Push the current object to the array\n      acc[key].push(obj)\n\n      return acc\n    },\n    {}\n  )\n\n  const users = conversations.map(({ messages, ...user }) => user)\n\n  return (\n    <>\n      {/* ===== Top Heading ===== */}\n      <Header>\n        <Search />\n        <div className='ms-auto flex items-center space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      <Main fixed>\n        <section className='flex h-full gap-6'>\n          {/* Left Side */}\n          <div className='flex w-full flex-col gap-2 sm:w-56 lg:w-72 2xl:w-80'>\n            <div className='sticky top-0 z-10 -mx-4 bg-background px-4 pb-3 shadow-md sm:static sm:z-auto sm:mx-0 sm:p-0 sm:shadow-none'>\n              <div className='flex items-center justify-between py-2'>\n                <div className='flex gap-2'>\n                  <h1 className='text-2xl font-bold'>Inbox</h1>\n                  <MessagesSquare size={20} />\n                </div>\n\n                <Button\n                  size='icon'\n                  variant='ghost'\n                  onClick={() => setCreateConversationDialog(true)}\n                  className='rounded-lg'\n                >\n                  <Edit size={24} className='stroke-muted-foreground' />\n                </Button>\n              </div>\n\n              <label\n                className={cn(\n                  'focus-within:ring-1 focus-within:ring-ring focus-within:outline-hidden',\n                  'flex h-10 w-full items-center space-x-0 rounded-md border border-border ps-2'\n                )}\n              >\n                <SearchIcon size={15} className='me-2 stroke-slate-500' />\n                <span className='sr-only'>Search</span>\n                <input\n                  type='text'\n                  className='w-full flex-1 bg-inherit text-sm focus-visible:outline-hidden'\n                  placeholder='Search chat...'\n                  value={search}\n                  onChange={(e) => setSearch(e.target.value)}\n                />\n              </label>\n            </div>\n\n            <ScrollArea className='-mx-3 h-full overflow-scroll p-3'>\n              {filteredChatList.map((chatUsr) => {\n                const { id, profile, username, messages, fullName } = chatUsr\n                const lastConvo = messages[0]\n                const lastMsg =\n                  lastConvo.sender === 'You'\n                    ? `You: ${lastConvo.message}`\n                    : lastConvo.message\n                return (\n                  <Fragment key={id}>\n                    <button\n                      type='button'\n                      className={cn(\n                        'group hover:bg-accent hover:text-accent-foreground',\n                        `flex w-full rounded-md px-2 py-2 text-start text-sm`,\n                        selectedUser?.id === id && 'sm:bg-muted'\n                      )}\n                      onClick={() => {\n                        setSelectedUser(chatUsr)\n                        setMobileSelectedUser(chatUsr)\n                      }}\n                    >\n                      <div className='flex gap-2'>\n                        <Avatar>\n                          <AvatarImage src={profile} alt={username} />\n                          <AvatarFallback>{username}</AvatarFallback>\n                        </Avatar>\n                        <div>\n                          <span className='col-start-2 row-span-2 font-medium'>\n                            {fullName}\n                          </span>\n                          <span className='col-start-2 row-span-2 row-start-2 line-clamp-2 text-ellipsis text-muted-foreground group-hover:text-accent-foreground/90'>\n                            {lastMsg}\n                          </span>\n                        </div>\n                      </div>\n                    </button>\n                    <Separator className='my-1' />\n                  </Fragment>\n                )\n              })}\n            </ScrollArea>\n          </div>\n\n          {/* Right Side */}\n          {selectedUser ? (\n            <div\n              className={cn(\n                'absolute inset-0 start-full z-50 hidden w-full flex-1 flex-col border bg-background shadow-xs sm:static sm:z-auto sm:flex sm:rounded-md',\n                mobileSelectedUser && 'start-0 flex'\n              )}\n            >\n              {/* Top Part */}\n              <div className='mb-1 flex flex-none justify-between bg-card p-4 shadow-lg sm:rounded-t-md'>\n                {/* Left */}\n                <div className='flex gap-3'>\n                  <Button\n                    size='icon'\n                    variant='ghost'\n                    className='-ms-2 h-full sm:hidden'\n                    onClick={() => setMobileSelectedUser(null)}\n                  >\n                    <ArrowLeft className='rtl:rotate-180' />\n                  </Button>\n                  <div className='flex items-center gap-2 lg:gap-4'>\n                    <Avatar className='size-9 lg:size-11'>\n                      <AvatarImage\n                        src={selectedUser.profile}\n                        alt={selectedUser.username}\n                      />\n                      <AvatarFallback>{selectedUser.username}</AvatarFallback>\n                    </Avatar>\n                    <div>\n                      <span className='col-start-2 row-span-2 text-sm font-medium lg:text-base'>\n                        {selectedUser.fullName}\n                      </span>\n                      <span className='col-start-2 row-span-2 row-start-2 line-clamp-1 block max-w-32 text-xs text-nowrap text-ellipsis text-muted-foreground lg:max-w-none lg:text-sm'>\n                        {selectedUser.title}\n                      </span>\n                    </div>\n                  </div>\n                </div>\n\n                {/* Right */}\n                <div className='-me-1 flex items-center gap-1 lg:gap-2'>\n                  <Button\n                    size='icon'\n                    variant='ghost'\n                    className='hidden size-8 rounded-full sm:inline-flex lg:size-10'\n                  >\n                    <Video size={22} className='stroke-muted-foreground' />\n                  </Button>\n                  <Button\n                    size='icon'\n                    variant='ghost'\n                    className='hidden size-8 rounded-full sm:inline-flex lg:size-10'\n                  >\n                    <Phone size={22} className='stroke-muted-foreground' />\n                  </Button>\n                  <Button\n                    size='icon'\n                    variant='ghost'\n                    className='h-10 rounded-md sm:h-8 sm:w-4 lg:h-10 lg:w-6'\n                  >\n                    <MoreVertical className='stroke-muted-foreground sm:size-5' />\n                  </Button>\n                </div>\n              </div>\n\n              {/* Conversation */}\n              <div className='flex flex-1 flex-col gap-2 rounded-md px-4 pt-0 pb-4'>\n                <div className='flex size-full flex-1'>\n                  <div className='chat-text-container relative -me-4 flex flex-1 flex-col overflow-y-hidden'>\n                    <div className='chat-flex flex h-40 w-full grow flex-col-reverse justify-start gap-4 overflow-y-auto py-2 pe-4 pb-4'>\n                      {currentMessage &&\n                        Object.keys(currentMessage).map((key) => (\n                          <Fragment key={key}>\n                            {currentMessage[key].map((msg, index) => (\n                              <div\n                                key={`${msg.sender}-${msg.timestamp}-${index}`}\n                                className={cn(\n                                  'chat-box max-w-72 px-3 py-2 wrap-break-word shadow-lg',\n                                  msg.sender === 'You'\n                                    ? 'self-end rounded-[16px_16px_0_16px] bg-primary/90 text-primary-foreground/75'\n                                    : 'self-start rounded-[16px_16px_16px_0] bg-muted'\n                                )}\n                              >\n                                {msg.message}{' '}\n                                <span\n                                  className={cn(\n                                    'mt-1 block text-xs font-light text-foreground/75 italic',\n                                    msg.sender === 'You' &&\n                                      'text-end text-primary-foreground/85'\n                                  )}\n                                >\n                                  {format(msg.timestamp, 'h:mm a')}\n                                </span>\n                              </div>\n                            ))}\n                            <div className='text-center text-xs'>{key}</div>\n                          </Fragment>\n                        ))}\n                    </div>\n                  </div>\n                </div>\n                <form className='flex w-full flex-none gap-2'>\n                  <div className='flex flex-1 items-center gap-2 rounded-md border border-input bg-card px-2 py-1 focus-within:ring-1 focus-within:ring-ring focus-within:outline-hidden lg:gap-4'>\n                    <div className='space-x-1'>\n                      <Button\n                        size='icon'\n                        type='button'\n                        variant='ghost'\n                        className='h-8 rounded-md'\n                      >\n                        <Plus size={20} className='stroke-muted-foreground' />\n                      </Button>\n                      <Button\n                        size='icon'\n                        type='button'\n                        variant='ghost'\n                        className='hidden h-8 rounded-md lg:inline-flex'\n                      >\n                        <ImagePlus\n                          size={20}\n                          className='stroke-muted-foreground'\n                        />\n                      </Button>\n                      <Button\n                        size='icon'\n                        type='button'\n                        variant='ghost'\n                        className='hidden h-8 rounded-md lg:inline-flex'\n                      >\n                        <Paperclip\n                          size={20}\n                          className='stroke-muted-foreground'\n                        />\n                      </Button>\n                    </div>\n                    <label className='flex-1'>\n                      <span className='sr-only'>Chat Text Box</span>\n                      <input\n                        type='text'\n                        placeholder='Type your messages...'\n                        className='h-8 w-full bg-inherit focus-visible:outline-hidden'\n                      />\n                    </label>\n                    <Button\n                      variant='ghost'\n                      size='icon'\n                      className='hidden sm:inline-flex'\n                    >\n                      <Send size={20} />\n                    </Button>\n                  </div>\n                  <Button className='h-full sm:hidden'>\n                    <Send size={18} /> Send\n                  </Button>\n                </form>\n              </div>\n            </div>\n          ) : (\n            <div\n              className={cn(\n                'absolute inset-0 start-full z-50 hidden w-full flex-1 flex-col justify-center rounded-md border bg-card shadow-xs sm:static sm:z-auto sm:flex'\n              )}\n            >\n              <div className='flex flex-col items-center space-y-6'>\n                <div className='flex size-16 items-center justify-center rounded-full border-2 border-border'>\n                  <MessagesSquare className='size-8' />\n                </div>\n                <div className='space-y-2 text-center'>\n                  <h1 className='text-xl font-semibold'>Your messages</h1>\n                  <p className='text-sm text-muted-foreground'>\n                    Send a message to start a chat.\n                  </p>\n                </div>\n                <Button onClick={() => setCreateConversationDialog(true)}>\n                  Send message\n                </Button>\n              </div>\n            </div>\n          )}\n        </section>\n        <NewChat\n          users={users}\n          onOpenChange={setCreateConversationDialog}\n          open={createConversationDialogOpened}\n        />\n      </Main>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/dashboard/components/analytics-chart.tsx",
    "content": "import { Area, AreaChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'\n\nconst data = [\n  {\n    name: 'Mon',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Tue',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Wed',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Thu',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Fri',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Sat',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n  {\n    name: 'Sun',\n    clicks: Math.floor(Math.random() * 900) + 100,\n    uniques: Math.floor(Math.random() * 700) + 80,\n  },\n]\n\nexport function AnalyticsChart() {\n  return (\n    <ResponsiveContainer width='100%' height={300}>\n      <AreaChart data={data}>\n        <XAxis\n          dataKey='name'\n          stroke='#888888'\n          fontSize={12}\n          tickLine={false}\n          axisLine={false}\n        />\n        <YAxis\n          stroke='#888888'\n          fontSize={12}\n          tickLine={false}\n          axisLine={false}\n        />\n        <Area\n          type='monotone'\n          dataKey='clicks'\n          stroke='currentColor'\n          className='text-primary'\n          fill='currentColor'\n          fillOpacity={0.15}\n        />\n        <Area\n          type='monotone'\n          dataKey='uniques'\n          stroke='currentColor'\n          className='text-muted-foreground'\n          fill='currentColor'\n          fillOpacity={0.1}\n        />\n      </AreaChart>\n    </ResponsiveContainer>\n  )\n}\n"
  },
  {
    "path": "src/features/dashboard/components/analytics.tsx",
    "content": "import {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { AnalyticsChart } from './analytics-chart'\n\nexport function Analytics() {\n  return (\n    <div className='space-y-4'>\n      <Card>\n        <CardHeader>\n          <CardTitle>Traffic Overview</CardTitle>\n          <CardDescription>Weekly clicks and unique visitors</CardDescription>\n        </CardHeader>\n        <CardContent className='px-6'>\n          <AnalyticsChart />\n        </CardContent>\n      </Card>\n      <div className='grid gap-4 sm:grid-cols-2 lg:grid-cols-4'>\n        <Card>\n          <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n            <CardTitle className='text-sm font-medium'>Total Clicks</CardTitle>\n            <svg\n              xmlns='http://www.w3.org/2000/svg'\n              viewBox='0 0 24 24'\n              fill='none'\n              stroke='currentColor'\n              strokeLinecap='round'\n              strokeLinejoin='round'\n              strokeWidth='2'\n              className='h-4 w-4 text-muted-foreground'\n            >\n              <path d='M3 3v18h18' />\n              <path d='M7 15l4-4 4 4 4-6' />\n            </svg>\n          </CardHeader>\n          <CardContent>\n            <div className='text-2xl font-bold'>1,248</div>\n            <p className='text-xs text-muted-foreground'>+12.4% vs last week</p>\n          </CardContent>\n        </Card>\n        <Card>\n          <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n            <CardTitle className='text-sm font-medium'>\n              Unique Visitors\n            </CardTitle>\n            <svg\n              xmlns='http://www.w3.org/2000/svg'\n              viewBox='0 0 24 24'\n              fill='none'\n              stroke='currentColor'\n              strokeLinecap='round'\n              strokeLinejoin='round'\n              strokeWidth='2'\n              className='h-4 w-4 text-muted-foreground'\n            >\n              <circle cx='12' cy='7' r='4' />\n              <path d='M6 21v-2a6 6 0 0 1 12 0v2' />\n            </svg>\n          </CardHeader>\n          <CardContent>\n            <div className='text-2xl font-bold'>832</div>\n            <p className='text-xs text-muted-foreground'>+5.8% vs last week</p>\n          </CardContent>\n        </Card>\n        <Card>\n          <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n            <CardTitle className='text-sm font-medium'>Bounce Rate</CardTitle>\n            <svg\n              xmlns='http://www.w3.org/2000/svg'\n              viewBox='0 0 24 24'\n              fill='none'\n              stroke='currentColor'\n              strokeLinecap='round'\n              strokeLinejoin='round'\n              strokeWidth='2'\n              className='h-4 w-4 text-muted-foreground'\n            >\n              <path d='M3 12h6l3 6 3-6h6' />\n            </svg>\n          </CardHeader>\n          <CardContent>\n            <div className='text-2xl font-bold'>42%</div>\n            <p className='text-xs text-muted-foreground'>-3.2% vs last week</p>\n          </CardContent>\n        </Card>\n        <Card>\n          <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n            <CardTitle className='text-sm font-medium'>Avg. Session</CardTitle>\n            <svg\n              xmlns='http://www.w3.org/2000/svg'\n              viewBox='0 0 24 24'\n              fill='none'\n              stroke='currentColor'\n              strokeLinecap='round'\n              strokeLinejoin='round'\n              strokeWidth='2'\n              className='h-4 w-4 text-muted-foreground'\n            >\n              <circle cx='12' cy='12' r='10' />\n              <path d='M12 6v6l4 2' />\n            </svg>\n          </CardHeader>\n          <CardContent>\n            <div className='text-2xl font-bold'>3m 24s</div>\n            <p className='text-xs text-muted-foreground'>+18s vs last week</p>\n          </CardContent>\n        </Card>\n      </div>\n      <div className='grid grid-cols-1 gap-4 lg:grid-cols-7'>\n        <Card className='col-span-1 lg:col-span-4'>\n          <CardHeader>\n            <CardTitle>Referrers</CardTitle>\n            <CardDescription>Top sources driving traffic</CardDescription>\n          </CardHeader>\n          <CardContent>\n            <SimpleBarList\n              items={[\n                { name: 'Direct', value: 512 },\n                { name: 'Product Hunt', value: 238 },\n                { name: 'Twitter', value: 174 },\n                { name: 'Blog', value: 104 },\n              ]}\n              barClass='bg-primary'\n              valueFormatter={(n) => `${n}`}\n            />\n          </CardContent>\n        </Card>\n        <Card className='col-span-1 lg:col-span-3'>\n          <CardHeader>\n            <CardTitle>Devices</CardTitle>\n            <CardDescription>How users access your app</CardDescription>\n          </CardHeader>\n          <CardContent>\n            <SimpleBarList\n              items={[\n                { name: 'Desktop', value: 74 },\n                { name: 'Mobile', value: 22 },\n                { name: 'Tablet', value: 4 },\n              ]}\n              barClass='bg-muted-foreground'\n              valueFormatter={(n) => `${n}%`}\n            />\n          </CardContent>\n        </Card>\n      </div>\n    </div>\n  )\n}\n\nfunction SimpleBarList({\n  items,\n  valueFormatter,\n  barClass,\n}: {\n  items: { name: string; value: number }[]\n  valueFormatter: (n: number) => string\n  barClass: string\n}) {\n  const max = Math.max(...items.map((i) => i.value), 1)\n  return (\n    <ul className='space-y-3'>\n      {items.map((i) => {\n        const width = `${Math.round((i.value / max) * 100)}%`\n        return (\n          <li key={i.name} className='flex items-center justify-between gap-3'>\n            <div className='min-w-0 flex-1'>\n              <div className='mb-1 truncate text-xs text-muted-foreground'>\n                {i.name}\n              </div>\n              <div className='h-2.5 w-full rounded-full bg-muted'>\n                <div\n                  className={`h-2.5 rounded-full ${barClass}`}\n                  style={{ width }}\n                />\n              </div>\n            </div>\n            <div className='ps-2 text-xs font-medium tabular-nums'>\n              {valueFormatter(i.value)}\n            </div>\n          </li>\n        )\n      })}\n    </ul>\n  )\n}\n"
  },
  {
    "path": "src/features/dashboard/components/overview.tsx",
    "content": "import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'\n\nconst data = [\n  {\n    name: 'Jan',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Feb',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Mar',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Apr',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'May',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Jun',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Jul',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Aug',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Sep',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Oct',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Nov',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n  {\n    name: 'Dec',\n    total: Math.floor(Math.random() * 5000) + 1000,\n  },\n]\n\nexport function Overview() {\n  return (\n    <ResponsiveContainer width='100%' height={350}>\n      <BarChart data={data}>\n        <XAxis\n          dataKey='name'\n          stroke='#888888'\n          fontSize={12}\n          tickLine={false}\n          axisLine={false}\n        />\n        <YAxis\n          direction='ltr'\n          stroke='#888888'\n          fontSize={12}\n          tickLine={false}\n          axisLine={false}\n          tickFormatter={(value) => `$${value}`}\n        />\n        <Bar\n          dataKey='total'\n          fill='currentColor'\n          radius={[4, 4, 0, 0]}\n          className='fill-primary'\n        />\n      </BarChart>\n    </ResponsiveContainer>\n  )\n}\n"
  },
  {
    "path": "src/features/dashboard/components/recent-sales.tsx",
    "content": "import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\n\nexport function RecentSales() {\n  return (\n    <div className='space-y-8'>\n      <div className='flex items-center gap-4'>\n        <Avatar className='h-9 w-9'>\n          <AvatarImage src='/avatars/01.png' alt='Avatar' />\n          <AvatarFallback>OM</AvatarFallback>\n        </Avatar>\n        <div className='flex flex-1 flex-wrap items-center justify-between'>\n          <div className='space-y-1'>\n            <p className='text-sm leading-none font-medium'>Olivia Martin</p>\n            <p className='text-sm text-muted-foreground'>\n              olivia.martin@email.com\n            </p>\n          </div>\n          <div className='font-medium'>+$1,999.00</div>\n        </div>\n      </div>\n      <div className='flex items-center gap-4'>\n        <Avatar className='flex h-9 w-9 items-center justify-center space-y-0 border'>\n          <AvatarImage src='/avatars/02.png' alt='Avatar' />\n          <AvatarFallback>JL</AvatarFallback>\n        </Avatar>\n        <div className='flex flex-1 flex-wrap items-center justify-between'>\n          <div className='space-y-1'>\n            <p className='text-sm leading-none font-medium'>Jackson Lee</p>\n            <p className='text-sm text-muted-foreground'>\n              jackson.lee@email.com\n            </p>\n          </div>\n          <div className='font-medium'>+$39.00</div>\n        </div>\n      </div>\n      <div className='flex items-center gap-4'>\n        <Avatar className='h-9 w-9'>\n          <AvatarImage src='/avatars/03.png' alt='Avatar' />\n          <AvatarFallback>IN</AvatarFallback>\n        </Avatar>\n        <div className='flex flex-1 flex-wrap items-center justify-between'>\n          <div className='space-y-1'>\n            <p className='text-sm leading-none font-medium'>Isabella Nguyen</p>\n            <p className='text-sm text-muted-foreground'>\n              isabella.nguyen@email.com\n            </p>\n          </div>\n          <div className='font-medium'>+$299.00</div>\n        </div>\n      </div>\n\n      <div className='flex items-center gap-4'>\n        <Avatar className='h-9 w-9'>\n          <AvatarImage src='/avatars/04.png' alt='Avatar' />\n          <AvatarFallback>WK</AvatarFallback>\n        </Avatar>\n        <div className='flex flex-1 flex-wrap items-center justify-between'>\n          <div className='space-y-1'>\n            <p className='text-sm leading-none font-medium'>William Kim</p>\n            <p className='text-sm text-muted-foreground'>will@email.com</p>\n          </div>\n          <div className='font-medium'>+$99.00</div>\n        </div>\n      </div>\n\n      <div className='flex items-center gap-4'>\n        <Avatar className='h-9 w-9'>\n          <AvatarImage src='/avatars/05.png' alt='Avatar' />\n          <AvatarFallback>SD</AvatarFallback>\n        </Avatar>\n        <div className='flex flex-1 flex-wrap items-center justify-between'>\n          <div className='space-y-1'>\n            <p className='text-sm leading-none font-medium'>Sofia Davis</p>\n            <p className='text-sm text-muted-foreground'>\n              sofia.davis@email.com\n            </p>\n          </div>\n          <div className='font-medium'>+$39.00</div>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/dashboard/index.tsx",
    "content": "import { Button } from '@/components/ui/button'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { TopNav } from '@/components/layout/top-nav'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { Analytics } from './components/analytics'\nimport { Overview } from './components/overview'\nimport { RecentSales } from './components/recent-sales'\n\nexport function Dashboard() {\n  return (\n    <>\n      {/* ===== Top Heading ===== */}\n      <Header>\n        <TopNav links={topNav} />\n        <div className='ms-auto flex items-center space-x-4'>\n          <Search />\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      {/* ===== Main ===== */}\n      <Main>\n        <div className='mb-2 flex items-center justify-between space-y-2'>\n          <h1 className='text-2xl font-bold tracking-tight'>Dashboard</h1>\n          <div className='flex items-center space-x-2'>\n            <Button>Download</Button>\n          </div>\n        </div>\n        <Tabs\n          orientation='vertical'\n          defaultValue='overview'\n          className='space-y-4'\n        >\n          <div className='w-full overflow-x-auto pb-2'>\n            <TabsList>\n              <TabsTrigger value='overview'>Overview</TabsTrigger>\n              <TabsTrigger value='analytics'>Analytics</TabsTrigger>\n              <TabsTrigger value='reports' disabled>\n                Reports\n              </TabsTrigger>\n              <TabsTrigger value='notifications' disabled>\n                Notifications\n              </TabsTrigger>\n            </TabsList>\n          </div>\n          <TabsContent value='overview' className='space-y-4'>\n            <div className='grid gap-4 sm:grid-cols-2 lg:grid-cols-4'>\n              <Card>\n                <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n                  <CardTitle className='text-sm font-medium'>\n                    Total Revenue\n                  </CardTitle>\n                  <svg\n                    xmlns='http://www.w3.org/2000/svg'\n                    viewBox='0 0 24 24'\n                    fill='none'\n                    stroke='currentColor'\n                    strokeLinecap='round'\n                    strokeLinejoin='round'\n                    strokeWidth='2'\n                    className='h-4 w-4 text-muted-foreground'\n                  >\n                    <path d='M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6' />\n                  </svg>\n                </CardHeader>\n                <CardContent>\n                  <div className='text-2xl font-bold'>$45,231.89</div>\n                  <p className='text-xs text-muted-foreground'>\n                    +20.1% from last month\n                  </p>\n                </CardContent>\n              </Card>\n              <Card>\n                <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n                  <CardTitle className='text-sm font-medium'>\n                    Subscriptions\n                  </CardTitle>\n                  <svg\n                    xmlns='http://www.w3.org/2000/svg'\n                    viewBox='0 0 24 24'\n                    fill='none'\n                    stroke='currentColor'\n                    strokeLinecap='round'\n                    strokeLinejoin='round'\n                    strokeWidth='2'\n                    className='h-4 w-4 text-muted-foreground'\n                  >\n                    <path d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2' />\n                    <circle cx='9' cy='7' r='4' />\n                    <path d='M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75' />\n                  </svg>\n                </CardHeader>\n                <CardContent>\n                  <div className='text-2xl font-bold'>+2350</div>\n                  <p className='text-xs text-muted-foreground'>\n                    +180.1% from last month\n                  </p>\n                </CardContent>\n              </Card>\n              <Card>\n                <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n                  <CardTitle className='text-sm font-medium'>Sales</CardTitle>\n                  <svg\n                    xmlns='http://www.w3.org/2000/svg'\n                    viewBox='0 0 24 24'\n                    fill='none'\n                    stroke='currentColor'\n                    strokeLinecap='round'\n                    strokeLinejoin='round'\n                    strokeWidth='2'\n                    className='h-4 w-4 text-muted-foreground'\n                  >\n                    <rect width='20' height='14' x='2' y='5' rx='2' />\n                    <path d='M2 10h20' />\n                  </svg>\n                </CardHeader>\n                <CardContent>\n                  <div className='text-2xl font-bold'>+12,234</div>\n                  <p className='text-xs text-muted-foreground'>\n                    +19% from last month\n                  </p>\n                </CardContent>\n              </Card>\n              <Card>\n                <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>\n                  <CardTitle className='text-sm font-medium'>\n                    Active Now\n                  </CardTitle>\n                  <svg\n                    xmlns='http://www.w3.org/2000/svg'\n                    viewBox='0 0 24 24'\n                    fill='none'\n                    stroke='currentColor'\n                    strokeLinecap='round'\n                    strokeLinejoin='round'\n                    strokeWidth='2'\n                    className='h-4 w-4 text-muted-foreground'\n                  >\n                    <path d='M22 12h-4l-3 9L9 3l-3 9H2' />\n                  </svg>\n                </CardHeader>\n                <CardContent>\n                  <div className='text-2xl font-bold'>+573</div>\n                  <p className='text-xs text-muted-foreground'>\n                    +201 since last hour\n                  </p>\n                </CardContent>\n              </Card>\n            </div>\n            <div className='grid grid-cols-1 gap-4 lg:grid-cols-7'>\n              <Card className='col-span-1 lg:col-span-4'>\n                <CardHeader>\n                  <CardTitle>Overview</CardTitle>\n                </CardHeader>\n                <CardContent className='ps-2'>\n                  <Overview />\n                </CardContent>\n              </Card>\n              <Card className='col-span-1 lg:col-span-3'>\n                <CardHeader>\n                  <CardTitle>Recent Sales</CardTitle>\n                  <CardDescription>\n                    You made 265 sales this month.\n                  </CardDescription>\n                </CardHeader>\n                <CardContent>\n                  <RecentSales />\n                </CardContent>\n              </Card>\n            </div>\n          </TabsContent>\n          <TabsContent value='analytics' className='space-y-4'>\n            <Analytics />\n          </TabsContent>\n        </Tabs>\n      </Main>\n    </>\n  )\n}\n\nconst topNav = [\n  {\n    title: 'Overview',\n    href: 'dashboard/overview',\n    isActive: true,\n    disabled: false,\n  },\n  {\n    title: 'Customers',\n    href: 'dashboard/customers',\n    isActive: false,\n    disabled: true,\n  },\n  {\n    title: 'Products',\n    href: 'dashboard/products',\n    isActive: false,\n    disabled: true,\n  },\n  {\n    title: 'Settings',\n    href: 'dashboard/settings',\n    isActive: false,\n    disabled: true,\n  },\n]\n"
  },
  {
    "path": "src/features/errors/forbidden.tsx",
    "content": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport function ForbiddenError() {\n  const navigate = useNavigate()\n  const { history } = useRouter()\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <h1 className='text-[7rem] leading-tight font-bold'>403</h1>\n        <span className='font-medium'>Access Forbidden</span>\n        <p className='text-center text-muted-foreground'>\n          You don't have necessary permission <br />\n          to view this resource.\n        </p>\n        <div className='mt-6 flex gap-4'>\n          <Button variant='outline' onClick={() => history.go(-1)}>\n            Go Back\n          </Button>\n          <Button onClick={() => navigate({ to: '/' })}>Back to Home</Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/errors/general-error.tsx",
    "content": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\n\ntype GeneralErrorProps = React.HTMLAttributes<HTMLDivElement> & {\n  minimal?: boolean\n}\n\nexport function GeneralError({\n  className,\n  minimal = false,\n}: GeneralErrorProps) {\n  const navigate = useNavigate()\n  const { history } = useRouter()\n  return (\n    <div className={cn('h-svh w-full', className)}>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        {!minimal && (\n          <h1 className='text-[7rem] leading-tight font-bold'>500</h1>\n        )}\n        <span className='font-medium'>Oops! Something went wrong {`:')`}</span>\n        <p className='text-center text-muted-foreground'>\n          We apologize for the inconvenience. <br /> Please try again later.\n        </p>\n        {!minimal && (\n          <div className='mt-6 flex gap-4'>\n            <Button variant='outline' onClick={() => history.go(-1)}>\n              Go Back\n            </Button>\n            <Button onClick={() => navigate({ to: '/' })}>Back to Home</Button>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/errors/maintenance-error.tsx",
    "content": "import { Button } from '@/components/ui/button'\n\nexport function MaintenanceError() {\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <h1 className='text-[7rem] leading-tight font-bold'>503</h1>\n        <span className='font-medium'>Website is under maintenance!</span>\n        <p className='text-center text-muted-foreground'>\n          The site is not available at the moment. <br />\n          We'll be back online shortly.\n        </p>\n        <div className='mt-6 flex gap-4'>\n          <Button variant='outline'>Learn more</Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/errors/not-found-error.tsx",
    "content": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport function NotFoundError() {\n  const navigate = useNavigate()\n  const { history } = useRouter()\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <h1 className='text-[7rem] leading-tight font-bold'>404</h1>\n        <span className='font-medium'>Oops! Page Not Found!</span>\n        <p className='text-center text-muted-foreground'>\n          It seems like the page you're looking for <br />\n          does not exist or might have been removed.\n        </p>\n        <div className='mt-6 flex gap-4'>\n          <Button variant='outline' onClick={() => history.go(-1)}>\n            Go Back\n          </Button>\n          <Button onClick={() => navigate({ to: '/' })}>Back to Home</Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/errors/unauthorized-error.tsx",
    "content": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport function UnauthorisedError() {\n  const navigate = useNavigate()\n  const { history } = useRouter()\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <h1 className='text-[7rem] leading-tight font-bold'>401</h1>\n        <span className='font-medium'>Unauthorized Access</span>\n        <p className='text-center text-muted-foreground'>\n          Please log in with the appropriate credentials <br /> to access this\n          resource.\n        </p>\n        <div className='mt-6 flex gap-4'>\n          <Button variant='outline' onClick={() => history.go(-1)}>\n            Go Back\n          </Button>\n          <Button onClick={() => navigate({ to: '/' })}>Back to Home</Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/account/account-form.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { CaretSortIcon, CheckIcon } from '@radix-ui/react-icons'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover'\nimport { DatePicker } from '@/components/date-picker'\n\nconst languages = [\n  { label: 'English', value: 'en' },\n  { label: 'French', value: 'fr' },\n  { label: 'German', value: 'de' },\n  { label: 'Spanish', value: 'es' },\n  { label: 'Portuguese', value: 'pt' },\n  { label: 'Russian', value: 'ru' },\n  { label: 'Japanese', value: 'ja' },\n  { label: 'Korean', value: 'ko' },\n  { label: 'Chinese', value: 'zh' },\n] as const\n\nconst accountFormSchema = z.object({\n  name: z\n    .string()\n    .min(1, 'Please enter your name.')\n    .min(2, 'Name must be at least 2 characters.')\n    .max(30, 'Name must not be longer than 30 characters.'),\n  dob: z.date('Please select your date of birth.'),\n  language: z.string('Please select a language.'),\n})\n\ntype AccountFormValues = z.infer<typeof accountFormSchema>\n\n// This can come from your database or API.\nconst defaultValues: Partial<AccountFormValues> = {\n  name: '',\n}\n\nexport function AccountForm() {\n  const form = useForm<AccountFormValues>({\n    resolver: zodResolver(accountFormSchema),\n    defaultValues,\n  })\n\n  function onSubmit(data: AccountFormValues) {\n    showSubmittedData(data)\n  }\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'>\n        <FormField\n          control={form.control}\n          name='name'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Name</FormLabel>\n              <FormControl>\n                <Input placeholder='Your name' {...field} />\n              </FormControl>\n              <FormDescription>\n                This is the name that will be displayed on your profile and in\n                emails.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='dob'\n          render={({ field }) => (\n            <FormItem className='flex flex-col'>\n              <FormLabel>Date of birth</FormLabel>\n              <DatePicker selected={field.value} onSelect={field.onChange} />\n              <FormDescription>\n                Your date of birth is used to calculate your age.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='language'\n          render={({ field }) => (\n            <FormItem className='flex flex-col'>\n              <FormLabel>Language</FormLabel>\n              <Popover>\n                <PopoverTrigger asChild>\n                  <FormControl>\n                    <Button\n                      variant='outline'\n                      role='combobox'\n                      className={cn(\n                        'w-[200px] justify-between',\n                        !field.value && 'text-muted-foreground'\n                      )}\n                    >\n                      {field.value\n                        ? languages.find(\n                            (language) => language.value === field.value\n                          )?.label\n                        : 'Select language'}\n                      <CaretSortIcon className='ms-2 h-4 w-4 shrink-0 opacity-50' />\n                    </Button>\n                  </FormControl>\n                </PopoverTrigger>\n                <PopoverContent className='w-[200px] p-0'>\n                  <Command>\n                    <CommandInput placeholder='Search language...' />\n                    <CommandEmpty>No language found.</CommandEmpty>\n                    <CommandGroup>\n                      <CommandList>\n                        {languages.map((language) => (\n                          <CommandItem\n                            value={language.label}\n                            key={language.value}\n                            onSelect={() => {\n                              form.setValue('language', language.value)\n                            }}\n                          >\n                            <CheckIcon\n                              className={cn(\n                                'size-4',\n                                language.value === field.value\n                                  ? 'opacity-100'\n                                  : 'opacity-0'\n                              )}\n                            />\n                            {language.label}\n                          </CommandItem>\n                        ))}\n                      </CommandList>\n                    </CommandGroup>\n                  </Command>\n                </PopoverContent>\n              </Popover>\n              <FormDescription>\n                This is the language that will be used in the dashboard.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button type='submit'>Update account</Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/account/index.tsx",
    "content": "import { ContentSection } from '../components/content-section'\nimport { AccountForm } from './account-form'\n\nexport function SettingsAccount() {\n  return (\n    <ContentSection\n      title='Account'\n      desc='Update your account settings. Set your preferred language and\n          timezone.'\n    >\n      <AccountForm />\n    </ContentSection>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/appearance/appearance-form.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { ChevronDownIcon } from '@radix-ui/react-icons'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { fonts } from '@/config/fonts'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { cn } from '@/lib/utils'\nimport { useFont } from '@/context/font-provider'\nimport { useTheme } from '@/context/theme-provider'\nimport { Button, buttonVariants } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'\n\nconst appearanceFormSchema = z.object({\n  theme: z.enum(['light', 'dark']),\n  font: z.enum(fonts),\n})\n\ntype AppearanceFormValues = z.infer<typeof appearanceFormSchema>\n\nexport function AppearanceForm() {\n  const { font, setFont } = useFont()\n  const { theme, setTheme } = useTheme()\n\n  // This can come from your database or API.\n  const defaultValues: Partial<AppearanceFormValues> = {\n    theme: theme as 'light' | 'dark',\n    font,\n  }\n\n  const form = useForm<AppearanceFormValues>({\n    resolver: zodResolver(appearanceFormSchema),\n    defaultValues,\n  })\n\n  function onSubmit(data: AppearanceFormValues) {\n    if (data.font != font) setFont(data.font)\n    if (data.theme != theme) setTheme(data.theme)\n\n    showSubmittedData(data)\n  }\n\n  return (\n    <Form {...form}>\n      <form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'>\n        <FormField\n          control={form.control}\n          name='font'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Font</FormLabel>\n              <div className='relative w-max'>\n                <FormControl>\n                  <select\n                    className={cn(\n                      buttonVariants({ variant: 'outline' }),\n                      'w-[200px] appearance-none font-normal capitalize',\n                      'dark:bg-background dark:hover:bg-background'\n                    )}\n                    {...field}\n                  >\n                    {fonts.map((font) => (\n                      <option key={font} value={font}>\n                        {font}\n                      </option>\n                    ))}\n                  </select>\n                </FormControl>\n                <ChevronDownIcon className='absolute end-3 top-2.5 h-4 w-4 opacity-50' />\n              </div>\n              <FormDescription className='font-manrope'>\n                Set the font you want to use in the dashboard.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='theme'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Theme</FormLabel>\n              <FormDescription>\n                Select the theme for the dashboard.\n              </FormDescription>\n              <FormMessage />\n              <RadioGroup\n                onValueChange={field.onChange}\n                defaultValue={field.value}\n                className='grid max-w-md grid-cols-2 gap-8 pt-2'\n              >\n                <FormItem>\n                  <FormLabel className='[&:has([data-state=checked])>div]:border-primary'>\n                    <FormControl>\n                      <RadioGroupItem value='light' className='sr-only' />\n                    </FormControl>\n                    <div className='items-center rounded-md border-2 border-muted p-1 hover:border-accent'>\n                      <div className='space-y-2 rounded-sm bg-[#ecedef] p-2'>\n                        <div className='space-y-2 rounded-md bg-white p-2 shadow-xs'>\n                          <div className='h-2 w-[80px] rounded-lg bg-[#ecedef]' />\n                          <div className='h-2 w-[100px] rounded-lg bg-[#ecedef]' />\n                        </div>\n                        <div className='flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs'>\n                          <div className='h-4 w-4 rounded-full bg-[#ecedef]' />\n                          <div className='h-2 w-[100px] rounded-lg bg-[#ecedef]' />\n                        </div>\n                        <div className='flex items-center space-x-2 rounded-md bg-white p-2 shadow-xs'>\n                          <div className='h-4 w-4 rounded-full bg-[#ecedef]' />\n                          <div className='h-2 w-[100px] rounded-lg bg-[#ecedef]' />\n                        </div>\n                      </div>\n                    </div>\n                    <span className='block w-full p-2 text-center font-normal'>\n                      Light\n                    </span>\n                  </FormLabel>\n                </FormItem>\n                <FormItem>\n                  <FormLabel className='[&:has([data-state=checked])>div]:border-primary'>\n                    <FormControl>\n                      <RadioGroupItem value='dark' className='sr-only' />\n                    </FormControl>\n                    <div className='items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground'>\n                      <div className='space-y-2 rounded-sm bg-slate-950 p-2'>\n                        <div className='space-y-2 rounded-md bg-slate-800 p-2 shadow-xs'>\n                          <div className='h-2 w-[80px] rounded-lg bg-slate-400' />\n                          <div className='h-2 w-[100px] rounded-lg bg-slate-400' />\n                        </div>\n                        <div className='flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs'>\n                          <div className='h-4 w-4 rounded-full bg-slate-400' />\n                          <div className='h-2 w-[100px] rounded-lg bg-slate-400' />\n                        </div>\n                        <div className='flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-xs'>\n                          <div className='h-4 w-4 rounded-full bg-slate-400' />\n                          <div className='h-2 w-[100px] rounded-lg bg-slate-400' />\n                        </div>\n                      </div>\n                    </div>\n                    <span className='block w-full p-2 text-center font-normal'>\n                      Dark\n                    </span>\n                  </FormLabel>\n                </FormItem>\n              </RadioGroup>\n            </FormItem>\n          )}\n        />\n\n        <Button type='submit'>Update preferences</Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/appearance/index.tsx",
    "content": "import { ContentSection } from '../components/content-section'\nimport { AppearanceForm } from './appearance-form'\n\nexport function SettingsAppearance() {\n  return (\n    <ContentSection\n      title='Appearance'\n      desc='Customize the appearance of the app. Automatically switch between day\n          and night themes.'\n    >\n      <AppearanceForm />\n    </ContentSection>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/components/content-section.tsx",
    "content": "import { Separator } from '@/components/ui/separator'\n\ntype ContentSectionProps = {\n  title: string\n  desc: string\n  children: React.JSX.Element\n}\n\nexport function ContentSection({ title, desc, children }: ContentSectionProps) {\n  return (\n    <div className='flex flex-1 flex-col'>\n      <div className='flex-none'>\n        <h3 className='text-lg font-medium'>{title}</h3>\n        <p className='text-sm text-muted-foreground'>{desc}</p>\n      </div>\n      <Separator className='my-4 flex-none' />\n      <div className='faded-bottom h-full w-full overflow-y-auto scroll-smooth pe-4 pb-12'>\n        <div className='-mx-1 px-1.5 lg:max-w-xl'>{children}</div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/components/sidebar-nav.tsx",
    "content": "import { useState, type JSX } from 'react'\nimport { useLocation, useNavigate, Link } from '@tanstack/react-router'\nimport { cn } from '@/lib/utils'\nimport { buttonVariants } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\n\ntype SidebarNavProps = React.HTMLAttributes<HTMLElement> & {\n  items: {\n    href: string\n    title: string\n    icon: JSX.Element\n  }[]\n}\n\nexport function SidebarNav({ className, items, ...props }: SidebarNavProps) {\n  const { pathname } = useLocation()\n  const navigate = useNavigate()\n  const [val, setVal] = useState(pathname ?? '/settings')\n\n  const handleSelect = (e: string) => {\n    setVal(e)\n    navigate({ to: e })\n  }\n\n  return (\n    <>\n      <div className='p-1 md:hidden'>\n        <Select value={val} onValueChange={handleSelect}>\n          <SelectTrigger className='h-12 sm:w-48'>\n            <SelectValue placeholder='Theme' />\n          </SelectTrigger>\n          <SelectContent>\n            {items.map((item) => (\n              <SelectItem key={item.href} value={item.href}>\n                <div className='flex gap-x-4 px-2 py-1'>\n                  <span className='scale-125'>{item.icon}</span>\n                  <span className='text-md'>{item.title}</span>\n                </div>\n              </SelectItem>\n            ))}\n          </SelectContent>\n        </Select>\n      </div>\n\n      <ScrollArea\n        orientation='horizontal'\n        type='always'\n        className='hidden w-full min-w-40 bg-background px-1 py-2 md:block'\n      >\n        <nav\n          className={cn(\n            'flex space-x-2 py-1 lg:flex-col lg:space-y-1 lg:space-x-0',\n            className\n          )}\n          {...props}\n        >\n          {items.map((item) => (\n            <Link\n              key={item.href}\n              to={item.href}\n              className={cn(\n                buttonVariants({ variant: 'ghost' }),\n                pathname === item.href\n                  ? 'bg-muted hover:bg-accent'\n                  : 'hover:bg-accent hover:underline',\n                'justify-start'\n              )}\n            >\n              <span className='me-2'>{item.icon}</span>\n              {item.title}\n            </Link>\n          ))}\n        </nav>\n      </ScrollArea>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/display/display-form.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport { Checkbox } from '@/components/ui/checkbox'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\n\nconst items = [\n  {\n    id: 'recents',\n    label: 'Recents',\n  },\n  {\n    id: 'home',\n    label: 'Home',\n  },\n  {\n    id: 'applications',\n    label: 'Applications',\n  },\n  {\n    id: 'desktop',\n    label: 'Desktop',\n  },\n  {\n    id: 'downloads',\n    label: 'Downloads',\n  },\n  {\n    id: 'documents',\n    label: 'Documents',\n  },\n] as const\n\nconst displayFormSchema = z.object({\n  items: z.array(z.string()).refine((value) => value.some((item) => item), {\n    message: 'You have to select at least one item.',\n  }),\n})\n\ntype DisplayFormValues = z.infer<typeof displayFormSchema>\n\n// This can come from your database or API.\nconst defaultValues: Partial<DisplayFormValues> = {\n  items: ['recents', 'home'],\n}\n\nexport function DisplayForm() {\n  const form = useForm<DisplayFormValues>({\n    resolver: zodResolver(displayFormSchema),\n    defaultValues,\n  })\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit((data) => showSubmittedData(data))}\n        className='space-y-8'\n      >\n        <FormField\n          control={form.control}\n          name='items'\n          render={() => (\n            <FormItem>\n              <div className='mb-4'>\n                <FormLabel className='text-base'>Sidebar</FormLabel>\n                <FormDescription>\n                  Select the items you want to display in the sidebar.\n                </FormDescription>\n              </div>\n              {items.map((item) => (\n                <FormField\n                  key={item.id}\n                  control={form.control}\n                  name='items'\n                  render={({ field }) => {\n                    return (\n                      <FormItem\n                        key={item.id}\n                        className='flex flex-row items-start'\n                      >\n                        <FormControl>\n                          <Checkbox\n                            checked={field.value?.includes(item.id)}\n                            onCheckedChange={(checked) => {\n                              return checked\n                                ? field.onChange([...field.value, item.id])\n                                : field.onChange(\n                                    field.value?.filter(\n                                      (value) => value !== item.id\n                                    )\n                                  )\n                            }}\n                          />\n                        </FormControl>\n                        <FormLabel className='font-normal'>\n                          {item.label}\n                        </FormLabel>\n                      </FormItem>\n                    )\n                  }}\n                />\n              ))}\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <Button type='submit'>Update display</Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/display/index.tsx",
    "content": "import { ContentSection } from '../components/content-section'\nimport { DisplayForm } from './display-form'\n\nexport function SettingsDisplay() {\n  return (\n    <ContentSection\n      title='Display'\n      desc=\"Turn items on or off to control what's displayed in the app.\"\n    >\n      <DisplayForm />\n    </ContentSection>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/index.tsx",
    "content": "import { Outlet } from '@tanstack/react-router'\nimport { Monitor, Bell, Palette, Wrench, UserCog } from 'lucide-react'\nimport { Separator } from '@/components/ui/separator'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { SidebarNav } from './components/sidebar-nav'\n\nconst sidebarNavItems = [\n  {\n    title: 'Profile',\n    href: '/settings',\n    icon: <UserCog size={18} />,\n  },\n  {\n    title: 'Account',\n    href: '/settings/account',\n    icon: <Wrench size={18} />,\n  },\n  {\n    title: 'Appearance',\n    href: '/settings/appearance',\n    icon: <Palette size={18} />,\n  },\n  {\n    title: 'Notifications',\n    href: '/settings/notifications',\n    icon: <Bell size={18} />,\n  },\n  {\n    title: 'Display',\n    href: '/settings/display',\n    icon: <Monitor size={18} />,\n  },\n]\n\nexport function Settings() {\n  return (\n    <>\n      {/* ===== Top Heading ===== */}\n      <Header>\n        <Search />\n        <div className='ms-auto flex items-center space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      <Main fixed>\n        <div className='space-y-0.5'>\n          <h1 className='text-2xl font-bold tracking-tight md:text-3xl'>\n            Settings\n          </h1>\n          <p className='text-muted-foreground'>\n            Manage your account settings and set e-mail preferences.\n          </p>\n        </div>\n        <Separator className='my-4 lg:my-6' />\n        <div className='flex flex-1 flex-col space-y-2 overflow-hidden md:space-y-2 lg:flex-row lg:space-y-0 lg:space-x-12'>\n          <aside className='top-0 lg:sticky lg:w-1/5'>\n            <SidebarNav items={sidebarNavItems} />\n          </aside>\n          <div className='flex w-full overflow-y-hidden p-1'>\n            <Outlet />\n          </div>\n        </div>\n      </Main>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/notifications/index.tsx",
    "content": "import { ContentSection } from '../components/content-section'\nimport { NotificationsForm } from './notifications-form'\n\nexport function SettingsNotifications() {\n  return (\n    <ContentSection\n      title='Notifications'\n      desc='Configure how you receive notifications.'\n    >\n      <NotificationsForm />\n    </ContentSection>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/notifications/notifications-form.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { Link } from '@tanstack/react-router'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport { Checkbox } from '@/components/ui/checkbox'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'\nimport { Switch } from '@/components/ui/switch'\n\nconst notificationsFormSchema = z.object({\n  type: z.enum(['all', 'mentions', 'none'], {\n    error: (iss) =>\n      iss.input === undefined\n        ? 'Please select a notification type.'\n        : undefined,\n  }),\n  mobile: z.boolean().default(false).optional(),\n  communication_emails: z.boolean().default(false).optional(),\n  social_emails: z.boolean().default(false).optional(),\n  marketing_emails: z.boolean().default(false).optional(),\n  security_emails: z.boolean(),\n})\n\ntype NotificationsFormValues = z.infer<typeof notificationsFormSchema>\n\n// This can come from your database or API.\nconst defaultValues: Partial<NotificationsFormValues> = {\n  communication_emails: false,\n  marketing_emails: false,\n  social_emails: true,\n  security_emails: true,\n}\n\nexport function NotificationsForm() {\n  const form = useForm<NotificationsFormValues>({\n    resolver: zodResolver(notificationsFormSchema),\n    defaultValues,\n  })\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit((data) => showSubmittedData(data))}\n        className='space-y-8'\n      >\n        <FormField\n          control={form.control}\n          name='type'\n          render={({ field }) => (\n            <FormItem className='relative space-y-3'>\n              <FormLabel>Notify me about...</FormLabel>\n              <FormControl>\n                <RadioGroup\n                  onValueChange={field.onChange}\n                  defaultValue={field.value}\n                  className='flex flex-col gap-2'\n                >\n                  <FormItem className='flex items-center'>\n                    <FormControl>\n                      <RadioGroupItem value='all' />\n                    </FormControl>\n                    <FormLabel className='font-normal'>\n                      All new messages\n                    </FormLabel>\n                  </FormItem>\n                  <FormItem className='flex items-center'>\n                    <FormControl>\n                      <RadioGroupItem value='mentions' />\n                    </FormControl>\n                    <FormLabel className='font-normal'>\n                      Direct messages and mentions\n                    </FormLabel>\n                  </FormItem>\n                  <FormItem className='flex items-center'>\n                    <FormControl>\n                      <RadioGroupItem value='none' />\n                    </FormControl>\n                    <FormLabel className='font-normal'>Nothing</FormLabel>\n                  </FormItem>\n                </RadioGroup>\n              </FormControl>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <div className='relative'>\n          <h3 className='mb-4 text-lg font-medium'>Email Notifications</h3>\n          <div className='space-y-4'>\n            <FormField\n              control={form.control}\n              name='communication_emails'\n              render={({ field }) => (\n                <FormItem className='flex flex-row items-center justify-between rounded-lg border p-4'>\n                  <div className='space-y-0.5'>\n                    <FormLabel className='text-base'>\n                      Communication emails\n                    </FormLabel>\n                    <FormDescription>\n                      Receive emails about your account activity.\n                    </FormDescription>\n                  </div>\n                  <FormControl>\n                    <Switch\n                      checked={field.value}\n                      onCheckedChange={field.onChange}\n                    />\n                  </FormControl>\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='marketing_emails'\n              render={({ field }) => (\n                <FormItem className='flex flex-row items-center justify-between rounded-lg border p-4'>\n                  <div className='space-y-0.5'>\n                    <FormLabel className='text-base'>\n                      Marketing emails\n                    </FormLabel>\n                    <FormDescription>\n                      Receive emails about new products, features, and more.\n                    </FormDescription>\n                  </div>\n                  <FormControl>\n                    <Switch\n                      checked={field.value}\n                      onCheckedChange={field.onChange}\n                    />\n                  </FormControl>\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='social_emails'\n              render={({ field }) => (\n                <FormItem className='flex flex-row items-center justify-between rounded-lg border p-4'>\n                  <div className='space-y-0.5'>\n                    <FormLabel className='text-base'>Social emails</FormLabel>\n                    <FormDescription>\n                      Receive emails for friend requests, follows, and more.\n                    </FormDescription>\n                  </div>\n                  <FormControl>\n                    <Switch\n                      checked={field.value}\n                      onCheckedChange={field.onChange}\n                    />\n                  </FormControl>\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='security_emails'\n              render={({ field }) => (\n                <FormItem className='flex flex-row items-center justify-between rounded-lg border p-4'>\n                  <div className='space-y-0.5'>\n                    <FormLabel className='text-base'>Security emails</FormLabel>\n                    <FormDescription>\n                      Receive emails about your account activity and security.\n                    </FormDescription>\n                  </div>\n                  <FormControl>\n                    <Switch\n                      checked={field.value}\n                      onCheckedChange={field.onChange}\n                      disabled\n                      aria-readonly\n                    />\n                  </FormControl>\n                </FormItem>\n              )}\n            />\n          </div>\n        </div>\n        <FormField\n          control={form.control}\n          name='mobile'\n          render={({ field }) => (\n            <FormItem className='relative flex flex-row items-start'>\n              <FormControl>\n                <Checkbox\n                  checked={field.value}\n                  onCheckedChange={field.onChange}\n                />\n              </FormControl>\n              <div className='space-y-1 leading-none'>\n                <FormLabel>\n                  Use different settings for my mobile devices\n                </FormLabel>\n                <FormDescription>\n                  You can manage your mobile notifications in the{' '}\n                  <Link\n                    to='/settings'\n                    className='underline decoration-dashed underline-offset-4 hover:decoration-solid'\n                  >\n                    mobile settings\n                  </Link>{' '}\n                  page.\n                </FormDescription>\n              </div>\n            </FormItem>\n          )}\n        />\n        <Button type='submit'>Update notifications</Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/profile/index.tsx",
    "content": "import { ContentSection } from '../components/content-section'\nimport { ProfileForm } from './profile-form'\n\nexport function SettingsProfile() {\n  return (\n    <ContentSection\n      title='Profile'\n      desc='This is how others will see you on the site.'\n    >\n      <ProfileForm />\n    </ContentSection>\n  )\n}\n"
  },
  {
    "path": "src/features/settings/profile/profile-form.tsx",
    "content": "import { z } from 'zod'\nimport { useFieldArray, useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { Link } from '@tanstack/react-router'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\nimport { Textarea } from '@/components/ui/textarea'\n\nconst profileFormSchema = z.object({\n  username: z\n    .string('Please enter your username.')\n    .min(2, 'Username must be at least 2 characters.')\n    .max(30, 'Username must not be longer than 30 characters.'),\n  email: z.email({\n    error: (iss) =>\n      iss.input === undefined\n        ? 'Please select an email to display.'\n        : undefined,\n  }),\n  bio: z.string().max(160).min(4),\n  urls: z\n    .array(\n      z.object({\n        value: z.url('Please enter a valid URL.'),\n      })\n    )\n    .optional(),\n})\n\ntype ProfileFormValues = z.infer<typeof profileFormSchema>\n\n// This can come from your database or API.\nconst defaultValues: Partial<ProfileFormValues> = {\n  bio: 'I own a computer.',\n  urls: [\n    { value: 'https://shadcn.com' },\n    { value: 'http://twitter.com/shadcn' },\n  ],\n}\n\nexport function ProfileForm() {\n  const form = useForm<ProfileFormValues>({\n    resolver: zodResolver(profileFormSchema),\n    defaultValues,\n    mode: 'onChange',\n  })\n\n  const { fields, append } = useFieldArray({\n    name: 'urls',\n    control: form.control,\n  })\n\n  return (\n    <Form {...form}>\n      <form\n        onSubmit={form.handleSubmit((data) => showSubmittedData(data))}\n        className='space-y-8'\n      >\n        <FormField\n          control={form.control}\n          name='username'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Username</FormLabel>\n              <FormControl>\n                <Input placeholder='shadcn' {...field} />\n              </FormControl>\n              <FormDescription>\n                This is your public display name. It can be your real name or a\n                pseudonym. You can only change this once every 30 days.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='email'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Email</FormLabel>\n              <Select onValueChange={field.onChange} defaultValue={field.value}>\n                <FormControl>\n                  <SelectTrigger>\n                    <SelectValue placeholder='Select a verified email to display' />\n                  </SelectTrigger>\n                </FormControl>\n                <SelectContent>\n                  <SelectItem value='m@example.com'>m@example.com</SelectItem>\n                  <SelectItem value='m@google.com'>m@google.com</SelectItem>\n                  <SelectItem value='m@support.com'>m@support.com</SelectItem>\n                </SelectContent>\n              </Select>\n              <FormDescription>\n                You can manage verified email addresses in your{' '}\n                <Link to='/'>email settings</Link>.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <FormField\n          control={form.control}\n          name='bio'\n          render={({ field }) => (\n            <FormItem>\n              <FormLabel>Bio</FormLabel>\n              <FormControl>\n                <Textarea\n                  placeholder='Tell us a little bit about yourself'\n                  className='resize-none'\n                  {...field}\n                />\n              </FormControl>\n              <FormDescription>\n                You can <span>@mention</span> other users and organizations to\n                link to them.\n              </FormDescription>\n              <FormMessage />\n            </FormItem>\n          )}\n        />\n        <div>\n          {fields.map((field, index) => (\n            <FormField\n              control={form.control}\n              key={field.id}\n              name={`urls.${index}.value`}\n              render={({ field }) => (\n                <FormItem>\n                  <FormLabel className={cn(index !== 0 && 'sr-only')}>\n                    URLs\n                  </FormLabel>\n                  <FormDescription className={cn(index !== 0 && 'sr-only')}>\n                    Add links to your website, blog, or social media profiles.\n                  </FormDescription>\n                  <FormControl className={cn(index !== 0 && 'mt-1.5')}>\n                    <Input {...field} />\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n          ))}\n          <Button\n            type='button'\n            variant='outline'\n            size='sm'\n            className='mt-2'\n            onClick={() => append({ value: '' })}\n          >\n            Add URL\n          </Button>\n        </div>\n        <Button type='submit'>Update profile</Button>\n      </form>\n    </Form>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/data-table-bulk-actions.tsx",
    "content": "import { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { Trash2, CircleArrowUp, ArrowUpDown, Download } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { sleep } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\nimport { DataTableBulkActions as BulkActionsToolbar } from '@/components/data-table'\nimport { priorities, statuses } from '../data/data'\nimport { type Task } from '../data/schema'\nimport { TasksMultiDeleteDialog } from './tasks-multi-delete-dialog'\n\ntype DataTableBulkActionsProps<TData> = {\n  table: Table<TData>\n}\n\nexport function DataTableBulkActions<TData>({\n  table,\n}: DataTableBulkActionsProps<TData>) {\n  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)\n  const selectedRows = table.getFilteredSelectedRowModel().rows\n\n  const handleBulkStatusChange = (status: string) => {\n    const selectedTasks = selectedRows.map((row) => row.original as Task)\n    toast.promise(sleep(2000), {\n      loading: 'Updating status...',\n      success: () => {\n        table.resetRowSelection()\n        return `Status updated to \"${status}\" for ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''}.`\n      },\n      error: 'Error',\n    })\n    table.resetRowSelection()\n  }\n\n  const handleBulkPriorityChange = (priority: string) => {\n    const selectedTasks = selectedRows.map((row) => row.original as Task)\n    toast.promise(sleep(2000), {\n      loading: 'Updating priority...',\n      success: () => {\n        table.resetRowSelection()\n        return `Priority updated to \"${priority}\" for ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''}.`\n      },\n      error: 'Error',\n    })\n    table.resetRowSelection()\n  }\n\n  const handleBulkExport = () => {\n    const selectedTasks = selectedRows.map((row) => row.original as Task)\n    toast.promise(sleep(2000), {\n      loading: 'Exporting tasks...',\n      success: () => {\n        table.resetRowSelection()\n        return `Exported ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''} to CSV.`\n      },\n      error: 'Error',\n    })\n    table.resetRowSelection()\n  }\n\n  return (\n    <>\n      <BulkActionsToolbar table={table} entityName='task'>\n        <DropdownMenu>\n          <Tooltip>\n            <TooltipTrigger asChild>\n              <DropdownMenuTrigger asChild>\n                <Button\n                  variant='outline'\n                  size='icon'\n                  className='size-8'\n                  aria-label='Update status'\n                  title='Update status'\n                >\n                  <CircleArrowUp />\n                  <span className='sr-only'>Update status</span>\n                </Button>\n              </DropdownMenuTrigger>\n            </TooltipTrigger>\n            <TooltipContent>\n              <p>Update status</p>\n            </TooltipContent>\n          </Tooltip>\n          <DropdownMenuContent sideOffset={14}>\n            {statuses.map((status) => (\n              <DropdownMenuItem\n                key={status.value}\n                defaultValue={status.value}\n                onClick={() => handleBulkStatusChange(status.value)}\n              >\n                {status.icon && (\n                  <status.icon className='size-4 text-muted-foreground' />\n                )}\n                {status.label}\n              </DropdownMenuItem>\n            ))}\n          </DropdownMenuContent>\n        </DropdownMenu>\n\n        <DropdownMenu>\n          <Tooltip>\n            <TooltipTrigger asChild>\n              <DropdownMenuTrigger asChild>\n                <Button\n                  variant='outline'\n                  size='icon'\n                  className='size-8'\n                  aria-label='Update priority'\n                  title='Update priority'\n                >\n                  <ArrowUpDown />\n                  <span className='sr-only'>Update priority</span>\n                </Button>\n              </DropdownMenuTrigger>\n            </TooltipTrigger>\n            <TooltipContent>\n              <p>Update priority</p>\n            </TooltipContent>\n          </Tooltip>\n          <DropdownMenuContent sideOffset={14}>\n            {priorities.map((priority) => (\n              <DropdownMenuItem\n                key={priority.value}\n                defaultValue={priority.value}\n                onClick={() => handleBulkPriorityChange(priority.value)}\n              >\n                {priority.icon && (\n                  <priority.icon className='size-4 text-muted-foreground' />\n                )}\n                {priority.label}\n              </DropdownMenuItem>\n            ))}\n          </DropdownMenuContent>\n        </DropdownMenu>\n\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='outline'\n              size='icon'\n              onClick={() => handleBulkExport()}\n              className='size-8'\n              aria-label='Export tasks'\n              title='Export tasks'\n            >\n              <Download />\n              <span className='sr-only'>Export tasks</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Export tasks</p>\n          </TooltipContent>\n        </Tooltip>\n\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='destructive'\n              size='icon'\n              onClick={() => setShowDeleteConfirm(true)}\n              className='size-8'\n              aria-label='Delete selected tasks'\n              title='Delete selected tasks'\n            >\n              <Trash2 />\n              <span className='sr-only'>Delete selected tasks</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Delete selected tasks</p>\n          </TooltipContent>\n        </Tooltip>\n      </BulkActionsToolbar>\n\n      <TasksMultiDeleteDialog\n        open={showDeleteConfirm}\n        onOpenChange={setShowDeleteConfirm}\n        table={table}\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/data-table-row-actions.tsx",
    "content": "import { DotsHorizontalIcon } from '@radix-ui/react-icons'\nimport { type Row } from '@tanstack/react-table'\nimport { Trash2 } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubContent,\n  DropdownMenuSubTrigger,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { labels } from '../data/data'\nimport { taskSchema } from '../data/schema'\nimport { useTasks } from './tasks-provider'\n\ntype DataTableRowActionsProps<TData> = {\n  row: Row<TData>\n}\n\nexport function DataTableRowActions<TData>({\n  row,\n}: DataTableRowActionsProps<TData>) {\n  const task = taskSchema.parse(row.original)\n\n  const { setOpen, setCurrentRow } = useTasks()\n\n  return (\n    <DropdownMenu modal={false}>\n      <DropdownMenuTrigger asChild>\n        <Button\n          variant='ghost'\n          className='flex h-8 w-8 p-0 data-[state=open]:bg-muted'\n        >\n          <DotsHorizontalIcon className='h-4 w-4' />\n          <span className='sr-only'>Open menu</span>\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align='end' className='w-[160px]'>\n        <DropdownMenuItem\n          onClick={() => {\n            setCurrentRow(task)\n            setOpen('update')\n          }}\n        >\n          Edit\n        </DropdownMenuItem>\n        <DropdownMenuItem disabled>Make a copy</DropdownMenuItem>\n        <DropdownMenuItem disabled>Favorite</DropdownMenuItem>\n        <DropdownMenuSeparator />\n        <DropdownMenuSub>\n          <DropdownMenuSubTrigger>Labels</DropdownMenuSubTrigger>\n          <DropdownMenuSubContent>\n            <DropdownMenuRadioGroup value={task.label}>\n              {labels.map((label) => (\n                <DropdownMenuRadioItem key={label.value} value={label.value}>\n                  {label.label}\n                </DropdownMenuRadioItem>\n              ))}\n            </DropdownMenuRadioGroup>\n          </DropdownMenuSubContent>\n        </DropdownMenuSub>\n        <DropdownMenuSeparator />\n        <DropdownMenuItem\n          onClick={() => {\n            setCurrentRow(task)\n            setOpen('delete')\n          }}\n        >\n          Delete\n          <DropdownMenuShortcut>\n            <Trash2 size={16} />\n          </DropdownMenuShortcut>\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-columns.tsx",
    "content": "import { type ColumnDef } from '@tanstack/react-table'\nimport { Badge } from '@/components/ui/badge'\nimport { Checkbox } from '@/components/ui/checkbox'\nimport { DataTableColumnHeader } from '@/components/data-table'\nimport { labels, priorities, statuses } from '../data/data'\nimport { type Task } from '../data/schema'\nimport { DataTableRowActions } from './data-table-row-actions'\n\nexport const tasksColumns: ColumnDef<Task>[] = [\n  {\n    id: 'select',\n    header: ({ table }) => (\n      <Checkbox\n        checked={\n          table.getIsAllPageRowsSelected() ||\n          (table.getIsSomePageRowsSelected() && 'indeterminate')\n        }\n        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n        aria-label='Select all'\n        className='translate-y-[2px]'\n      />\n    ),\n    cell: ({ row }) => (\n      <Checkbox\n        checked={row.getIsSelected()}\n        onCheckedChange={(value) => row.toggleSelected(!!value)}\n        aria-label='Select row'\n        className='translate-y-[2px]'\n      />\n    ),\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    accessorKey: 'id',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Task' />\n    ),\n    cell: ({ row }) => <div className='w-[80px]'>{row.getValue('id')}</div>,\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    accessorKey: 'title',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Title' />\n    ),\n    meta: {\n      className: 'ps-1 max-w-0 w-2/3',\n      tdClassName: 'ps-4',\n    },\n    cell: ({ row }) => {\n      const label = labels.find((label) => label.value === row.original.label)\n\n      return (\n        <div className='flex space-x-2'>\n          {label && <Badge variant='outline'>{label.label}</Badge>}\n          <span className='truncate font-medium'>{row.getValue('title')}</span>\n        </div>\n      )\n    },\n  },\n  {\n    accessorKey: 'status',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Status' />\n    ),\n    meta: { className: 'ps-1', tdClassName: 'ps-4' },\n    cell: ({ row }) => {\n      const status = statuses.find(\n        (status) => status.value === row.getValue('status')\n      )\n\n      if (!status) {\n        return null\n      }\n\n      return (\n        <div className='flex w-[100px] items-center gap-2'>\n          {status.icon && (\n            <status.icon className='size-4 text-muted-foreground' />\n          )}\n          <span>{status.label}</span>\n        </div>\n      )\n    },\n    filterFn: (row, id, value) => {\n      return value.includes(row.getValue(id))\n    },\n  },\n  {\n    accessorKey: 'priority',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Priority' />\n    ),\n    meta: { className: 'ps-1', tdClassName: 'ps-3' },\n    cell: ({ row }) => {\n      const priority = priorities.find(\n        (priority) => priority.value === row.getValue('priority')\n      )\n\n      if (!priority) {\n        return null\n      }\n\n      return (\n        <div className='flex items-center gap-2'>\n          {priority.icon && (\n            <priority.icon className='size-4 text-muted-foreground' />\n          )}\n          <span>{priority.label}</span>\n        </div>\n      )\n    },\n    filterFn: (row, id, value) => {\n      return value.includes(row.getValue(id))\n    },\n  },\n  {\n    id: 'actions',\n    cell: ({ row }) => <DataTableRowActions row={row} />,\n  },\n]\n"
  },
  {
    "path": "src/features/tasks/components/tasks-dialogs.tsx",
    "content": "import { showSubmittedData } from '@/lib/show-submitted-data'\nimport { ConfirmDialog } from '@/components/confirm-dialog'\nimport { TasksImportDialog } from './tasks-import-dialog'\nimport { TasksMutateDrawer } from './tasks-mutate-drawer'\nimport { useTasks } from './tasks-provider'\n\nexport function TasksDialogs() {\n  const { open, setOpen, currentRow, setCurrentRow } = useTasks()\n  return (\n    <>\n      <TasksMutateDrawer\n        key='task-create'\n        open={open === 'create'}\n        onOpenChange={() => setOpen('create')}\n      />\n\n      <TasksImportDialog\n        key='tasks-import'\n        open={open === 'import'}\n        onOpenChange={() => setOpen('import')}\n      />\n\n      {currentRow && (\n        <>\n          <TasksMutateDrawer\n            key={`task-update-${currentRow.id}`}\n            open={open === 'update'}\n            onOpenChange={() => {\n              setOpen('update')\n              setTimeout(() => {\n                setCurrentRow(null)\n              }, 500)\n            }}\n            currentRow={currentRow}\n          />\n\n          <ConfirmDialog\n            key='task-delete'\n            destructive\n            open={open === 'delete'}\n            onOpenChange={() => {\n              setOpen('delete')\n              setTimeout(() => {\n                setCurrentRow(null)\n              }, 500)\n            }}\n            handleConfirm={() => {\n              setOpen(null)\n              setTimeout(() => {\n                setCurrentRow(null)\n              }, 500)\n              showSubmittedData(\n                currentRow,\n                'The following task has been deleted:'\n              )\n            }}\n            className='max-w-md'\n            title={`Delete this task: ${currentRow.id} ?`}\n            desc={\n              <>\n                You are about to delete a task with the ID{' '}\n                <strong>{currentRow.id}</strong>. <br />\n                This action cannot be undone.\n              </>\n            }\n            confirmText='Delete'\n          />\n        </>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-import-dialog.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\n\nconst formSchema = z.object({\n  file: z\n    .instanceof(FileList)\n    .refine((files) => files.length > 0, {\n      message: 'Please upload a file',\n    })\n    .refine(\n      (files) => ['text/csv'].includes(files?.[0]?.type),\n      'Please upload csv format.'\n    ),\n})\n\ntype TaskImportDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nexport function TasksImportDialog({\n  open,\n  onOpenChange,\n}: TaskImportDialogProps) {\n  const form = useForm<z.infer<typeof formSchema>>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { file: undefined },\n  })\n\n  const fileRef = form.register('file')\n\n  const onSubmit = () => {\n    const file = form.getValues('file')\n\n    if (file && file[0]) {\n      const fileDetails = {\n        name: file[0].name,\n        size: file[0].size,\n        type: file[0].type,\n      }\n      showSubmittedData(fileDetails, 'You have imported the following file:')\n    }\n    onOpenChange(false)\n  }\n\n  return (\n    <Dialog\n      open={open}\n      onOpenChange={(val) => {\n        onOpenChange(val)\n        form.reset()\n      }}\n    >\n      <DialogContent className='gap-2 sm:max-w-sm'>\n        <DialogHeader className='text-start'>\n          <DialogTitle>Import Tasks</DialogTitle>\n          <DialogDescription>\n            Import tasks quickly from a CSV file.\n          </DialogDescription>\n        </DialogHeader>\n        <Form {...form}>\n          <form id='task-import-form' onSubmit={form.handleSubmit(onSubmit)}>\n            <FormField\n              control={form.control}\n              name='file'\n              render={() => (\n                <FormItem className='my-2'>\n                  <FormLabel>File</FormLabel>\n                  <FormControl>\n                    <Input type='file' {...fileRef} className='h-8 py-0' />\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n          </form>\n        </Form>\n        <DialogFooter className='gap-2'>\n          <DialogClose asChild>\n            <Button variant='outline'>Close</Button>\n          </DialogClose>\n          <Button type='submit' form='task-import-form'>\n            Import\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-multi-delete-dialog.tsx",
    "content": "'use client'\n\nimport { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { AlertTriangle } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { sleep } from '@/lib/utils'\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { ConfirmDialog } from '@/components/confirm-dialog'\n\ntype TaskMultiDeleteDialogProps<TData> = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  table: Table<TData>\n}\n\nconst CONFIRM_WORD = 'DELETE'\n\nexport function TasksMultiDeleteDialog<TData>({\n  open,\n  onOpenChange,\n  table,\n}: TaskMultiDeleteDialogProps<TData>) {\n  const [value, setValue] = useState('')\n\n  const selectedRows = table.getFilteredSelectedRowModel().rows\n\n  const handleDelete = () => {\n    if (value.trim() !== CONFIRM_WORD) {\n      toast.error(`Please type \"${CONFIRM_WORD}\" to confirm.`)\n      return\n    }\n\n    onOpenChange(false)\n\n    toast.promise(sleep(2000), {\n      loading: 'Deleting tasks...',\n      success: () => {\n        setValue('')\n        table.resetRowSelection()\n        return `Deleted ${selectedRows.length} ${\n          selectedRows.length > 1 ? 'tasks' : 'task'\n        }`\n      },\n      error: 'Error',\n    })\n  }\n\n  return (\n    <ConfirmDialog\n      open={open}\n      onOpenChange={onOpenChange}\n      handleConfirm={handleDelete}\n      disabled={value.trim() !== CONFIRM_WORD}\n      title={\n        <span className='text-destructive'>\n          <AlertTriangle\n            className='me-1 inline-block stroke-destructive'\n            size={18}\n          />{' '}\n          Delete {selectedRows.length}{' '}\n          {selectedRows.length > 1 ? 'tasks' : 'task'}\n        </span>\n      }\n      desc={\n        <div className='space-y-4'>\n          <p className='mb-2'>\n            Are you sure you want to delete the selected tasks? <br />\n            This action cannot be undone.\n          </p>\n\n          <Label className='my-4 flex flex-col items-start gap-1.5'>\n            <span className=''>Confirm by typing \"{CONFIRM_WORD}\":</span>\n            <Input\n              value={value}\n              onChange={(e) => setValue(e.target.value)}\n              placeholder={`Type \"${CONFIRM_WORD}\" to confirm.`}\n            />\n          </Label>\n\n          <Alert variant='destructive'>\n            <AlertTitle>Warning!</AlertTitle>\n            <AlertDescription>\n              Please be careful, this operation can not be rolled back.\n            </AlertDescription>\n          </Alert>\n        </div>\n      }\n      confirmText='Delete'\n      destructive\n    />\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-mutate-drawer.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'\nimport {\n  Sheet,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n} from '@/components/ui/sheet'\nimport { SelectDropdown } from '@/components/select-dropdown'\nimport { type Task } from '../data/schema'\n\ntype TaskMutateDrawerProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  currentRow?: Task\n}\n\nconst formSchema = z.object({\n  title: z.string().min(1, 'Title is required.'),\n  status: z.string().min(1, 'Please select a status.'),\n  label: z.string().min(1, 'Please select a label.'),\n  priority: z.string().min(1, 'Please choose a priority.'),\n})\ntype TaskForm = z.infer<typeof formSchema>\n\nexport function TasksMutateDrawer({\n  open,\n  onOpenChange,\n  currentRow,\n}: TaskMutateDrawerProps) {\n  const isUpdate = !!currentRow\n\n  const form = useForm<TaskForm>({\n    resolver: zodResolver(formSchema),\n    defaultValues: currentRow ?? {\n      title: '',\n      status: '',\n      label: '',\n      priority: '',\n    },\n  })\n\n  const onSubmit = (data: TaskForm) => {\n    // do something with the form data\n    onOpenChange(false)\n    form.reset()\n    showSubmittedData(data)\n  }\n\n  return (\n    <Sheet\n      open={open}\n      onOpenChange={(v) => {\n        onOpenChange(v)\n        form.reset()\n      }}\n    >\n      <SheetContent className='flex flex-col'>\n        <SheetHeader className='text-start'>\n          <SheetTitle>{isUpdate ? 'Update' : 'Create'} Task</SheetTitle>\n          <SheetDescription>\n            {isUpdate\n              ? 'Update the task by providing necessary info.'\n              : 'Add a new task by providing necessary info.'}\n            Click save when you&apos;re done.\n          </SheetDescription>\n        </SheetHeader>\n        <Form {...form}>\n          <form\n            id='tasks-form'\n            onSubmit={form.handleSubmit(onSubmit)}\n            className='flex-1 space-y-6 overflow-y-auto px-4'\n          >\n            <FormField\n              control={form.control}\n              name='title'\n              render={({ field }) => (\n                <FormItem>\n                  <FormLabel>Title</FormLabel>\n                  <FormControl>\n                    <Input {...field} placeholder='Enter a title' />\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='status'\n              render={({ field }) => (\n                <FormItem>\n                  <FormLabel>Status</FormLabel>\n                  <SelectDropdown\n                    defaultValue={field.value}\n                    onValueChange={field.onChange}\n                    placeholder='Select dropdown'\n                    items={[\n                      { label: 'In Progress', value: 'in progress' },\n                      { label: 'Backlog', value: 'backlog' },\n                      { label: 'Todo', value: 'todo' },\n                      { label: 'Canceled', value: 'canceled' },\n                      { label: 'Done', value: 'done' },\n                    ]}\n                  />\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='label'\n              render={({ field }) => (\n                <FormItem className='relative'>\n                  <FormLabel>Label</FormLabel>\n                  <FormControl>\n                    <RadioGroup\n                      onValueChange={field.onChange}\n                      defaultValue={field.value}\n                      className='flex flex-col space-y-1'\n                    >\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='documentation' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>\n                          Documentation\n                        </FormLabel>\n                      </FormItem>\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='feature' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>Feature</FormLabel>\n                      </FormItem>\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='bug' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>Bug</FormLabel>\n                      </FormItem>\n                    </RadioGroup>\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='priority'\n              render={({ field }) => (\n                <FormItem className='relative'>\n                  <FormLabel>Priority</FormLabel>\n                  <FormControl>\n                    <RadioGroup\n                      onValueChange={field.onChange}\n                      defaultValue={field.value}\n                      className='flex flex-col space-y-1'\n                    >\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='high' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>High</FormLabel>\n                      </FormItem>\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='medium' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>Medium</FormLabel>\n                      </FormItem>\n                      <FormItem className='flex items-center'>\n                        <FormControl>\n                          <RadioGroupItem value='low' />\n                        </FormControl>\n                        <FormLabel className='font-normal'>Low</FormLabel>\n                      </FormItem>\n                    </RadioGroup>\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n          </form>\n        </Form>\n        <SheetFooter className='gap-2'>\n          <SheetClose asChild>\n            <Button variant='outline'>Close</Button>\n          </SheetClose>\n          <Button form='tasks-form' type='submit'>\n            Save changes\n          </Button>\n        </SheetFooter>\n      </SheetContent>\n    </Sheet>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-primary-buttons.tsx",
    "content": "import { Download, Plus } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { useTasks } from './tasks-provider'\n\nexport function TasksPrimaryButtons() {\n  const { setOpen } = useTasks()\n  return (\n    <div className='flex gap-2'>\n      <Button\n        variant='outline'\n        className='space-x-1'\n        onClick={() => setOpen('import')}\n      >\n        <span>Import</span> <Download size={18} />\n      </Button>\n      <Button className='space-x-1' onClick={() => setOpen('create')}>\n        <span>Create</span> <Plus size={18} />\n      </Button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-provider.tsx",
    "content": "import React, { useState } from 'react'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { type Task } from '../data/schema'\n\ntype TasksDialogType = 'create' | 'update' | 'delete' | 'import'\n\ntype TasksContextType = {\n  open: TasksDialogType | null\n  setOpen: (str: TasksDialogType | null) => void\n  currentRow: Task | null\n  setCurrentRow: React.Dispatch<React.SetStateAction<Task | null>>\n}\n\nconst TasksContext = React.createContext<TasksContextType | null>(null)\n\nexport function TasksProvider({ children }: { children: React.ReactNode }) {\n  const [open, setOpen] = useDialogState<TasksDialogType>(null)\n  const [currentRow, setCurrentRow] = useState<Task | null>(null)\n\n  return (\n    <TasksContext value={{ open, setOpen, currentRow, setCurrentRow }}>\n      {children}\n    </TasksContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const useTasks = () => {\n  const tasksContext = React.useContext(TasksContext)\n\n  if (!tasksContext) {\n    throw new Error('useTasks has to be used within <TasksContext>')\n  }\n\n  return tasksContext\n}\n"
  },
  {
    "path": "src/features/tasks/components/tasks-table.tsx",
    "content": "import { useEffect, useState } from 'react'\nimport { getRouteApi } from '@tanstack/react-router'\nimport {\n  type SortingState,\n  type VisibilityState,\n  flexRender,\n  getCoreRowModel,\n  getFacetedRowModel,\n  getFacetedUniqueValues,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  useReactTable,\n} from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { useTableUrlState } from '@/hooks/use-table-url-state'\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table'\nimport { DataTablePagination, DataTableToolbar } from '@/components/data-table'\nimport { priorities, statuses } from '../data/data'\nimport { type Task } from '../data/schema'\nimport { DataTableBulkActions } from './data-table-bulk-actions'\nimport { tasksColumns as columns } from './tasks-columns'\n\nconst route = getRouteApi('/_authenticated/tasks/')\n\ntype DataTableProps = {\n  data: Task[]\n}\n\nexport function TasksTable({ data }: DataTableProps) {\n  // Local UI-only states\n  const [rowSelection, setRowSelection] = useState({})\n  const [sorting, setSorting] = useState<SortingState>([])\n  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})\n\n  // Local state management for table (uncomment to use local-only state, not synced with URL)\n  // const [globalFilter, onGlobalFilterChange] = useState('')\n  // const [columnFilters, onColumnFiltersChange] = useState<ColumnFiltersState>([])\n  // const [pagination, onPaginationChange] = useState<PaginationState>({ pageIndex: 0, pageSize: 10 })\n\n  // Synced with URL states (updated to match route search schema defaults)\n  const {\n    globalFilter,\n    onGlobalFilterChange,\n    columnFilters,\n    onColumnFiltersChange,\n    pagination,\n    onPaginationChange,\n    ensurePageInRange,\n  } = useTableUrlState({\n    search: route.useSearch(),\n    navigate: route.useNavigate(),\n    pagination: { defaultPage: 1, defaultPageSize: 10 },\n    globalFilter: { enabled: true, key: 'filter' },\n    columnFilters: [\n      { columnId: 'status', searchKey: 'status', type: 'array' },\n      { columnId: 'priority', searchKey: 'priority', type: 'array' },\n    ],\n  })\n\n  // eslint-disable-next-line react-hooks/incompatible-library\n  const table = useReactTable({\n    data,\n    columns,\n    state: {\n      sorting,\n      columnVisibility,\n      rowSelection,\n      columnFilters,\n      globalFilter,\n      pagination,\n    },\n    enableRowSelection: true,\n    onRowSelectionChange: setRowSelection,\n    onSortingChange: setSorting,\n    onColumnVisibilityChange: setColumnVisibility,\n    globalFilterFn: (row, _columnId, filterValue) => {\n      const id = String(row.getValue('id')).toLowerCase()\n      const title = String(row.getValue('title')).toLowerCase()\n      const searchValue = String(filterValue).toLowerCase()\n\n      return id.includes(searchValue) || title.includes(searchValue)\n    },\n    getCoreRowModel: getCoreRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    getPaginationRowModel: getPaginationRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    getFacetedRowModel: getFacetedRowModel(),\n    getFacetedUniqueValues: getFacetedUniqueValues(),\n    onPaginationChange,\n    onGlobalFilterChange,\n    onColumnFiltersChange,\n  })\n\n  const pageCount = table.getPageCount()\n  useEffect(() => {\n    ensurePageInRange(pageCount)\n  }, [pageCount, ensurePageInRange])\n\n  return (\n    <div\n      className={cn(\n        'max-sm:has-[div[role=\"toolbar\"]]:mb-16', // Add margin bottom to the table on mobile when the toolbar is visible\n        'flex flex-1 flex-col gap-4'\n      )}\n    >\n      <DataTableToolbar\n        table={table}\n        searchPlaceholder='Filter by title or ID...'\n        filters={[\n          {\n            columnId: 'status',\n            title: 'Status',\n            options: statuses,\n          },\n          {\n            columnId: 'priority',\n            title: 'Priority',\n            options: priorities,\n          },\n        ]}\n      />\n      <div className='overflow-hidden rounded-md border'>\n        <Table className='min-w-xl'>\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id}>\n                {headerGroup.headers.map((header) => {\n                  return (\n                    <TableHead\n                      key={header.id}\n                      colSpan={header.colSpan}\n                      className={cn(\n                        header.column.columnDef.meta?.className,\n                        header.column.columnDef.meta?.thClassName\n                      )}\n                    >\n                      {header.isPlaceholder\n                        ? null\n                        : flexRender(\n                            header.column.columnDef.header,\n                            header.getContext()\n                          )}\n                    </TableHead>\n                  )\n                })}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows?.length ? (\n              table.getRowModel().rows.map((row) => (\n                <TableRow\n                  key={row.id}\n                  data-state={row.getIsSelected() && 'selected'}\n                >\n                  {row.getVisibleCells().map((cell) => (\n                    <TableCell\n                      key={cell.id}\n                      className={cn(\n                        cell.column.columnDef.meta?.className,\n                        cell.column.columnDef.meta?.tdClassName\n                      )}\n                    >\n                      {flexRender(\n                        cell.column.columnDef.cell,\n                        cell.getContext()\n                      )}\n                    </TableCell>\n                  ))}\n                </TableRow>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell\n                  colSpan={columns.length}\n                  className='h-24 text-center'\n                >\n                  No results.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n      <DataTablePagination table={table} className='mt-auto' />\n      <DataTableBulkActions table={table} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/tasks/data/data.tsx",
    "content": "import {\n  ArrowDown,\n  ArrowRight,\n  ArrowUp,\n  Circle,\n  CheckCircle,\n  AlertCircle,\n  Timer,\n  HelpCircle,\n  CircleOff,\n} from 'lucide-react'\n\nexport const labels = [\n  {\n    value: 'bug',\n    label: 'Bug',\n  },\n  {\n    value: 'feature',\n    label: 'Feature',\n  },\n  {\n    value: 'documentation',\n    label: 'Documentation',\n  },\n]\n\nexport const statuses = [\n  {\n    label: 'Backlog',\n    value: 'backlog' as const,\n    icon: HelpCircle,\n  },\n  {\n    label: 'Todo',\n    value: 'todo' as const,\n    icon: Circle,\n  },\n  {\n    label: 'In Progress',\n    value: 'in progress' as const,\n    icon: Timer,\n  },\n  {\n    label: 'Done',\n    value: 'done' as const,\n    icon: CheckCircle,\n  },\n  {\n    label: 'Canceled',\n    value: 'canceled' as const,\n    icon: CircleOff,\n  },\n]\n\nexport const priorities = [\n  {\n    label: 'Low',\n    value: 'low' as const,\n    icon: ArrowDown,\n  },\n  {\n    label: 'Medium',\n    value: 'medium' as const,\n    icon: ArrowRight,\n  },\n  {\n    label: 'High',\n    value: 'high' as const,\n    icon: ArrowUp,\n  },\n  {\n    label: 'Critical',\n    value: 'critical' as const,\n    icon: AlertCircle,\n  },\n]\n"
  },
  {
    "path": "src/features/tasks/data/schema.ts",
    "content": "import { z } from 'zod'\n\n// We're keeping a simple non-relational schema here.\n// IRL, you will have a schema for your data models.\nexport const taskSchema = z.object({\n  id: z.string(),\n  title: z.string(),\n  status: z.string(),\n  label: z.string(),\n  priority: z.string(),\n})\n\nexport type Task = z.infer<typeof taskSchema>\n"
  },
  {
    "path": "src/features/tasks/data/tasks.ts",
    "content": "import { faker } from '@faker-js/faker'\n\n// Set a fixed seed for consistent data generation\nfaker.seed(12345)\n\nexport const tasks = Array.from({ length: 100 }, () => {\n  const statuses = [\n    'todo',\n    'in progress',\n    'done',\n    'canceled',\n    'backlog',\n  ] as const\n  const labels = ['bug', 'feature', 'documentation'] as const\n  const priorities = ['low', 'medium', 'high'] as const\n\n  return {\n    id: `TASK-${faker.number.int({ min: 1000, max: 9999 })}`,\n    title: faker.lorem.sentence({ min: 5, max: 15 }),\n    status: faker.helpers.arrayElement(statuses),\n    label: faker.helpers.arrayElement(labels),\n    priority: faker.helpers.arrayElement(priorities),\n    createdAt: faker.date.past(),\n    updatedAt: faker.date.recent(),\n    assignee: faker.person.fullName(),\n    description: faker.lorem.paragraph({ min: 1, max: 3 }),\n    dueDate: faker.date.future(),\n  }\n})\n"
  },
  {
    "path": "src/features/tasks/index.tsx",
    "content": "import { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { TasksDialogs } from './components/tasks-dialogs'\nimport { TasksPrimaryButtons } from './components/tasks-primary-buttons'\nimport { TasksProvider } from './components/tasks-provider'\nimport { TasksTable } from './components/tasks-table'\nimport { tasks } from './data/tasks'\n\nexport function Tasks() {\n  return (\n    <TasksProvider>\n      <Header fixed>\n        <Search />\n        <div className='ms-auto flex items-center space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      <Main className='flex flex-1 flex-col gap-4 sm:gap-6'>\n        <div className='flex flex-wrap items-end justify-between gap-2'>\n          <div>\n            <h2 className='text-2xl font-bold tracking-tight'>Tasks</h2>\n            <p className='text-muted-foreground'>\n              Here&apos;s a list of your tasks for this month!\n            </p>\n          </div>\n          <TasksPrimaryButtons />\n        </div>\n        <TasksTable data={tasks} />\n      </Main>\n\n      <TasksDialogs />\n    </TasksProvider>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/data-table-bulk-actions.tsx",
    "content": "import { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { Trash2, UserX, UserCheck, Mail } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { sleep } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\nimport { DataTableBulkActions as BulkActionsToolbar } from '@/components/data-table'\nimport { type User } from '../data/schema'\nimport { UsersMultiDeleteDialog } from './users-multi-delete-dialog'\n\ntype DataTableBulkActionsProps<TData> = {\n  table: Table<TData>\n}\n\nexport function DataTableBulkActions<TData>({\n  table,\n}: DataTableBulkActionsProps<TData>) {\n  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)\n  const selectedRows = table.getFilteredSelectedRowModel().rows\n\n  const handleBulkStatusChange = (status: 'active' | 'inactive') => {\n    const selectedUsers = selectedRows.map((row) => row.original as User)\n    toast.promise(sleep(2000), {\n      loading: `${status === 'active' ? 'Activating' : 'Deactivating'} users...`,\n      success: () => {\n        table.resetRowSelection()\n        return `${status === 'active' ? 'Activated' : 'Deactivated'} ${selectedUsers.length} user${selectedUsers.length > 1 ? 's' : ''}`\n      },\n      error: `Error ${status === 'active' ? 'activating' : 'deactivating'} users`,\n    })\n    table.resetRowSelection()\n  }\n\n  const handleBulkInvite = () => {\n    const selectedUsers = selectedRows.map((row) => row.original as User)\n    toast.promise(sleep(2000), {\n      loading: 'Inviting users...',\n      success: () => {\n        table.resetRowSelection()\n        return `Invited ${selectedUsers.length} user${selectedUsers.length > 1 ? 's' : ''}`\n      },\n      error: 'Error inviting users',\n    })\n    table.resetRowSelection()\n  }\n\n  return (\n    <>\n      <BulkActionsToolbar table={table} entityName='user'>\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='outline'\n              size='icon'\n              onClick={handleBulkInvite}\n              className='size-8'\n              aria-label='Invite selected users'\n              title='Invite selected users'\n            >\n              <Mail />\n              <span className='sr-only'>Invite selected users</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Invite selected users</p>\n          </TooltipContent>\n        </Tooltip>\n\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='outline'\n              size='icon'\n              onClick={() => handleBulkStatusChange('active')}\n              className='size-8'\n              aria-label='Activate selected users'\n              title='Activate selected users'\n            >\n              <UserCheck />\n              <span className='sr-only'>Activate selected users</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Activate selected users</p>\n          </TooltipContent>\n        </Tooltip>\n\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='outline'\n              size='icon'\n              onClick={() => handleBulkStatusChange('inactive')}\n              className='size-8'\n              aria-label='Deactivate selected users'\n              title='Deactivate selected users'\n            >\n              <UserX />\n              <span className='sr-only'>Deactivate selected users</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Deactivate selected users</p>\n          </TooltipContent>\n        </Tooltip>\n\n        <Tooltip>\n          <TooltipTrigger asChild>\n            <Button\n              variant='destructive'\n              size='icon'\n              onClick={() => setShowDeleteConfirm(true)}\n              className='size-8'\n              aria-label='Delete selected users'\n              title='Delete selected users'\n            >\n              <Trash2 />\n              <span className='sr-only'>Delete selected users</span>\n            </Button>\n          </TooltipTrigger>\n          <TooltipContent>\n            <p>Delete selected users</p>\n          </TooltipContent>\n        </Tooltip>\n      </BulkActionsToolbar>\n\n      <UsersMultiDeleteDialog\n        table={table}\n        open={showDeleteConfirm}\n        onOpenChange={setShowDeleteConfirm}\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/data-table-row-actions.tsx",
    "content": "import { DotsHorizontalIcon } from '@radix-ui/react-icons'\nimport { type Row } from '@tanstack/react-table'\nimport { Trash2, UserPen } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { type User } from '../data/schema'\nimport { useUsers } from './users-provider'\n\ntype DataTableRowActionsProps = {\n  row: Row<User>\n}\n\nexport function DataTableRowActions({ row }: DataTableRowActionsProps) {\n  const { setOpen, setCurrentRow } = useUsers()\n  return (\n    <>\n      <DropdownMenu modal={false}>\n        <DropdownMenuTrigger asChild>\n          <Button\n            variant='ghost'\n            className='flex h-8 w-8 p-0 data-[state=open]:bg-muted'\n          >\n            <DotsHorizontalIcon className='h-4 w-4' />\n            <span className='sr-only'>Open menu</span>\n          </Button>\n        </DropdownMenuTrigger>\n        <DropdownMenuContent align='end' className='w-[160px]'>\n          <DropdownMenuItem\n            onClick={() => {\n              setCurrentRow(row.original)\n              setOpen('edit')\n            }}\n          >\n            Edit\n            <DropdownMenuShortcut>\n              <UserPen size={16} />\n            </DropdownMenuShortcut>\n          </DropdownMenuItem>\n          <DropdownMenuSeparator />\n          <DropdownMenuItem\n            onClick={() => {\n              setCurrentRow(row.original)\n              setOpen('delete')\n            }}\n            className='text-red-500!'\n          >\n            Delete\n            <DropdownMenuShortcut>\n              <Trash2 size={16} />\n            </DropdownMenuShortcut>\n          </DropdownMenuItem>\n        </DropdownMenuContent>\n      </DropdownMenu>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-action-dialog.tsx",
    "content": "'use client'\n\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport { PasswordInput } from '@/components/password-input'\nimport { SelectDropdown } from '@/components/select-dropdown'\nimport { roles } from '../data/data'\nimport { type User } from '../data/schema'\n\nconst formSchema = z\n  .object({\n    firstName: z.string().min(1, 'First Name is required.'),\n    lastName: z.string().min(1, 'Last Name is required.'),\n    username: z.string().min(1, 'Username is required.'),\n    phoneNumber: z.string().min(1, 'Phone number is required.'),\n    email: z.email({\n      error: (iss) => (iss.input === '' ? 'Email is required.' : undefined),\n    }),\n    password: z.string().transform((pwd) => pwd.trim()),\n    role: z.string().min(1, 'Role is required.'),\n    confirmPassword: z.string().transform((pwd) => pwd.trim()),\n    isEdit: z.boolean(),\n  })\n  .refine(\n    (data) => {\n      if (data.isEdit && !data.password) return true\n      return data.password.length > 0\n    },\n    {\n      message: 'Password is required.',\n      path: ['password'],\n    }\n  )\n  .refine(\n    ({ isEdit, password }) => {\n      if (isEdit && !password) return true\n      return password.length >= 8\n    },\n    {\n      message: 'Password must be at least 8 characters long.',\n      path: ['password'],\n    }\n  )\n  .refine(\n    ({ isEdit, password }) => {\n      if (isEdit && !password) return true\n      return /[a-z]/.test(password)\n    },\n    {\n      message: 'Password must contain at least one lowercase letter.',\n      path: ['password'],\n    }\n  )\n  .refine(\n    ({ isEdit, password }) => {\n      if (isEdit && !password) return true\n      return /\\d/.test(password)\n    },\n    {\n      message: 'Password must contain at least one number.',\n      path: ['password'],\n    }\n  )\n  .refine(\n    ({ isEdit, password, confirmPassword }) => {\n      if (isEdit && !password) return true\n      return password === confirmPassword\n    },\n    {\n      message: \"Passwords don't match.\",\n      path: ['confirmPassword'],\n    }\n  )\ntype UserForm = z.infer<typeof formSchema>\n\ntype UserActionDialogProps = {\n  currentRow?: User\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nexport function UsersActionDialog({\n  currentRow,\n  open,\n  onOpenChange,\n}: UserActionDialogProps) {\n  const isEdit = !!currentRow\n  const form = useForm<UserForm>({\n    resolver: zodResolver(formSchema),\n    defaultValues: isEdit\n      ? {\n          ...currentRow,\n          password: '',\n          confirmPassword: '',\n          isEdit,\n        }\n      : {\n          firstName: '',\n          lastName: '',\n          username: '',\n          email: '',\n          role: '',\n          phoneNumber: '',\n          password: '',\n          confirmPassword: '',\n          isEdit,\n        },\n  })\n\n  const onSubmit = (values: UserForm) => {\n    form.reset()\n    showSubmittedData(values)\n    onOpenChange(false)\n  }\n\n  const isPasswordTouched = !!form.formState.dirtyFields.password\n\n  return (\n    <Dialog\n      open={open}\n      onOpenChange={(state) => {\n        form.reset()\n        onOpenChange(state)\n      }}\n    >\n      <DialogContent className='sm:max-w-lg'>\n        <DialogHeader className='text-start'>\n          <DialogTitle>{isEdit ? 'Edit User' : 'Add New User'}</DialogTitle>\n          <DialogDescription>\n            {isEdit ? 'Update the user here. ' : 'Create new user here. '}\n            Click save when you&apos;re done.\n          </DialogDescription>\n        </DialogHeader>\n        <div className='h-105 w-[calc(100%+0.75rem)] overflow-y-auto py-1 pe-3'>\n          <Form {...form}>\n            <form\n              id='user-form'\n              onSubmit={form.handleSubmit(onSubmit)}\n              className='space-y-4 px-0.5'\n            >\n              <FormField\n                control={form.control}\n                name='firstName'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      First Name\n                    </FormLabel>\n                    <FormControl>\n                      <Input\n                        placeholder='John'\n                        className='col-span-4'\n                        autoComplete='off'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='lastName'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      Last Name\n                    </FormLabel>\n                    <FormControl>\n                      <Input\n                        placeholder='Doe'\n                        className='col-span-4'\n                        autoComplete='off'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='username'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      Username\n                    </FormLabel>\n                    <FormControl>\n                      <Input\n                        placeholder='john_doe'\n                        className='col-span-4'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='email'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>Email</FormLabel>\n                    <FormControl>\n                      <Input\n                        placeholder='john.doe@gmail.com'\n                        className='col-span-4'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='phoneNumber'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      Phone Number\n                    </FormLabel>\n                    <FormControl>\n                      <Input\n                        placeholder='+123456789'\n                        className='col-span-4'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='role'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>Role</FormLabel>\n                    <SelectDropdown\n                      defaultValue={field.value}\n                      onValueChange={field.onChange}\n                      placeholder='Select a role'\n                      className='col-span-4'\n                      items={roles.map(({ label, value }) => ({\n                        label,\n                        value,\n                      }))}\n                    />\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='password'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      Password\n                    </FormLabel>\n                    <FormControl>\n                      <PasswordInput\n                        placeholder='e.g., S3cur3P@ssw0rd'\n                        className='col-span-4'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n              <FormField\n                control={form.control}\n                name='confirmPassword'\n                render={({ field }) => (\n                  <FormItem className='grid grid-cols-6 items-center space-y-0 gap-x-4 gap-y-1'>\n                    <FormLabel className='col-span-2 text-end'>\n                      Confirm Password\n                    </FormLabel>\n                    <FormControl>\n                      <PasswordInput\n                        disabled={!isPasswordTouched}\n                        placeholder='e.g., S3cur3P@ssw0rd'\n                        className='col-span-4'\n                        {...field}\n                      />\n                    </FormControl>\n                    <FormMessage className='col-span-4 col-start-3' />\n                  </FormItem>\n                )}\n              />\n            </form>\n          </Form>\n        </div>\n        <DialogFooter>\n          <Button type='submit' form='user-form'>\n            Save changes\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-columns.tsx",
    "content": "import { type ColumnDef } from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Checkbox } from '@/components/ui/checkbox'\nimport { DataTableColumnHeader } from '@/components/data-table'\nimport { LongText } from '@/components/long-text'\nimport { callTypes, roles } from '../data/data'\nimport { type User } from '../data/schema'\nimport { DataTableRowActions } from './data-table-row-actions'\n\nexport const usersColumns: ColumnDef<User>[] = [\n  {\n    id: 'select',\n    header: ({ table }) => (\n      <Checkbox\n        checked={\n          table.getIsAllPageRowsSelected() ||\n          (table.getIsSomePageRowsSelected() && 'indeterminate')\n        }\n        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n        aria-label='Select all'\n        className='translate-y-[2px]'\n      />\n    ),\n    meta: {\n      className: cn('max-md:sticky start-0 z-10 rounded-tl-[inherit]'),\n    },\n    cell: ({ row }) => (\n      <Checkbox\n        checked={row.getIsSelected()}\n        onCheckedChange={(value) => row.toggleSelected(!!value)}\n        aria-label='Select row'\n        className='translate-y-[2px]'\n      />\n    ),\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    accessorKey: 'username',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Username' />\n    ),\n    cell: ({ row }) => (\n      <LongText className='max-w-36 ps-3'>{row.getValue('username')}</LongText>\n    ),\n    meta: {\n      className: cn(\n        'drop-shadow-[0_1px_2px_rgb(0_0_0_/_0.1)] dark:drop-shadow-[0_1px_2px_rgb(255_255_255_/_0.1)]',\n        'ps-0.5 max-md:sticky start-6 @4xl/content:table-cell @4xl/content:drop-shadow-none'\n      ),\n    },\n    enableHiding: false,\n  },\n  {\n    id: 'fullName',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Name' />\n    ),\n    cell: ({ row }) => {\n      const { firstName, lastName } = row.original\n      const fullName = `${firstName} ${lastName}`\n      return <LongText className='max-w-36'>{fullName}</LongText>\n    },\n    meta: { className: 'w-36' },\n  },\n  {\n    accessorKey: 'email',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Email' />\n    ),\n    cell: ({ row }) => (\n      <div className='w-fit ps-2 text-nowrap'>{row.getValue('email')}</div>\n    ),\n  },\n  {\n    accessorKey: 'phoneNumber',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Phone Number' />\n    ),\n    cell: ({ row }) => <div>{row.getValue('phoneNumber')}</div>,\n    enableSorting: false,\n  },\n  {\n    accessorKey: 'status',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Status' />\n    ),\n    cell: ({ row }) => {\n      const { status } = row.original\n      const badgeColor = callTypes.get(status)\n      return (\n        <div className='flex space-x-2'>\n          <Badge variant='outline' className={cn('capitalize', badgeColor)}>\n            {row.getValue('status')}\n          </Badge>\n        </div>\n      )\n    },\n    filterFn: (row, id, value) => {\n      return value.includes(row.getValue(id))\n    },\n    enableHiding: false,\n    enableSorting: false,\n  },\n  {\n    accessorKey: 'role',\n    header: ({ column }) => (\n      <DataTableColumnHeader column={column} title='Role' />\n    ),\n    cell: ({ row }) => {\n      const { role } = row.original\n      const userType = roles.find(({ value }) => value === role)\n\n      if (!userType) {\n        return null\n      }\n\n      return (\n        <div className='flex items-center gap-x-2'>\n          {userType.icon && (\n            <userType.icon size={16} className='text-muted-foreground' />\n          )}\n          <span className='text-sm capitalize'>{row.getValue('role')}</span>\n        </div>\n      )\n    },\n    filterFn: (row, id, value) => {\n      return value.includes(row.getValue(id))\n    },\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    id: 'actions',\n    cell: DataTableRowActions,\n  },\n]\n"
  },
  {
    "path": "src/features/users/components/users-delete-dialog.tsx",
    "content": "'use client'\n\nimport { useState } from 'react'\nimport { AlertTriangle } from 'lucide-react'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { ConfirmDialog } from '@/components/confirm-dialog'\nimport { type User } from '../data/schema'\n\ntype UserDeleteDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  currentRow: User\n}\n\nexport function UsersDeleteDialog({\n  open,\n  onOpenChange,\n  currentRow,\n}: UserDeleteDialogProps) {\n  const [value, setValue] = useState('')\n\n  const handleDelete = () => {\n    if (value.trim() !== currentRow.username) return\n\n    onOpenChange(false)\n    showSubmittedData(currentRow, 'The following user has been deleted:')\n  }\n\n  return (\n    <ConfirmDialog\n      open={open}\n      onOpenChange={onOpenChange}\n      handleConfirm={handleDelete}\n      disabled={value.trim() !== currentRow.username}\n      title={\n        <span className='text-destructive'>\n          <AlertTriangle\n            className='me-1 inline-block stroke-destructive'\n            size={18}\n          />{' '}\n          Delete User\n        </span>\n      }\n      desc={\n        <div className='space-y-4'>\n          <p className='mb-2'>\n            Are you sure you want to delete{' '}\n            <span className='font-bold'>{currentRow.username}</span>?\n            <br />\n            This action will permanently remove the user with the role of{' '}\n            <span className='font-bold'>\n              {currentRow.role.toUpperCase()}\n            </span>{' '}\n            from the system. This cannot be undone.\n          </p>\n\n          <Label className='my-2'>\n            Username:\n            <Input\n              value={value}\n              onChange={(e) => setValue(e.target.value)}\n              placeholder='Enter username to confirm deletion.'\n            />\n          </Label>\n\n          <Alert variant='destructive'>\n            <AlertTitle>Warning!</AlertTitle>\n            <AlertDescription>\n              Please be careful, this operation can not be rolled back.\n            </AlertDescription>\n          </Alert>\n        </div>\n      }\n      confirmText='Delete'\n      destructive\n    />\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-dialogs.tsx",
    "content": "import { UsersActionDialog } from './users-action-dialog'\nimport { UsersDeleteDialog } from './users-delete-dialog'\nimport { UsersInviteDialog } from './users-invite-dialog'\nimport { useUsers } from './users-provider'\n\nexport function UsersDialogs() {\n  const { open, setOpen, currentRow, setCurrentRow } = useUsers()\n  return (\n    <>\n      <UsersActionDialog\n        key='user-add'\n        open={open === 'add'}\n        onOpenChange={() => setOpen('add')}\n      />\n\n      <UsersInviteDialog\n        key='user-invite'\n        open={open === 'invite'}\n        onOpenChange={() => setOpen('invite')}\n      />\n\n      {currentRow && (\n        <>\n          <UsersActionDialog\n            key={`user-edit-${currentRow.id}`}\n            open={open === 'edit'}\n            onOpenChange={() => {\n              setOpen('edit')\n              setTimeout(() => {\n                setCurrentRow(null)\n              }, 500)\n            }}\n            currentRow={currentRow}\n          />\n\n          <UsersDeleteDialog\n            key={`user-delete-${currentRow.id}`}\n            open={open === 'delete'}\n            onOpenChange={() => {\n              setOpen('delete')\n              setTimeout(() => {\n                setCurrentRow(null)\n              }, 500)\n            }}\n            currentRow={currentRow}\n          />\n        </>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-invite-dialog.tsx",
    "content": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { MailPlus, Send } from 'lucide-react'\nimport { showSubmittedData } from '@/lib/show-submitted-data'\nimport { Button } from '@/components/ui/button'\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { SelectDropdown } from '@/components/select-dropdown'\nimport { roles } from '../data/data'\n\nconst formSchema = z.object({\n  email: z.email({\n    error: (iss) =>\n      iss.input === '' ? 'Please enter an email to invite.' : undefined,\n  }),\n  role: z.string().min(1, 'Role is required.'),\n  desc: z.string().optional(),\n})\n\ntype UserInviteForm = z.infer<typeof formSchema>\n\ntype UserInviteDialogProps = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n}\n\nexport function UsersInviteDialog({\n  open,\n  onOpenChange,\n}: UserInviteDialogProps) {\n  const form = useForm<UserInviteForm>({\n    resolver: zodResolver(formSchema),\n    defaultValues: { email: '', role: '', desc: '' },\n  })\n\n  const onSubmit = (values: UserInviteForm) => {\n    form.reset()\n    showSubmittedData(values)\n    onOpenChange(false)\n  }\n\n  return (\n    <Dialog\n      open={open}\n      onOpenChange={(state) => {\n        form.reset()\n        onOpenChange(state)\n      }}\n    >\n      <DialogContent className='sm:max-w-md'>\n        <DialogHeader className='text-start'>\n          <DialogTitle className='flex items-center gap-2'>\n            <MailPlus /> Invite User\n          </DialogTitle>\n          <DialogDescription>\n            Invite new user to join your team by sending them an email\n            invitation. Assign a role to define their access level.\n          </DialogDescription>\n        </DialogHeader>\n        <Form {...form}>\n          <form\n            id='user-invite-form'\n            onSubmit={form.handleSubmit(onSubmit)}\n            className='space-y-4'\n          >\n            <FormField\n              control={form.control}\n              name='email'\n              render={({ field }) => (\n                <FormItem>\n                  <FormLabel>Email</FormLabel>\n                  <FormControl>\n                    <Input\n                      type='email'\n                      placeholder='eg: john.doe@gmail.com'\n                      {...field}\n                    />\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='role'\n              render={({ field }) => (\n                <FormItem>\n                  <FormLabel>Role</FormLabel>\n                  <SelectDropdown\n                    defaultValue={field.value}\n                    onValueChange={field.onChange}\n                    placeholder='Select a role'\n                    items={roles.map(({ label, value }) => ({\n                      label,\n                      value,\n                    }))}\n                  />\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n            <FormField\n              control={form.control}\n              name='desc'\n              render={({ field }) => (\n                <FormItem className=''>\n                  <FormLabel>Description (optional)</FormLabel>\n                  <FormControl>\n                    <Textarea\n                      className='resize-none'\n                      placeholder='Add a personal note to your invitation (optional)'\n                      {...field}\n                    />\n                  </FormControl>\n                  <FormMessage />\n                </FormItem>\n              )}\n            />\n          </form>\n        </Form>\n        <DialogFooter className='gap-y-2'>\n          <DialogClose asChild>\n            <Button variant='outline'>Cancel</Button>\n          </DialogClose>\n          <Button type='submit' form='user-invite-form'>\n            Invite <Send />\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-multi-delete-dialog.tsx",
    "content": "'use client'\n\nimport { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { AlertTriangle } from 'lucide-react'\nimport { toast } from 'sonner'\nimport { sleep } from '@/lib/utils'\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { ConfirmDialog } from '@/components/confirm-dialog'\n\ntype UserMultiDeleteDialogProps<TData> = {\n  open: boolean\n  onOpenChange: (open: boolean) => void\n  table: Table<TData>\n}\n\nconst CONFIRM_WORD = 'DELETE'\n\nexport function UsersMultiDeleteDialog<TData>({\n  open,\n  onOpenChange,\n  table,\n}: UserMultiDeleteDialogProps<TData>) {\n  const [value, setValue] = useState('')\n\n  const selectedRows = table.getFilteredSelectedRowModel().rows\n\n  const handleDelete = () => {\n    if (value.trim() !== CONFIRM_WORD) {\n      toast.error(`Please type \"${CONFIRM_WORD}\" to confirm.`)\n      return\n    }\n\n    onOpenChange(false)\n\n    toast.promise(sleep(2000), {\n      loading: 'Deleting users...',\n      success: () => {\n        setValue('')\n        table.resetRowSelection()\n        return `Deleted ${selectedRows.length} ${\n          selectedRows.length > 1 ? 'users' : 'user'\n        }`\n      },\n      error: 'Error',\n    })\n  }\n\n  return (\n    <ConfirmDialog\n      open={open}\n      onOpenChange={onOpenChange}\n      handleConfirm={handleDelete}\n      disabled={value.trim() !== CONFIRM_WORD}\n      title={\n        <span className='text-destructive'>\n          <AlertTriangle\n            className='me-1 inline-block stroke-destructive'\n            size={18}\n          />{' '}\n          Delete {selectedRows.length}{' '}\n          {selectedRows.length > 1 ? 'users' : 'user'}\n        </span>\n      }\n      desc={\n        <div className='space-y-4'>\n          <p className='mb-2'>\n            Are you sure you want to delete the selected users? <br />\n            This action cannot be undone.\n          </p>\n\n          <Label className='my-4 flex flex-col items-start gap-1.5'>\n            <span className=''>Confirm by typing \"{CONFIRM_WORD}\":</span>\n            <Input\n              value={value}\n              onChange={(e) => setValue(e.target.value)}\n              placeholder={`Type \"${CONFIRM_WORD}\" to confirm.`}\n            />\n          </Label>\n\n          <Alert variant='destructive'>\n            <AlertTitle>Warning!</AlertTitle>\n            <AlertDescription>\n              Please be careful, this operation can not be rolled back.\n            </AlertDescription>\n          </Alert>\n        </div>\n      }\n      confirmText='Delete'\n      destructive\n    />\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-primary-buttons.tsx",
    "content": "import { MailPlus, UserPlus } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { useUsers } from './users-provider'\n\nexport function UsersPrimaryButtons() {\n  const { setOpen } = useUsers()\n  return (\n    <div className='flex gap-2'>\n      <Button\n        variant='outline'\n        className='space-x-1'\n        onClick={() => setOpen('invite')}\n      >\n        <span>Invite User</span> <MailPlus size={18} />\n      </Button>\n      <Button className='space-x-1' onClick={() => setOpen('add')}>\n        <span>Add User</span> <UserPlus size={18} />\n      </Button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/users/components/users-provider.tsx",
    "content": "import React, { useState } from 'react'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { type User } from '../data/schema'\n\ntype UsersDialogType = 'invite' | 'add' | 'edit' | 'delete'\n\ntype UsersContextType = {\n  open: UsersDialogType | null\n  setOpen: (str: UsersDialogType | null) => void\n  currentRow: User | null\n  setCurrentRow: React.Dispatch<React.SetStateAction<User | null>>\n}\n\nconst UsersContext = React.createContext<UsersContextType | null>(null)\n\nexport function UsersProvider({ children }: { children: React.ReactNode }) {\n  const [open, setOpen] = useDialogState<UsersDialogType>(null)\n  const [currentRow, setCurrentRow] = useState<User | null>(null)\n\n  return (\n    <UsersContext value={{ open, setOpen, currentRow, setCurrentRow }}>\n      {children}\n    </UsersContext>\n  )\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const useUsers = () => {\n  const usersContext = React.useContext(UsersContext)\n\n  if (!usersContext) {\n    throw new Error('useUsers has to be used within <UsersContext>')\n  }\n\n  return usersContext\n}\n"
  },
  {
    "path": "src/features/users/components/users-table.tsx",
    "content": "import { useEffect, useState } from 'react'\nimport {\n  type SortingState,\n  type VisibilityState,\n  flexRender,\n  getCoreRowModel,\n  getFacetedRowModel,\n  getFacetedUniqueValues,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  useReactTable,\n} from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { type NavigateFn, useTableUrlState } from '@/hooks/use-table-url-state'\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table'\nimport { DataTablePagination, DataTableToolbar } from '@/components/data-table'\nimport { roles } from '../data/data'\nimport { type User } from '../data/schema'\nimport { DataTableBulkActions } from './data-table-bulk-actions'\nimport { usersColumns as columns } from './users-columns'\n\ntype DataTableProps = {\n  data: User[]\n  search: Record<string, unknown>\n  navigate: NavigateFn\n}\n\nexport function UsersTable({ data, search, navigate }: DataTableProps) {\n  // Local UI-only states\n  const [rowSelection, setRowSelection] = useState({})\n  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})\n  const [sorting, setSorting] = useState<SortingState>([])\n\n  // Local state management for table (uncomment to use local-only state, not synced with URL)\n  // const [columnFilters, onColumnFiltersChange] = useState<ColumnFiltersState>([])\n  // const [pagination, onPaginationChange] = useState<PaginationState>({ pageIndex: 0, pageSize: 10 })\n\n  // Synced with URL states (keys/defaults mirror users route search schema)\n  const {\n    columnFilters,\n    onColumnFiltersChange,\n    pagination,\n    onPaginationChange,\n    ensurePageInRange,\n  } = useTableUrlState({\n    search,\n    navigate,\n    pagination: { defaultPage: 1, defaultPageSize: 10 },\n    globalFilter: { enabled: false },\n    columnFilters: [\n      // username per-column text filter\n      { columnId: 'username', searchKey: 'username', type: 'string' },\n      { columnId: 'status', searchKey: 'status', type: 'array' },\n      { columnId: 'role', searchKey: 'role', type: 'array' },\n    ],\n  })\n\n  // eslint-disable-next-line react-hooks/incompatible-library\n  const table = useReactTable({\n    data,\n    columns,\n    state: {\n      sorting,\n      pagination,\n      rowSelection,\n      columnFilters,\n      columnVisibility,\n    },\n    enableRowSelection: true,\n    onPaginationChange,\n    onColumnFiltersChange,\n    onRowSelectionChange: setRowSelection,\n    onSortingChange: setSorting,\n    onColumnVisibilityChange: setColumnVisibility,\n    getPaginationRowModel: getPaginationRowModel(),\n    getCoreRowModel: getCoreRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    getFacetedRowModel: getFacetedRowModel(),\n    getFacetedUniqueValues: getFacetedUniqueValues(),\n  })\n\n  useEffect(() => {\n    ensurePageInRange(table.getPageCount())\n  }, [table, ensurePageInRange])\n\n  return (\n    <div\n      className={cn(\n        'max-sm:has-[div[role=\"toolbar\"]]:mb-16', // Add margin bottom to the table on mobile when the toolbar is visible\n        'flex flex-1 flex-col gap-4'\n      )}\n    >\n      <DataTableToolbar\n        table={table}\n        searchPlaceholder='Filter users...'\n        searchKey='username'\n        filters={[\n          {\n            columnId: 'status',\n            title: 'Status',\n            options: [\n              { label: 'Active', value: 'active' },\n              { label: 'Inactive', value: 'inactive' },\n              { label: 'Invited', value: 'invited' },\n              { label: 'Suspended', value: 'suspended' },\n            ],\n          },\n          {\n            columnId: 'role',\n            title: 'Role',\n            options: roles.map((role) => ({ ...role })),\n          },\n        ]}\n      />\n      <div className='overflow-hidden rounded-md border'>\n        <Table>\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id} className='group/row'>\n                {headerGroup.headers.map((header) => {\n                  return (\n                    <TableHead\n                      key={header.id}\n                      colSpan={header.colSpan}\n                      className={cn(\n                        'bg-background group-hover/row:bg-muted group-data-[state=selected]/row:bg-muted',\n                        header.column.columnDef.meta?.className,\n                        header.column.columnDef.meta?.thClassName\n                      )}\n                    >\n                      {header.isPlaceholder\n                        ? null\n                        : flexRender(\n                            header.column.columnDef.header,\n                            header.getContext()\n                          )}\n                    </TableHead>\n                  )\n                })}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows?.length ? (\n              table.getRowModel().rows.map((row) => (\n                <TableRow\n                  key={row.id}\n                  data-state={row.getIsSelected() && 'selected'}\n                  className='group/row'\n                >\n                  {row.getVisibleCells().map((cell) => (\n                    <TableCell\n                      key={cell.id}\n                      className={cn(\n                        'bg-background group-hover/row:bg-muted group-data-[state=selected]/row:bg-muted',\n                        cell.column.columnDef.meta?.className,\n                        cell.column.columnDef.meta?.tdClassName\n                      )}\n                    >\n                      {flexRender(\n                        cell.column.columnDef.cell,\n                        cell.getContext()\n                      )}\n                    </TableCell>\n                  ))}\n                </TableRow>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell\n                  colSpan={columns.length}\n                  className='h-24 text-center'\n                >\n                  No results.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n      <DataTablePagination table={table} className='mt-auto' />\n      <DataTableBulkActions table={table} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/features/users/data/data.ts",
    "content": "import { Shield, UserCheck, Users, CreditCard } from 'lucide-react'\nimport { type UserStatus } from './schema'\n\nexport const callTypes = new Map<UserStatus, string>([\n  ['active', 'bg-teal-100/30 text-teal-900 dark:text-teal-200 border-teal-200'],\n  ['inactive', 'bg-neutral-300/40 border-neutral-300'],\n  ['invited', 'bg-sky-200/40 text-sky-900 dark:text-sky-100 border-sky-300'],\n  [\n    'suspended',\n    'bg-destructive/10 dark:bg-destructive/50 text-destructive dark:text-primary border-destructive/10',\n  ],\n])\n\nexport const roles = [\n  {\n    label: 'Superadmin',\n    value: 'superadmin',\n    icon: Shield,\n  },\n  {\n    label: 'Admin',\n    value: 'admin',\n    icon: UserCheck,\n  },\n  {\n    label: 'Manager',\n    value: 'manager',\n    icon: Users,\n  },\n  {\n    label: 'Cashier',\n    value: 'cashier',\n    icon: CreditCard,\n  },\n] as const\n"
  },
  {
    "path": "src/features/users/data/schema.ts",
    "content": "import { z } from 'zod'\n\nconst userStatusSchema = z.union([\n  z.literal('active'),\n  z.literal('inactive'),\n  z.literal('invited'),\n  z.literal('suspended'),\n])\nexport type UserStatus = z.infer<typeof userStatusSchema>\n\nconst userRoleSchema = z.union([\n  z.literal('superadmin'),\n  z.literal('admin'),\n  z.literal('cashier'),\n  z.literal('manager'),\n])\n\nconst userSchema = z.object({\n  id: z.string(),\n  firstName: z.string(),\n  lastName: z.string(),\n  username: z.string(),\n  email: z.string(),\n  phoneNumber: z.string(),\n  status: userStatusSchema,\n  role: userRoleSchema,\n  createdAt: z.coerce.date(),\n  updatedAt: z.coerce.date(),\n})\nexport type User = z.infer<typeof userSchema>\n\nexport const userListSchema = z.array(userSchema)\n"
  },
  {
    "path": "src/features/users/data/users.ts",
    "content": "import { faker } from '@faker-js/faker'\n\n// Set a fixed seed for consistent data generation\nfaker.seed(67890)\n\nexport const users = Array.from({ length: 500 }, () => {\n  const firstName = faker.person.firstName()\n  const lastName = faker.person.lastName()\n  return {\n    id: faker.string.uuid(),\n    firstName,\n    lastName,\n    username: faker.internet\n      .username({ firstName, lastName })\n      .toLocaleLowerCase(),\n    email: faker.internet.email({ firstName }).toLocaleLowerCase(),\n    phoneNumber: faker.phone.number({ style: 'international' }),\n    status: faker.helpers.arrayElement([\n      'active',\n      'inactive',\n      'invited',\n      'suspended',\n    ]),\n    role: faker.helpers.arrayElement([\n      'superadmin',\n      'admin',\n      'cashier',\n      'manager',\n    ]),\n    createdAt: faker.date.past(),\n    updatedAt: faker.date.recent(),\n  }\n})\n"
  },
  {
    "path": "src/features/users/index.tsx",
    "content": "import { getRouteApi } from '@tanstack/react-router'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { UsersDialogs } from './components/users-dialogs'\nimport { UsersPrimaryButtons } from './components/users-primary-buttons'\nimport { UsersProvider } from './components/users-provider'\nimport { UsersTable } from './components/users-table'\nimport { users } from './data/users'\n\nconst route = getRouteApi('/_authenticated/users/')\n\nexport function Users() {\n  const search = route.useSearch()\n  const navigate = route.useNavigate()\n\n  return (\n    <UsersProvider>\n      <Header fixed>\n        <Search />\n        <div className='ms-auto flex items-center space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n\n      <Main className='flex flex-1 flex-col gap-4 sm:gap-6'>\n        <div className='flex flex-wrap items-end justify-between gap-2'>\n          <div>\n            <h2 className='text-2xl font-bold tracking-tight'>User List</h2>\n            <p className='text-muted-foreground'>\n              Manage your users and their roles here.\n            </p>\n          </div>\n          <UsersPrimaryButtons />\n        </div>\n        <UsersTable data={users} search={search} navigate={navigate} />\n      </Main>\n\n      <UsersDialogs />\n    </UsersProvider>\n  )\n}\n"
  },
  {
    "path": "src/hooks/use-dialog-state.tsx",
    "content": "import { useState } from 'react'\n\n/**\n * Custom hook for confirm dialog\n * @param initialState string | null\n * @returns A stateful value, and a function to update it.\n * @example const [open, setOpen] = useDialogState<\"approve\" | \"reject\">()\n */\nexport default function useDialogState<T extends string | boolean>(\n  initialState: T | null = null\n) {\n  const [open, _setOpen] = useState<T | null>(initialState)\n\n  const setOpen = (str: T | null) =>\n    _setOpen((prev) => (prev === str ? null : str))\n\n  return [open, setOpen] as const\n}\n"
  },
  {
    "path": "src/hooks/use-mobile.tsx",
    "content": "import * as React from 'react'\n\nconst MOBILE_BREAKPOINT = 768\nconst MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`\n\nexport function useIsMobile() {\n  return React.useSyncExternalStore(\n    (callback) => {\n      const mql = window.matchMedia(MOBILE_QUERY)\n      mql.addEventListener('change', callback)\n      return () => mql.removeEventListener('change', callback)\n    },\n    () => window.matchMedia(MOBILE_QUERY).matches,\n    () => false\n  )\n}\n"
  },
  {
    "path": "src/hooks/use-table-url-state.ts",
    "content": "import { useMemo, useState } from 'react'\nimport type {\n  ColumnFiltersState,\n  OnChangeFn,\n  PaginationState,\n} from '@tanstack/react-table'\n\ntype SearchRecord = Record<string, unknown>\n\nexport type NavigateFn = (opts: {\n  search:\n    | true\n    | SearchRecord\n    | ((prev: SearchRecord) => Partial<SearchRecord> | SearchRecord)\n  replace?: boolean\n}) => void\n\ntype UseTableUrlStateParams = {\n  search: SearchRecord\n  navigate: NavigateFn\n  pagination?: {\n    pageKey?: string\n    pageSizeKey?: string\n    defaultPage?: number\n    defaultPageSize?: number\n  }\n  globalFilter?: {\n    enabled?: boolean\n    key?: string\n    trim?: boolean\n  }\n  columnFilters?: Array<\n    | {\n        columnId: string\n        searchKey: string\n        type?: 'string'\n        // Optional transformers for custom types\n        serialize?: (value: unknown) => unknown\n        deserialize?: (value: unknown) => unknown\n      }\n    | {\n        columnId: string\n        searchKey: string\n        type: 'array'\n        serialize?: (value: unknown) => unknown\n        deserialize?: (value: unknown) => unknown\n      }\n  >\n}\n\ntype UseTableUrlStateReturn = {\n  // Global filter\n  globalFilter?: string\n  onGlobalFilterChange?: OnChangeFn<string>\n  // Column filters\n  columnFilters: ColumnFiltersState\n  onColumnFiltersChange: OnChangeFn<ColumnFiltersState>\n  // Pagination\n  pagination: PaginationState\n  onPaginationChange: OnChangeFn<PaginationState>\n  // Helpers\n  ensurePageInRange: (\n    pageCount: number,\n    opts?: { resetTo?: 'first' | 'last' }\n  ) => void\n}\n\nexport function useTableUrlState(\n  params: UseTableUrlStateParams\n): UseTableUrlStateReturn {\n  const {\n    search,\n    navigate,\n    pagination: paginationCfg,\n    globalFilter: globalFilterCfg,\n    columnFilters: columnFiltersCfg = [],\n  } = params\n\n  const pageKey = paginationCfg?.pageKey ?? ('page' as string)\n  const pageSizeKey = paginationCfg?.pageSizeKey ?? ('pageSize' as string)\n  const defaultPage = paginationCfg?.defaultPage ?? 1\n  const defaultPageSize = paginationCfg?.defaultPageSize ?? 10\n\n  const globalFilterKey = globalFilterCfg?.key ?? ('filter' as string)\n  const globalFilterEnabled = globalFilterCfg?.enabled ?? true\n  const trimGlobal = globalFilterCfg?.trim ?? true\n\n  // Build initial column filters from the current search params\n  const initialColumnFilters: ColumnFiltersState = useMemo(() => {\n    const collected: ColumnFiltersState = []\n    for (const cfg of columnFiltersCfg) {\n      const raw = (search as SearchRecord)[cfg.searchKey]\n      const deserialize = cfg.deserialize ?? ((v: unknown) => v)\n      if (cfg.type === 'string') {\n        const value = (deserialize(raw) as string) ?? ''\n        if (typeof value === 'string' && value.trim() !== '') {\n          collected.push({ id: cfg.columnId, value })\n        }\n      } else {\n        // default to array type\n        const value = (deserialize(raw) as unknown[]) ?? []\n        if (Array.isArray(value) && value.length > 0) {\n          collected.push({ id: cfg.columnId, value })\n        }\n      }\n    }\n    return collected\n  }, [columnFiltersCfg, search])\n\n  const [columnFilters, setColumnFilters] =\n    useState<ColumnFiltersState>(initialColumnFilters)\n\n  const pagination: PaginationState = useMemo(() => {\n    const rawPage = (search as SearchRecord)[pageKey]\n    const rawPageSize = (search as SearchRecord)[pageSizeKey]\n    const pageNum = typeof rawPage === 'number' ? rawPage : defaultPage\n    const pageSizeNum =\n      typeof rawPageSize === 'number' ? rawPageSize : defaultPageSize\n    return { pageIndex: Math.max(0, pageNum - 1), pageSize: pageSizeNum }\n  }, [search, pageKey, pageSizeKey, defaultPage, defaultPageSize])\n\n  const onPaginationChange: OnChangeFn<PaginationState> = (updater) => {\n    const next = typeof updater === 'function' ? updater(pagination) : updater\n    const nextPage = next.pageIndex + 1\n    const nextPageSize = next.pageSize\n    navigate({\n      search: (prev) => ({\n        ...(prev as SearchRecord),\n        [pageKey]: nextPage <= defaultPage ? undefined : nextPage,\n        [pageSizeKey]:\n          nextPageSize === defaultPageSize ? undefined : nextPageSize,\n      }),\n    })\n  }\n\n  const [globalFilter, setGlobalFilter] = useState<string | undefined>(() => {\n    if (!globalFilterEnabled) return undefined\n    const raw = (search as SearchRecord)[globalFilterKey]\n    return typeof raw === 'string' ? raw : ''\n  })\n\n  const onGlobalFilterChange: OnChangeFn<string> | undefined =\n    globalFilterEnabled\n      ? (updater) => {\n          const next =\n            typeof updater === 'function'\n              ? updater(globalFilter ?? '')\n              : updater\n          const value = trimGlobal ? next.trim() : next\n          setGlobalFilter(value)\n          navigate({\n            search: (prev) => ({\n              ...(prev as SearchRecord),\n              [pageKey]: undefined,\n              [globalFilterKey]: value ? value : undefined,\n            }),\n          })\n        }\n      : undefined\n\n  const onColumnFiltersChange: OnChangeFn<ColumnFiltersState> = (updater) => {\n    const next =\n      typeof updater === 'function' ? updater(columnFilters) : updater\n    setColumnFilters(next)\n\n    const patch: Record<string, unknown> = {}\n\n    for (const cfg of columnFiltersCfg) {\n      const found = next.find((f) => f.id === cfg.columnId)\n      const serialize = cfg.serialize ?? ((v: unknown) => v)\n      if (cfg.type === 'string') {\n        const value =\n          typeof found?.value === 'string' ? (found.value as string) : ''\n        patch[cfg.searchKey] =\n          value.trim() !== '' ? serialize(value) : undefined\n      } else {\n        const value = Array.isArray(found?.value)\n          ? (found!.value as unknown[])\n          : []\n        patch[cfg.searchKey] = value.length > 0 ? serialize(value) : undefined\n      }\n    }\n\n    navigate({\n      search: (prev) => ({\n        ...(prev as SearchRecord),\n        [pageKey]: undefined,\n        ...patch,\n      }),\n    })\n  }\n\n  const ensurePageInRange = (\n    pageCount: number,\n    opts: { resetTo?: 'first' | 'last' } = { resetTo: 'first' }\n  ) => {\n    const currentPage = (search as SearchRecord)[pageKey]\n    const pageNum = typeof currentPage === 'number' ? currentPage : defaultPage\n    if (pageCount > 0 && pageNum > pageCount) {\n      navigate({\n        replace: true,\n        search: (prev) => ({\n          ...(prev as SearchRecord),\n          [pageKey]: opts.resetTo === 'last' ? pageCount : undefined,\n        }),\n      })\n    }\n  }\n\n  return {\n    globalFilter: globalFilterEnabled ? (globalFilter ?? '') : undefined,\n    onGlobalFilterChange,\n    columnFilters,\n    onColumnFiltersChange,\n    pagination,\n    onPaginationChange,\n    ensurePageInRange,\n  }\n}\n"
  },
  {
    "path": "src/lib/cookies.ts",
    "content": "/**\n * Cookie utility functions using manual document.cookie approach\n * Replaces js-cookie dependency for better consistency\n */\n\nconst DEFAULT_MAX_AGE = 60 * 60 * 24 * 7 // 7 days\n\n/**\n * Get a cookie value by name\n */\nexport function getCookie(name: string): string | undefined {\n  if (typeof document === 'undefined') return undefined\n\n  const value = `; ${document.cookie}`\n  const parts = value.split(`; ${name}=`)\n  if (parts.length === 2) {\n    const cookieValue = parts.pop()?.split(';').shift()\n    return cookieValue\n  }\n  return undefined\n}\n\n/**\n * Set a cookie with name, value, and optional max age\n */\nexport function setCookie(\n  name: string,\n  value: string,\n  maxAge: number = DEFAULT_MAX_AGE\n): void {\n  if (typeof document === 'undefined') return\n\n  document.cookie = `${name}=${value}; path=/; max-age=${maxAge}`\n}\n\n/**\n * Remove a cookie by setting its max age to 0\n */\nexport function removeCookie(name: string): void {\n  if (typeof document === 'undefined') return\n\n  document.cookie = `${name}=; path=/; max-age=0`\n}\n"
  },
  {
    "path": "src/lib/handle-server-error.ts",
    "content": "import { AxiosError } from 'axios'\nimport { toast } from 'sonner'\n\nexport function handleServerError(error: unknown) {\n  // eslint-disable-next-line no-console\n  console.log(error)\n\n  let errMsg = 'Something went wrong!'\n\n  if (\n    error &&\n    typeof error === 'object' &&\n    'status' in error &&\n    Number(error.status) === 204\n  ) {\n    errMsg = 'Content not found.'\n  }\n\n  if (error instanceof AxiosError) {\n    errMsg = error.response?.data.title\n  }\n\n  toast.error(errMsg)\n}\n"
  },
  {
    "path": "src/lib/show-submitted-data.tsx",
    "content": "import { toast } from 'sonner'\n\nexport function showSubmittedData(\n  data: unknown,\n  title: string = 'You submitted the following values:'\n) {\n  toast.message(title, {\n    description: (\n      // w-[340px]\n      <pre className='mt-2 w-full overflow-x-auto rounded-md bg-slate-950 p-4'>\n        <code className='text-white'>{JSON.stringify(data, null, 2)}</code>\n      </pre>\n    ),\n  })\n}\n"
  },
  {
    "path": "src/lib/utils.ts",
    "content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n\nexport function sleep(ms: number = 1000) {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Generates page numbers for pagination with ellipsis\n * @param currentPage - Current page number (1-based)\n * @param totalPages - Total number of pages\n * @returns Array of page numbers and ellipsis strings\n *\n * Examples:\n * - Small dataset (≤5 pages): [1, 2, 3, 4, 5]\n * - Near beginning: [1, 2, 3, 4, '...', 10]\n * - In middle: [1, '...', 4, 5, 6, '...', 10]\n * - Near end: [1, '...', 7, 8, 9, 10]\n */\nexport function getPageNumbers(currentPage: number, totalPages: number) {\n  const maxVisiblePages = 5 // Maximum number of page buttons to show\n  const rangeWithDots = []\n\n  if (totalPages <= maxVisiblePages) {\n    // If total pages is 5 or less, show all pages\n    for (let i = 1; i <= totalPages; i++) {\n      rangeWithDots.push(i)\n    }\n  } else {\n    // Always show first page\n    rangeWithDots.push(1)\n\n    if (currentPage <= 3) {\n      // Near the beginning: [1] [2] [3] [4] ... [10]\n      for (let i = 2; i <= 4; i++) {\n        rangeWithDots.push(i)\n      }\n      rangeWithDots.push('...', totalPages)\n    } else if (currentPage >= totalPages - 2) {\n      // Near the end: [1] ... [7] [8] [9] [10]\n      rangeWithDots.push('...')\n      for (let i = totalPages - 3; i <= totalPages; i++) {\n        rangeWithDots.push(i)\n      }\n    } else {\n      // In the middle: [1] ... [4] [5] [6] ... [10]\n      rangeWithDots.push('...')\n      for (let i = currentPage - 1; i <= currentPage + 1; i++) {\n        rangeWithDots.push(i)\n      }\n      rangeWithDots.push('...', totalPages)\n    }\n  }\n\n  return rangeWithDots\n}\n"
  },
  {
    "path": "src/main.tsx",
    "content": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { AxiosError } from 'axios'\nimport {\n  QueryCache,\n  QueryClient,\n  QueryClientProvider,\n} from '@tanstack/react-query'\nimport { RouterProvider, createRouter } from '@tanstack/react-router'\nimport { toast } from 'sonner'\nimport { useAuthStore } from '@/stores/auth-store'\nimport { handleServerError } from '@/lib/handle-server-error'\nimport { DirectionProvider } from './context/direction-provider'\nimport { FontProvider } from './context/font-provider'\nimport { ThemeProvider } from './context/theme-provider'\n// Generated Routes\nimport { routeTree } from './routeTree.gen'\n// Styles\nimport './styles/index.css'\n\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      retry: (failureCount, error) => {\n        // eslint-disable-next-line no-console\n        if (import.meta.env.DEV) console.log({ failureCount, error })\n\n        if (failureCount >= 0 && import.meta.env.DEV) return false\n        if (failureCount > 3 && import.meta.env.PROD) return false\n\n        return !(\n          error instanceof AxiosError &&\n          [401, 403].includes(error.response?.status ?? 0)\n        )\n      },\n      refetchOnWindowFocus: import.meta.env.PROD,\n      staleTime: 10 * 1000, // 10s\n    },\n    mutations: {\n      onError: (error) => {\n        handleServerError(error)\n\n        if (error instanceof AxiosError) {\n          if (error.response?.status === 304) {\n            toast.error('Content not modified!')\n          }\n        }\n      },\n    },\n  },\n  queryCache: new QueryCache({\n    onError: (error) => {\n      if (error instanceof AxiosError) {\n        if (error.response?.status === 401) {\n          toast.error('Session expired!')\n          useAuthStore.getState().auth.reset()\n          const redirect = `${router.history.location.href}`\n          router.navigate({ to: '/sign-in', search: { redirect } })\n        }\n        if (error.response?.status === 500) {\n          toast.error('Internal Server Error!')\n          // Only navigate to error page in production to avoid disrupting HMR in development\n          if (import.meta.env.PROD) {\n            router.navigate({ to: '/500' })\n          }\n        }\n        if (error.response?.status === 403) {\n          // router.navigate(\"/forbidden\", { replace: true });\n        }\n      }\n    },\n  }),\n})\n\n// Create a new router instance\nconst router = createRouter({\n  routeTree,\n  context: { queryClient },\n  defaultPreload: 'intent',\n  defaultPreloadStaleTime: 0,\n})\n\n// Register the router instance for type safety\ndeclare module '@tanstack/react-router' {\n  interface Register {\n    router: typeof router\n  }\n}\n\n// Render the app\nconst rootElement = document.getElementById('root')!\nif (!rootElement.innerHTML) {\n  const root = ReactDOM.createRoot(rootElement)\n  root.render(\n    <StrictMode>\n      <QueryClientProvider client={queryClient}>\n        <ThemeProvider>\n          <FontProvider>\n            <DirectionProvider>\n              <RouterProvider router={router} />\n            </DirectionProvider>\n          </FontProvider>\n        </ThemeProvider>\n      </QueryClientProvider>\n    </StrictMode>\n  )\n}\n"
  },
  {
    "path": "src/routeTree.gen.ts",
    "content": "/* eslint-disable */\n\n// @ts-nocheck\n\n// noinspection JSUnusedGlobalSymbols\n\n// This file was automatically generated by TanStack Router.\n// You should NOT make any changes in this file as it will be overwritten.\n// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.\n\nimport { Route as rootRouteImport } from './routes/__root'\nimport { Route as ClerkRouteRouteImport } from './routes/clerk/route'\nimport { Route as AuthenticatedRouteRouteImport } from './routes/_authenticated/route'\nimport { Route as AuthenticatedIndexRouteImport } from './routes/_authenticated/index'\nimport { Route as errors503RouteImport } from './routes/(errors)/503'\nimport { Route as errors500RouteImport } from './routes/(errors)/500'\nimport { Route as errors404RouteImport } from './routes/(errors)/404'\nimport { Route as errors403RouteImport } from './routes/(errors)/403'\nimport { Route as errors401RouteImport } from './routes/(errors)/401'\nimport { Route as authSignUpRouteImport } from './routes/(auth)/sign-up'\nimport { Route as authSignIn2RouteImport } from './routes/(auth)/sign-in-2'\nimport { Route as authSignInRouteImport } from './routes/(auth)/sign-in'\nimport { Route as authOtpRouteImport } from './routes/(auth)/otp'\nimport { Route as authForgotPasswordRouteImport } from './routes/(auth)/forgot-password'\nimport { Route as ClerkAuthenticatedRouteRouteImport } from './routes/clerk/_authenticated/route'\nimport { Route as ClerkauthRouteRouteImport } from './routes/clerk/(auth)/route'\nimport { Route as AuthenticatedSettingsRouteRouteImport } from './routes/_authenticated/settings/route'\nimport { Route as AuthenticatedUsersIndexRouteImport } from './routes/_authenticated/users/index'\nimport { Route as AuthenticatedTasksIndexRouteImport } from './routes/_authenticated/tasks/index'\nimport { Route as AuthenticatedSettingsIndexRouteImport } from './routes/_authenticated/settings/index'\nimport { Route as AuthenticatedHelpCenterIndexRouteImport } from './routes/_authenticated/help-center/index'\nimport { Route as AuthenticatedChatsIndexRouteImport } from './routes/_authenticated/chats/index'\nimport { Route as AuthenticatedAppsIndexRouteImport } from './routes/_authenticated/apps/index'\nimport { Route as ClerkAuthenticatedUserManagementRouteImport } from './routes/clerk/_authenticated/user-management'\nimport { Route as ClerkauthSignUpRouteImport } from './routes/clerk/(auth)/sign-up'\nimport { Route as ClerkauthSignInRouteImport } from './routes/clerk/(auth)/sign-in'\nimport { Route as AuthenticatedSettingsNotificationsRouteImport } from './routes/_authenticated/settings/notifications'\nimport { Route as AuthenticatedSettingsDisplayRouteImport } from './routes/_authenticated/settings/display'\nimport { Route as AuthenticatedSettingsAppearanceRouteImport } from './routes/_authenticated/settings/appearance'\nimport { Route as AuthenticatedSettingsAccountRouteImport } from './routes/_authenticated/settings/account'\nimport { Route as AuthenticatedErrorsErrorRouteImport } from './routes/_authenticated/errors/$error'\n\nconst ClerkRouteRoute = ClerkRouteRouteImport.update({\n  id: '/clerk',\n  path: '/clerk',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst AuthenticatedRouteRoute = AuthenticatedRouteRouteImport.update({\n  id: '/_authenticated',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst AuthenticatedIndexRoute = AuthenticatedIndexRouteImport.update({\n  id: '/',\n  path: '/',\n  getParentRoute: () => AuthenticatedRouteRoute,\n} as any)\nconst errors503Route = errors503RouteImport.update({\n  id: '/(errors)/503',\n  path: '/503',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst errors500Route = errors500RouteImport.update({\n  id: '/(errors)/500',\n  path: '/500',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst errors404Route = errors404RouteImport.update({\n  id: '/(errors)/404',\n  path: '/404',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst errors403Route = errors403RouteImport.update({\n  id: '/(errors)/403',\n  path: '/403',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst errors401Route = errors401RouteImport.update({\n  id: '/(errors)/401',\n  path: '/401',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst authSignUpRoute = authSignUpRouteImport.update({\n  id: '/(auth)/sign-up',\n  path: '/sign-up',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst authSignIn2Route = authSignIn2RouteImport.update({\n  id: '/(auth)/sign-in-2',\n  path: '/sign-in-2',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst authSignInRoute = authSignInRouteImport.update({\n  id: '/(auth)/sign-in',\n  path: '/sign-in',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst authOtpRoute = authOtpRouteImport.update({\n  id: '/(auth)/otp',\n  path: '/otp',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst authForgotPasswordRoute = authForgotPasswordRouteImport.update({\n  id: '/(auth)/forgot-password',\n  path: '/forgot-password',\n  getParentRoute: () => rootRouteImport,\n} as any)\nconst ClerkAuthenticatedRouteRoute = ClerkAuthenticatedRouteRouteImport.update({\n  id: '/_authenticated',\n  getParentRoute: () => ClerkRouteRoute,\n} as any)\nconst ClerkauthRouteRoute = ClerkauthRouteRouteImport.update({\n  id: '/(auth)',\n  getParentRoute: () => ClerkRouteRoute,\n} as any)\nconst AuthenticatedSettingsRouteRoute =\n  AuthenticatedSettingsRouteRouteImport.update({\n    id: '/settings',\n    path: '/settings',\n    getParentRoute: () => AuthenticatedRouteRoute,\n  } as any)\nconst AuthenticatedUsersIndexRoute = AuthenticatedUsersIndexRouteImport.update({\n  id: '/users/',\n  path: '/users/',\n  getParentRoute: () => AuthenticatedRouteRoute,\n} as any)\nconst AuthenticatedTasksIndexRoute = AuthenticatedTasksIndexRouteImport.update({\n  id: '/tasks/',\n  path: '/tasks/',\n  getParentRoute: () => AuthenticatedRouteRoute,\n} as any)\nconst AuthenticatedSettingsIndexRoute =\n  AuthenticatedSettingsIndexRouteImport.update({\n    id: '/',\n    path: '/',\n    getParentRoute: () => AuthenticatedSettingsRouteRoute,\n  } as any)\nconst AuthenticatedHelpCenterIndexRoute =\n  AuthenticatedHelpCenterIndexRouteImport.update({\n    id: '/help-center/',\n    path: '/help-center/',\n    getParentRoute: () => AuthenticatedRouteRoute,\n  } as any)\nconst AuthenticatedChatsIndexRoute = AuthenticatedChatsIndexRouteImport.update({\n  id: '/chats/',\n  path: '/chats/',\n  getParentRoute: () => AuthenticatedRouteRoute,\n} as any)\nconst AuthenticatedAppsIndexRoute = AuthenticatedAppsIndexRouteImport.update({\n  id: '/apps/',\n  path: '/apps/',\n  getParentRoute: () => AuthenticatedRouteRoute,\n} as any)\nconst ClerkAuthenticatedUserManagementRoute =\n  ClerkAuthenticatedUserManagementRouteImport.update({\n    id: '/user-management',\n    path: '/user-management',\n    getParentRoute: () => ClerkAuthenticatedRouteRoute,\n  } as any)\nconst ClerkauthSignUpRoute = ClerkauthSignUpRouteImport.update({\n  id: '/sign-up',\n  path: '/sign-up',\n  getParentRoute: () => ClerkauthRouteRoute,\n} as any)\nconst ClerkauthSignInRoute = ClerkauthSignInRouteImport.update({\n  id: '/sign-in',\n  path: '/sign-in',\n  getParentRoute: () => ClerkauthRouteRoute,\n} as any)\nconst AuthenticatedSettingsNotificationsRoute =\n  AuthenticatedSettingsNotificationsRouteImport.update({\n    id: '/notifications',\n    path: '/notifications',\n    getParentRoute: () => AuthenticatedSettingsRouteRoute,\n  } as any)\nconst AuthenticatedSettingsDisplayRoute =\n  AuthenticatedSettingsDisplayRouteImport.update({\n    id: '/display',\n    path: '/display',\n    getParentRoute: () => AuthenticatedSettingsRouteRoute,\n  } as any)\nconst AuthenticatedSettingsAppearanceRoute =\n  AuthenticatedSettingsAppearanceRouteImport.update({\n    id: '/appearance',\n    path: '/appearance',\n    getParentRoute: () => AuthenticatedSettingsRouteRoute,\n  } as any)\nconst AuthenticatedSettingsAccountRoute =\n  AuthenticatedSettingsAccountRouteImport.update({\n    id: '/account',\n    path: '/account',\n    getParentRoute: () => AuthenticatedSettingsRouteRoute,\n  } as any)\nconst AuthenticatedErrorsErrorRoute =\n  AuthenticatedErrorsErrorRouteImport.update({\n    id: '/errors/$error',\n    path: '/errors/$error',\n    getParentRoute: () => AuthenticatedRouteRoute,\n  } as any)\n\nexport interface FileRoutesByFullPath {\n  '/clerk': typeof ClerkAuthenticatedRouteRouteWithChildren\n  '/settings': typeof AuthenticatedSettingsRouteRouteWithChildren\n  '/forgot-password': typeof authForgotPasswordRoute\n  '/otp': typeof authOtpRoute\n  '/sign-in': typeof authSignInRoute\n  '/sign-in-2': typeof authSignIn2Route\n  '/sign-up': typeof authSignUpRoute\n  '/401': typeof errors401Route\n  '/403': typeof errors403Route\n  '/404': typeof errors404Route\n  '/500': typeof errors500Route\n  '/503': typeof errors503Route\n  '/': typeof AuthenticatedIndexRoute\n  '/errors/$error': typeof AuthenticatedErrorsErrorRoute\n  '/settings/account': typeof AuthenticatedSettingsAccountRoute\n  '/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute\n  '/settings/display': typeof AuthenticatedSettingsDisplayRoute\n  '/settings/notifications': typeof AuthenticatedSettingsNotificationsRoute\n  '/clerk/sign-in': typeof ClerkauthSignInRoute\n  '/clerk/sign-up': typeof ClerkauthSignUpRoute\n  '/clerk/user-management': typeof ClerkAuthenticatedUserManagementRoute\n  '/apps': typeof AuthenticatedAppsIndexRoute\n  '/chats': typeof AuthenticatedChatsIndexRoute\n  '/help-center': typeof AuthenticatedHelpCenterIndexRoute\n  '/settings/': typeof AuthenticatedSettingsIndexRoute\n  '/tasks': typeof AuthenticatedTasksIndexRoute\n  '/users': typeof AuthenticatedUsersIndexRoute\n}\nexport interface FileRoutesByTo {\n  '/clerk': typeof ClerkAuthenticatedRouteRouteWithChildren\n  '/forgot-password': typeof authForgotPasswordRoute\n  '/otp': typeof authOtpRoute\n  '/sign-in': typeof authSignInRoute\n  '/sign-in-2': typeof authSignIn2Route\n  '/sign-up': typeof authSignUpRoute\n  '/401': typeof errors401Route\n  '/403': typeof errors403Route\n  '/404': typeof errors404Route\n  '/500': typeof errors500Route\n  '/503': typeof errors503Route\n  '/': typeof AuthenticatedIndexRoute\n  '/errors/$error': typeof AuthenticatedErrorsErrorRoute\n  '/settings/account': typeof AuthenticatedSettingsAccountRoute\n  '/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute\n  '/settings/display': typeof AuthenticatedSettingsDisplayRoute\n  '/settings/notifications': typeof AuthenticatedSettingsNotificationsRoute\n  '/clerk/sign-in': typeof ClerkauthSignInRoute\n  '/clerk/sign-up': typeof ClerkauthSignUpRoute\n  '/clerk/user-management': typeof ClerkAuthenticatedUserManagementRoute\n  '/apps': typeof AuthenticatedAppsIndexRoute\n  '/chats': typeof AuthenticatedChatsIndexRoute\n  '/help-center': typeof AuthenticatedHelpCenterIndexRoute\n  '/settings': typeof AuthenticatedSettingsIndexRoute\n  '/tasks': typeof AuthenticatedTasksIndexRoute\n  '/users': typeof AuthenticatedUsersIndexRoute\n}\nexport interface FileRoutesById {\n  __root__: typeof rootRouteImport\n  '/_authenticated': typeof AuthenticatedRouteRouteWithChildren\n  '/clerk': typeof ClerkRouteRouteWithChildren\n  '/_authenticated/settings': typeof AuthenticatedSettingsRouteRouteWithChildren\n  '/clerk/(auth)': typeof ClerkauthRouteRouteWithChildren\n  '/clerk/_authenticated': typeof ClerkAuthenticatedRouteRouteWithChildren\n  '/(auth)/forgot-password': typeof authForgotPasswordRoute\n  '/(auth)/otp': typeof authOtpRoute\n  '/(auth)/sign-in': typeof authSignInRoute\n  '/(auth)/sign-in-2': typeof authSignIn2Route\n  '/(auth)/sign-up': typeof authSignUpRoute\n  '/(errors)/401': typeof errors401Route\n  '/(errors)/403': typeof errors403Route\n  '/(errors)/404': typeof errors404Route\n  '/(errors)/500': typeof errors500Route\n  '/(errors)/503': typeof errors503Route\n  '/_authenticated/': typeof AuthenticatedIndexRoute\n  '/_authenticated/errors/$error': typeof AuthenticatedErrorsErrorRoute\n  '/_authenticated/settings/account': typeof AuthenticatedSettingsAccountRoute\n  '/_authenticated/settings/appearance': typeof AuthenticatedSettingsAppearanceRoute\n  '/_authenticated/settings/display': typeof AuthenticatedSettingsDisplayRoute\n  '/_authenticated/settings/notifications': typeof AuthenticatedSettingsNotificationsRoute\n  '/clerk/(auth)/sign-in': typeof ClerkauthSignInRoute\n  '/clerk/(auth)/sign-up': typeof ClerkauthSignUpRoute\n  '/clerk/_authenticated/user-management': typeof ClerkAuthenticatedUserManagementRoute\n  '/_authenticated/apps/': typeof AuthenticatedAppsIndexRoute\n  '/_authenticated/chats/': typeof AuthenticatedChatsIndexRoute\n  '/_authenticated/help-center/': typeof AuthenticatedHelpCenterIndexRoute\n  '/_authenticated/settings/': typeof AuthenticatedSettingsIndexRoute\n  '/_authenticated/tasks/': typeof AuthenticatedTasksIndexRoute\n  '/_authenticated/users/': typeof AuthenticatedUsersIndexRoute\n}\nexport interface FileRouteTypes {\n  fileRoutesByFullPath: FileRoutesByFullPath\n  fullPaths:\n    | '/clerk'\n    | '/settings'\n    | '/forgot-password'\n    | '/otp'\n    | '/sign-in'\n    | '/sign-in-2'\n    | '/sign-up'\n    | '/401'\n    | '/403'\n    | '/404'\n    | '/500'\n    | '/503'\n    | '/'\n    | '/errors/$error'\n    | '/settings/account'\n    | '/settings/appearance'\n    | '/settings/display'\n    | '/settings/notifications'\n    | '/clerk/sign-in'\n    | '/clerk/sign-up'\n    | '/clerk/user-management'\n    | '/apps'\n    | '/chats'\n    | '/help-center'\n    | '/settings/'\n    | '/tasks'\n    | '/users'\n  fileRoutesByTo: FileRoutesByTo\n  to:\n    | '/clerk'\n    | '/forgot-password'\n    | '/otp'\n    | '/sign-in'\n    | '/sign-in-2'\n    | '/sign-up'\n    | '/401'\n    | '/403'\n    | '/404'\n    | '/500'\n    | '/503'\n    | '/'\n    | '/errors/$error'\n    | '/settings/account'\n    | '/settings/appearance'\n    | '/settings/display'\n    | '/settings/notifications'\n    | '/clerk/sign-in'\n    | '/clerk/sign-up'\n    | '/clerk/user-management'\n    | '/apps'\n    | '/chats'\n    | '/help-center'\n    | '/settings'\n    | '/tasks'\n    | '/users'\n  id:\n    | '__root__'\n    | '/_authenticated'\n    | '/clerk'\n    | '/_authenticated/settings'\n    | '/clerk/(auth)'\n    | '/clerk/_authenticated'\n    | '/(auth)/forgot-password'\n    | '/(auth)/otp'\n    | '/(auth)/sign-in'\n    | '/(auth)/sign-in-2'\n    | '/(auth)/sign-up'\n    | '/(errors)/401'\n    | '/(errors)/403'\n    | '/(errors)/404'\n    | '/(errors)/500'\n    | '/(errors)/503'\n    | '/_authenticated/'\n    | '/_authenticated/errors/$error'\n    | '/_authenticated/settings/account'\n    | '/_authenticated/settings/appearance'\n    | '/_authenticated/settings/display'\n    | '/_authenticated/settings/notifications'\n    | '/clerk/(auth)/sign-in'\n    | '/clerk/(auth)/sign-up'\n    | '/clerk/_authenticated/user-management'\n    | '/_authenticated/apps/'\n    | '/_authenticated/chats/'\n    | '/_authenticated/help-center/'\n    | '/_authenticated/settings/'\n    | '/_authenticated/tasks/'\n    | '/_authenticated/users/'\n  fileRoutesById: FileRoutesById\n}\nexport interface RootRouteChildren {\n  AuthenticatedRouteRoute: typeof AuthenticatedRouteRouteWithChildren\n  ClerkRouteRoute: typeof ClerkRouteRouteWithChildren\n  authForgotPasswordRoute: typeof authForgotPasswordRoute\n  authOtpRoute: typeof authOtpRoute\n  authSignInRoute: typeof authSignInRoute\n  authSignIn2Route: typeof authSignIn2Route\n  authSignUpRoute: typeof authSignUpRoute\n  errors401Route: typeof errors401Route\n  errors403Route: typeof errors403Route\n  errors404Route: typeof errors404Route\n  errors500Route: typeof errors500Route\n  errors503Route: typeof errors503Route\n}\n\ndeclare module '@tanstack/react-router' {\n  interface FileRoutesByPath {\n    '/clerk': {\n      id: '/clerk'\n      path: '/clerk'\n      fullPath: '/clerk'\n      preLoaderRoute: typeof ClerkRouteRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/_authenticated': {\n      id: '/_authenticated'\n      path: ''\n      fullPath: ''\n      preLoaderRoute: typeof AuthenticatedRouteRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/_authenticated/': {\n      id: '/_authenticated/'\n      path: '/'\n      fullPath: '/'\n      preLoaderRoute: typeof AuthenticatedIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/(errors)/503': {\n      id: '/(errors)/503'\n      path: '/503'\n      fullPath: '/503'\n      preLoaderRoute: typeof errors503RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(errors)/500': {\n      id: '/(errors)/500'\n      path: '/500'\n      fullPath: '/500'\n      preLoaderRoute: typeof errors500RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(errors)/404': {\n      id: '/(errors)/404'\n      path: '/404'\n      fullPath: '/404'\n      preLoaderRoute: typeof errors404RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(errors)/403': {\n      id: '/(errors)/403'\n      path: '/403'\n      fullPath: '/403'\n      preLoaderRoute: typeof errors403RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(errors)/401': {\n      id: '/(errors)/401'\n      path: '/401'\n      fullPath: '/401'\n      preLoaderRoute: typeof errors401RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(auth)/sign-up': {\n      id: '/(auth)/sign-up'\n      path: '/sign-up'\n      fullPath: '/sign-up'\n      preLoaderRoute: typeof authSignUpRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(auth)/sign-in-2': {\n      id: '/(auth)/sign-in-2'\n      path: '/sign-in-2'\n      fullPath: '/sign-in-2'\n      preLoaderRoute: typeof authSignIn2RouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(auth)/sign-in': {\n      id: '/(auth)/sign-in'\n      path: '/sign-in'\n      fullPath: '/sign-in'\n      preLoaderRoute: typeof authSignInRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(auth)/otp': {\n      id: '/(auth)/otp'\n      path: '/otp'\n      fullPath: '/otp'\n      preLoaderRoute: typeof authOtpRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/(auth)/forgot-password': {\n      id: '/(auth)/forgot-password'\n      path: '/forgot-password'\n      fullPath: '/forgot-password'\n      preLoaderRoute: typeof authForgotPasswordRouteImport\n      parentRoute: typeof rootRouteImport\n    }\n    '/clerk/_authenticated': {\n      id: '/clerk/_authenticated'\n      path: ''\n      fullPath: '/clerk'\n      preLoaderRoute: typeof ClerkAuthenticatedRouteRouteImport\n      parentRoute: typeof ClerkRouteRoute\n    }\n    '/clerk/(auth)': {\n      id: '/clerk/(auth)'\n      path: ''\n      fullPath: '/clerk'\n      preLoaderRoute: typeof ClerkauthRouteRouteImport\n      parentRoute: typeof ClerkRouteRoute\n    }\n    '/_authenticated/settings': {\n      id: '/_authenticated/settings'\n      path: '/settings'\n      fullPath: '/settings'\n      preLoaderRoute: typeof AuthenticatedSettingsRouteRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/_authenticated/users/': {\n      id: '/_authenticated/users/'\n      path: '/users'\n      fullPath: '/users'\n      preLoaderRoute: typeof AuthenticatedUsersIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/_authenticated/tasks/': {\n      id: '/_authenticated/tasks/'\n      path: '/tasks'\n      fullPath: '/tasks'\n      preLoaderRoute: typeof AuthenticatedTasksIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/_authenticated/settings/': {\n      id: '/_authenticated/settings/'\n      path: '/'\n      fullPath: '/settings/'\n      preLoaderRoute: typeof AuthenticatedSettingsIndexRouteImport\n      parentRoute: typeof AuthenticatedSettingsRouteRoute\n    }\n    '/_authenticated/help-center/': {\n      id: '/_authenticated/help-center/'\n      path: '/help-center'\n      fullPath: '/help-center'\n      preLoaderRoute: typeof AuthenticatedHelpCenterIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/_authenticated/chats/': {\n      id: '/_authenticated/chats/'\n      path: '/chats'\n      fullPath: '/chats'\n      preLoaderRoute: typeof AuthenticatedChatsIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/_authenticated/apps/': {\n      id: '/_authenticated/apps/'\n      path: '/apps'\n      fullPath: '/apps'\n      preLoaderRoute: typeof AuthenticatedAppsIndexRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n    '/clerk/_authenticated/user-management': {\n      id: '/clerk/_authenticated/user-management'\n      path: '/user-management'\n      fullPath: '/clerk/user-management'\n      preLoaderRoute: typeof ClerkAuthenticatedUserManagementRouteImport\n      parentRoute: typeof ClerkAuthenticatedRouteRoute\n    }\n    '/clerk/(auth)/sign-up': {\n      id: '/clerk/(auth)/sign-up'\n      path: '/sign-up'\n      fullPath: '/clerk/sign-up'\n      preLoaderRoute: typeof ClerkauthSignUpRouteImport\n      parentRoute: typeof ClerkauthRouteRoute\n    }\n    '/clerk/(auth)/sign-in': {\n      id: '/clerk/(auth)/sign-in'\n      path: '/sign-in'\n      fullPath: '/clerk/sign-in'\n      preLoaderRoute: typeof ClerkauthSignInRouteImport\n      parentRoute: typeof ClerkauthRouteRoute\n    }\n    '/_authenticated/settings/notifications': {\n      id: '/_authenticated/settings/notifications'\n      path: '/notifications'\n      fullPath: '/settings/notifications'\n      preLoaderRoute: typeof AuthenticatedSettingsNotificationsRouteImport\n      parentRoute: typeof AuthenticatedSettingsRouteRoute\n    }\n    '/_authenticated/settings/display': {\n      id: '/_authenticated/settings/display'\n      path: '/display'\n      fullPath: '/settings/display'\n      preLoaderRoute: typeof AuthenticatedSettingsDisplayRouteImport\n      parentRoute: typeof AuthenticatedSettingsRouteRoute\n    }\n    '/_authenticated/settings/appearance': {\n      id: '/_authenticated/settings/appearance'\n      path: '/appearance'\n      fullPath: '/settings/appearance'\n      preLoaderRoute: typeof AuthenticatedSettingsAppearanceRouteImport\n      parentRoute: typeof AuthenticatedSettingsRouteRoute\n    }\n    '/_authenticated/settings/account': {\n      id: '/_authenticated/settings/account'\n      path: '/account'\n      fullPath: '/settings/account'\n      preLoaderRoute: typeof AuthenticatedSettingsAccountRouteImport\n      parentRoute: typeof AuthenticatedSettingsRouteRoute\n    }\n    '/_authenticated/errors/$error': {\n      id: '/_authenticated/errors/$error'\n      path: '/errors/$error'\n      fullPath: '/errors/$error'\n      preLoaderRoute: typeof AuthenticatedErrorsErrorRouteImport\n      parentRoute: typeof AuthenticatedRouteRoute\n    }\n  }\n}\n\ninterface AuthenticatedSettingsRouteRouteChildren {\n  AuthenticatedSettingsAccountRoute: typeof AuthenticatedSettingsAccountRoute\n  AuthenticatedSettingsAppearanceRoute: typeof AuthenticatedSettingsAppearanceRoute\n  AuthenticatedSettingsDisplayRoute: typeof AuthenticatedSettingsDisplayRoute\n  AuthenticatedSettingsNotificationsRoute: typeof AuthenticatedSettingsNotificationsRoute\n  AuthenticatedSettingsIndexRoute: typeof AuthenticatedSettingsIndexRoute\n}\n\nconst AuthenticatedSettingsRouteRouteChildren: AuthenticatedSettingsRouteRouteChildren =\n  {\n    AuthenticatedSettingsAccountRoute: AuthenticatedSettingsAccountRoute,\n    AuthenticatedSettingsAppearanceRoute: AuthenticatedSettingsAppearanceRoute,\n    AuthenticatedSettingsDisplayRoute: AuthenticatedSettingsDisplayRoute,\n    AuthenticatedSettingsNotificationsRoute:\n      AuthenticatedSettingsNotificationsRoute,\n    AuthenticatedSettingsIndexRoute: AuthenticatedSettingsIndexRoute,\n  }\n\nconst AuthenticatedSettingsRouteRouteWithChildren =\n  AuthenticatedSettingsRouteRoute._addFileChildren(\n    AuthenticatedSettingsRouteRouteChildren,\n  )\n\ninterface AuthenticatedRouteRouteChildren {\n  AuthenticatedSettingsRouteRoute: typeof AuthenticatedSettingsRouteRouteWithChildren\n  AuthenticatedIndexRoute: typeof AuthenticatedIndexRoute\n  AuthenticatedErrorsErrorRoute: typeof AuthenticatedErrorsErrorRoute\n  AuthenticatedAppsIndexRoute: typeof AuthenticatedAppsIndexRoute\n  AuthenticatedChatsIndexRoute: typeof AuthenticatedChatsIndexRoute\n  AuthenticatedHelpCenterIndexRoute: typeof AuthenticatedHelpCenterIndexRoute\n  AuthenticatedTasksIndexRoute: typeof AuthenticatedTasksIndexRoute\n  AuthenticatedUsersIndexRoute: typeof AuthenticatedUsersIndexRoute\n}\n\nconst AuthenticatedRouteRouteChildren: AuthenticatedRouteRouteChildren = {\n  AuthenticatedSettingsRouteRoute: AuthenticatedSettingsRouteRouteWithChildren,\n  AuthenticatedIndexRoute: AuthenticatedIndexRoute,\n  AuthenticatedErrorsErrorRoute: AuthenticatedErrorsErrorRoute,\n  AuthenticatedAppsIndexRoute: AuthenticatedAppsIndexRoute,\n  AuthenticatedChatsIndexRoute: AuthenticatedChatsIndexRoute,\n  AuthenticatedHelpCenterIndexRoute: AuthenticatedHelpCenterIndexRoute,\n  AuthenticatedTasksIndexRoute: AuthenticatedTasksIndexRoute,\n  AuthenticatedUsersIndexRoute: AuthenticatedUsersIndexRoute,\n}\n\nconst AuthenticatedRouteRouteWithChildren =\n  AuthenticatedRouteRoute._addFileChildren(AuthenticatedRouteRouteChildren)\n\ninterface ClerkauthRouteRouteChildren {\n  ClerkauthSignInRoute: typeof ClerkauthSignInRoute\n  ClerkauthSignUpRoute: typeof ClerkauthSignUpRoute\n}\n\nconst ClerkauthRouteRouteChildren: ClerkauthRouteRouteChildren = {\n  ClerkauthSignInRoute: ClerkauthSignInRoute,\n  ClerkauthSignUpRoute: ClerkauthSignUpRoute,\n}\n\nconst ClerkauthRouteRouteWithChildren = ClerkauthRouteRoute._addFileChildren(\n  ClerkauthRouteRouteChildren,\n)\n\ninterface ClerkAuthenticatedRouteRouteChildren {\n  ClerkAuthenticatedUserManagementRoute: typeof ClerkAuthenticatedUserManagementRoute\n}\n\nconst ClerkAuthenticatedRouteRouteChildren: ClerkAuthenticatedRouteRouteChildren =\n  {\n    ClerkAuthenticatedUserManagementRoute:\n      ClerkAuthenticatedUserManagementRoute,\n  }\n\nconst ClerkAuthenticatedRouteRouteWithChildren =\n  ClerkAuthenticatedRouteRoute._addFileChildren(\n    ClerkAuthenticatedRouteRouteChildren,\n  )\n\ninterface ClerkRouteRouteChildren {\n  ClerkauthRouteRoute: typeof ClerkauthRouteRouteWithChildren\n  ClerkAuthenticatedRouteRoute: typeof ClerkAuthenticatedRouteRouteWithChildren\n}\n\nconst ClerkRouteRouteChildren: ClerkRouteRouteChildren = {\n  ClerkauthRouteRoute: ClerkauthRouteRouteWithChildren,\n  ClerkAuthenticatedRouteRoute: ClerkAuthenticatedRouteRouteWithChildren,\n}\n\nconst ClerkRouteRouteWithChildren = ClerkRouteRoute._addFileChildren(\n  ClerkRouteRouteChildren,\n)\n\nconst rootRouteChildren: RootRouteChildren = {\n  AuthenticatedRouteRoute: AuthenticatedRouteRouteWithChildren,\n  ClerkRouteRoute: ClerkRouteRouteWithChildren,\n  authForgotPasswordRoute: authForgotPasswordRoute,\n  authOtpRoute: authOtpRoute,\n  authSignInRoute: authSignInRoute,\n  authSignIn2Route: authSignIn2Route,\n  authSignUpRoute: authSignUpRoute,\n  errors401Route: errors401Route,\n  errors403Route: errors403Route,\n  errors404Route: errors404Route,\n  errors500Route: errors500Route,\n  errors503Route: errors503Route,\n}\nexport const routeTree = rootRouteImport\n  ._addFileChildren(rootRouteChildren)\n  ._addFileTypes<FileRouteTypes>()\n"
  },
  {
    "path": "src/routes/(auth)/forgot-password.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { ForgotPassword } from '@/features/auth/forgot-password'\n\nexport const Route = createFileRoute('/(auth)/forgot-password')({\n  component: ForgotPassword,\n})\n"
  },
  {
    "path": "src/routes/(auth)/otp.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { Otp } from '@/features/auth/otp'\n\nexport const Route = createFileRoute('/(auth)/otp')({\n  component: Otp,\n})\n"
  },
  {
    "path": "src/routes/(auth)/sign-in-2.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SignIn2 } from '@/features/auth/sign-in/sign-in-2'\n\nexport const Route = createFileRoute('/(auth)/sign-in-2')({\n  component: SignIn2,\n})\n"
  },
  {
    "path": "src/routes/(auth)/sign-in.tsx",
    "content": "import { z } from 'zod'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { SignIn } from '@/features/auth/sign-in'\n\nconst searchSchema = z.object({\n  redirect: z.string().optional(),\n})\n\nexport const Route = createFileRoute('/(auth)/sign-in')({\n  component: SignIn,\n  validateSearch: searchSchema,\n})\n"
  },
  {
    "path": "src/routes/(auth)/sign-up.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SignUp } from '@/features/auth/sign-up'\n\nexport const Route = createFileRoute('/(auth)/sign-up')({\n  component: SignUp,\n})\n"
  },
  {
    "path": "src/routes/(errors)/401.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { UnauthorisedError } from '@/features/errors/unauthorized-error'\n\nexport const Route = createFileRoute('/(errors)/401')({\n  component: UnauthorisedError,\n})\n"
  },
  {
    "path": "src/routes/(errors)/403.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { ForbiddenError } from '@/features/errors/forbidden'\n\nexport const Route = createFileRoute('/(errors)/403')({\n  component: ForbiddenError,\n})\n"
  },
  {
    "path": "src/routes/(errors)/404.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { NotFoundError } from '@/features/errors/not-found-error'\n\nexport const Route = createFileRoute('/(errors)/404')({\n  component: NotFoundError,\n})\n"
  },
  {
    "path": "src/routes/(errors)/500.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { GeneralError } from '@/features/errors/general-error'\n\nexport const Route = createFileRoute('/(errors)/500')({\n  component: GeneralError,\n})\n"
  },
  {
    "path": "src/routes/(errors)/503.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { MaintenanceError } from '@/features/errors/maintenance-error'\n\nexport const Route = createFileRoute('/(errors)/503')({\n  component: MaintenanceError,\n})\n"
  },
  {
    "path": "src/routes/__root.tsx",
    "content": "import { type QueryClient } from '@tanstack/react-query'\nimport { createRootRouteWithContext, Outlet } from '@tanstack/react-router'\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\nimport { Toaster } from '@/components/ui/sonner'\nimport { NavigationProgress } from '@/components/navigation-progress'\nimport { GeneralError } from '@/features/errors/general-error'\nimport { NotFoundError } from '@/features/errors/not-found-error'\n\nexport const Route = createRootRouteWithContext<{\n  queryClient: QueryClient\n}>()({\n  component: () => {\n    return (\n      <>\n        <NavigationProgress />\n        <Outlet />\n        <Toaster duration={5000} />\n        {import.meta.env.MODE === 'development' && (\n          <>\n            <ReactQueryDevtools buttonPosition='bottom-left' />\n            <TanStackRouterDevtools position='bottom-right' />\n          </>\n        )}\n      </>\n    )\n  },\n  notFoundComponent: NotFoundError,\n  errorComponent: GeneralError,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/apps/index.tsx",
    "content": "import z from 'zod'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { Apps } from '@/features/apps'\n\nconst appsSearchSchema = z.object({\n  type: z\n    .enum(['all', 'connected', 'notConnected'])\n    .optional()\n    .catch(undefined),\n  filter: z.string().optional().catch(''),\n  sort: z.enum(['asc', 'desc']).optional().catch(undefined),\n})\n\nexport const Route = createFileRoute('/_authenticated/apps/')({\n  validateSearch: appsSearchSchema,\n  component: Apps,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/chats/index.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { Chats } from '@/features/chats'\n\nexport const Route = createFileRoute('/_authenticated/chats/')({\n  component: Chats,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/errors/$error.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { ProfileDropdown } from '@/components/profile-dropdown'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { ForbiddenError } from '@/features/errors/forbidden'\nimport { GeneralError } from '@/features/errors/general-error'\nimport { MaintenanceError } from '@/features/errors/maintenance-error'\nimport { NotFoundError } from '@/features/errors/not-found-error'\nimport { UnauthorisedError } from '@/features/errors/unauthorized-error'\n\nexport const Route = createFileRoute('/_authenticated/errors/$error')({\n  component: RouteComponent,\n})\n\n// eslint-disable-next-line react-refresh/only-export-components\nfunction RouteComponent() {\n  const { error } = Route.useParams()\n\n  const errorMap: Record<string, React.ComponentType> = {\n    unauthorized: UnauthorisedError,\n    forbidden: ForbiddenError,\n    'not-found': NotFoundError,\n    'internal-server-error': GeneralError,\n    'maintenance-error': MaintenanceError,\n  }\n  const ErrorComponent = errorMap[error] || NotFoundError\n\n  return (\n    <>\n      <Header fixed className='border-b'>\n        <Search />\n        <div className='ms-auto flex items-center space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n          <ProfileDropdown />\n        </div>\n      </Header>\n      <div className='flex-1 [&>div]:h-full'>\n        <ErrorComponent />\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/routes/_authenticated/help-center/index.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { ComingSoon } from '@/components/coming-soon'\n\nexport const Route = createFileRoute('/_authenticated/help-center/')({\n  component: ComingSoon,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/index.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { Dashboard } from '@/features/dashboard'\n\nexport const Route = createFileRoute('/_authenticated/')({\n  component: Dashboard,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/route.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { AuthenticatedLayout } from '@/components/layout/authenticated-layout'\n\nexport const Route = createFileRoute('/_authenticated')({\n  component: AuthenticatedLayout,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/account.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SettingsAccount } from '@/features/settings/account'\n\nexport const Route = createFileRoute('/_authenticated/settings/account')({\n  component: SettingsAccount,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/appearance.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SettingsAppearance } from '@/features/settings/appearance'\n\nexport const Route = createFileRoute('/_authenticated/settings/appearance')({\n  component: SettingsAppearance,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/display.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SettingsDisplay } from '@/features/settings/display'\n\nexport const Route = createFileRoute('/_authenticated/settings/display')({\n  component: SettingsDisplay,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/index.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SettingsProfile } from '@/features/settings/profile'\n\nexport const Route = createFileRoute('/_authenticated/settings/')({\n  component: SettingsProfile,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/notifications.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SettingsNotifications } from '@/features/settings/notifications'\n\nexport const Route = createFileRoute('/_authenticated/settings/notifications')({\n  component: SettingsNotifications,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/settings/route.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { Settings } from '@/features/settings'\n\nexport const Route = createFileRoute('/_authenticated/settings')({\n  component: Settings,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/tasks/index.tsx",
    "content": "import z from 'zod'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { Tasks } from '@/features/tasks'\nimport { priorities, statuses } from '@/features/tasks/data/data'\n\nconst taskSearchSchema = z.object({\n  page: z.number().optional().catch(1),\n  pageSize: z.number().optional().catch(10),\n  status: z\n    .array(z.enum(statuses.map((status) => status.value)))\n    .optional()\n    .catch([]),\n  priority: z\n    .array(z.enum(priorities.map((priority) => priority.value)))\n    .optional()\n    .catch([]),\n  filter: z.string().optional().catch(''),\n})\n\nexport const Route = createFileRoute('/_authenticated/tasks/')({\n  validateSearch: taskSearchSchema,\n  component: Tasks,\n})\n"
  },
  {
    "path": "src/routes/_authenticated/users/index.tsx",
    "content": "import z from 'zod'\nimport { createFileRoute } from '@tanstack/react-router'\nimport { Users } from '@/features/users'\nimport { roles } from '@/features/users/data/data'\n\nconst usersSearchSchema = z.object({\n  page: z.number().optional().catch(1),\n  pageSize: z.number().optional().catch(10),\n  // Facet filters\n  status: z\n    .array(\n      z.union([\n        z.literal('active'),\n        z.literal('inactive'),\n        z.literal('invited'),\n        z.literal('suspended'),\n      ])\n    )\n    .optional()\n    .catch([]),\n  role: z\n    .array(z.enum(roles.map((r) => r.value as (typeof roles)[number]['value'])))\n    .optional()\n    .catch([]),\n  // Per-column text filter (example for username)\n  username: z.string().optional().catch(''),\n})\n\nexport const Route = createFileRoute('/_authenticated/users/')({\n  validateSearch: usersSearchSchema,\n  component: Users,\n})\n"
  },
  {
    "path": "src/routes/clerk/(auth)/route.tsx",
    "content": "import { createFileRoute, Link, Outlet } from '@tanstack/react-router'\nimport { ClerkFullLogo } from '@/assets/clerk-full-logo'\nimport { Logo } from '@/assets/logo'\nimport { LearnMore } from '@/components/learn-more'\n\nexport const Route = createFileRoute('/clerk/(auth)')({\n  component: ClerkAuthLayout,\n})\n\n// eslint-disable-next-line react-refresh/only-export-components\nfunction ClerkAuthLayout() {\n  return (\n    <div className='relative container grid h-svh flex-col items-center justify-center lg:max-w-none lg:grid-cols-2 lg:px-0'>\n      <div className='relative hidden h-full flex-col bg-muted p-10 text-white lg:flex dark:border-e'>\n        <div className='absolute inset-0 bg-slate-500' />\n        <Link\n          to='/'\n          className='relative z-20 flex items-center text-lg font-medium'\n        >\n          <Logo className='me-2' />\n          Shadcn Admin\n        </Link>\n\n        <ClerkFullLogo className='relative m-auto size-96' />\n\n        <div className='relative z-20 mt-auto'>\n          <blockquote className='space-y-2'>\n            <p className='text-lg'>\n              &ldquo; Lorem ipsum dolor sit amet consectetur adipisicing elit.\n              Sint, magni debitis inventore asperiores velit! &rdquo;\n            </p>\n            <footer className='text-sm'>John Doe</footer>\n          </blockquote>\n        </div>\n      </div>\n      <div className='lg:p-8'>\n        <div className='relative mx-auto flex w-full flex-col items-center justify-center gap-4'>\n          <LearnMore\n            defaultOpen\n            triggerProps={{\n              className: 'absolute -top-12 end-0 sm:end-20 size-6',\n            }}\n            contentProps={{ side: 'top', align: 'end', className: 'w-auto' }}\n          >\n            Welcome to the example Clerk auth page. <br />\n            Back to{' '}\n            <Link\n              to='/'\n              className='underline decoration-dashed underline-offset-2'\n            >\n              Dashboard\n            </Link>{' '}\n            ?\n          </LearnMore>\n          <Outlet />\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/routes/clerk/(auth)/sign-in.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SignIn } from '@clerk/clerk-react'\nimport { Skeleton } from '@/components/ui/skeleton'\n\nexport const Route = createFileRoute('/clerk/(auth)/sign-in')({\n  component: () => (\n    <SignIn\n      initialValues={{\n        emailAddress: 'your_mail+shadcn_admin@gmail.com',\n      }}\n      fallback={<Skeleton className='h-[30rem] w-[25rem]' />}\n    />\n  ),\n})\n"
  },
  {
    "path": "src/routes/clerk/(auth)/sign-up.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { SignUp } from '@clerk/clerk-react'\nimport { Skeleton } from '@/components/ui/skeleton'\n\nexport const Route = createFileRoute('/clerk/(auth)/sign-up')({\n  component: () => (\n    <SignUp fallback={<Skeleton className='h-[30rem] w-[25rem]' />} />\n  ),\n})\n"
  },
  {
    "path": "src/routes/clerk/_authenticated/route.tsx",
    "content": "import { createFileRoute } from '@tanstack/react-router'\nimport { AuthenticatedLayout } from '@/components/layout/authenticated-layout'\n\nexport const Route = createFileRoute('/clerk/_authenticated')({\n  component: AuthenticatedLayout,\n})\n"
  },
  {
    "path": "src/routes/clerk/_authenticated/user-management.tsx",
    "content": "/* eslint-disable react-refresh/only-export-components */\nimport { useEffect, useState } from 'react'\nimport {\n  createFileRoute,\n  Link,\n  useNavigate,\n  useRouter,\n} from '@tanstack/react-router'\nimport { SignedIn, useAuth, UserButton } from '@clerk/clerk-react'\nimport { ExternalLink, Loader2 } from 'lucide-react'\nimport { ClerkLogo } from '@/assets/clerk-logo'\nimport { Button } from '@/components/ui/button'\nimport { Header } from '@/components/layout/header'\nimport { Main } from '@/components/layout/main'\nimport { LearnMore } from '@/components/learn-more'\nimport { Search } from '@/components/search'\nimport { ThemeSwitch } from '@/components/theme-switch'\nimport { UsersDialogs } from '@/features/users/components/users-dialogs'\nimport { UsersPrimaryButtons } from '@/features/users/components/users-primary-buttons'\nimport { UsersProvider } from '@/features/users/components/users-provider'\nimport { UsersTable } from '@/features/users/components/users-table'\nimport { users } from '@/features/users/data/users'\n\nexport const Route = createFileRoute('/clerk/_authenticated/user-management')({\n  component: UserManagement,\n})\n\nfunction UserManagement() {\n  const search = Route.useSearch()\n  const navigate = Route.useNavigate()\n\n  const [opened, setOpened] = useState(true)\n  const { isLoaded, isSignedIn } = useAuth()\n\n  if (!isLoaded) {\n    return (\n      <div className='flex h-svh items-center justify-center'>\n        <Loader2 className='size-8 animate-spin' />\n      </div>\n    )\n  }\n\n  if (!isSignedIn) {\n    return <Unauthorized />\n  }\n\n  return (\n    <>\n      <SignedIn>\n        <UsersProvider>\n          <Header fixed>\n            <Search />\n            <div className='ms-auto flex items-center space-x-4'>\n              <ThemeSwitch />\n              <UserButton />\n            </div>\n          </Header>\n\n          <Main>\n            <div className='mb-2 flex flex-wrap items-center justify-between space-y-2'>\n              <div>\n                <h2 className='text-2xl font-bold tracking-tight'>User List</h2>\n                <div className='flex gap-1'>\n                  <p className='text-muted-foreground'>\n                    Manage your users and their roles here.\n                  </p>\n                  <LearnMore\n                    open={opened}\n                    onOpenChange={setOpened}\n                    contentProps={{ side: 'right' }}\n                  >\n                    <p>\n                      This is the same as{' '}\n                      <Link\n                        to='/users'\n                        className='text-blue-500 underline decoration-dashed underline-offset-2'\n                      >\n                        '/users'\n                      </Link>\n                    </p>\n\n                    <p className='mt-4'>\n                      You can sign out or manage/delete your account via the\n                      User Profile menu in the top-right corner of the page.\n                      <ExternalLink className='inline-block size-4' />\n                    </p>\n                  </LearnMore>\n                </div>\n              </div>\n              <UsersPrimaryButtons />\n            </div>\n            <div className='-mx-4 flex-1 overflow-auto px-4 py-1 lg:flex-row lg:space-y-0 lg:space-x-12'>\n              <UsersTable data={users} navigate={navigate} search={search} />\n            </div>\n          </Main>\n\n          <UsersDialogs />\n        </UsersProvider>\n      </SignedIn>\n    </>\n  )\n}\n\nconst COUNTDOWN = 5 // Countdown second\n\nfunction Unauthorized() {\n  const navigate = useNavigate()\n  const { history } = useRouter()\n\n  const [opened, setOpened] = useState(true)\n  const [cancelled, setCancelled] = useState(false)\n  const [countdown, setCountdown] = useState(COUNTDOWN)\n\n  // Set and run the countdown conditionally\n  useEffect(() => {\n    if (cancelled || opened) return\n    const interval = setInterval(() => {\n      setCountdown((prev) => (prev > 0 ? prev - 1 : 0))\n    }, 1000)\n    return () => clearInterval(interval)\n  }, [cancelled, opened])\n\n  // Navigate to sign-in page when countdown hits 0\n  useEffect(() => {\n    if (countdown > 0) return\n    navigate({ to: '/clerk/sign-in' })\n  }, [countdown, navigate])\n\n  return (\n    <div className='h-svh'>\n      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>\n        <h1 className='text-[7rem] leading-tight font-bold'>401</h1>\n        <span className='font-medium'>Unauthorized Access</span>\n        <p className='text-center text-muted-foreground'>\n          You must be authenticated via Clerk{' '}\n          <sup>\n            <LearnMore open={opened} onOpenChange={setOpened}>\n              <p>\n                This is the same as{' '}\n                <Link\n                  to='/users'\n                  className='text-blue-500 underline decoration-dashed underline-offset-2'\n                >\n                  '/users'\n                </Link>\n                .{' '}\n              </p>\n              <p>You must first sign in using Clerk to access this route. </p>\n\n              <p className='mt-4'>\n                After signing in, you'll be able to sign out or delete your\n                account via the User Profile dropdown on this page.\n              </p>\n            </LearnMore>\n          </sup>\n          <br />\n          to access this resource.\n        </p>\n        <div className='mt-6 flex gap-4'>\n          <Button variant='outline' onClick={() => history.go(-1)}>\n            Go Back\n          </Button>\n          <Button onClick={() => navigate({ to: '/clerk/sign-in' })}>\n            <ClerkLogo className='invert' /> Sign in\n          </Button>\n        </div>\n        <div className='mt-4 h-8 text-center'>\n          {!cancelled && !opened && (\n            <>\n              <p>\n                {countdown > 0\n                  ? `Redirecting to Sign In page in ${countdown}s`\n                  : `Redirecting...`}\n              </p>\n              <Button variant='link' onClick={() => setCancelled(true)}>\n                Cancel Redirect\n              </Button>\n            </>\n          )}\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/routes/clerk/route.tsx",
    "content": "/* eslint-disable react-refresh/only-export-components */\nimport { createFileRoute, Outlet } from '@tanstack/react-router'\nimport { ClerkProvider } from '@clerk/clerk-react'\nimport { ExternalLink, Key } from 'lucide-react'\nimport { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'\nimport { Separator } from '@/components/ui/separator'\nimport { SidebarTrigger } from '@/components/ui/sidebar'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { AuthenticatedLayout } from '@/components/layout/authenticated-layout'\nimport { Main } from '@/components/layout/main'\nimport { ThemeSwitch } from '@/components/theme-switch'\n\nexport const Route = createFileRoute('/clerk')({\n  component: RouteComponent,\n})\n\n// Import your Publishable Key\nconst PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY\n\nfunction RouteComponent() {\n  if (!PUBLISHABLE_KEY) {\n    return <MissingClerkPubKey />\n  }\n\n  return (\n    <ClerkProvider\n      publishableKey={PUBLISHABLE_KEY}\n      afterSignOutUrl='/clerk/sign-in'\n      signInUrl='/clerk/sign-in'\n      signUpUrl='/clerk/sign-up'\n      signInFallbackRedirectUrl='/clerk/user-management'\n      signUpFallbackRedirectUrl='/clerk/user-management'\n    >\n      <Outlet />\n    </ClerkProvider>\n  )\n}\n\nfunction MissingClerkPubKey() {\n  const codeBlock =\n    'bg-foreground/10 rounded-sm py-0.5 px-1 text-xs text-foreground font-bold'\n  return (\n    <AuthenticatedLayout>\n      <div className='bg-backgroundh-16 flex justify-between p-4'>\n        <SidebarTrigger variant='outline' className='scale-125 sm:scale-100' />\n        <div className='space-x-4'>\n          <ThemeSwitch />\n          <ConfigDrawer />\n        </div>\n      </div>\n      <Main className='flex flex-col items-center justify-start'>\n        <div className='max-w-2xl'>\n          <Alert>\n            <Key className='size-4' />\n            <AlertTitle>No Publishable Key Found!</AlertTitle>\n            <AlertDescription>\n              <p className='text-balance'>\n                You need to generate a publishable key from Clerk and put it\n                inside the <code className={codeBlock}>.env</code> file.\n              </p>\n            </AlertDescription>\n          </Alert>\n\n          <h1 className='mt-4 text-2xl font-bold'>Set your Clerk API key</h1>\n          <div className='mt-4 flex flex-col gap-y-4 text-foreground/75'>\n            <ol className='list-inside list-decimal space-y-1.5'>\n              <li>\n                In the{' '}\n                <a\n                  href='https://go.clerk.com/GttUAaK'\n                  target='_blank'\n                  className='underline decoration-dashed underline-offset-4 hover:decoration-solid'\n                >\n                  Clerk\n                  <sup>\n                    <ExternalLink className='inline-block size-4' />\n                  </sup>\n                </a>{' '}\n                Dashboard, navigate to the API keys page.\n              </li>\n              <li>\n                In the <strong>Quick Copy</strong> section, copy your Clerk\n                Publishable Key.\n              </li>\n              <li>\n                Rename <code className={codeBlock}>.env.example</code> to{' '}\n                <code className={codeBlock}>.env</code>\n              </li>\n              <li>\n                Paste your key into your <code className={codeBlock}>.env</code>{' '}\n                file.\n              </li>\n            </ol>\n            <p>The final result should resemble the following:</p>\n\n            <div className='@container space-y-2 rounded-md bg-slate-800 px-3 py-3 text-sm text-slate-200'>\n              <span className='ps-1'>.env</span>\n              <pre className='overflow-auto overscroll-x-contain rounded bg-slate-950 px-2 py-1 text-xs'>\n                <code>\n                  <span className='before:text-slate-400 md:before:pe-2 md:before:content-[\"1.\"]'>\n                    VITE_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY\n                  </span>\n                </code>\n              </pre>\n            </div>\n          </div>\n\n          <Separator className='my-4 w-full' />\n\n          <Alert>\n            <AlertTitle>Clerk Integration is Optional</AlertTitle>\n            <AlertDescription>\n              <p className='text-balance'>\n                The Clerk integration lives entirely inside{' '}\n                <code className={codeBlock}>src/routes/clerk</code>. If you plan\n                to use Clerk as your auth service, you might want to place{' '}\n                <code className={codeBlock}>ClerkProvider</code> at the root\n                route.\n              </p>\n              <p>\n                However, if you don't plan to use Clerk, you can safely remove\n                this directory and related dependency_{' '}\n                <code className={codeBlock}>@clerk/clerk-react</code>.\n              </p>\n              <p className='mt-2 text-sm'>\n                This setup is modular by design and won't affect the rest of the\n                application.\n              </p>\n            </AlertDescription>\n          </Alert>\n        </div>\n      </Main>\n    </AuthenticatedLayout>\n  )\n}\n"
  },
  {
    "path": "src/stores/auth-store.ts",
    "content": "import { create } from 'zustand'\nimport { getCookie, setCookie, removeCookie } from '@/lib/cookies'\n\nconst ACCESS_TOKEN = 'thisisjustarandomstring'\n\ninterface AuthUser {\n  accountNo: string\n  email: string\n  role: string[]\n  exp: number\n}\n\ninterface AuthState {\n  auth: {\n    user: AuthUser | null\n    setUser: (user: AuthUser | null) => void\n    accessToken: string\n    setAccessToken: (accessToken: string) => void\n    resetAccessToken: () => void\n    reset: () => void\n  }\n}\n\nexport const useAuthStore = create<AuthState>()((set) => {\n  const cookieState = getCookie(ACCESS_TOKEN)\n  const initToken = cookieState ? JSON.parse(cookieState) : ''\n  return {\n    auth: {\n      user: null,\n      setUser: (user) =>\n        set((state) => ({ ...state, auth: { ...state.auth, user } })),\n      accessToken: initToken,\n      setAccessToken: (accessToken) =>\n        set((state) => {\n          setCookie(ACCESS_TOKEN, JSON.stringify(accessToken))\n          return { ...state, auth: { ...state.auth, accessToken } }\n        }),\n      resetAccessToken: () =>\n        set((state) => {\n          removeCookie(ACCESS_TOKEN)\n          return { ...state, auth: { ...state.auth, accessToken: '' } }\n        }),\n      reset: () =>\n        set((state) => {\n          removeCookie(ACCESS_TOKEN)\n          return {\n            ...state,\n            auth: { ...state.auth, user: null, accessToken: '' },\n          }\n        }),\n    },\n  }\n})\n"
  },
  {
    "path": "src/styles/index.css",
    "content": "@import 'tailwindcss';\n@import 'tw-animate-css';\n@import './theme.css';\n\n@custom-variant dark (&:is(.dark *));\n\n@layer base {\n  * {\n    @apply border-border outline-ring/50;\n    scrollbar-width: thin;\n    scrollbar-color: var(--border) transparent;\n  }\n  html {\n    @apply overflow-x-hidden;\n  }\n  body {\n    @apply min-h-svh w-full bg-background text-foreground has-[div[data-variant='inset']]:bg-sidebar;\n  }\n\n  /* Override Radix scroll locking for sticky headers */\n  body[data-scroll-locked] {\n    overflow: unset !important;\n  }\n\n  /* Cursor pointer for buttons */\n  button:not(:disabled),\n  [role='button']:not(:disabled) {\n    cursor: pointer;\n  }\n\n  /* Prevent focus zoom on mobile devices */\n  @media screen and (max-width: 767px) {\n    input,\n    select,\n    textarea {\n      font-size: 16px !important;\n    }\n  }\n}\n\n@utility container {\n  margin-inline: auto;\n  padding-inline: 2rem;\n}\n\n@utility no-scrollbar {\n  /* Hide scrollbar for Chrome, Safari and Opera */\n  &::-webkit-scrollbar {\n    display: none;\n  }\n  /* Hide scrollbar for IE, Edge and Firefox */\n  -ms-overflow-style: none; /* IE and Edge */\n  scrollbar-width: none; /* Firefox */\n}\n\n@utility faded-bottom {\n  @apply after:pointer-events-none after:absolute after:start-0 after:bottom-0 after:hidden after:h-32 after:w-full after:rounded-b-2xl after:bg-[linear-gradient(180deg,transparent_10%,var(--background)_70%)] md:after:block;\n}\n\n/* styles.css */\n.CollapsibleContent {\n  overflow: hidden;\n}\n.CollapsibleContent[data-state='open'] {\n  animation: slideDown 300ms ease-out;\n}\n.CollapsibleContent[data-state='closed'] {\n  animation: slideUp 300ms ease-out;\n}\n\n@keyframes slideDown {\n  from {\n    height: 0;\n  }\n  to {\n    height: var(--radix-collapsible-content-height);\n  }\n}\n\n@keyframes slideUp {\n  from {\n    height: var(--radix-collapsible-content-height);\n  }\n  to {\n    height: 0;\n  }\n}\n"
  },
  {
    "path": "src/styles/theme.css",
    "content": ":root {\n  --radius: 0.625rem;\n  --background: oklch(1 0 0);\n  --foreground: oklch(0.129 0.042 264.695);\n  --card: oklch(1 0 0);\n  --card-foreground: oklch(0.129 0.042 264.695);\n  --popover: oklch(1 0 0);\n  --popover-foreground: oklch(0.129 0.042 264.695);\n  --primary: oklch(0.208 0.042 265.755);\n  --primary-foreground: oklch(0.984 0.003 247.858);\n  --secondary: oklch(0.968 0.007 247.896);\n  --secondary-foreground: oklch(0.208 0.042 265.755);\n  --muted: oklch(0.968 0.007 247.896);\n  --muted-foreground: oklch(0.554 0.046 257.417);\n  --accent: oklch(0.968 0.007 247.896);\n  --accent-foreground: oklch(0.208 0.042 265.755);\n  --destructive: oklch(0.577 0.245 27.325);\n  --border: oklch(0.929 0.013 255.508);\n  --input: oklch(0.929 0.013 255.508);\n  --ring: oklch(0.704 0.04 256.788);\n  --chart-1: oklch(0.646 0.222 41.116);\n  --chart-2: oklch(0.6 0.118 184.704);\n  --chart-3: oklch(0.398 0.07 227.392);\n  --chart-4: oklch(0.828 0.189 84.429);\n  --chart-5: oklch(0.769 0.188 70.08);\n\n  --sidebar: var(--background);\n  --sidebar-foreground: var(--foreground);\n  --sidebar-primary: var(--primary);\n  --sidebar-primary-foreground: var(--primary-foreground);\n  --sidebar-accent: var(--accent);\n  --sidebar-accent-foreground: var(--accent-foreground);\n  --sidebar-border: var(--border);\n  --sidebar-ring: var(--ring);\n}\n\n.dark {\n  --background: oklch(0.129 0.042 264.695);\n  --foreground: oklch(0.984 0.003 247.858);\n  --card: oklch(0.14 0.04 259.21);\n  --card-foreground: oklch(0.984 0.003 247.858);\n  --popover: oklch(0.208 0.042 265.755);\n  --popover-foreground: oklch(0.984 0.003 247.858);\n  --primary: oklch(0.929 0.013 255.508);\n  --primary-foreground: oklch(0.208 0.042 265.755);\n  --secondary: oklch(0.279 0.041 260.031);\n  --secondary-foreground: oklch(0.984 0.003 247.858);\n  --muted: oklch(0.279 0.041 260.031);\n  --muted-foreground: oklch(0.704 0.04 256.788);\n  --accent: oklch(0.279 0.041 260.031);\n  --accent-foreground: oklch(0.984 0.003 247.858);\n  --destructive: oklch(0.704 0.191 22.216);\n  --border: oklch(1 0 0 / 10%);\n  --input: oklch(1 0 0 / 15%);\n  --ring: oklch(0.551 0.027 264.364);\n  --chart-1: oklch(0.488 0.243 264.376);\n  --chart-2: oklch(0.696 0.17 162.48);\n  --chart-3: oklch(0.769 0.188 70.08);\n  --chart-4: oklch(0.627 0.265 303.9);\n  --chart-5: oklch(0.645 0.246 16.439);\n}\n\n@theme inline {\n  --font-inter: 'Inter', 'sans-serif';\n  --font-manrope: 'Manrope', 'sans-serif';\n\n  --radius-sm: calc(var(--radius) - 4px);\n  --radius-md: calc(var(--radius) - 2px);\n  --radius-lg: var(--radius);\n  --radius-xl: calc(var(--radius) + 4px);\n  --color-background: var(--background);\n  --color-foreground: var(--foreground);\n  --color-card: var(--card);\n  --color-card-foreground: var(--card-foreground);\n  --color-popover: var(--popover);\n  --color-popover-foreground: var(--popover-foreground);\n  --color-primary: var(--primary);\n  --color-primary-foreground: var(--primary-foreground);\n  --color-secondary: var(--secondary);\n  --color-secondary-foreground: var(--secondary-foreground);\n  --color-muted: var(--muted);\n  --color-muted-foreground: var(--muted-foreground);\n  --color-accent: var(--accent);\n  --color-accent-foreground: var(--accent-foreground);\n  --color-destructive: var(--destructive);\n  --color-border: var(--border);\n  --color-input: var(--input);\n  --color-ring: var(--ring);\n  --color-chart-1: var(--chart-1);\n  --color-chart-2: var(--chart-2);\n  --color-chart-3: var(--chart-3);\n  --color-chart-4: var(--chart-4);\n  --color-chart-5: var(--chart-5);\n  --color-sidebar: var(--sidebar);\n  --color-sidebar-foreground: var(--sidebar-foreground);\n  --color-sidebar-primary: var(--sidebar-primary);\n  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n  --color-sidebar-accent: var(--sidebar-accent);\n  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n  --color-sidebar-border: var(--sidebar-border);\n  --color-sidebar-ring: var(--sidebar-ring);\n}\n"
  },
  {
    "path": "src/tanstack-table.d.ts",
    "content": "import '@tanstack/react-table'\n\ndeclare module '@tanstack/react-table' {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  interface ColumnMeta<TData, TValue> {\n    className?: string // apply to both th and td\n    tdClassName?: string\n    thClassName?: string\n  }\n}\n"
  },
  {
    "path": "src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Alias */\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    },\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ],\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"Bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "vite.config.ts",
    "content": "import path from 'path'\nimport { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react-swc'\nimport tailwindcss from '@tailwindcss/vite'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [\n    tanstackRouter({\n      target: 'react',\n      autoCodeSplitting: true,\n    }),\n    react(),\n    tailwindcss(),\n  ],\n  resolve: {\n    alias: {\n      '@': path.resolve(__dirname, './src'),\n    },\n  },\n})\n"
  }
]