@podosoft/podokit 0.2.0 → 0.4.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.
- package/README.md +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/fullstack-nest-svelte/apps/api/package.json +29 -11
- package/dist/templates/fullstack-nest-svelte/apps/api/src/app.module.ts +3 -0
- package/dist/templates/fullstack-nest-svelte/apps/api/tsconfig.json +14 -5
- package/dist/templates/fullstack-nest-svelte/apps/web/package.json +8 -6
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/api.ts +5 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/alert/alert-action.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/alert/alert-description.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/alert/alert-title.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/alert/alert.svelte +43 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/alert/index.ts +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar-badge.svelte +26 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar-fallback.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar-group-count.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar-group.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar-image.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/avatar.svelte +26 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/avatar/index.ts +22 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/badge/badge.svelte +49 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/badge/index.ts +2 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-close.svelte +11 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-content.svelte +48 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-description.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-footer.svelte +32 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-overlay.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-portal.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-title.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/dialog.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dialog/index.ts +34 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +44 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +34 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/dropdown-menu/index.ts +54 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/index.ts +37 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-content.svelte +45 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-group-heading.svelte +21 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-group.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-item.svelte +40 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-label.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-portal.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-separator.svelte +18 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select-trigger.svelte +29 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/select/select.svelte +11 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/separator/index.ts +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/separator/separator.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/skeleton/index.ts +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/skeleton/skeleton.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/sonner/index.ts +1 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/sonner/sonner.svelte +34 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/index.ts +28 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-body.svelte +15 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-caption.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-cell.svelte +15 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-footer.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-head.svelte +15 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-header.svelte +20 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table-row.svelte +15 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/table/table.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tabs/index.ts +18 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tabs/tabs-content.svelte +17 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tabs/tabs-list.svelte +40 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tabs/tabs-trigger.svelte +23 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tabs/tabs.svelte +19 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/index.ts +19 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/i18n/ko.ts +5 -2
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/api.ts +19 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/backend-proxy.ts +43 -4
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/+page.svelte +8 -3
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/api/[...path]/+server.ts +12 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/api/auth/[...all]/+server.ts +12 -0
- package/dist/templates/fullstack-nest-svelte/dot-gitignore +5 -0
- package/dist/templates/fullstack-nest-svelte/package.json +11 -3
- package/dist/templates/fullstack-nest-svelte/tests/README.md +15 -0
- package/dist/templates/fullstack-nest-svelte/tests/api/health.api.spec.ts +14 -0
- package/dist/templates/fullstack-nest-svelte/tests/package.json +14 -0
- package/dist/templates/fullstack-nest-svelte/tests/playwright.config.ts +25 -0
- package/dist/templates/fullstack-nest-svelte/tests/ui/smoke.ui.spec.ts +8 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/app.d.ts +23 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/hooks.server.ts +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/app-sidebar.svelte +59 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/language-switch.svelte +33 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/sidebar-user-menu.svelte +44 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/table-pagination.svelte +40 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/theme-toggle.svelte +27 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/collapsible/collapsible-content.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/collapsible/collapsible-trigger.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/collapsible/collapsible.svelte +11 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/collapsible/index.ts +13 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/index.ts +31 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-content.svelte +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-ellipsis.svelte +22 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-item.svelte +14 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-link.svelte +42 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-next-button.svelte +31 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-next.svelte +26 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-prev-button.svelte +31 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination-previous.svelte +26 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/pagination/pagination.svelte +28 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/index.ts +34 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-close.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-content.svelte +55 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-description.svelte +17 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-footer.svelte +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-header.svelte +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-overlay.svelte +17 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-portal.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-title.svelte +17 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sheet/sheet.svelte +7 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/constants.ts +6 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/context.svelte.ts +81 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/index.ts +75 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-content.svelte +24 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-footer.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-group-action.svelte +33 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-group-content.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-group-label.svelte +33 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-group.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-header.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-input.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-inset.svelte +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-action.svelte +37 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte +24 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-button.svelte +102 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-item.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte +36 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte +39 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-menu.svelte +21 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-provider.svelte +53 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-rail.svelte +36 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-separator.svelte +19 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar-trigger.svelte +36 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/ui/sidebar/sidebar.svelte +108 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/user-avatar.svelte +12 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/hooks/is-mobile.svelte.ts +9 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/i18n/index.ts +27 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/i18n/messages.ts +359 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/+layout.server.ts +14 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/+layout.svelte +50 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/+page.svelte +25 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/account/+page.server.ts +5 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/account/+page.svelte +374 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/audit/+page.server.ts +8 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/audit/+page.svelte +78 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/sessions/+page.server.ts +8 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/sessions/+page.svelte +122 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/users/+page.server.ts +9 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/users/+page.svelte +406 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(auth)/+layout.svelte +13 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(auth)/forgot-password/+page.svelte +54 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(auth)/login/+page.svelte +59 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(auth)/reset-password/+page.svelte +51 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(auth)/signup/+page.svelte +60 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/+layout.server.ts +22 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/+layout.svelte +20 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/+page.svelte +22 -0
- package/dist/templates/modules/admin-dashboard/files/tests/api/audit.api.spec.ts +48 -0
- package/dist/templates/modules/admin-dashboard/files/tests/api/auth.api.spec.ts +43 -0
- package/dist/templates/modules/admin-dashboard/files/tests/api/users-admin.api.spec.ts +134 -0
- package/dist/templates/modules/admin-dashboard/files/tests/helpers/accounts.ts +6 -0
- package/dist/templates/modules/admin-dashboard/files/tests/helpers/hydration.ts +9 -0
- package/dist/templates/modules/admin-dashboard/files/tests/playwright.config.ts +26 -0
- package/dist/templates/modules/admin-dashboard/files/tests/seed.setup.ts +29 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/account.ui.spec.ts +55 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/audit.ui.spec.ts +16 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/auth.ui.spec.ts +45 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/dashboard.ui.spec.ts +25 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/guards.ui.spec.ts +21 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/i18n.ui.spec.ts +13 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/sessions.ui.spec.ts +15 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/sidebar.ui.spec.ts +16 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/users-crud.ui.spec.ts +129 -0
- package/dist/templates/modules/admin-dashboard/files/tests/ui/users.ui.spec.ts +19 -0
- package/dist/templates/modules/admin-dashboard/module.manifest.json +41 -0
- package/dist/templates/modules/api-key-auth/files/apps/api/src/api-key/api-key.decorator.ts +9 -0
- package/dist/templates/modules/api-key-auth/files/apps/api/src/api-key/api-key.guard.ts +29 -0
- package/dist/templates/modules/api-key-auth/files/apps/api/src/api-key/api-key.module.ts +9 -0
- package/dist/templates/modules/api-key-auth/files/apps/api/src/machine/machine.controller.ts +14 -0
- package/dist/templates/modules/api-key-auth/module.manifest.json +19 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/README.md +59 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit-events.ts +34 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit-hook.ts +70 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit-log.entity.ts +46 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit.controller.ts +21 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit.decorator.ts +23 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit.interceptor.ts +54 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit.module.ts +14 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/audit/audit.service.ts +36 -0
- package/dist/templates/modules/audit-log/files/apps/api/src/migrations/1720300000000-InitAuditLogs.ts +31 -0
- package/dist/templates/modules/audit-log/module.manifest.json +39 -0
- package/dist/templates/modules/auth/files/apps/api/src/account/account.controller.ts +30 -0
- package/dist/templates/modules/auth/files/apps/api/src/account/account.module.ts +5 -0
- package/dist/templates/modules/auth/files/apps/api/src/auth/auth.ts +59 -0
- package/dist/templates/modules/auth/files/apps/api/src/health/health.controller.ts +26 -0
- package/dist/templates/modules/auth/module.manifest.json +70 -0
- package/dist/templates/modules/bullmq/module.manifest.json +11 -3
- package/dist/templates/modules/logging/files/apps/api/src/logging/logging.module.ts +29 -0
- package/dist/templates/modules/logging/module.manifest.json +27 -0
- package/dist/templates/modules/rate-limit/files/apps/api/src/rate-limit/rate-limit.module.ts +26 -0
- package/dist/templates/modules/rate-limit/module.manifest.json +25 -0
- package/dist/templates/todo/apps/api/package.json +29 -11
- package/dist/templates/todo/apps/api/src/app.module.ts +3 -0
- package/dist/templates/todo/apps/api/tsconfig.json +14 -5
- package/dist/templates/todo/apps/web/package.json +8 -6
- package/dist/templates/todo/apps/web/src/lib/api.ts +5 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/alert/alert-action.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/alert/alert-description.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/alert/alert-title.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/alert/alert.svelte +43 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/alert/index.ts +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar-badge.svelte +26 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar-fallback.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar-group-count.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar-group.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar-image.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/avatar.svelte +26 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/avatar/index.ts +22 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/badge/badge.svelte +49 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/badge/index.ts +2 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-close.svelte +11 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-content.svelte +48 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-description.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-footer.svelte +32 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-overlay.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-portal.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-title.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/dialog.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dialog/index.ts +34 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +44 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +34 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/dropdown-menu/index.ts +54 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/index.ts +37 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-content.svelte +45 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-group-heading.svelte +21 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-group.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-item.svelte +40 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-label.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-portal.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-separator.svelte +18 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select-trigger.svelte +29 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/select/select.svelte +11 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/separator/index.ts +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/separator/separator.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/skeleton/index.ts +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/skeleton/skeleton.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/sonner/index.ts +1 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/sonner/sonner.svelte +34 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/index.ts +28 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-body.svelte +15 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-caption.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-cell.svelte +15 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-footer.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-head.svelte +15 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-header.svelte +20 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table-row.svelte +15 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/table/table.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tabs/index.ts +18 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tabs/tabs-content.svelte +17 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tabs/tabs-list.svelte +40 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tabs/tabs-trigger.svelte +23 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tabs/tabs.svelte +19 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/index.ts +19 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/templates/todo/apps/web/src/lib/i18n/ko.ts +5 -2
- package/dist/templates/todo/apps/web/src/lib/server/api.ts +19 -0
- package/dist/templates/todo/apps/web/src/lib/server/backend-proxy.ts +43 -4
- package/dist/templates/todo/apps/web/src/routes/+page.svelte +19 -18
- package/dist/templates/todo/apps/web/src/routes/api/[...path]/+server.ts +12 -0
- package/dist/templates/todo/apps/web/src/routes/api/auth/[...all]/+server.ts +12 -0
- package/dist/templates/todo/dot-gitignore +5 -0
- package/dist/templates/todo/package.json +11 -3
- package/dist/templates/todo/tests/README.md +15 -0
- package/dist/templates/todo/tests/api/health.api.spec.ts +14 -0
- package/dist/templates/todo/tests/package.json +14 -0
- package/dist/templates/todo/tests/playwright.config.ts +25 -0
- package/dist/templates/todo/tests/ui/smoke.ui.spec.ts +8 -0
- package/package.json +2 -2
- package/dist/templates/fullstack-nest-svelte/apps/api/test/health.e2e-spec.ts +0 -23
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/api/health/+server.ts +0 -12
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.controller.ts +0 -31
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.module.ts +0 -22
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/auth.service.ts +0 -44
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/dto/login.dto.ts +0 -12
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/dto/register.dto.ts +0 -13
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/jwt-auth.guard.ts +0 -5
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/jwt.strategy.ts +0 -23
- package/dist/templates/modules/auth-jwt/files/apps/api/src/auth/user.entity.ts +0 -16
- package/dist/templates/modules/auth-jwt/files/apps/api/src/migrations/1720200000000-InitUsers.ts +0 -23
- package/dist/templates/modules/auth-jwt/module.manifest.json +0 -31
- package/dist/templates/todo/apps/api/test/health.e2e-spec.ts +0 -23
- package/dist/templates/todo/apps/web/src/routes/api/health/+server.ts +0 -12
- package/dist/templates/todo/apps/web/src/routes/api/todos/+server.ts +0 -24
- package/dist/templates/todo/apps/web/src/routes/api/todos/[id]/+server.ts +0 -24
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from "$lib/components/ui/button/index.js";
|
|
3
|
+
import PanelLeftIcon from '@lucide/svelte/icons/panel-left';
|
|
4
|
+
import { cn } from "$lib/utils.js";
|
|
5
|
+
import type { ComponentProps } from "svelte";
|
|
6
|
+
import { useSidebar } from "./context.svelte.js";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
ref = $bindable(null),
|
|
10
|
+
class: className,
|
|
11
|
+
onclick,
|
|
12
|
+
...restProps
|
|
13
|
+
}: ComponentProps<typeof Button> & {
|
|
14
|
+
onclick?: (e: MouseEvent) => void;
|
|
15
|
+
} = $props();
|
|
16
|
+
|
|
17
|
+
const sidebar = useSidebar();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Button
|
|
21
|
+
bind:ref
|
|
22
|
+
data-sidebar="trigger"
|
|
23
|
+
data-slot="sidebar-trigger"
|
|
24
|
+
variant="ghost"
|
|
25
|
+
size="icon-sm"
|
|
26
|
+
class={cn("cn-sidebar-trigger", className)}
|
|
27
|
+
type="button"
|
|
28
|
+
onclick={(e) => {
|
|
29
|
+
onclick?.(e);
|
|
30
|
+
sidebar.toggle();
|
|
31
|
+
}}
|
|
32
|
+
{...restProps}
|
|
33
|
+
>
|
|
34
|
+
<PanelLeftIcon />
|
|
35
|
+
<span class="sr-only">Toggle Sidebar</span>
|
|
36
|
+
</Button>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Sheet from "$lib/components/ui/sheet/index.js";
|
|
3
|
+
import { cn, type WithElementRef } from "$lib/utils.js";
|
|
4
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
|
+
import { SIDEBAR_WIDTH_MOBILE } from "./constants.js";
|
|
6
|
+
import { useSidebar } from "./context.svelte.js";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
ref = $bindable(null),
|
|
10
|
+
side = "left",
|
|
11
|
+
variant = "sidebar",
|
|
12
|
+
collapsible = "offcanvas",
|
|
13
|
+
class: className,
|
|
14
|
+
children,
|
|
15
|
+
...restProps
|
|
16
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
17
|
+
side?: "left" | "right";
|
|
18
|
+
variant?: "sidebar" | "floating" | "inset";
|
|
19
|
+
collapsible?: "offcanvas" | "icon" | "none";
|
|
20
|
+
} = $props();
|
|
21
|
+
|
|
22
|
+
const sidebar = useSidebar();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{#if collapsible === "none"}
|
|
26
|
+
<div
|
|
27
|
+
class={cn(
|
|
28
|
+
"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
|
|
29
|
+
className
|
|
30
|
+
)}
|
|
31
|
+
bind:this={ref}
|
|
32
|
+
{...restProps}
|
|
33
|
+
>
|
|
34
|
+
{@render children?.()}
|
|
35
|
+
</div>
|
|
36
|
+
{:else if sidebar.isMobile}
|
|
37
|
+
<Sheet.Root
|
|
38
|
+
bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)}
|
|
39
|
+
{...restProps}
|
|
40
|
+
>
|
|
41
|
+
<Sheet.Content
|
|
42
|
+
bind:ref
|
|
43
|
+
data-sidebar="sidebar"
|
|
44
|
+
data-slot="sidebar"
|
|
45
|
+
data-mobile="true"
|
|
46
|
+
class={cn(
|
|
47
|
+
"bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden",
|
|
48
|
+
className
|
|
49
|
+
)}
|
|
50
|
+
style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
|
|
51
|
+
{side}
|
|
52
|
+
>
|
|
53
|
+
<Sheet.Header class="sr-only">
|
|
54
|
+
<Sheet.Title>Sidebar</Sheet.Title>
|
|
55
|
+
<Sheet.Description>Displays the mobile sidebar.</Sheet.Description>
|
|
56
|
+
</Sheet.Header>
|
|
57
|
+
<div class="flex h-full w-full flex-col">
|
|
58
|
+
{@render children?.()}
|
|
59
|
+
</div>
|
|
60
|
+
</Sheet.Content>
|
|
61
|
+
</Sheet.Root>
|
|
62
|
+
{:else}
|
|
63
|
+
<div
|
|
64
|
+
bind:this={ref}
|
|
65
|
+
class="text-sidebar-foreground group peer hidden md:block"
|
|
66
|
+
data-state={sidebar.state}
|
|
67
|
+
data-collapsible={sidebar.state === "collapsed" ? collapsible : ""}
|
|
68
|
+
data-variant={variant}
|
|
69
|
+
data-side={side}
|
|
70
|
+
data-slot="sidebar"
|
|
71
|
+
>
|
|
72
|
+
<!-- This is what handles the sidebar gap on desktop -->
|
|
73
|
+
<div
|
|
74
|
+
data-slot="sidebar-gap"
|
|
75
|
+
class={cn(
|
|
76
|
+
"transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent",
|
|
77
|
+
"group-data-[collapsible=offcanvas]:w-0",
|
|
78
|
+
"group-data-[side=right]:rotate-180",
|
|
79
|
+
variant === "floating" || variant === "inset"
|
|
80
|
+
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
|
81
|
+
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
|
82
|
+
)}
|
|
83
|
+
></div>
|
|
84
|
+
<div
|
|
85
|
+
data-slot="sidebar-container"
|
|
86
|
+
class={cn(
|
|
87
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
88
|
+
side === "left"
|
|
89
|
+
? "start-0 group-data-[collapsible=offcanvas]:start-[calc(var(--sidebar-width)*-1)]"
|
|
90
|
+
: "end-0 group-data-[collapsible=offcanvas]:end-[calc(var(--sidebar-width)*-1)]",
|
|
91
|
+
// Adjust the padding for floating and inset variants.
|
|
92
|
+
variant === "floating" || variant === "inset"
|
|
93
|
+
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
|
94
|
+
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-e group-data-[side=right]:border-s",
|
|
95
|
+
className
|
|
96
|
+
)}
|
|
97
|
+
{...restProps}
|
|
98
|
+
>
|
|
99
|
+
<div
|
|
100
|
+
data-sidebar="sidebar"
|
|
101
|
+
data-slot="sidebar-inner"
|
|
102
|
+
class="bg-sidebar group-data-[variant=floating]:ring-sidebar-border group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 flex size-full flex-col"
|
|
103
|
+
>
|
|
104
|
+
{@render children?.()}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
{/if}
|
package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/user-avatar.svelte
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Avatar from "$lib/components/ui/avatar";
|
|
3
|
+
import type { SessionUser } from "../../app.d.ts";
|
|
4
|
+
|
|
5
|
+
let { user, class: className }: { user: Pick<SessionUser, "name" | "email" | "image">; class?: string } = $props();
|
|
6
|
+
const initials = $derived((user.name || user.email || "?").slice(0, 2).toUpperCase());
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<Avatar.Root class={className}>
|
|
10
|
+
{#if user.image}<Avatar.Image src={user.image} alt={user.name} />{/if}
|
|
11
|
+
<Avatar.Fallback>{initials}</Avatar.Fallback>
|
|
12
|
+
</Avatar.Root>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
import type { Locale, Messages } from "./messages";
|
|
3
|
+
|
|
4
|
+
const KEY = Symbol("i18n");
|
|
5
|
+
|
|
6
|
+
export type I18nContext = { readonly t: Messages; readonly locale: Locale };
|
|
7
|
+
|
|
8
|
+
export function setI18nContext(ctx: I18nContext): void {
|
|
9
|
+
setContext(KEY, ctx);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getI18n(): I18nContext {
|
|
13
|
+
return getContext(KEY) as I18nContext;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Fill {name}-style placeholders in a message.
|
|
17
|
+
export function fmt(template: string, values: Record<string, string | number>): string {
|
|
18
|
+
return template.replace(/\{(\w+)\}/g, (match, key: string) =>
|
|
19
|
+
key in values ? String(values[key]) : match,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Render a timestamp in the viewer's own locale and timezone (browser defaults),
|
|
24
|
+
// so dates always match the user's regional settings. Used across all pages.
|
|
25
|
+
export function formatDateTime(value: string | Date): string {
|
|
26
|
+
return new Date(value).toLocaleString();
|
|
27
|
+
}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
// Static message catalogs for the admin dashboard. Default locale is English.
|
|
2
|
+
export const LOCALES = ["en", "ko"] as const;
|
|
3
|
+
export type Locale = (typeof LOCALES)[number];
|
|
4
|
+
export const defaultLocale: Locale = "en";
|
|
5
|
+
|
|
6
|
+
export const localeNames: Record<Locale, string> = {
|
|
7
|
+
en: "English",
|
|
8
|
+
ko: "한국어",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const en = {
|
|
12
|
+
common: { appName: "Admin" },
|
|
13
|
+
landing: { title: "Welcome", subtitle: "This is your app's home page. Replace it with your own content — the admin area lives under /admin.", openAdmin: "Open admin" },
|
|
14
|
+
language: { label: "Language" },
|
|
15
|
+
theme: { toggle: "Toggle theme", light: "Light", dark: "Dark", system: "System" },
|
|
16
|
+
auth: {
|
|
17
|
+
signInTitle: "Sign in",
|
|
18
|
+
signInDesc: "Enter your credentials to continue.",
|
|
19
|
+
email: "Email",
|
|
20
|
+
password: "Password",
|
|
21
|
+
forgot: "Forgot?",
|
|
22
|
+
signIn: "Sign in",
|
|
23
|
+
signingIn: "Signing in…",
|
|
24
|
+
noAccount: "No account?",
|
|
25
|
+
signUp: "Sign up",
|
|
26
|
+
signInFailed: "Sign in failed",
|
|
27
|
+
createTitle: "Create account",
|
|
28
|
+
createDesc: "Sign up to get started.",
|
|
29
|
+
name: "Name",
|
|
30
|
+
create: "Create account",
|
|
31
|
+
creating: "Creating…",
|
|
32
|
+
haveAccount: "Have an account?",
|
|
33
|
+
signUpFailed: "Sign up failed",
|
|
34
|
+
resetTitle: "Reset password",
|
|
35
|
+
resetDesc: "We'll send a reset link to your email.",
|
|
36
|
+
sendReset: "Send reset link",
|
|
37
|
+
sending: "Sending…",
|
|
38
|
+
resetSent: "If that email exists, a reset link is on its way.",
|
|
39
|
+
backToSignIn: "Back to sign in",
|
|
40
|
+
requestFailed: "Request failed",
|
|
41
|
+
newTitle: "Set a new password",
|
|
42
|
+
newPassword: "New password",
|
|
43
|
+
updatePassword: "Update password",
|
|
44
|
+
updating: "Updating…",
|
|
45
|
+
missingToken: "Missing or invalid reset token.",
|
|
46
|
+
resetFailed: "Reset failed",
|
|
47
|
+
},
|
|
48
|
+
nav: { overview: "Overview", users: "Users", sessions: "Sessions", audit: "Audit log", account: "Account", signOut: "Sign out" },
|
|
49
|
+
dashboard: { title: "Dashboard", welcome: "Welcome back, {name}.", yourRole: "Your role", signedInAs: "Signed in as" },
|
|
50
|
+
audit: { title: "Audit log", when: "When", actor: "Actor", action: "Action", target: "Target", ip: "IP", empty: "No audit entries.", loadFailed: "Failed to load audit log", total: "{count} entries" },
|
|
51
|
+
users: {
|
|
52
|
+
title: "Users",
|
|
53
|
+
search: "Search by email…",
|
|
54
|
+
name: "Name",
|
|
55
|
+
email: "Email",
|
|
56
|
+
role: "Role",
|
|
57
|
+
status: "Status",
|
|
58
|
+
active: "Active",
|
|
59
|
+
banned: "Banned",
|
|
60
|
+
makeUser: "Make user",
|
|
61
|
+
makeAdmin: "Make admin",
|
|
62
|
+
ban: "Ban",
|
|
63
|
+
unban: "Unban",
|
|
64
|
+
empty: "No users.",
|
|
65
|
+
total: "{count} users",
|
|
66
|
+
previous: "Previous",
|
|
67
|
+
next: "Next",
|
|
68
|
+
roleSet: "Role set to {role}",
|
|
69
|
+
userBanned: "User banned",
|
|
70
|
+
userUnbanned: "User unbanned",
|
|
71
|
+
loadFailed: "Failed to load users",
|
|
72
|
+
actionFailed: "Action failed",
|
|
73
|
+
addUser: "Add user",
|
|
74
|
+
createTitle: "Create user",
|
|
75
|
+
password: "Password",
|
|
76
|
+
create: "Create",
|
|
77
|
+
cancel: "Cancel",
|
|
78
|
+
userCreated: "User created",
|
|
79
|
+
setPassword: "Set password",
|
|
80
|
+
newPassword: "New password",
|
|
81
|
+
save: "Save",
|
|
82
|
+
passwordSet: "Password updated",
|
|
83
|
+
delete: "Delete",
|
|
84
|
+
deleteTitle: "Delete user",
|
|
85
|
+
deleteConfirm: "Delete {email}? This cannot be undone.",
|
|
86
|
+
userDeleted: "User deleted",
|
|
87
|
+
confirmPassword: "Confirm password",
|
|
88
|
+
confirmNewPassword: "Confirm new password",
|
|
89
|
+
passwordMismatch: "Passwords do not match",
|
|
90
|
+
edit: "Edit",
|
|
91
|
+
editTitle: "Edit user",
|
|
92
|
+
userUpdated: "User updated",
|
|
93
|
+
impersonate: "Impersonate",
|
|
94
|
+
banTitle: "Ban user",
|
|
95
|
+
banReason: "Reason (optional)",
|
|
96
|
+
banExpiryDays: "Expires in (days, optional)",
|
|
97
|
+
stopImpersonating: "Stop impersonating",
|
|
98
|
+
impersonatingAs: "Impersonating {email}",
|
|
99
|
+
manage: "Manage",
|
|
100
|
+
revokeSession: "Revoke",
|
|
101
|
+
},
|
|
102
|
+
sessions: {
|
|
103
|
+
title: "Active sessions",
|
|
104
|
+
device: "Device",
|
|
105
|
+
ip: "IP",
|
|
106
|
+
since: "Since",
|
|
107
|
+
revoke: "Revoke",
|
|
108
|
+
unknown: "Unknown",
|
|
109
|
+
empty: "No active sessions.",
|
|
110
|
+
revoked: "Session revoked",
|
|
111
|
+
loadFailed: "Failed to load sessions",
|
|
112
|
+
revokeFailed: "Failed to revoke",
|
|
113
|
+
status: "Status",
|
|
114
|
+
current: "Current",
|
|
115
|
+
signOutOthers: "Sign out other sessions",
|
|
116
|
+
othersRevoked: "Signed out other sessions",
|
|
117
|
+
total: "{count} sessions",
|
|
118
|
+
},
|
|
119
|
+
adminSessions: {
|
|
120
|
+
title: "User sessions",
|
|
121
|
+
user: "User",
|
|
122
|
+
device: "Device",
|
|
123
|
+
ip: "IP",
|
|
124
|
+
since: "Since",
|
|
125
|
+
revoke: "Revoke session",
|
|
126
|
+
revokeAll: "Revoke all for user",
|
|
127
|
+
unknown: "Unknown",
|
|
128
|
+
empty: "No active sessions.",
|
|
129
|
+
revoked: "Session revoked",
|
|
130
|
+
allRevoked: "All sessions revoked for user",
|
|
131
|
+
loadFailed: "Failed to load sessions",
|
|
132
|
+
total: "{count} sessions",
|
|
133
|
+
},
|
|
134
|
+
account: {
|
|
135
|
+
title: "Account",
|
|
136
|
+
profile: "Profile",
|
|
137
|
+
name: "Name",
|
|
138
|
+
email: "Email",
|
|
139
|
+
role: "Role",
|
|
140
|
+
changePassword: "Change password",
|
|
141
|
+
currentPassword: "Current password",
|
|
142
|
+
newPassword: "New password",
|
|
143
|
+
update: "Update password",
|
|
144
|
+
updating: "Updating…",
|
|
145
|
+
changed: "Password changed",
|
|
146
|
+
changeFailed: "Failed to change password",
|
|
147
|
+
nav: { profile: "Profile", security: "Security", connected: "Connected", sessions: "Sessions", danger: "Danger zone" },
|
|
148
|
+
twoFactorTitle: "Two-factor authentication",
|
|
149
|
+
twoFactorDesc: "Add a one-time code from your authenticator app at sign-in.",
|
|
150
|
+
twoFactorOn: "Enabled",
|
|
151
|
+
twoFactorOff: "Disabled",
|
|
152
|
+
enable: "Enable",
|
|
153
|
+
disable: "Disable",
|
|
154
|
+
password: "Password",
|
|
155
|
+
scanHint: "Add this to your authenticator app, then enter the 6-digit code.",
|
|
156
|
+
setupKey: "Setup key (otpauth URI)",
|
|
157
|
+
backupCodes: "Backup codes — store them somewhere safe",
|
|
158
|
+
code: "Verification code",
|
|
159
|
+
verify: "Verify",
|
|
160
|
+
twoFactorEnabled: "Two-factor enabled",
|
|
161
|
+
twoFactorDisabled: "Two-factor disabled",
|
|
162
|
+
connectedTitle: "Connected accounts",
|
|
163
|
+
connectedDesc: "Link social accounts to sign in with them.",
|
|
164
|
+
connect: "Connect",
|
|
165
|
+
disconnect: "Disconnect",
|
|
166
|
+
connected: "Connected",
|
|
167
|
+
notConnected: "Not connected",
|
|
168
|
+
disconnected: "Disconnected",
|
|
169
|
+
dangerTitle: "Delete account",
|
|
170
|
+
dangerDesc: "Permanently delete your account and all associated data.",
|
|
171
|
+
deleteAccount: "Delete account",
|
|
172
|
+
deleteAccountConfirm: "This permanently deletes your account and cannot be undone. Enter your password to confirm.",
|
|
173
|
+
accountDeleted: "Account deleted",
|
|
174
|
+
save: "Save changes",
|
|
175
|
+
saved: "Profile updated",
|
|
176
|
+
saveFailed: "Failed to save profile",
|
|
177
|
+
verified: "Verified",
|
|
178
|
+
unverified: "Unverified",
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export type Messages = typeof en;
|
|
183
|
+
|
|
184
|
+
const ko: Messages = {
|
|
185
|
+
common: { appName: "관리자" },
|
|
186
|
+
landing: { title: "환영합니다", subtitle: "앱의 홈 페이지입니다. 원하는 내용으로 교체하세요 — 관리자 기능은 /admin 에 있습니다.", openAdmin: "관리자 열기" },
|
|
187
|
+
language: { label: "언어" },
|
|
188
|
+
theme: { toggle: "테마 전환", light: "라이트", dark: "다크", system: "시스템" },
|
|
189
|
+
auth: {
|
|
190
|
+
signInTitle: "로그인",
|
|
191
|
+
signInDesc: "계속하려면 로그인하세요.",
|
|
192
|
+
email: "이메일",
|
|
193
|
+
password: "비밀번호",
|
|
194
|
+
forgot: "비밀번호 찾기",
|
|
195
|
+
signIn: "로그인",
|
|
196
|
+
signingIn: "로그인 중…",
|
|
197
|
+
noAccount: "계정이 없으신가요?",
|
|
198
|
+
signUp: "회원가입",
|
|
199
|
+
signInFailed: "로그인에 실패했습니다",
|
|
200
|
+
createTitle: "회원가입",
|
|
201
|
+
createDesc: "가입하고 시작하세요.",
|
|
202
|
+
name: "이름",
|
|
203
|
+
create: "계정 만들기",
|
|
204
|
+
creating: "생성 중…",
|
|
205
|
+
haveAccount: "이미 계정이 있으신가요?",
|
|
206
|
+
signUpFailed: "회원가입에 실패했습니다",
|
|
207
|
+
resetTitle: "비밀번호 재설정",
|
|
208
|
+
resetDesc: "이메일로 재설정 링크를 보내드립니다.",
|
|
209
|
+
sendReset: "재설정 링크 보내기",
|
|
210
|
+
sending: "전송 중…",
|
|
211
|
+
resetSent: "해당 이메일이 존재하면 재설정 링크가 전송됩니다.",
|
|
212
|
+
backToSignIn: "로그인으로 돌아가기",
|
|
213
|
+
requestFailed: "요청에 실패했습니다",
|
|
214
|
+
newTitle: "새 비밀번호 설정",
|
|
215
|
+
newPassword: "새 비밀번호",
|
|
216
|
+
updatePassword: "비밀번호 변경",
|
|
217
|
+
updating: "변경 중…",
|
|
218
|
+
missingToken: "재설정 토큰이 없거나 유효하지 않습니다.",
|
|
219
|
+
resetFailed: "재설정에 실패했습니다",
|
|
220
|
+
},
|
|
221
|
+
nav: { overview: "개요", users: "회원", sessions: "세션", audit: "감사 로그", account: "계정", signOut: "로그아웃" },
|
|
222
|
+
dashboard: { title: "대시보드", welcome: "{name}님, 환영합니다.", yourRole: "내 권한", signedInAs: "로그인 계정" },
|
|
223
|
+
audit: { title: "감사 로그", when: "시각", actor: "수행자", action: "동작", target: "대상", ip: "IP", empty: "감사 기록이 없습니다.", loadFailed: "감사 로그를 불러오지 못했습니다", total: "항목 {count}개" },
|
|
224
|
+
users: {
|
|
225
|
+
title: "회원",
|
|
226
|
+
search: "이메일로 검색…",
|
|
227
|
+
name: "이름",
|
|
228
|
+
email: "이메일",
|
|
229
|
+
role: "권한",
|
|
230
|
+
status: "상태",
|
|
231
|
+
active: "활성",
|
|
232
|
+
banned: "차단됨",
|
|
233
|
+
makeUser: "일반 사용자로",
|
|
234
|
+
makeAdmin: "관리자로",
|
|
235
|
+
ban: "차단",
|
|
236
|
+
unban: "차단 해제",
|
|
237
|
+
empty: "회원이 없습니다.",
|
|
238
|
+
total: "회원 {count}명",
|
|
239
|
+
previous: "이전",
|
|
240
|
+
next: "다음",
|
|
241
|
+
roleSet: "권한을 {role}(으)로 변경했습니다",
|
|
242
|
+
userBanned: "회원을 차단했습니다",
|
|
243
|
+
userUnbanned: "차단을 해제했습니다",
|
|
244
|
+
loadFailed: "회원 목록을 불러오지 못했습니다",
|
|
245
|
+
actionFailed: "작업에 실패했습니다",
|
|
246
|
+
addUser: "사용자 추가",
|
|
247
|
+
createTitle: "사용자 생성",
|
|
248
|
+
password: "비밀번호",
|
|
249
|
+
create: "생성",
|
|
250
|
+
cancel: "취소",
|
|
251
|
+
userCreated: "사용자를 생성했습니다",
|
|
252
|
+
setPassword: "비밀번호 설정",
|
|
253
|
+
newPassword: "새 비밀번호",
|
|
254
|
+
save: "저장",
|
|
255
|
+
passwordSet: "비밀번호를 변경했습니다",
|
|
256
|
+
delete: "삭제",
|
|
257
|
+
deleteTitle: "사용자 삭제",
|
|
258
|
+
deleteConfirm: "{email} 사용자를 삭제할까요? 되돌릴 수 없습니다.",
|
|
259
|
+
userDeleted: "사용자를 삭제했습니다",
|
|
260
|
+
confirmPassword: "비밀번호 확인",
|
|
261
|
+
confirmNewPassword: "새 비밀번호 확인",
|
|
262
|
+
passwordMismatch: "비밀번호가 일치하지 않습니다",
|
|
263
|
+
edit: "편집",
|
|
264
|
+
editTitle: "사용자 편집",
|
|
265
|
+
userUpdated: "사용자를 수정했습니다",
|
|
266
|
+
impersonate: "이 사용자로 로그인",
|
|
267
|
+
banTitle: "사용자 차단",
|
|
268
|
+
banReason: "사유 (선택)",
|
|
269
|
+
banExpiryDays: "만료 (일, 선택)",
|
|
270
|
+
stopImpersonating: "대리 로그인 종료",
|
|
271
|
+
impersonatingAs: "{email} 사용자로 대리 로그인 중",
|
|
272
|
+
manage: "관리",
|
|
273
|
+
revokeSession: "종료",
|
|
274
|
+
},
|
|
275
|
+
sessions: {
|
|
276
|
+
title: "활성 세션",
|
|
277
|
+
device: "기기",
|
|
278
|
+
ip: "IP",
|
|
279
|
+
since: "시작",
|
|
280
|
+
revoke: "종료",
|
|
281
|
+
unknown: "알 수 없음",
|
|
282
|
+
empty: "활성 세션이 없습니다.",
|
|
283
|
+
revoked: "세션을 종료했습니다",
|
|
284
|
+
loadFailed: "세션을 불러오지 못했습니다",
|
|
285
|
+
revokeFailed: "세션 종료에 실패했습니다",
|
|
286
|
+
status: "상태",
|
|
287
|
+
current: "현재",
|
|
288
|
+
signOutOthers: "다른 세션 모두 종료",
|
|
289
|
+
othersRevoked: "다른 세션을 모두 종료했습니다",
|
|
290
|
+
total: "세션 {count}개",
|
|
291
|
+
},
|
|
292
|
+
adminSessions: {
|
|
293
|
+
title: "사용자 세션",
|
|
294
|
+
user: "사용자",
|
|
295
|
+
device: "기기",
|
|
296
|
+
ip: "IP",
|
|
297
|
+
since: "시작",
|
|
298
|
+
revoke: "세션 종료",
|
|
299
|
+
revokeAll: "사용자 세션 모두 종료",
|
|
300
|
+
unknown: "알 수 없음",
|
|
301
|
+
empty: "활성 세션이 없습니다.",
|
|
302
|
+
revoked: "세션을 종료했습니다",
|
|
303
|
+
allRevoked: "사용자의 세션을 모두 종료했습니다",
|
|
304
|
+
loadFailed: "세션을 불러오지 못했습니다",
|
|
305
|
+
total: "세션 {count}개",
|
|
306
|
+
},
|
|
307
|
+
account: {
|
|
308
|
+
title: "계정",
|
|
309
|
+
profile: "프로필",
|
|
310
|
+
name: "이름",
|
|
311
|
+
email: "이메일",
|
|
312
|
+
role: "권한",
|
|
313
|
+
changePassword: "비밀번호 변경",
|
|
314
|
+
currentPassword: "현재 비밀번호",
|
|
315
|
+
newPassword: "새 비밀번호",
|
|
316
|
+
update: "비밀번호 변경",
|
|
317
|
+
updating: "변경 중…",
|
|
318
|
+
changed: "비밀번호를 변경했습니다",
|
|
319
|
+
changeFailed: "비밀번호 변경에 실패했습니다",
|
|
320
|
+
nav: { profile: "프로필", security: "보안", connected: "연결", sessions: "세션", danger: "위험 영역" },
|
|
321
|
+
twoFactorTitle: "2단계 인증",
|
|
322
|
+
twoFactorDesc: "로그인 시 인증 앱의 일회용 코드를 추가로 요구합니다.",
|
|
323
|
+
twoFactorOn: "사용 중",
|
|
324
|
+
twoFactorOff: "사용 안 함",
|
|
325
|
+
enable: "사용",
|
|
326
|
+
disable: "해제",
|
|
327
|
+
password: "비밀번호",
|
|
328
|
+
scanHint: "인증 앱에 등록한 뒤 6자리 코드를 입력하세요.",
|
|
329
|
+
setupKey: "설정 키 (otpauth URI)",
|
|
330
|
+
backupCodes: "백업 코드 — 안전한 곳에 보관하세요",
|
|
331
|
+
code: "인증 코드",
|
|
332
|
+
verify: "확인",
|
|
333
|
+
twoFactorEnabled: "2단계 인증을 사용합니다",
|
|
334
|
+
twoFactorDisabled: "2단계 인증을 해제했습니다",
|
|
335
|
+
connectedTitle: "연결된 계정",
|
|
336
|
+
connectedDesc: "소셜 계정을 연결하면 해당 계정으로 로그인할 수 있습니다.",
|
|
337
|
+
connect: "연결",
|
|
338
|
+
disconnect: "연결 해제",
|
|
339
|
+
connected: "연결됨",
|
|
340
|
+
notConnected: "연결 안 됨",
|
|
341
|
+
disconnected: "연결을 해제했습니다",
|
|
342
|
+
dangerTitle: "계정 삭제",
|
|
343
|
+
dangerDesc: "계정과 모든 관련 데이터를 영구히 삭제합니다.",
|
|
344
|
+
deleteAccount: "계정 삭제",
|
|
345
|
+
deleteAccountConfirm: "계정이 영구히 삭제되며 되돌릴 수 없습니다. 확인하려면 비밀번호를 입력하세요.",
|
|
346
|
+
accountDeleted: "계정을 삭제했습니다",
|
|
347
|
+
save: "변경 저장",
|
|
348
|
+
saved: "프로필을 저장했습니다",
|
|
349
|
+
saveFailed: "프로필 저장에 실패했습니다",
|
|
350
|
+
verified: "인증됨",
|
|
351
|
+
unverified: "미인증",
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
export const messages: Record<Locale, Messages> = { en, ko };
|
|
356
|
+
|
|
357
|
+
export function resolveLocale(value: string | undefined | null): Locale {
|
|
358
|
+
return LOCALES.includes(value as Locale) ? (value as Locale) : defaultLocale;
|
|
359
|
+
}
|
package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/+layout.server.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LayoutServerLoad } from "./$types";
|
|
2
|
+
|
|
3
|
+
type Capabilities = { twoFactor: boolean; providers: string[]; deleteAccount: boolean; auditLog: boolean };
|
|
4
|
+
|
|
5
|
+
export const load: LayoutServerLoad = async ({ locals, fetch }) => {
|
|
6
|
+
let capabilities: Capabilities = { twoFactor: false, providers: [], deleteAccount: false, auditLog: false };
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetch("/api/account/capabilities");
|
|
9
|
+
if (res.ok) capabilities = (await res.json()) as Capabilities;
|
|
10
|
+
} catch {
|
|
11
|
+
/* keep defaults */
|
|
12
|
+
}
|
|
13
|
+
return { user: locals.user, impersonating: !!locals.session?.impersonatedBy, capabilities };
|
|
14
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { goto } from "$app/navigation";
|
|
3
|
+
import * as Sidebar from "$lib/components/ui/sidebar";
|
|
4
|
+
import { Separator } from "$lib/components/ui/separator";
|
|
5
|
+
import { Button } from "$lib/components/ui/button";
|
|
6
|
+
import AppSidebar from "$lib/components/app-sidebar.svelte";
|
|
7
|
+
import ThemeToggle from "$lib/components/theme-toggle.svelte";
|
|
8
|
+
import LanguageSwitch from "$lib/components/language-switch.svelte";
|
|
9
|
+
import { Toaster } from "$lib/components/ui/sonner";
|
|
10
|
+
import { api } from "$lib/api";
|
|
11
|
+
import { getI18n } from "$lib/i18n";
|
|
12
|
+
import type { SessionUser } from "../../app.d.ts";
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
children,
|
|
16
|
+
data,
|
|
17
|
+
}: {
|
|
18
|
+
children: import("svelte").Snippet;
|
|
19
|
+
data: { user: SessionUser; impersonating: boolean; capabilities: { auditLog?: boolean } };
|
|
20
|
+
} = $props();
|
|
21
|
+
const i18n = getI18n();
|
|
22
|
+
|
|
23
|
+
async function stopImpersonating(): Promise<void> {
|
|
24
|
+
await api.auth.admin.stopImpersonating();
|
|
25
|
+
await goto("/admin", { invalidateAll: true });
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<Sidebar.Provider>
|
|
30
|
+
<AppSidebar user={data.user} capabilities={data.capabilities} />
|
|
31
|
+
<Sidebar.Inset>
|
|
32
|
+
{#if data.impersonating}
|
|
33
|
+
<div class="bg-primary text-primary-foreground flex items-center justify-between gap-2 px-4 py-2 text-sm">
|
|
34
|
+
<span>{i18n.t.users.impersonatingAs.replace("{email}", data.user.email)}</span>
|
|
35
|
+
<Button variant="secondary" size="sm" onclick={stopImpersonating}>{i18n.t.users.stopImpersonating}</Button>
|
|
36
|
+
</div>
|
|
37
|
+
{/if}
|
|
38
|
+
<header class="flex h-14 items-center gap-2 border-b px-4">
|
|
39
|
+
<Sidebar.Trigger />
|
|
40
|
+
<Separator orientation="vertical" class="mr-2 h-4" />
|
|
41
|
+
<div class="flex-1"></div>
|
|
42
|
+
<LanguageSwitch />
|
|
43
|
+
<ThemeToggle />
|
|
44
|
+
</header>
|
|
45
|
+
<main class="flex-1 overflow-auto p-6">
|
|
46
|
+
{@render children()}
|
|
47
|
+
</main>
|
|
48
|
+
</Sidebar.Inset>
|
|
49
|
+
</Sidebar.Provider>
|
|
50
|
+
<Toaster />
|
package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(app)/admin/+page.svelte
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Card from "$lib/components/ui/card";
|
|
3
|
+
import { getI18n, fmt } from "$lib/i18n";
|
|
4
|
+
import type { SessionUser } from "../../../app.d.ts";
|
|
5
|
+
|
|
6
|
+
let { data }: { data: { user: SessionUser } } = $props();
|
|
7
|
+
const i18n = getI18n();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<div class="flex flex-col gap-6">
|
|
11
|
+
<div>
|
|
12
|
+
<h1 class="text-2xl font-semibold">{i18n.t.dashboard.title}</h1>
|
|
13
|
+
<p class="text-muted-foreground text-sm">{fmt(i18n.t.dashboard.welcome, { name: data.user.name })}</p>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
16
|
+
<Card.Root>
|
|
17
|
+
<Card.Header><Card.Title>{i18n.t.dashboard.yourRole}</Card.Title></Card.Header>
|
|
18
|
+
<Card.Content class="text-2xl font-semibold capitalize">{data.user.role ?? "user"}</Card.Content>
|
|
19
|
+
</Card.Root>
|
|
20
|
+
<Card.Root>
|
|
21
|
+
<Card.Header><Card.Title>{i18n.t.dashboard.signedInAs}</Card.Title></Card.Header>
|
|
22
|
+
<Card.Content class="text-muted-foreground truncate text-sm">{data.user.email}</Card.Content>
|
|
23
|
+
</Card.Root>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|