create-nala 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/index.js +227 -0
  4. package/package.json +48 -0
  5. package/template/.env.example +45 -0
  6. package/template/_gitignore +33 -0
  7. package/template/components.json +24 -0
  8. package/template/index.html +30 -0
  9. package/template/package.json +51 -0
  10. package/template/public/favicon.svg +15 -0
  11. package/template/public/icons.svg +24 -0
  12. package/template/public/img/avatar.webp +0 -0
  13. package/template/public/screenshot.png +0 -0
  14. package/template/src/App.vue +15 -0
  15. package/template/src/auto-imports.d.ts +691 -0
  16. package/template/src/components/AppLogo.vue +159 -0
  17. package/template/src/components/EmptyState.vue +60 -0
  18. package/template/src/components/PageHeader.vue +60 -0
  19. package/template/src/components/layout/AppNavbar.vue +159 -0
  20. package/template/src/components/layout/AppSidebar.vue +74 -0
  21. package/template/src/components/layout/CommandSearchDialog.vue +120 -0
  22. package/template/src/components/ui/accordion/Accordion.vue +15 -0
  23. package/template/src/components/ui/accordion/AccordionContent.vue +20 -0
  24. package/template/src/components/ui/accordion/AccordionItem.vue +20 -0
  25. package/template/src/components/ui/accordion/AccordionTrigger.vue +34 -0
  26. package/template/src/components/ui/accordion/index.ts +4 -0
  27. package/template/src/components/ui/alert/Alert.vue +21 -0
  28. package/template/src/components/ui/alert/AlertDescription.vue +17 -0
  29. package/template/src/components/ui/alert/AlertTitle.vue +17 -0
  30. package/template/src/components/ui/alert/index.ts +30 -0
  31. package/template/src/components/ui/alert-dialog/AlertDialog.vue +15 -0
  32. package/template/src/components/ui/alert-dialog/AlertDialogAction.vue +18 -0
  33. package/template/src/components/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  34. package/template/src/components/ui/alert-dialog/AlertDialogContent.vue +44 -0
  35. package/template/src/components/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  36. package/template/src/components/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  37. package/template/src/components/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  38. package/template/src/components/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  39. package/template/src/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  40. package/template/src/components/ui/alert-dialog/index.ts +9 -0
  41. package/template/src/components/ui/avatar/Avatar.vue +50 -0
  42. package/template/src/components/ui/avatar/AvatarFallback.vue +21 -0
  43. package/template/src/components/ui/avatar/AvatarGroup.vue +69 -0
  44. package/template/src/components/ui/avatar/AvatarImage.vue +16 -0
  45. package/template/src/components/ui/avatar/index.ts +4 -0
  46. package/template/src/components/ui/badge/Badge.vue +40 -0
  47. package/template/src/components/ui/badge/index.ts +45 -0
  48. package/template/src/components/ui/breadcrumb/Breadcrumb.vue +17 -0
  49. package/template/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  50. package/template/src/components/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  51. package/template/src/components/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  52. package/template/src/components/ui/breadcrumb/BreadcrumbList.vue +17 -0
  53. package/template/src/components/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  54. package/template/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  55. package/template/src/components/ui/breadcrumb/index.ts +7 -0
  56. package/template/src/components/ui/button/Button.spec.ts +46 -0
  57. package/template/src/components/ui/button/Button.vue +31 -0
  58. package/template/src/components/ui/button/index.ts +41 -0
  59. package/template/src/components/ui/calendar/Calendar.vue +106 -0
  60. package/template/src/components/ui/calendar/index.ts +1 -0
  61. package/template/src/components/ui/card/Card.vue +29 -0
  62. package/template/src/components/ui/card/CardAction.vue +17 -0
  63. package/template/src/components/ui/card/CardContent.vue +17 -0
  64. package/template/src/components/ui/card/CardDescription.vue +17 -0
  65. package/template/src/components/ui/card/CardFooter.vue +17 -0
  66. package/template/src/components/ui/card/CardHeader.vue +29 -0
  67. package/template/src/components/ui/card/CardTitle.vue +17 -0
  68. package/template/src/components/ui/card/index.ts +7 -0
  69. package/template/src/components/ui/chart/AreaChart.vue +143 -0
  70. package/template/src/components/ui/chart/BarChart.vue +142 -0
  71. package/template/src/components/ui/chart/DonutChart.vue +75 -0
  72. package/template/src/components/ui/chart/LineChart.vue +132 -0
  73. package/template/src/components/ui/chart/index.ts +4 -0
  74. package/template/src/components/ui/checkbox/Checkbox.vue +57 -0
  75. package/template/src/components/ui/checkbox/index.ts +1 -0
  76. package/template/src/components/ui/collapsible/Collapsible.vue +15 -0
  77. package/template/src/components/ui/collapsible/CollapsibleContent.vue +18 -0
  78. package/template/src/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
  79. package/template/src/components/ui/collapsible/index.ts +3 -0
  80. package/template/src/components/ui/command/Command.vue +88 -0
  81. package/template/src/components/ui/command/CommandDialog.vue +31 -0
  82. package/template/src/components/ui/command/CommandEmpty.vue +27 -0
  83. package/template/src/components/ui/command/CommandGroup.vue +45 -0
  84. package/template/src/components/ui/command/CommandInput.vue +39 -0
  85. package/template/src/components/ui/command/CommandItem.vue +76 -0
  86. package/template/src/components/ui/command/CommandList.vue +25 -0
  87. package/template/src/components/ui/command/CommandSeparator.vue +21 -0
  88. package/template/src/components/ui/command/CommandShortcut.vue +17 -0
  89. package/template/src/components/ui/command/index.ts +25 -0
  90. package/template/src/components/ui/context-menu/ContextMenu.vue +15 -0
  91. package/template/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +36 -0
  92. package/template/src/components/ui/context-menu/ContextMenuContent.vue +33 -0
  93. package/template/src/components/ui/context-menu/ContextMenuGroup.vue +12 -0
  94. package/template/src/components/ui/context-menu/ContextMenuItem.vue +36 -0
  95. package/template/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
  96. package/template/src/components/ui/context-menu/ContextMenuRadioGroup.vue +18 -0
  97. package/template/src/components/ui/context-menu/ContextMenuRadioItem.vue +36 -0
  98. package/template/src/components/ui/context-menu/ContextMenuSeparator.vue +18 -0
  99. package/template/src/components/ui/context-menu/ContextMenuShortcut.vue +17 -0
  100. package/template/src/components/ui/context-menu/ContextMenuSub.vue +15 -0
  101. package/template/src/components/ui/context-menu/ContextMenuSubContent.vue +36 -0
  102. package/template/src/components/ui/context-menu/ContextMenuSubTrigger.vue +32 -0
  103. package/template/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
  104. package/template/src/components/ui/context-menu/index.ts +14 -0
  105. package/template/src/components/ui/date-picker/DatePicker.vue +233 -0
  106. package/template/src/components/ui/date-picker/index.ts +1 -0
  107. package/template/src/components/ui/dialog/Dialog.vue +19 -0
  108. package/template/src/components/ui/dialog/DialogClose.vue +15 -0
  109. package/template/src/components/ui/dialog/DialogContent.vue +53 -0
  110. package/template/src/components/ui/dialog/DialogDescription.vue +23 -0
  111. package/template/src/components/ui/dialog/DialogFooter.vue +27 -0
  112. package/template/src/components/ui/dialog/DialogHeader.vue +17 -0
  113. package/template/src/components/ui/dialog/DialogOverlay.vue +21 -0
  114. package/template/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  115. package/template/src/components/ui/dialog/DialogTitle.vue +23 -0
  116. package/template/src/components/ui/dialog/DialogTrigger.vue +15 -0
  117. package/template/src/components/ui/dialog/index.ts +10 -0
  118. package/template/src/components/ui/dropdown-menu/DropdownMenu.vue +19 -0
  119. package/template/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  120. package/template/src/components/ui/dropdown-menu/DropdownMenuContent.vue +41 -0
  121. package/template/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  122. package/template/src/components/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  123. package/template/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  124. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  125. package/template/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  126. package/template/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  127. package/template/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  128. package/template/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  129. package/template/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  130. package/template/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  131. package/template/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  132. package/template/src/components/ui/dropdown-menu/index.ts +16 -0
  133. package/template/src/components/ui/form/FormControl.vue +17 -0
  134. package/template/src/components/ui/form/FormDescription.vue +21 -0
  135. package/template/src/components/ui/form/FormItem.vue +23 -0
  136. package/template/src/components/ui/form/FormLabel.vue +25 -0
  137. package/template/src/components/ui/form/FormMessage.vue +23 -0
  138. package/template/src/components/ui/form/index.ts +7 -0
  139. package/template/src/components/ui/form/injectionKeys.ts +4 -0
  140. package/template/src/components/ui/form/useFormField.ts +30 -0
  141. package/template/src/components/ui/hover-card/HoverCard.vue +19 -0
  142. package/template/src/components/ui/hover-card/HoverCardContent.vue +43 -0
  143. package/template/src/components/ui/hover-card/HoverCardTrigger.vue +15 -0
  144. package/template/src/components/ui/hover-card/index.ts +3 -0
  145. package/template/src/components/ui/index.ts +47 -0
  146. package/template/src/components/ui/input/Input.vue +33 -0
  147. package/template/src/components/ui/input/InputAddon.vue +29 -0
  148. package/template/src/components/ui/input/InputGroup.vue +17 -0
  149. package/template/src/components/ui/input/InputIcon.vue +29 -0
  150. package/template/src/components/ui/input/index.ts +4 -0
  151. package/template/src/components/ui/kbd/Kbd.vue +30 -0
  152. package/template/src/components/ui/kbd/index.ts +1 -0
  153. package/template/src/components/ui/label/Label.vue +26 -0
  154. package/template/src/components/ui/label/index.ts +1 -0
  155. package/template/src/components/ui/loading-bar/LoadingBar.vue +41 -0
  156. package/template/src/components/ui/loading-bar/index.ts +2 -0
  157. package/template/src/components/ui/pagination/Pagination.vue +26 -0
  158. package/template/src/components/ui/pagination/PaginationContent.vue +22 -0
  159. package/template/src/components/ui/pagination/PaginationEllipsis.vue +25 -0
  160. package/template/src/components/ui/pagination/PaginationFirst.vue +33 -0
  161. package/template/src/components/ui/pagination/PaginationItem.vue +34 -0
  162. package/template/src/components/ui/pagination/PaginationLast.vue +33 -0
  163. package/template/src/components/ui/pagination/PaginationNext.vue +33 -0
  164. package/template/src/components/ui/pagination/PaginationPrevious.vue +33 -0
  165. package/template/src/components/ui/pagination/index.ts +8 -0
  166. package/template/src/components/ui/pin-input/PinInput.vue +28 -0
  167. package/template/src/components/ui/pin-input/PinInputGroup.vue +18 -0
  168. package/template/src/components/ui/pin-input/PinInputInput.vue +24 -0
  169. package/template/src/components/ui/pin-input/PinInputSeparator.vue +21 -0
  170. package/template/src/components/ui/pin-input/index.ts +4 -0
  171. package/template/src/components/ui/popover/Popover.vue +19 -0
  172. package/template/src/components/ui/popover/PopoverAnchor.vue +15 -0
  173. package/template/src/components/ui/popover/PopoverContent.vue +45 -0
  174. package/template/src/components/ui/popover/PopoverTrigger.vue +15 -0
  175. package/template/src/components/ui/popover/index.ts +4 -0
  176. package/template/src/components/ui/progress/Progress.vue +35 -0
  177. package/template/src/components/ui/progress/index.ts +1 -0
  178. package/template/src/components/ui/radio-group/RadioGroup.vue +23 -0
  179. package/template/src/components/ui/radio-group/RadioGroupItem.vue +30 -0
  180. package/template/src/components/ui/radio-group/index.ts +2 -0
  181. package/template/src/components/ui/scroll-area/ScrollArea.vue +40 -0
  182. package/template/src/components/ui/scroll-area/ScrollBar.vue +44 -0
  183. package/template/src/components/ui/scroll-area/index.ts +2 -0
  184. package/template/src/components/ui/select/Select.vue +19 -0
  185. package/template/src/components/ui/select/SelectContent.vue +51 -0
  186. package/template/src/components/ui/select/SelectGroup.vue +15 -0
  187. package/template/src/components/ui/select/SelectItem.vue +44 -0
  188. package/template/src/components/ui/select/SelectItemText.vue +15 -0
  189. package/template/src/components/ui/select/SelectLabel.vue +17 -0
  190. package/template/src/components/ui/select/SelectScrollDownButton.vue +26 -0
  191. package/template/src/components/ui/select/SelectScrollUpButton.vue +26 -0
  192. package/template/src/components/ui/select/SelectSeparator.vue +19 -0
  193. package/template/src/components/ui/select/SelectTrigger.vue +33 -0
  194. package/template/src/components/ui/select/SelectValue.vue +15 -0
  195. package/template/src/components/ui/select/index.ts +11 -0
  196. package/template/src/components/ui/separator/Separator.vue +29 -0
  197. package/template/src/components/ui/separator/index.ts +1 -0
  198. package/template/src/components/ui/sheet/Sheet.vue +19 -0
  199. package/template/src/components/ui/sheet/SheetClose.vue +15 -0
  200. package/template/src/components/ui/sheet/SheetContent.vue +62 -0
  201. package/template/src/components/ui/sheet/SheetDescription.vue +21 -0
  202. package/template/src/components/ui/sheet/SheetFooter.vue +16 -0
  203. package/template/src/components/ui/sheet/SheetHeader.vue +15 -0
  204. package/template/src/components/ui/sheet/SheetOverlay.vue +21 -0
  205. package/template/src/components/ui/sheet/SheetTitle.vue +21 -0
  206. package/template/src/components/ui/sheet/SheetTrigger.vue +15 -0
  207. package/template/src/components/ui/sheet/index.ts +8 -0
  208. package/template/src/components/ui/sidebar/Sidebar.vue +113 -0
  209. package/template/src/components/ui/sidebar/SidebarContent.vue +18 -0
  210. package/template/src/components/ui/sidebar/SidebarControl.vue +53 -0
  211. package/template/src/components/ui/sidebar/SidebarFooter.vue +18 -0
  212. package/template/src/components/ui/sidebar/SidebarGroup.vue +18 -0
  213. package/template/src/components/ui/sidebar/SidebarGroupAction.vue +27 -0
  214. package/template/src/components/ui/sidebar/SidebarGroupContent.vue +18 -0
  215. package/template/src/components/ui/sidebar/SidebarGroupLabel.vue +25 -0
  216. package/template/src/components/ui/sidebar/SidebarHeader.vue +18 -0
  217. package/template/src/components/ui/sidebar/SidebarInput.vue +22 -0
  218. package/template/src/components/ui/sidebar/SidebarInset.vue +21 -0
  219. package/template/src/components/ui/sidebar/SidebarMenu.vue +18 -0
  220. package/template/src/components/ui/sidebar/SidebarMenuAction.vue +35 -0
  221. package/template/src/components/ui/sidebar/SidebarMenuBadge.vue +26 -0
  222. package/template/src/components/ui/sidebar/SidebarMenuButton.vue +48 -0
  223. package/template/src/components/ui/sidebar/SidebarMenuButtonChild.vue +36 -0
  224. package/template/src/components/ui/sidebar/SidebarMenuItem.vue +18 -0
  225. package/template/src/components/ui/sidebar/SidebarMenuSkeleton.vue +35 -0
  226. package/template/src/components/ui/sidebar/SidebarMenuSub.vue +22 -0
  227. package/template/src/components/ui/sidebar/SidebarMenuSubButton.vue +36 -0
  228. package/template/src/components/ui/sidebar/SidebarMenuSubItem.vue +18 -0
  229. package/template/src/components/ui/sidebar/SidebarProvider.vue +136 -0
  230. package/template/src/components/ui/sidebar/SidebarRail.vue +33 -0
  231. package/template/src/components/ui/sidebar/SidebarSeparator.vue +19 -0
  232. package/template/src/components/ui/sidebar/SidebarTrigger.vue +27 -0
  233. package/template/src/components/ui/sidebar/index.ts +61 -0
  234. package/template/src/components/ui/sidebar/utils.ts +27 -0
  235. package/template/src/components/ui/skeleton/Skeleton.vue +17 -0
  236. package/template/src/components/ui/skeleton/index.ts +1 -0
  237. package/template/src/components/ui/slider/Slider.vue +42 -0
  238. package/template/src/components/ui/slider/index.ts +1 -0
  239. package/template/src/components/ui/sonner/Sonner.vue +42 -0
  240. package/template/src/components/ui/sonner/index.ts +2 -0
  241. package/template/src/components/ui/stepper/Stepper.vue +102 -0
  242. package/template/src/components/ui/stepper/index.ts +1 -0
  243. package/template/src/components/ui/switch/Switch.vue +38 -0
  244. package/template/src/components/ui/switch/index.ts +1 -0
  245. package/template/src/components/ui/table/Table.vue +16 -0
  246. package/template/src/components/ui/table/TableBody.vue +17 -0
  247. package/template/src/components/ui/table/TableCaption.vue +17 -0
  248. package/template/src/components/ui/table/TableCell.vue +22 -0
  249. package/template/src/components/ui/table/TableEmpty.vue +34 -0
  250. package/template/src/components/ui/table/TableFooter.vue +17 -0
  251. package/template/src/components/ui/table/TableHead.vue +17 -0
  252. package/template/src/components/ui/table/TableHeader.vue +17 -0
  253. package/template/src/components/ui/table/TableRow.vue +17 -0
  254. package/template/src/components/ui/table/index.ts +9 -0
  255. package/template/src/components/ui/table/utils.ts +10 -0
  256. package/template/src/components/ui/tabs/Tabs.vue +24 -0
  257. package/template/src/components/ui/tabs/TabsContent.vue +21 -0
  258. package/template/src/components/ui/tabs/TabsList.vue +24 -0
  259. package/template/src/components/ui/tabs/TabsTrigger.vue +26 -0
  260. package/template/src/components/ui/tabs/index.ts +4 -0
  261. package/template/src/components/ui/textarea/Textarea.vue +28 -0
  262. package/template/src/components/ui/textarea/index.ts +1 -0
  263. package/template/src/components/ui/timeline/Timeline.vue +73 -0
  264. package/template/src/components/ui/timeline/index.ts +1 -0
  265. package/template/src/components/ui/toggle/Toggle.vue +35 -0
  266. package/template/src/components/ui/toggle/index.ts +28 -0
  267. package/template/src/components/ui/toggle-group/ToggleGroup.vue +41 -0
  268. package/template/src/components/ui/toggle-group/ToggleGroupItem.vue +43 -0
  269. package/template/src/components/ui/toggle-group/index.ts +12 -0
  270. package/template/src/components/ui/tooltip/Tooltip.vue +19 -0
  271. package/template/src/components/ui/tooltip/TooltipContent.vue +34 -0
  272. package/template/src/components/ui/tooltip/TooltipProvider.vue +14 -0
  273. package/template/src/components/ui/tooltip/TooltipTrigger.vue +15 -0
  274. package/template/src/components/ui/tooltip/index.ts +4 -0
  275. package/template/src/components.d.ts +228 -0
  276. package/template/src/composables/useFormatter.ts +105 -0
  277. package/template/src/composables/useThemeConfig.ts +252 -0
  278. package/template/src/layouts/AdminLayout.vue +55 -0
  279. package/template/src/layouts/AuthLayout.vue +42 -0
  280. package/template/src/lib/axios.spec.ts +46 -0
  281. package/template/src/lib/axios.ts +243 -0
  282. package/template/src/lib/formatters.spec.ts +137 -0
  283. package/template/src/lib/formatters.ts +332 -0
  284. package/template/src/lib/loading-bar.ts +103 -0
  285. package/template/src/lib/utils.spec.ts +26 -0
  286. package/template/src/lib/utils.ts +7 -0
  287. package/template/src/lib/validation.spec.ts +78 -0
  288. package/template/src/main.ts +13 -0
  289. package/template/src/router/index.ts +147 -0
  290. package/template/src/services/auth.service.spec.ts +93 -0
  291. package/template/src/services/auth.service.ts +243 -0
  292. package/template/src/services/index.ts +3 -0
  293. package/template/src/services/types.ts +28 -0
  294. package/template/src/services/user.service.spec.ts +91 -0
  295. package/template/src/services/user.service.ts +283 -0
  296. package/template/src/stores/auth.spec.ts +52 -0
  297. package/template/src/stores/auth.ts +130 -0
  298. package/template/src/style.css +587 -0
  299. package/template/src/views/_starter/BlankView.vue +47 -0
  300. package/template/src/views/auth/ConfirmEmailView.vue +209 -0
  301. package/template/src/views/auth/ForgotPasswordView.vue +151 -0
  302. package/template/src/views/auth/LockScreenView.vue +175 -0
  303. package/template/src/views/auth/LoginView.vue +54 -0
  304. package/template/src/views/auth/RegisterView.vue +265 -0
  305. package/template/src/views/auth/ResetPasswordView.vue +260 -0
  306. package/template/src/views/auth/VerifyOtpView.vue +261 -0
  307. package/template/src/views/dashboard/IndexView.vue +159 -0
  308. package/template/src/views/errors/ComingSoonView.vue +241 -0
  309. package/template/src/views/errors/MaintenanceView.vue +252 -0
  310. package/template/src/views/errors/NotFoundView.vue +81 -0
  311. package/template/src/views/errors/ServerErrorView.vue +101 -0
  312. package/template/src/views/errors/UnauthorizedView.vue +64 -0
  313. package/template/tsconfig.app.json +27 -0
  314. package/template/tsconfig.json +19 -0
  315. package/template/tsconfig.node.json +23 -0
  316. package/template/vite.config.ts +46 -0
