Fix members routing - restructure as directory for detail page to work

Move members.tsx to members/index.tsx so $memberId.tsx resolves as a
sibling route. Fixes member detail page not loading when navigating
from members list.
This commit is contained in:
Ryan Moon
2026-03-28 13:30:30 -05:00
parent 95bf9472e0
commit f359f92071
4 changed files with 534 additions and 38 deletions

View File

@@ -15,7 +15,7 @@ import {
} from '@/components/ui/dropdown-menu'
import { Search, Plus, MoreVertical, Pencil, Users } from 'lucide-react'
export const Route = createFileRoute('/_authenticated/members')({
export const Route = createFileRoute('/_authenticated/members/')({
validateSearch: (search: Record<string, unknown>) => ({
page: Number(search.page) || 1,
limit: Number(search.limit) || 25,

View File

@@ -0,0 +1,367 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as LoginRouteImport } from './routes/login'
import { Route as AuthenticatedRouteImport } from './routes/_authenticated'
import { Route as AuthenticatedIndexRouteImport } from './routes/_authenticated/index'
import { Route as AuthenticatedHelpRouteImport } from './routes/_authenticated/help'
import { Route as AuthenticatedMembersIndexRouteImport } from './routes/_authenticated/members/index'
import { Route as AuthenticatedAccountsIndexRouteImport } from './routes/_authenticated/accounts/index'
import { Route as AuthenticatedMembersMemberIdRouteImport } from './routes/_authenticated/members/$memberId'
import { Route as AuthenticatedAccountsNewRouteImport } from './routes/_authenticated/accounts/new'
import { Route as AuthenticatedAccountsAccountIdRouteImport } from './routes/_authenticated/accounts/$accountId'
import { Route as AuthenticatedAccountsAccountIdIndexRouteImport } from './routes/_authenticated/accounts/$accountId/index'
import { Route as AuthenticatedAccountsAccountIdTaxExemptionsRouteImport } from './routes/_authenticated/accounts/$accountId/tax-exemptions'
import { Route as AuthenticatedAccountsAccountIdProcessorLinksRouteImport } from './routes/_authenticated/accounts/$accountId/processor-links'
import { Route as AuthenticatedAccountsAccountIdPaymentMethodsRouteImport } from './routes/_authenticated/accounts/$accountId/payment-methods'
import { Route as AuthenticatedAccountsAccountIdMembersRouteImport } from './routes/_authenticated/accounts/$accountId/members'
const LoginRoute = LoginRouteImport.update({
id: '/login',
path: '/login',
getParentRoute: () => rootRouteImport,
} as any)
const AuthenticatedRoute = AuthenticatedRouteImport.update({
id: '/_authenticated',
getParentRoute: () => rootRouteImport,
} as any)
const AuthenticatedIndexRoute = AuthenticatedIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedHelpRoute = AuthenticatedHelpRouteImport.update({
id: '/help',
path: '/help',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedMembersIndexRoute =
AuthenticatedMembersIndexRouteImport.update({
id: '/members/',
path: '/members/',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsIndexRoute =
AuthenticatedAccountsIndexRouteImport.update({
id: '/accounts/',
path: '/accounts/',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedMembersMemberIdRoute =
AuthenticatedMembersMemberIdRouteImport.update({
id: '/members/$memberId',
path: '/members/$memberId',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsNewRoute =
AuthenticatedAccountsNewRouteImport.update({
id: '/accounts/new',
path: '/accounts/new',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsAccountIdRoute =
AuthenticatedAccountsAccountIdRouteImport.update({
id: '/accounts/$accountId',
path: '/accounts/$accountId',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsAccountIdIndexRoute =
AuthenticatedAccountsAccountIdIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => AuthenticatedAccountsAccountIdRoute,
} as any)
const AuthenticatedAccountsAccountIdTaxExemptionsRoute =
AuthenticatedAccountsAccountIdTaxExemptionsRouteImport.update({
id: '/tax-exemptions',
path: '/tax-exemptions',
getParentRoute: () => AuthenticatedAccountsAccountIdRoute,
} as any)
const AuthenticatedAccountsAccountIdProcessorLinksRoute =
AuthenticatedAccountsAccountIdProcessorLinksRouteImport.update({
id: '/processor-links',
path: '/processor-links',
getParentRoute: () => AuthenticatedAccountsAccountIdRoute,
} as any)
const AuthenticatedAccountsAccountIdPaymentMethodsRoute =
AuthenticatedAccountsAccountIdPaymentMethodsRouteImport.update({
id: '/payment-methods',
path: '/payment-methods',
getParentRoute: () => AuthenticatedAccountsAccountIdRoute,
} as any)
const AuthenticatedAccountsAccountIdMembersRoute =
AuthenticatedAccountsAccountIdMembersRouteImport.update({
id: '/members',
path: '/members',
getParentRoute: () => AuthenticatedAccountsAccountIdRoute,
} as any)
export interface FileRoutesByFullPath {
'/': typeof AuthenticatedIndexRoute
'/login': typeof LoginRoute
'/help': typeof AuthenticatedHelpRoute
'/accounts/$accountId': typeof AuthenticatedAccountsAccountIdRouteWithChildren
'/accounts/new': typeof AuthenticatedAccountsNewRoute
'/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/accounts/': typeof AuthenticatedAccountsIndexRoute
'/members/': typeof AuthenticatedMembersIndexRoute
'/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
'/accounts/$accountId/tax-exemptions': typeof AuthenticatedAccountsAccountIdTaxExemptionsRoute
'/accounts/$accountId/': typeof AuthenticatedAccountsAccountIdIndexRoute
}
export interface FileRoutesByTo {
'/login': typeof LoginRoute
'/help': typeof AuthenticatedHelpRoute
'/': typeof AuthenticatedIndexRoute
'/accounts/new': typeof AuthenticatedAccountsNewRoute
'/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/accounts': typeof AuthenticatedAccountsIndexRoute
'/members': typeof AuthenticatedMembersIndexRoute
'/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
'/accounts/$accountId/tax-exemptions': typeof AuthenticatedAccountsAccountIdTaxExemptionsRoute
'/accounts/$accountId': typeof AuthenticatedAccountsAccountIdIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/_authenticated': typeof AuthenticatedRouteWithChildren
'/login': typeof LoginRoute
'/_authenticated/help': typeof AuthenticatedHelpRoute
'/_authenticated/': typeof AuthenticatedIndexRoute
'/_authenticated/accounts/$accountId': typeof AuthenticatedAccountsAccountIdRouteWithChildren
'/_authenticated/accounts/new': typeof AuthenticatedAccountsNewRoute
'/_authenticated/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/_authenticated/accounts/': typeof AuthenticatedAccountsIndexRoute
'/_authenticated/members/': typeof AuthenticatedMembersIndexRoute
'/_authenticated/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/_authenticated/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/_authenticated/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
'/_authenticated/accounts/$accountId/tax-exemptions': typeof AuthenticatedAccountsAccountIdTaxExemptionsRoute
'/_authenticated/accounts/$accountId/': typeof AuthenticatedAccountsAccountIdIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/'
| '/login'
| '/help'
| '/accounts/$accountId'
| '/accounts/new'
| '/members/$memberId'
| '/accounts/'
| '/members/'
| '/accounts/$accountId/members'
| '/accounts/$accountId/payment-methods'
| '/accounts/$accountId/processor-links'
| '/accounts/$accountId/tax-exemptions'
| '/accounts/$accountId/'
fileRoutesByTo: FileRoutesByTo
to:
| '/login'
| '/help'
| '/'
| '/accounts/new'
| '/members/$memberId'
| '/accounts'
| '/members'
| '/accounts/$accountId/members'
| '/accounts/$accountId/payment-methods'
| '/accounts/$accountId/processor-links'
| '/accounts/$accountId/tax-exemptions'
| '/accounts/$accountId'
id:
| '__root__'
| '/_authenticated'
| '/login'
| '/_authenticated/help'
| '/_authenticated/'
| '/_authenticated/accounts/$accountId'
| '/_authenticated/accounts/new'
| '/_authenticated/members/$memberId'
| '/_authenticated/accounts/'
| '/_authenticated/members/'
| '/_authenticated/accounts/$accountId/members'
| '/_authenticated/accounts/$accountId/payment-methods'
| '/_authenticated/accounts/$accountId/processor-links'
| '/_authenticated/accounts/$accountId/tax-exemptions'
| '/_authenticated/accounts/$accountId/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
AuthenticatedRoute: typeof AuthenticatedRouteWithChildren
LoginRoute: typeof LoginRoute
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/login': {
id: '/login'
path: '/login'
fullPath: '/login'
preLoaderRoute: typeof LoginRouteImport
parentRoute: typeof rootRouteImport
}
'/_authenticated': {
id: '/_authenticated'
path: ''
fullPath: '/'
preLoaderRoute: typeof AuthenticatedRouteImport
parentRoute: typeof rootRouteImport
}
'/_authenticated/': {
id: '/_authenticated/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof AuthenticatedIndexRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/help': {
id: '/_authenticated/help'
path: '/help'
fullPath: '/help'
preLoaderRoute: typeof AuthenticatedHelpRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/members/': {
id: '/_authenticated/members/'
path: '/members'
fullPath: '/members/'
preLoaderRoute: typeof AuthenticatedMembersIndexRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/': {
id: '/_authenticated/accounts/'
path: '/accounts'
fullPath: '/accounts/'
preLoaderRoute: typeof AuthenticatedAccountsIndexRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/members/$memberId': {
id: '/_authenticated/members/$memberId'
path: '/members/$memberId'
fullPath: '/members/$memberId'
preLoaderRoute: typeof AuthenticatedMembersMemberIdRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/new': {
id: '/_authenticated/accounts/new'
path: '/accounts/new'
fullPath: '/accounts/new'
preLoaderRoute: typeof AuthenticatedAccountsNewRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/$accountId': {
id: '/_authenticated/accounts/$accountId'
path: '/accounts/$accountId'
fullPath: '/accounts/$accountId'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/$accountId/': {
id: '/_authenticated/accounts/$accountId/'
path: '/'
fullPath: '/accounts/$accountId/'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdIndexRouteImport
parentRoute: typeof AuthenticatedAccountsAccountIdRoute
}
'/_authenticated/accounts/$accountId/tax-exemptions': {
id: '/_authenticated/accounts/$accountId/tax-exemptions'
path: '/tax-exemptions'
fullPath: '/accounts/$accountId/tax-exemptions'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdTaxExemptionsRouteImport
parentRoute: typeof AuthenticatedAccountsAccountIdRoute
}
'/_authenticated/accounts/$accountId/processor-links': {
id: '/_authenticated/accounts/$accountId/processor-links'
path: '/processor-links'
fullPath: '/accounts/$accountId/processor-links'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdProcessorLinksRouteImport
parentRoute: typeof AuthenticatedAccountsAccountIdRoute
}
'/_authenticated/accounts/$accountId/payment-methods': {
id: '/_authenticated/accounts/$accountId/payment-methods'
path: '/payment-methods'
fullPath: '/accounts/$accountId/payment-methods'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdPaymentMethodsRouteImport
parentRoute: typeof AuthenticatedAccountsAccountIdRoute
}
'/_authenticated/accounts/$accountId/members': {
id: '/_authenticated/accounts/$accountId/members'
path: '/members'
fullPath: '/accounts/$accountId/members'
preLoaderRoute: typeof AuthenticatedAccountsAccountIdMembersRouteImport
parentRoute: typeof AuthenticatedAccountsAccountIdRoute
}
}
}
interface AuthenticatedAccountsAccountIdRouteChildren {
AuthenticatedAccountsAccountIdMembersRoute: typeof AuthenticatedAccountsAccountIdMembersRoute
AuthenticatedAccountsAccountIdPaymentMethodsRoute: typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
AuthenticatedAccountsAccountIdProcessorLinksRoute: typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
AuthenticatedAccountsAccountIdTaxExemptionsRoute: typeof AuthenticatedAccountsAccountIdTaxExemptionsRoute
AuthenticatedAccountsAccountIdIndexRoute: typeof AuthenticatedAccountsAccountIdIndexRoute
}
const AuthenticatedAccountsAccountIdRouteChildren: AuthenticatedAccountsAccountIdRouteChildren =
{
AuthenticatedAccountsAccountIdMembersRoute:
AuthenticatedAccountsAccountIdMembersRoute,
AuthenticatedAccountsAccountIdPaymentMethodsRoute:
AuthenticatedAccountsAccountIdPaymentMethodsRoute,
AuthenticatedAccountsAccountIdProcessorLinksRoute:
AuthenticatedAccountsAccountIdProcessorLinksRoute,
AuthenticatedAccountsAccountIdTaxExemptionsRoute:
AuthenticatedAccountsAccountIdTaxExemptionsRoute,
AuthenticatedAccountsAccountIdIndexRoute:
AuthenticatedAccountsAccountIdIndexRoute,
}
const AuthenticatedAccountsAccountIdRouteWithChildren =
AuthenticatedAccountsAccountIdRoute._addFileChildren(
AuthenticatedAccountsAccountIdRouteChildren,
)
interface AuthenticatedRouteChildren {
AuthenticatedHelpRoute: typeof AuthenticatedHelpRoute
AuthenticatedIndexRoute: typeof AuthenticatedIndexRoute
AuthenticatedAccountsAccountIdRoute: typeof AuthenticatedAccountsAccountIdRouteWithChildren
AuthenticatedAccountsNewRoute: typeof AuthenticatedAccountsNewRoute
AuthenticatedMembersMemberIdRoute: typeof AuthenticatedMembersMemberIdRoute
AuthenticatedAccountsIndexRoute: typeof AuthenticatedAccountsIndexRoute
AuthenticatedMembersIndexRoute: typeof AuthenticatedMembersIndexRoute
}
const AuthenticatedRouteChildren: AuthenticatedRouteChildren = {
AuthenticatedHelpRoute: AuthenticatedHelpRoute,
AuthenticatedIndexRoute: AuthenticatedIndexRoute,
AuthenticatedAccountsAccountIdRoute:
AuthenticatedAccountsAccountIdRouteWithChildren,
AuthenticatedAccountsNewRoute: AuthenticatedAccountsNewRoute,
AuthenticatedMembersMemberIdRoute: AuthenticatedMembersMemberIdRoute,
AuthenticatedAccountsIndexRoute: AuthenticatedAccountsIndexRoute,
AuthenticatedMembersIndexRoute: AuthenticatedMembersIndexRoute,
}
const AuthenticatedRouteWithChildren = AuthenticatedRoute._addFileChildren(
AuthenticatedRouteChildren,
)
const rootRouteChildren: RootRouteChildren = {
AuthenticatedRoute: AuthenticatedRouteWithChildren,
LoginRoute: LoginRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

View File

@@ -12,8 +12,8 @@ import { Route as rootRouteImport } from './routes/__root'
import { Route as LoginRouteImport } from './routes/login'
import { Route as AuthenticatedRouteImport } from './routes/_authenticated'
import { Route as AuthenticatedIndexRouteImport } from './routes/_authenticated/index'
import { Route as AuthenticatedMembersRouteImport } from './routes/_authenticated/members'
import { Route as AuthenticatedHelpRouteImport } from './routes/_authenticated/help'
import { Route as AuthenticatedMembersIndexRouteImport } from './routes/_authenticated/members/index'
import { Route as AuthenticatedAccountsIndexRouteImport } from './routes/_authenticated/accounts/index'
import { Route as AuthenticatedMembersMemberIdRouteImport } from './routes/_authenticated/members/$memberId'
import { Route as AuthenticatedAccountsNewRouteImport } from './routes/_authenticated/accounts/new'
@@ -38,16 +38,17 @@ const AuthenticatedIndexRoute = AuthenticatedIndexRouteImport.update({
path: '/',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedMembersRoute = AuthenticatedMembersRouteImport.update({
id: '/members',
path: '/members',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedHelpRoute = AuthenticatedHelpRouteImport.update({
id: '/help',
path: '/help',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedMembersIndexRoute =
AuthenticatedMembersIndexRouteImport.update({
id: '/members/',
path: '/members/',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsIndexRoute =
AuthenticatedAccountsIndexRouteImport.update({
id: '/accounts/',
@@ -56,9 +57,9 @@ const AuthenticatedAccountsIndexRoute =
} as any)
const AuthenticatedMembersMemberIdRoute =
AuthenticatedMembersMemberIdRouteImport.update({
id: '/$memberId',
path: '/$memberId',
getParentRoute: () => AuthenticatedMembersRoute,
id: '/members/$memberId',
path: '/members/$memberId',
getParentRoute: () => AuthenticatedRoute,
} as any)
const AuthenticatedAccountsNewRoute =
AuthenticatedAccountsNewRouteImport.update({
@@ -107,11 +108,11 @@ export interface FileRoutesByFullPath {
'/': typeof AuthenticatedIndexRoute
'/login': typeof LoginRoute
'/help': typeof AuthenticatedHelpRoute
'/members': typeof AuthenticatedMembersRouteWithChildren
'/accounts/$accountId': typeof AuthenticatedAccountsAccountIdRouteWithChildren
'/accounts/new': typeof AuthenticatedAccountsNewRoute
'/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/accounts/': typeof AuthenticatedAccountsIndexRoute
'/members/': typeof AuthenticatedMembersIndexRoute
'/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
@@ -121,11 +122,11 @@ export interface FileRoutesByFullPath {
export interface FileRoutesByTo {
'/login': typeof LoginRoute
'/help': typeof AuthenticatedHelpRoute
'/members': typeof AuthenticatedMembersRouteWithChildren
'/': typeof AuthenticatedIndexRoute
'/accounts/new': typeof AuthenticatedAccountsNewRoute
'/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/accounts': typeof AuthenticatedAccountsIndexRoute
'/members': typeof AuthenticatedMembersIndexRoute
'/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
@@ -137,12 +138,12 @@ export interface FileRoutesById {
'/_authenticated': typeof AuthenticatedRouteWithChildren
'/login': typeof LoginRoute
'/_authenticated/help': typeof AuthenticatedHelpRoute
'/_authenticated/members': typeof AuthenticatedMembersRouteWithChildren
'/_authenticated/': typeof AuthenticatedIndexRoute
'/_authenticated/accounts/$accountId': typeof AuthenticatedAccountsAccountIdRouteWithChildren
'/_authenticated/accounts/new': typeof AuthenticatedAccountsNewRoute
'/_authenticated/members/$memberId': typeof AuthenticatedMembersMemberIdRoute
'/_authenticated/accounts/': typeof AuthenticatedAccountsIndexRoute
'/_authenticated/members/': typeof AuthenticatedMembersIndexRoute
'/_authenticated/accounts/$accountId/members': typeof AuthenticatedAccountsAccountIdMembersRoute
'/_authenticated/accounts/$accountId/payment-methods': typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
'/_authenticated/accounts/$accountId/processor-links': typeof AuthenticatedAccountsAccountIdProcessorLinksRoute
@@ -155,11 +156,11 @@ export interface FileRouteTypes {
| '/'
| '/login'
| '/help'
| '/members'
| '/accounts/$accountId'
| '/accounts/new'
| '/members/$memberId'
| '/accounts/'
| '/members/'
| '/accounts/$accountId/members'
| '/accounts/$accountId/payment-methods'
| '/accounts/$accountId/processor-links'
@@ -169,11 +170,11 @@ export interface FileRouteTypes {
to:
| '/login'
| '/help'
| '/members'
| '/'
| '/accounts/new'
| '/members/$memberId'
| '/accounts'
| '/members'
| '/accounts/$accountId/members'
| '/accounts/$accountId/payment-methods'
| '/accounts/$accountId/processor-links'
@@ -184,12 +185,12 @@ export interface FileRouteTypes {
| '/_authenticated'
| '/login'
| '/_authenticated/help'
| '/_authenticated/members'
| '/_authenticated/'
| '/_authenticated/accounts/$accountId'
| '/_authenticated/accounts/new'
| '/_authenticated/members/$memberId'
| '/_authenticated/accounts/'
| '/_authenticated/members/'
| '/_authenticated/accounts/$accountId/members'
| '/_authenticated/accounts/$accountId/payment-methods'
| '/_authenticated/accounts/$accountId/processor-links'
@@ -225,13 +226,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedIndexRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/members': {
id: '/_authenticated/members'
path: '/members'
fullPath: '/members'
preLoaderRoute: typeof AuthenticatedMembersRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/help': {
id: '/_authenticated/help'
path: '/help'
@@ -239,6 +233,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedHelpRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/members/': {
id: '/_authenticated/members/'
path: '/members'
fullPath: '/members/'
preLoaderRoute: typeof AuthenticatedMembersIndexRouteImport
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/': {
id: '/_authenticated/accounts/'
path: '/accounts'
@@ -248,10 +249,10 @@ declare module '@tanstack/react-router' {
}
'/_authenticated/members/$memberId': {
id: '/_authenticated/members/$memberId'
path: '/$memberId'
path: '/members/$memberId'
fullPath: '/members/$memberId'
preLoaderRoute: typeof AuthenticatedMembersMemberIdRouteImport
parentRoute: typeof AuthenticatedMembersRoute
parentRoute: typeof AuthenticatedRoute
}
'/_authenticated/accounts/new': {
id: '/_authenticated/accounts/new'
@@ -305,17 +306,6 @@ declare module '@tanstack/react-router' {
}
}
interface AuthenticatedMembersRouteChildren {
AuthenticatedMembersMemberIdRoute: typeof AuthenticatedMembersMemberIdRoute
}
const AuthenticatedMembersRouteChildren: AuthenticatedMembersRouteChildren = {
AuthenticatedMembersMemberIdRoute: AuthenticatedMembersMemberIdRoute,
}
const AuthenticatedMembersRouteWithChildren =
AuthenticatedMembersRoute._addFileChildren(AuthenticatedMembersRouteChildren)
interface AuthenticatedAccountsAccountIdRouteChildren {
AuthenticatedAccountsAccountIdMembersRoute: typeof AuthenticatedAccountsAccountIdMembersRoute
AuthenticatedAccountsAccountIdPaymentMethodsRoute: typeof AuthenticatedAccountsAccountIdPaymentMethodsRoute
@@ -345,21 +335,23 @@ const AuthenticatedAccountsAccountIdRouteWithChildren =
interface AuthenticatedRouteChildren {
AuthenticatedHelpRoute: typeof AuthenticatedHelpRoute
AuthenticatedMembersRoute: typeof AuthenticatedMembersRouteWithChildren
AuthenticatedIndexRoute: typeof AuthenticatedIndexRoute
AuthenticatedAccountsAccountIdRoute: typeof AuthenticatedAccountsAccountIdRouteWithChildren
AuthenticatedAccountsNewRoute: typeof AuthenticatedAccountsNewRoute
AuthenticatedMembersMemberIdRoute: typeof AuthenticatedMembersMemberIdRoute
AuthenticatedAccountsIndexRoute: typeof AuthenticatedAccountsIndexRoute
AuthenticatedMembersIndexRoute: typeof AuthenticatedMembersIndexRoute
}
const AuthenticatedRouteChildren: AuthenticatedRouteChildren = {
AuthenticatedHelpRoute: AuthenticatedHelpRoute,
AuthenticatedMembersRoute: AuthenticatedMembersRouteWithChildren,
AuthenticatedIndexRoute: AuthenticatedIndexRoute,
AuthenticatedAccountsAccountIdRoute:
AuthenticatedAccountsAccountIdRouteWithChildren,
AuthenticatedAccountsNewRoute: AuthenticatedAccountsNewRoute,
AuthenticatedMembersMemberIdRoute: AuthenticatedMembersMemberIdRoute,
AuthenticatedAccountsIndexRoute: AuthenticatedAccountsIndexRoute,
AuthenticatedMembersIndexRoute: AuthenticatedMembersIndexRoute,
}
const AuthenticatedRouteWithChildren = AuthenticatedRoute._addFileChildren(

View File

@@ -0,0 +1,137 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import { globalMemberListOptions, type MemberWithAccount } from '@/api/members'
import { usePagination } from '@/hooks/use-pagination'
import { DataTable, type Column } from '@/components/shared/data-table'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Search, Plus, MoreVertical, Pencil, Users } from 'lucide-react'
export const Route = createFileRoute('/_authenticated/members/')({
validateSearch: (search: Record<string, unknown>) => ({
page: Number(search.page) || 1,
limit: Number(search.limit) || 25,
q: (search.q as string) || undefined,
sort: (search.sort as string) || undefined,
order: (search.order as 'asc' | 'desc') || 'asc',
}),
component: MembersListPage,
})
function MembersListPage() {
const navigate = useNavigate()
const { params, setPage, setSearch, setSort } = usePagination()
const [searchInput, setSearchInput] = useState(params.q ?? '')
const { data, isLoading } = useQuery(globalMemberListOptions(params))
function handleSearchSubmit(e: React.FormEvent) {
e.preventDefault()
setSearch(searchInput)
}
const memberColumns: Column<MemberWithAccount>[] = [
{
key: 'memberNumber',
header: '#',
render: (row) => <span className="font-mono text-sm text-muted-foreground">{row.memberNumber ?? '-'}</span>,
},
{
key: 'last_name',
header: 'Name',
sortable: true,
render: (row) => <span className="font-medium">{row.firstName} {row.lastName}</span>,
},
{
key: 'email',
header: 'Email',
sortable: true,
render: (row) => row.email ?? <span className="text-muted-foreground">-</span>,
},
{
key: 'phone',
header: 'Phone',
render: (row) => row.phone ?? <span className="text-muted-foreground">-</span>,
},
{
key: 'accountName',
header: 'Account',
render: (row) => row.accountName ?? <span className="text-muted-foreground">-</span>,
},
{
key: 'status',
header: 'Status',
render: (row) => row.isMinor ? <Badge variant="secondary">Minor</Badge> : <Badge>Adult</Badge>,
},
{
key: 'actions',
header: '',
render: (row) => (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0" onClick={(e) => e.stopPropagation()}>
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => navigate({ to: '/members/$memberId', params: { memberId: row.id } })}>
<Pencil className="mr-2 h-4 w-4" />
Edit
</DropdownMenuItem>
<DropdownMenuItem onClick={() => navigate({ to: '/accounts/$accountId', params: { accountId: row.accountId } })}>
<Users className="mr-2 h-4 w-4" />
View Account
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
),
},
]
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">Members</h1>
<Button onClick={() => navigate({ to: '/accounts/new' })}>
<Plus className="mr-2 h-4 w-4" />
New Member
</Button>
</div>
<form onSubmit={handleSearchSubmit} className="flex gap-2 max-w-sm">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Search members..."
value={searchInput}
onChange={(e) => setSearchInput(e.target.value)}
className="pl-9"
/>
</div>
<Button type="submit" variant="secondary">Search</Button>
</form>
<DataTable
columns={memberColumns}
data={data?.data ?? []}
loading={isLoading}
page={params.page}
totalPages={data?.pagination.totalPages ?? 1}
total={data?.pagination.total ?? 0}
sort={params.sort}
order={params.order}
onPageChange={setPage}
onSort={setSort}
onRowClick={(member) => navigate({ to: '/members/$memberId', params: { memberId: member.id } })}
/>
</div>
)
}