diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 168ecf5..664057c 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -401,3 +401,11 @@ Plans: Plans: - [ ] TBD (promote with /gsd:review-backlog when ready) + +### Phase 999.12: Admin UX Polish (BACKLOG) +**Goal**: Overhaul admin panel UX with TanStack Table (sortable/groupable columns) and cmdk (GitLab-style composable filter bar with field→operator→value token input). Hide FAB on /admin/* pages. Replace tag inline form with popup modal. Show tags expanded on item rows (collapse to +N when tight). Group items by brand. Prominent search bar on both admin list pages. +**Requirements**: TBD +**Plans**: TBD + +Plans: +- [ ] TBD (promote with /gsd:review-backlog when ready) diff --git a/.planning/phases/35-bug-fixes/35-UAT.md b/.planning/phases/35-bug-fixes/35-UAT.md new file mode 100644 index 0000000..95af424 --- /dev/null +++ b/.planning/phases/35-bug-fixes/35-UAT.md @@ -0,0 +1,74 @@ +--- +status: complete +phase: 35-bug-fixes +source: [35-01-SUMMARY.md, 35-02-SUMMARY.md, 35-03-SUMMARY.md] +started: 2026-04-20T00:00:00.000Z +updated: 2026-04-20T00:01:00.000Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Thread Add Candidate Opens Catalog Search +expected: On a thread detail page, clicking "Add Candidate" opens the CatalogSearchOverlay (same overlay used elsewhere), not a local modal form. +result: pass + +### 2. Image Skeleton and Fade-In on Cards +expected: On collection, thread candidates, or catalog pages, images show a gray pulsing skeleton placeholder while loading. Once the image loads, it fades in smoothly (opacity transition). Cards without images show the category icon placeholder as before. +result: pass + +### 3. Login Page Redirects to OIDC +expected: Navigating to /login immediately redirects to the Logto OIDC provider. No sign-in card or button is shown — at most a brief "Signing in..." text before the redirect. +result: pass + +### 4. Cursor Pointer on Interactive Elements +expected: Hovering over clickable ItemCards (in collection), FabMenu buttons, and BottomTabBar tab buttons shows a pointer cursor. Non-navigable ItemCards (e.g., in setup view) keep the default cursor. +result: issue +reported: "cursor-pointer missing on add-to-collection and thread buttons on item details page, and the small instant-add button in catalog search" +severity: minor + +## Summary + +total: 4 +passed: 3 +issues: 1 +pending: 0 +skipped: 0 +blocked: 0 + +## Gaps + +- truth: "All interactive elements show cursor-pointer on hover" + status: failed + reason: "User reported: cursor-pointer missing on add-to-collection and thread buttons on item details page, and the small instant-add button in catalog search" + severity: minor + test: 4 + artifacts: [] + missing: [] + +- truth: "CatalogSearchOverlay z-index should not cover the UserMenu dropdown" + status: failed + reason: "User reported: the add candidate global search lays above the context menu which opens when clicking the avatar" + severity: minor + test: bonus + artifacts: [] + missing: [] + +- truth: "Catalog search instant-add button persists after inspecting an item and returning" + status: failed + reason: "User reported: when adding an item, you click on one to inspect it, then go back to the search, the small instant-add button isn't there" + severity: major + test: bonus + artifacts: [] + missing: [] + +- truth: "Thread creation dialog uses the CategoryPicker component" + status: failed + reason: "User reported: new thread creation dialogue doesn't use the category selector component but instead uses its own" + severity: minor + test: bonus + artifacts: [] + missing: [] diff --git a/.planning/phases/36-admin-role-panel-foundation/36-UAT.md b/.planning/phases/36-admin-role-panel-foundation/36-UAT.md new file mode 100644 index 0000000..beb2ced --- /dev/null +++ b/.planning/phases/36-admin-role-panel-foundation/36-UAT.md @@ -0,0 +1,42 @@ +--- +status: complete +phase: 36-admin-role-panel-foundation +source: [36-01-SUMMARY.md, 36-02-SUMMARY.md] +started: 2026-04-20T00:02:00.000Z +updated: 2026-04-20T00:03:00.000Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Admin Link in UserMenu +expected: As an admin user, clicking the avatar/user menu shows an "Admin" link at the top of the dropdown (with a shield icon). Non-admin users do not see this link. +result: pass + +### 2. Admin Panel Access and Guard +expected: Navigating to /admin as an admin user shows the admin panel with a sidebar. Non-admin users are redirected to /. +result: pass + +### 3. Admin Sidebar Navigation +expected: The admin sidebar shows "Items" and "Tags" links. Both are clickable (not disabled/greyed out). +result: pass + +### 4. Admin API Protection +expected: Hitting /api/admin/ as a non-admin user returns 403 Forbidden. Unauthenticated requests return 401. +result: pass + +## Summary + +total: 4 +passed: 4 +issues: 0 +pending: 0 +skipped: 0 +blocked: 0 + +## Gaps + +[none] diff --git a/.planning/phases/37-admin-global-item-management/37-UAT.md b/.planning/phases/37-admin-global-item-management/37-UAT.md new file mode 100644 index 0000000..48ef9a0 --- /dev/null +++ b/.planning/phases/37-admin-global-item-management/37-UAT.md @@ -0,0 +1,60 @@ +--- +status: complete +phase: 37-admin-global-item-management +source: [37-01-SUMMARY.md, 37-02-SUMMARY.md] +started: 2026-04-20T00:04:00.000Z +updated: 2026-04-20T00:05:00.000Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Admin Items List Page +expected: Navigating to /admin/items shows a data table of all global catalog items with search input, tag filter chips, skeleton loading state, and infinite scroll when there are many items. +result: pass + +### 2. Admin Items Search and Filter +expected: Typing in the search input filters items by name. Clicking tag filter chips narrows results to items with that tag. Both work together. +result: pass + +### 3. Admin Item Edit Page +expected: Clicking an item in the list navigates to its edit page showing all fields (name, manufacturer, weight, price, etc.), a manufacturer dropdown, and a TagInput chip component for managing tags. +result: issue +reported: "nothing happening when clicking an item in the list" +severity: major + +### 4. Admin Item Delete with Confirmation +expected: On the edit page, clicking "Delete" shows a confirmation dialog that mentions how many users have this item in their collection (ownerCount). Confirming deletes the item and returns to the list. +result: issue +reported: "navigating directly to /admin/items/1 still shows the catalogue list, edit page doesn't render" +severity: major + +## Summary + +total: 4 +passed: 2 +issues: 2 +pending: 0 +skipped: 0 +blocked: 0 + +## Gaps + +- truth: "Clicking an item in the admin items list navigates to its edit page" + status: failed + reason: "User reported: nothing happening when clicking an item in the list" + severity: major + test: 3 + artifacts: [] + missing: [] + +- truth: "Admin item edit page renders at /admin/items/$itemId" + status: failed + reason: "User reported: navigating directly to /admin/items/1 still shows the catalogue list, edit page doesn't render" + severity: major + test: 4 + artifacts: [] + missing: [] diff --git a/.planning/phases/38-admin-tag-management/38-UAT.md b/.planning/phases/38-admin-tag-management/38-UAT.md new file mode 100644 index 0000000..d4b2e3b --- /dev/null +++ b/.planning/phases/38-admin-tag-management/38-UAT.md @@ -0,0 +1,70 @@ +--- +status: complete +phase: 38-admin-tag-management +source: [38-01-SUMMARY.md, 38-02-SUMMARY.md] +started: 2026-04-20T00:06:00.000Z +updated: 2026-04-20T00:07:00.000Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Tag List with Tree View +expected: Navigating to /admin/tags shows a collapsible tree view of all tags. Tags with children have a chevron to expand/collapse. Indentation shows hierarchy. Search input filters the tree in place. +result: pass + +### 2. Quick-Add Tag +expected: An inline form at the top lets you type a tag name, optionally pick a parent from a dropdown (default: "No parent (top-level)"), and click "Add Tag" to create it. The new tag appears in the tree immediately. +result: issue +reported: "creating a duplicate tag shows unknown error because backend returns 500 instead of proper error. also the inline form is ugly and hard to navigate" +severity: minor + +### 3. Tag Edit Page — Rename and Reparent +expected: Clicking a tag navigates to /admin/tags/$tagId showing a name field and a parent picker dropdown. The parent picker excludes the current tag and all its descendants (cycle prevention). Saving updates the tag. +result: issue +reported: "navigates to correct URL (e.g. /admin/tags/4) but still shows the tag list view, edit page doesn't render" +severity: major + +### 4. Tag Delete with Impact Confirmation +expected: On the tag edit page, clicking "Delete Tag" shows a confirmation dialog mentioning how many items use this tag and how many child tags it has. Confirming deletes the tag and returns to the list. +result: blocked +blocked_by: other +reason: "edit page doesn't render due to same routing issue as Phase 37" + +## Summary + +total: 4 +passed: 1 +issues: 2 +pending: 0 +skipped: 0 +blocked: 1 + +## Gaps + +- truth: "Duplicate tag name returns a user-friendly error message" + status: failed + reason: "User reported: backend returns 500, UI shows unknown error" + severity: minor + test: 2 + artifacts: [] + missing: [] + +- truth: "Inline tag creation form is usable and visually consistent" + status: failed + reason: "User reported: the inline form is ugly and hard to navigate" + severity: cosmetic + test: 2 + artifacts: [] + missing: [] + +- truth: "Admin tag edit page renders at /admin/tags/$tagId" + status: failed + reason: "User reported: navigates to correct URL but still shows the tag list view, edit page doesn't render" + severity: major + test: 3 + artifacts: [] + missing: [] diff --git a/.planning/phases/999.12-admin-ux-polish/.gitkeep b/.planning/phases/999.12-admin-ux-polish/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/client/routeTree.gen.ts b/src/client/routeTree.gen.ts index 315b76e..2117de4 100644 --- a/src/client/routeTree.gen.ts +++ b/src/client/routeTree.gen.ts @@ -22,11 +22,11 @@ import { Route as UsersUserIdRouteImport } from './routes/users/$userId' import { Route as SetupsSetupIdRouteImport } from './routes/setups/$setupId' import { Route as ItemsItemIdRouteImport } from './routes/items/$itemId' import { Route as GlobalItemsGlobalItemIdRouteImport } from './routes/global-items/$globalItemId' -import { Route as AdminTagsRouteImport } from './routes/admin/tags' -import { Route as AdminItemsRouteImport } from './routes/admin/items' import { Route as ThreadsThreadIdIndexRouteImport } from './routes/threads/$threadId/index' -import { Route as AdminTagsTagIdRouteImport } from './routes/admin/tags.$tagId' -import { Route as AdminItemsItemIdRouteImport } from './routes/admin/items.$itemId' +import { Route as AdminTagsIndexRouteImport } from './routes/admin/tags/index' +import { Route as AdminItemsIndexRouteImport } from './routes/admin/items/index' +import { Route as AdminTagsTagIdRouteImport } from './routes/admin/tags/$tagId' +import { Route as AdminItemsItemIdRouteImport } from './routes/admin/items/$itemId' import { Route as ThreadsThreadIdCandidatesCandidateIdRouteImport } from './routes/threads/$threadId/candidates/$candidateId' const SettingsRoute = SettingsRouteImport.update({ @@ -94,30 +94,30 @@ const GlobalItemsGlobalItemIdRoute = GlobalItemsGlobalItemIdRouteImport.update({ path: '/global-items/$globalItemId', getParentRoute: () => rootRouteImport, } as any) -const AdminTagsRoute = AdminTagsRouteImport.update({ - id: '/tags', - path: '/tags', - getParentRoute: () => AdminRoute, -} as any) -const AdminItemsRoute = AdminItemsRouteImport.update({ - id: '/items', - path: '/items', - getParentRoute: () => AdminRoute, -} as any) const ThreadsThreadIdIndexRoute = ThreadsThreadIdIndexRouteImport.update({ id: '/threads/$threadId/', path: '/threads/$threadId/', getParentRoute: () => rootRouteImport, } as any) +const AdminTagsIndexRoute = AdminTagsIndexRouteImport.update({ + id: '/tags/', + path: '/tags/', + getParentRoute: () => AdminRoute, +} as any) +const AdminItemsIndexRoute = AdminItemsIndexRouteImport.update({ + id: '/items/', + path: '/items/', + getParentRoute: () => AdminRoute, +} as any) const AdminTagsTagIdRoute = AdminTagsTagIdRouteImport.update({ - id: '/$tagId', - path: '/$tagId', - getParentRoute: () => AdminTagsRoute, + id: '/tags/$tagId', + path: '/tags/$tagId', + getParentRoute: () => AdminRoute, } as any) const AdminItemsItemIdRoute = AdminItemsItemIdRouteImport.update({ - id: '/$itemId', - path: '/$itemId', - getParentRoute: () => AdminItemsRoute, + id: '/items/$itemId', + path: '/items/$itemId', + getParentRoute: () => AdminRoute, } as any) const ThreadsThreadIdCandidatesCandidateIdRoute = ThreadsThreadIdCandidatesCandidateIdRouteImport.update({ @@ -132,8 +132,6 @@ export interface FileRoutesByFullPath { '/login': typeof LoginRoute '/profile': typeof ProfileRoute '/settings': typeof SettingsRoute - '/admin/items': typeof AdminItemsRouteWithChildren - '/admin/tags': typeof AdminTagsRouteWithChildren '/global-items/$globalItemId': typeof GlobalItemsGlobalItemIdRoute '/items/$itemId': typeof ItemsItemIdRoute '/setups/$setupId': typeof SetupsSetupIdRoute @@ -144,6 +142,8 @@ export interface FileRoutesByFullPath { '/setups/': typeof SetupsIndexRoute '/admin/items/$itemId': typeof AdminItemsItemIdRoute '/admin/tags/$tagId': typeof AdminTagsTagIdRoute + '/admin/items/': typeof AdminItemsIndexRoute + '/admin/tags/': typeof AdminTagsIndexRoute '/threads/$threadId/': typeof ThreadsThreadIdIndexRoute '/threads/$threadId/candidates/$candidateId': typeof ThreadsThreadIdCandidatesCandidateIdRoute } @@ -152,8 +152,6 @@ export interface FileRoutesByTo { '/login': typeof LoginRoute '/profile': typeof ProfileRoute '/settings': typeof SettingsRoute - '/admin/items': typeof AdminItemsRouteWithChildren - '/admin/tags': typeof AdminTagsRouteWithChildren '/global-items/$globalItemId': typeof GlobalItemsGlobalItemIdRoute '/items/$itemId': typeof ItemsItemIdRoute '/setups/$setupId': typeof SetupsSetupIdRoute @@ -164,6 +162,8 @@ export interface FileRoutesByTo { '/setups': typeof SetupsIndexRoute '/admin/items/$itemId': typeof AdminItemsItemIdRoute '/admin/tags/$tagId': typeof AdminTagsTagIdRoute + '/admin/items': typeof AdminItemsIndexRoute + '/admin/tags': typeof AdminTagsIndexRoute '/threads/$threadId': typeof ThreadsThreadIdIndexRoute '/threads/$threadId/candidates/$candidateId': typeof ThreadsThreadIdCandidatesCandidateIdRoute } @@ -174,8 +174,6 @@ export interface FileRoutesById { '/login': typeof LoginRoute '/profile': typeof ProfileRoute '/settings': typeof SettingsRoute - '/admin/items': typeof AdminItemsRouteWithChildren - '/admin/tags': typeof AdminTagsRouteWithChildren '/global-items/$globalItemId': typeof GlobalItemsGlobalItemIdRoute '/items/$itemId': typeof ItemsItemIdRoute '/setups/$setupId': typeof SetupsSetupIdRoute @@ -186,6 +184,8 @@ export interface FileRoutesById { '/setups/': typeof SetupsIndexRoute '/admin/items/$itemId': typeof AdminItemsItemIdRoute '/admin/tags/$tagId': typeof AdminTagsTagIdRoute + '/admin/items/': typeof AdminItemsIndexRoute + '/admin/tags/': typeof AdminTagsIndexRoute '/threads/$threadId/': typeof ThreadsThreadIdIndexRoute '/threads/$threadId/candidates/$candidateId': typeof ThreadsThreadIdCandidatesCandidateIdRoute } @@ -197,8 +197,6 @@ export interface FileRouteTypes { | '/login' | '/profile' | '/settings' - | '/admin/items' - | '/admin/tags' | '/global-items/$globalItemId' | '/items/$itemId' | '/setups/$setupId' @@ -209,6 +207,8 @@ export interface FileRouteTypes { | '/setups/' | '/admin/items/$itemId' | '/admin/tags/$tagId' + | '/admin/items/' + | '/admin/tags/' | '/threads/$threadId/' | '/threads/$threadId/candidates/$candidateId' fileRoutesByTo: FileRoutesByTo @@ -217,8 +217,6 @@ export interface FileRouteTypes { | '/login' | '/profile' | '/settings' - | '/admin/items' - | '/admin/tags' | '/global-items/$globalItemId' | '/items/$itemId' | '/setups/$setupId' @@ -229,6 +227,8 @@ export interface FileRouteTypes { | '/setups' | '/admin/items/$itemId' | '/admin/tags/$tagId' + | '/admin/items' + | '/admin/tags' | '/threads/$threadId' | '/threads/$threadId/candidates/$candidateId' id: @@ -238,8 +238,6 @@ export interface FileRouteTypes { | '/login' | '/profile' | '/settings' - | '/admin/items' - | '/admin/tags' | '/global-items/$globalItemId' | '/items/$itemId' | '/setups/$setupId' @@ -250,6 +248,8 @@ export interface FileRouteTypes { | '/setups/' | '/admin/items/$itemId' | '/admin/tags/$tagId' + | '/admin/items/' + | '/admin/tags/' | '/threads/$threadId/' | '/threads/$threadId/candidates/$candidateId' fileRoutesById: FileRoutesById @@ -364,20 +364,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof GlobalItemsGlobalItemIdRouteImport parentRoute: typeof rootRouteImport } - '/admin/tags': { - id: '/admin/tags' - path: '/tags' - fullPath: '/admin/tags' - preLoaderRoute: typeof AdminTagsRouteImport - parentRoute: typeof AdminRoute - } - '/admin/items': { - id: '/admin/items' - path: '/items' - fullPath: '/admin/items' - preLoaderRoute: typeof AdminItemsRouteImport - parentRoute: typeof AdminRoute - } '/threads/$threadId/': { id: '/threads/$threadId/' path: '/threads/$threadId' @@ -385,19 +371,33 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ThreadsThreadIdIndexRouteImport parentRoute: typeof rootRouteImport } + '/admin/tags/': { + id: '/admin/tags/' + path: '/tags' + fullPath: '/admin/tags/' + preLoaderRoute: typeof AdminTagsIndexRouteImport + parentRoute: typeof AdminRoute + } + '/admin/items/': { + id: '/admin/items/' + path: '/items' + fullPath: '/admin/items/' + preLoaderRoute: typeof AdminItemsIndexRouteImport + parentRoute: typeof AdminRoute + } '/admin/tags/$tagId': { id: '/admin/tags/$tagId' - path: '/$tagId' + path: '/tags/$tagId' fullPath: '/admin/tags/$tagId' preLoaderRoute: typeof AdminTagsTagIdRouteImport - parentRoute: typeof AdminTagsRoute + parentRoute: typeof AdminRoute } '/admin/items/$itemId': { id: '/admin/items/$itemId' - path: '/$itemId' + path: '/items/$itemId' fullPath: '/admin/items/$itemId' preLoaderRoute: typeof AdminItemsItemIdRouteImport - parentRoute: typeof AdminItemsRoute + parentRoute: typeof AdminRoute } '/threads/$threadId/candidates/$candidateId': { id: '/threads/$threadId/candidates/$candidateId' @@ -409,40 +409,20 @@ declare module '@tanstack/react-router' { } } -interface AdminItemsRouteChildren { - AdminItemsItemIdRoute: typeof AdminItemsItemIdRoute -} - -const AdminItemsRouteChildren: AdminItemsRouteChildren = { - AdminItemsItemIdRoute: AdminItemsItemIdRoute, -} - -const AdminItemsRouteWithChildren = AdminItemsRoute._addFileChildren( - AdminItemsRouteChildren, -) - -interface AdminTagsRouteChildren { - AdminTagsTagIdRoute: typeof AdminTagsTagIdRoute -} - -const AdminTagsRouteChildren: AdminTagsRouteChildren = { - AdminTagsTagIdRoute: AdminTagsTagIdRoute, -} - -const AdminTagsRouteWithChildren = AdminTagsRoute._addFileChildren( - AdminTagsRouteChildren, -) - interface AdminRouteChildren { - AdminItemsRoute: typeof AdminItemsRouteWithChildren - AdminTagsRoute: typeof AdminTagsRouteWithChildren AdminIndexRoute: typeof AdminIndexRoute + AdminItemsItemIdRoute: typeof AdminItemsItemIdRoute + AdminTagsTagIdRoute: typeof AdminTagsTagIdRoute + AdminItemsIndexRoute: typeof AdminItemsIndexRoute + AdminTagsIndexRoute: typeof AdminTagsIndexRoute } const AdminRouteChildren: AdminRouteChildren = { - AdminItemsRoute: AdminItemsRouteWithChildren, - AdminTagsRoute: AdminTagsRouteWithChildren, AdminIndexRoute: AdminIndexRoute, + AdminItemsItemIdRoute: AdminItemsItemIdRoute, + AdminTagsTagIdRoute: AdminTagsTagIdRoute, + AdminItemsIndexRoute: AdminItemsIndexRoute, + AdminTagsIndexRoute: AdminTagsIndexRoute, } const AdminRouteWithChildren = AdminRoute._addFileChildren(AdminRouteChildren) diff --git a/src/client/routes/admin/items.$itemId.tsx b/src/client/routes/admin/items/$itemId.tsx similarity index 99% rename from src/client/routes/admin/items.$itemId.tsx rename to src/client/routes/admin/items/$itemId.tsx index 56c1c79..22bc011 100644 --- a/src/client/routes/admin/items.$itemId.tsx +++ b/src/client/routes/admin/items/$itemId.tsx @@ -4,8 +4,8 @@ import { useAdminGlobalItem, useDeleteAdminGlobalItem, useUpdateAdminGlobalItem, -} from "../../hooks/useAdminGlobalItems"; -import { apiGet } from "../../lib/api"; +} from "../../../hooks/useAdminGlobalItems"; +import { apiGet } from "../../../lib/api"; export const Route = createFileRoute("/admin/items/$itemId")({ component: AdminItemEditPage, diff --git a/src/client/routes/admin/items.tsx b/src/client/routes/admin/items/index.tsx similarity index 96% rename from src/client/routes/admin/items.tsx rename to src/client/routes/admin/items/index.tsx index 0fa40da..a92194b 100644 --- a/src/client/routes/admin/items.tsx +++ b/src/client/routes/admin/items/index.tsx @@ -1,10 +1,10 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { useEffect, useRef, useState } from "react"; -import { useAdminGlobalItems } from "../../hooks/useAdminGlobalItems"; -import { useFormatters } from "../../hooks/useFormatters"; -import { useTags } from "../../hooks/useTags"; +import { useAdminGlobalItems } from "../../../hooks/useAdminGlobalItems"; +import { useFormatters } from "../../../hooks/useFormatters"; +import { useTags } from "../../../hooks/useTags"; -export const Route = createFileRoute("/admin/items")({ +export const Route = createFileRoute("/admin/items/")({ component: AdminItemsPage, }); diff --git a/src/client/routes/admin/tags.$tagId.tsx b/src/client/routes/admin/tags/$tagId.tsx similarity index 99% rename from src/client/routes/admin/tags.$tagId.tsx rename to src/client/routes/admin/tags/$tagId.tsx index c652a3a..4c0c2fb 100644 --- a/src/client/routes/admin/tags.$tagId.tsx +++ b/src/client/routes/admin/tags/$tagId.tsx @@ -6,7 +6,7 @@ import { useAdminTags, useDeleteAdminTag, useUpdateAdminTag, -} from "../../hooks/useAdminTags"; +} from "../../../hooks/useAdminTags"; export const Route = createFileRoute("/admin/tags/$tagId")({ component: AdminTagEditPage, diff --git a/src/client/routes/admin/tags.tsx b/src/client/routes/admin/tags/index.tsx similarity index 98% rename from src/client/routes/admin/tags.tsx rename to src/client/routes/admin/tags/index.tsx index d43c919..e70ee1a 100644 --- a/src/client/routes/admin/tags.tsx +++ b/src/client/routes/admin/tags/index.tsx @@ -4,10 +4,10 @@ import { type AdminTag, useAdminTags, useCreateAdminTag, -} from "../../hooks/useAdminTags"; -import { LucideIcon } from "../../lib/iconData"; +} from "../../../hooks/useAdminTags"; +import { LucideIcon } from "../../../lib/iconData"; -export const Route = createFileRoute("/admin/tags")({ +export const Route = createFileRoute("/admin/tags/")({ component: AdminTagsPage, });