@@ -0,0 +1,252 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, onUnmounted } from 'vue'
3
+ import { useRouter } from 'vue-router'
4
+ import {
5
+ Wrench,
6
+ RefreshCw,
7
+ Home,
8
+ CheckCircle2,
9
+ Clock,
10
+ Bell,
11
+ Mail,
12
+ Activity,
13
+ } from '@lucide/vue'
14
+ import { Card, CardContent } from '@/components/ui/card'
15
+ import { Button } from '@/components/ui/button'
16
+ import { Input } from '@/components/ui/input'
17
+ import { Progress } from '@/components/ui/progress'
18
+ import AppLogo from '@/components/AppLogo.vue'
19
+ import { toast } from '@/components/ui/sonner'
20
+
21
+ const router = useRouter()
22
+
23
+ // Countdown Timer State (Target: 2 hours 45 minutes from now)
24
+ const hours = ref(2)
25
+ const minutes = ref(45)
26
+ const seconds = ref(18)
27
+ let timerInterval: ReturnType<typeof setInterval> | null = null
28
+
29
+ // Subscription State
30
+ const notifyEmail = ref('')
31
+ const isSubscribed = ref(false)
32
+ const isSubmitting = ref(false)
33
+ const isRefreshing = ref(false)
34
+
35
+ const maintenanceTasks = [
36
+ { id: 1, title: 'Database Backup & Snapshot', status: 'completed', desc: 'Immutable backup archive verified' },
37
+ { id: 2, title: 'Core API Cluster Upgrade', status: 'completed', desc: 'Deploying v2.4 kernel patches' },
38
+ { id: 3, title: 'Search Index Rebuilding', status: 'in-progress', progress: 78, desc: 'Vector indexes processing' },
39
+ { id: 4, title: 'Edge CDN Cache Warming', status: 'pending', desc: 'Global edge node cache purge' },
40
+ ]
41
+
42
+ onMounted(() => {
43
+ timerInterval = setInterval(() => {
44
+ if (seconds.value > 0) {
45
+ seconds.value--
46
+ } else {
47
+ if (minutes.value > 0) {
48
+ minutes.value--
49
+ seconds.value = 59
50
+ } else {
51
+ if (hours.value > 0) {
52
+ hours.value--
53
+ minutes.value = 59
54
+ seconds.value = 59
55
+ } else {
56
+ if (timerInterval) clearInterval(timerInterval)
57
+ }
58
+ }
59
+ }
60
+ }, 1000)
61
+ })
62
+
63
+ onUnmounted(() => {
64
+ if (timerInterval) clearInterval(timerInterval)
65
+ })
66
+
67
+ async function handleSubscribe() {
68
+ if (!notifyEmail.value || !notifyEmail.value.includes('@')) {
69
+ toast.error('Please enter a valid email address.')
70
+ return
71
+ }
72
+
73
+ isSubmitting.value = true
74
+ setTimeout(() => {
75
+ isSubmitting.value = false
76
+ isSubscribed.value = true
77
+ toast.success(`We will notify ${notifyEmail.value} as soon as systems are live!`)
78
+ }, 600)
79
+ }
80
+
81
+ function handleRefresh() {
82
+ isRefreshing.value = true
83
+ setTimeout(() => {
84
+ isRefreshing.value = false
85
+ toast.info('System status refreshed: Maintenance is 78% complete.')
86
+ }, 750)
87
+ }
88
+ </script>
89
+
90
+ <template>
91
+ <div class="flex min-h-[calc(100vh-6rem)] flex-col items-center justify-center p-4 sm:p-8">
92
+ <div class="w-full max-w-2xl space-y-8 text-center">
93
+ <!-- Brand Logo -->
94
+ <div class="flex justify-center pb-2">
95
+ <router-link to="/" class="inline-flex items-center gap-2.5 hover:opacity-90 transition-opacity">
96
+ <AppLogo class="h-10 w-10" withBackground withText textClass="text-2xl font-bold tracking-tight" />
97
+ </router-link>
98
+ </div>
99
+
100
+ <!-- Icon & Status Badge -->
101
+ <div class="space-y-3">
102
+ <div class="relative mx-auto flex h-20 w-20 items-center justify-center rounded-3xl bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-8 ring-amber-500/5 shadow-xs">
103
+ <Wrench class="h-10 w-10 animate-spin-slow" />
104
+ <span class="absolute -bottom-2 rounded-full bg-amber-500 text-white px-2.5 py-0.5 text-[10px] font-bold tracking-wider uppercase shadow-xs">
105
+ Maintenance
106
+ </span>
107
+ </div>
108
+
109
+ <div class="space-y-2 pt-2">
110
+ <h1 class="text-3xl sm:text-4xl font-extrabold tracking-tight text-foreground">
111
+ System Maintenance in Progress
112
+ </h1>
113
+ <p class="text-sm text-muted-foreground leading-relaxed max-w-lg mx-auto">
114
+ We are performing scheduled core infrastructure updates and database optimizations. All services are expected to resume shortly.
115
+ </p>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Live Countdown Card -->
120
+ <Card class="border-border/80 bg-card/80 backdrop-blur-xs shadow-md">
121
+ <CardContent class="p-6">
122
+ <p class="text-xs font-semibold uppercase tracking-widest text-muted-foreground mb-4">
123
+ Estimated Completion In
124
+ </p>
125
+
126
+ <div class="grid grid-cols-3 gap-3 sm:gap-6 max-w-sm mx-auto">
127
+ <!-- Hours -->
128
+ <div class="flex flex-col items-center p-3 rounded-xl bg-muted/40 border border-border/60">
129
+ <span class="text-3xl sm:text-4xl font-mono font-extrabold text-foreground">
130
+ {{ String(hours).padStart(2, '0') }}
131
+ </span>
132
+ <span class="text-[11px] font-medium text-muted-foreground uppercase mt-1">Hours</span>
133
+ </div>
134
+
135
+ <!-- Minutes -->
136
+ <div class="flex flex-col items-center p-3 rounded-xl bg-muted/40 border border-border/60">
137
+ <span class="text-3xl sm:text-4xl font-mono font-extrabold text-foreground">
138
+ {{ String(minutes).padStart(2, '0') }}
139
+ </span>
140
+ <span class="text-[11px] font-medium text-muted-foreground uppercase mt-1">Minutes</span>
141
+ </div>
142
+
143
+ <!-- Seconds -->
144
+ <div class="flex flex-col items-center p-3 rounded-xl bg-muted/40 border border-border/60">
145
+ <span class="text-3xl sm:text-4xl font-mono font-extrabold text-primary">
146
+ {{ String(seconds).padStart(2, '0') }}
147
+ </span>
148
+ <span class="text-[11px] font-medium text-muted-foreground uppercase mt-1">Seconds</span>
149
+ </div>
150
+ </div>
151
+
152
+ <!-- Live Progress Tracker -->
153
+ <div class="mt-8 pt-6 border-t border-border/60 text-left space-y-3">
154
+ <div class="flex items-center justify-between text-xs">
155
+ <span class="font-semibold text-foreground flex items-center gap-1.5">
156
+ <Activity class="h-3.5 w-3.5 text-primary animate-pulse" />
157
+ <span>Migration Pipeline Progress</span>
158
+ </span>
159
+ <span class="font-mono font-bold text-primary">78%</span>
160
+ </div>
161
+ <Progress :model-value="78" class="h-2" />
162
+
163
+ <!-- Subtask checklist -->
164
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5 pt-3">
165
+ <div
166
+ v-for="task in maintenanceTasks"
167
+ :key="task.id"
168
+ class="flex items-start gap-2.5 p-2.5 rounded-lg border border-border/50 bg-background/50 text-xs"
169
+ >
170
+ <CheckCircle2 v-if="task.status === 'completed'" class="h-4 w-4 text-emerald-500 shrink-0 mt-0.5" />
171
+ <RefreshCw v-else-if="task.status === 'in-progress'" class="h-4 w-4 text-primary animate-spin shrink-0 mt-0.5" />
172
+ <Clock v-else class="h-4 w-4 text-muted-foreground/50 shrink-0 mt-0.5" />
173
+
174
+ <div class="space-y-0.5">
175
+ <p class="font-medium text-foreground text-xs leading-none">{{ task.title }}</p>
176
+ <p class="text-[11px] text-muted-foreground">{{ task.desc }}</p>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </CardContent>
182
+ </Card>
183
+
184
+ <!-- Email Notification Capture -->
185
+ <Card class="border-border/80 bg-card/60 shadow-xs max-w-lg mx-auto">
186
+ <CardContent class="p-5 text-center">
187
+ <div v-if="!isSubscribed" class="space-y-3">
188
+ <div class="flex items-center justify-center gap-2 text-xs font-semibold text-foreground">
189
+ <Bell class="h-4 w-4 text-primary" />
190
+ <span>Get notified immediately when we're back online</span>
191
+ </div>
192
+
193
+ <form @submit.prevent="handleSubscribe" class="flex flex-col sm:flex-row gap-2">
194
+ <Input
195
+ v-model="notifyEmail"
196
+ type="email"
197
+ placeholder="Enter your work email"
198
+ class="h-9 text-xs bg-background"
199
+ required
200
+ />
201
+ <Button type="submit" size="sm" class="h-9 text-xs gap-1.5 shrink-0" :disabled="isSubmitting">
202
+ <Mail class="h-3.5 w-3.5" />
203
+ <span>{{ isSubmitting ? 'Subscribing...' : 'Notify Me' }}</span>
204
+ </Button>
205
+ </form>
206
+ </div>
207
+
208
+ <div v-else class="flex items-center justify-center gap-2 text-xs text-emerald-600 dark:text-emerald-400 font-medium py-1">
209
+ <CheckCircle2 class="h-4 w-4" />
210
+ <span>You're subscribed! We'll email you the moment systems are operational.</span>
211
+ </div>
212
+ </CardContent>
213
+ </Card>
214
+
215
+ <!-- Action Buttons -->
216
+ <div class="flex flex-wrap items-center justify-center gap-3 pt-2">
217
+ <Button
218
+ variant="outline"
219
+ class="gap-2 cursor-pointer text-xs h-9"
220
+ :disabled="isRefreshing"
221
+ @click="handleRefresh"
222
+ >
223
+ <RefreshCw class="h-3.5 w-3.5" :class="{ 'animate-spin': isRefreshing }" />
224
+ <span>{{ isRefreshing ? 'Checking...' : 'Refresh Status' }}</span>
225
+ </Button>
226
+
227
+ <Button
228
+ variant="default"
229
+ class="gap-2 cursor-pointer text-xs h-9"
230
+ @click="router.push('/')"
231
+ >
232
+ <Home class="h-3.5 w-3.5" />
233
+ <span>Dashboard Home</span>
234
+ </Button>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </template>
239
+
240
+ <style scoped>
241
+ @keyframes spinSlow {
242
+ from {
243
+ transform: rotate(0deg);
244
+ }
245
+ to {
246
+ transform: rotate(360deg);
247
+ }
248
+ }
249
+ .animate-spin-slow {
250
+ animation: spinSlow 12s linear infinite;
251
+ }
252
+ </style>
@@ -0,0 +1,81 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ FileQuestion,
4
+ ArrowLeft,
5
+ Home,
6
+ Layers,
7
+ Settings,
8
+ } from '@lucide/vue'
9
+
10
+ const router = useRouter()
11
+
12
+ const goBack = () => {
13
+ if (window.history.length > 1) {
14
+ router.back()
15
+ } else {
16
+ router.push('/')
17
+ }
18
+ }
19
+
20
+ const quickLinks = [
21
+ { label: 'Overview Dashboard', href: '/', icon: Home },
22
+ { label: 'UI Components', href: '/components/buttons', icon: Layers },
23
+ { label: 'System Settings', href: '/settings', icon: Settings },
24
+ ]
25
+ </script>
26
+
27
+ <template>
28
+ <div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center p-4 text-center sm:p-8">
29
+ <div class="w-full max-w-lg space-y-6">
30
+ <!-- Icon & Status Badge -->
31
+ <div class="relative mx-auto flex h-24 w-24 items-center justify-center rounded-3xl bg-primary/10 text-primary ring-8 ring-primary/5">
32
+ <FileQuestion class="h-12 w-12" />
33
+ <span class="absolute -bottom-2.5 rounded-full bg-primary px-3 py-0.5 text-[11px] font-bold tracking-wider text-primary-foreground uppercase shadow-xs">
34
+ 404 Error
35
+ </span>
36
+ </div>
37
+
38
+ <!-- Main Copy -->
39
+ <div class="space-y-2">
40
+ <h1 class="text-3xl font-extrabold tracking-tight sm:text-4xl text-foreground">
41
+ Page Not Found
42
+ </h1>
43
+ <p class="text-sm text-muted-foreground leading-relaxed max-w-md mx-auto">
44
+ The requested URL does not exist or has been moved. Check the URL spelling or choose one of the quick shortcuts below.
45
+ </p>
46
+ </div>
47
+
48
+ <!-- Quick Action Buttons -->
49
+ <div class="flex flex-col gap-2.5 sm:flex-row sm:justify-center pt-2">
50
+ <Button variant="outline" class="gap-2 cursor-pointer" @click="goBack">
51
+ <ArrowLeft class="h-4 w-4" />
52
+ Go Back
53
+ </Button>
54
+ <Button as-child class="gap-2 cursor-pointer">
55
+ <router-link to="/">
56
+ <Home class="h-4 w-4" />
57
+ Back to Dashboard
58
+ </router-link>
59
+ </Button>
60
+ </div>
61
+
62
+ <!-- Quick Helpful Links -->
63
+ <div class="pt-6 border-t border-border/60">
64
+ <p class="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-3">
65
+ Popular Destinations
66
+ </p>
67
+ <div class="grid grid-cols-1 sm:grid-cols-3 gap-2">
68
+ <router-link
69
+ v-for="link in quickLinks"
70
+ :key="link.href"
71
+ :to="link.href"
72
+ class="flex items-center justify-center gap-2 p-2.5 rounded-lg border border-border bg-card hover:border-primary/50 hover:bg-primary/5 text-xs font-medium text-foreground transition-all shadow-2xs"
73
+ >
74
+ <component :is="link.icon" class="h-3.5 w-3.5 text-muted-foreground" />
75
+ <span>{{ link.label }}</span>
76
+ </router-link>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </template>
@@ -0,0 +1,101 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ ServerCrash,
4
+ RefreshCw,
5
+ Home,
6
+ Activity,
7
+ Copy,
8
+ Check,
9
+ } from '@lucide/vue'
10
+
11
+ const isReloading = ref(false)
12
+ const copiedTrace = ref(false)
13
+ const traceId = ref('req_8f19da240b91_fra')
14
+
15
+ const handleReload = () => {
16
+ isReloading.value = true
17
+ setTimeout(() => {
18
+ window.location.reload()
19
+ }, 600)
20
+ }
21
+
22
+ const copyTraceId = () => {
23
+ navigator.clipboard.writeText(traceId.value)
24
+ copiedTrace.value = true
25
+ setTimeout(() => {
26
+ copiedTrace.value = false
27
+ }, 2000)
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <div class="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center p-4 text-center sm:p-8">
33
+ <div class="w-full max-w-lg space-y-6">
34
+ <!-- Icon & Status Badge -->
35
+ <div class="relative mx-auto flex h-24 w-24 items-center justify-center rounded-3xl bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-8 ring-amber-500/5">
36
+ <ServerCrash class="h-12 w-12" />
37
+ <span class="absolute -bottom-2.5 rounded-full bg-amber-600 text-white px-3 py-0.5 text-[11px] font-bold tracking-wider uppercase shadow-xs">
38
+ 500 Error
39
+ </span>
40
+ </div>
41
+
42
+ <!-- Main Copy -->
43
+ <div class="space-y-2">
44
+ <h1 class="text-3xl font-extrabold tracking-tight sm:text-4xl text-foreground">
45
+ Internal Server Error
46
+ </h1>
47
+ <p class="text-sm text-muted-foreground leading-relaxed max-w-md mx-auto">
48
+ Our gateway encountered an unexpected exception while processing this request. Our engineering team has been automatically notified.
49
+ </p>
50
+ </div>
51
+
52
+ <!-- Diagnostic Trace ID Card -->
53
+ <div class="rounded-xl border border-border bg-card p-3 max-w-sm mx-auto flex items-center justify-between text-xs font-mono shadow-2xs">
54
+ <div class="flex items-center gap-2 text-muted-foreground">
55
+ <span class="h-2 w-2 rounded-full bg-amber-500 animate-pulse"></span>
56
+ <span>Trace:</span>
57
+ <span class="text-foreground font-semibold">{{ traceId }}</span>
58
+ </div>
59
+ <button
60
+ type="button"
61
+ @click="copyTraceId"
62
+ class="text-muted-foreground hover:text-foreground cursor-pointer transition-colors p-1"
63
+ title="Copy Trace ID"
64
+ >
65
+ <Check v-if="copiedTrace" class="h-3.5 w-3.5 text-emerald-500" />
66
+ <Copy v-else class="h-3.5 w-3.5" />
67
+ </button>
68
+ </div>
69
+
70
+ <!-- Quick Action Buttons -->
71
+ <div class="flex flex-col gap-2.5 sm:flex-row sm:justify-center pt-2">
72
+ <Button
73
+ variant="outline"
74
+ class="gap-2 cursor-pointer"
75
+ :disabled="isReloading"
76
+ @click="handleReload"
77
+ >
78
+ <RefreshCw class="h-4 w-4" :class="{ 'animate-spin': isReloading }" />
79
+ {{ isReloading ? 'Reloading...' : 'Try Again' }}
80
+ </Button>
81
+ <Button as-child class="gap-2 cursor-pointer">
82
+ <router-link to="/">
83
+ <Home class="h-4 w-4" />
84
+ Back to Dashboard
85
+ </router-link>
86
+ </Button>
87
+ </div>
88
+
89
+ <!-- System Health Hint -->
90
+ <div class="pt-6 border-t border-border/60">
91
+ <div class="inline-flex items-center gap-2 text-xs text-muted-foreground">
92
+ <Activity class="h-3.5 w-3.5 text-emerald-500" />
93
+ <span>All global systems are operating nominally.</span>
94
+ <router-link to="/components/charts" class="font-medium text-primary hover:underline transition-colors">
95
+ View Status
96
+ </router-link>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </template>
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ import { useRouter } from 'vue-router'
3
+ import { Button } from '@/components/ui/button'
4
+ import { ShieldAlert, ArrowLeft, Home, HelpCircle } from '@lucide/vue'
5
+
6
+ const router = useRouter()
7
+
8
+ const goBack = () => {
9
+ if (window.history.length > 1) {
10
+ router.back()
11
+ } else {
12
+ router.push('/')
13
+ }
14
+ }
15
+ </script>
16
+
17
+ <template>
18
+ <div class="flex min-h-[calc(100vh-4rem)] flex-col items-center justify-center p-4 text-center sm:p-8">
19
+ <div class="w-full max-w-md space-y-6">
20
+ <!-- Icon & Status Badge -->
21
+ <div class="relative mx-auto flex h-24 w-24 items-center justify-center rounded-3xl bg-destructive/10 text-destructive ring-8 ring-destructive/5">
22
+ <ShieldAlert class="h-12 w-12" />
23
+ <span class="absolute -bottom-2.5 rounded-full bg-destructive px-2.5 py-0.5 text-[11px] font-bold tracking-wider text-destructive-foreground uppercase shadow-xs">
24
+ 403 Error
25
+ </span>
26
+ </div>
27
+
28
+ <!-- Main Copy -->
29
+ <div class="space-y-2">
30
+ <h1 class="text-3xl font-extrabold tracking-tight sm:text-4xl text-foreground">
31
+ Access Denied
32
+ </h1>
33
+ <p class="text-sm text-muted-foreground leading-relaxed">
34
+ You don't have permission to access this page or resource. If you believe this is an error, please contact your administrator.
35
+ </p>
36
+ </div>
37
+
38
+ <!-- Quick Action Buttons -->
39
+ <div class="flex flex-col gap-2.5 sm:flex-row sm:justify-center pt-2">
40
+ <Button variant="outline" class="gap-2 cursor-pointer" @click="goBack">
41
+ <ArrowLeft class="h-4 w-4" />
42
+ Go Back
43
+ </Button>
44
+ <Button as-child class="gap-2 cursor-pointer">
45
+ <router-link to="/">
46
+ <Home class="h-4 w-4" />
47
+ Back to Dashboard
48
+ </router-link>
49
+ </Button>
50
+ </div>
51
+
52
+ <!-- Help / Support Hint -->
53
+ <div class="pt-6 border-t border-border/60">
54
+ <div class="inline-flex items-center gap-1.5 text-xs text-muted-foreground">
55
+ <HelpCircle class="h-3.5 w-3.5" />
56
+ <span>Need elevated permissions?</span>
57
+ <router-link to="/settings" class="font-medium text-primary hover:underline transition-colors">
58
+ Contact Support
59
+ </router-link>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </template>
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "types": [
6
+ "vite/client",
7
+ "vitest/globals"
8
+ ],
9
+ "allowArbitraryExtensions": true,
10
+ /* Linting */
11
+ "noUnusedLocals": true,
12
+ "noUnusedParameters": true,
13
+ "erasableSyntaxOnly": true,
14
+ "noFallthroughCasesInSwitch": true,
15
+ "paths": {
16
+ "@/*": [
17
+ "./src/*"
18
+ ]
19
+ }
20
+ },
21
+ "include": [
22
+ "src/**/*.ts",
23
+ "src/**/*.d.ts",
24
+ "src/**/*.tsx",
25
+ "src/**/*.vue"
26
+ ]
27
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ {
5
+ "path": "./tsconfig.app.json"
6
+ },
7
+ {
8
+ "path": "./tsconfig.node.json"
9
+ }
10
+ ],
11
+ "compilerOptions": {
12
+ "baseUrl": ".",
13
+ "paths": {
14
+ "@/*": [
15
+ "./src/*"
16
+ ]
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023"],
6
+ "types": ["node"],
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "module": "nodenext",
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "erasableSyntaxOnly": true,
20
+ "noFallthroughCasesInSwitch": true
21
+ },
22
+ "include": ["vite.config.ts"]
23
+ }
@@ -0,0 +1,46 @@
1
+ /// <reference types="vitest/config" />
2
+ import path from 'node:path'
3
+ import { defineConfig } from 'vite'
4
+ import tailwindcss from '@tailwindcss/vite'
5
+ import vue from '@vitejs/plugin-vue'
6
+ import AutoImport from 'unplugin-auto-import/vite'
7
+ import Components from 'unplugin-vue-components/vite'
8
+
9
+ export default defineConfig({
10
+ test: {
11
+ environment: 'happy-dom',
12
+ globals: true,
13
+ },
14
+ plugins: [
15
+ vue(),
16
+ tailwindcss(),
17
+ AutoImport({
18
+ imports: [
19
+ 'vue',
20
+ 'vue-router',
21
+ 'pinia',
22
+ '@vueuse/core',
23
+ ],
24
+ dts: 'src/auto-imports.d.ts',
25
+ dirs: [
26
+ 'src/lib',
27
+ 'src/composables',
28
+ ],
29
+ vueTemplate: true,
30
+ }),
31
+ Components({
32
+ dirs: ['src/components'],
33
+ extensions: ['vue'],
34
+ dts: 'src/components.d.ts',
35
+ deep: true,
36
+ }),
37
+ ],
38
+ server: {
39
+ host: true,
40
+ },
41
+ resolve: {
42
+ alias: {
43
+ '@': path.resolve(import.meta.dirname, './src'),
44
+ },
45
+ },
46
+ })