# Directory Structure

This document describes the module organization and folder conventions for the frontend application.

## Overview

```
app/                          # Next.js App Router
├── (marketing)/              # Public marketing pages (i18n)
│   └── [locale]/             # Locale-based routing
└── (app)/                    # Protected application routes
    └── app/                  # Main application routes
modules/                      # Feature modules
├── [feature]/                # Feature module
│   ├── components/           # UI components
│   ├── hooks/                # Custom hooks
│   ├── context/              # React Context
│   ├── lib/                  # Utilities and data transforms
│   └── types/                # Frontend view model types
├── shared/                   # Shared components across features
└── ui/                       # UI component library
middleware.ts                 # Authentication & routing middleware
```

## Module Structure

### Feature Module Pattern

Each feature module should follow this structure:

```
modules/dashboard/
├── components/
│   ├── DashboardHeader.tsx
│   ├── StatsCard.tsx
│   ├── ActivityFeed.tsx
│   └── index.ts              # Barrel export
├── hooks/
│   ├── useDashboardStats.ts
│   ├── useActivityFeed.ts
│   └── index.ts
├── context/
│   ├── DashboardContext.tsx
│   └── index.ts
├── lib/
│   ├── formatters.ts         # Data formatting utilities
│   ├── transformers.ts       # API response transformers
│   └── constants.ts          # Feature-specific constants
├── types/
│   └── index.ts              # View model types
└── index.ts                  # Public API of the module
```

### Component Organization

```
components/
├── [ComponentName].tsx       # Main component file
├── [ComponentName].test.tsx  # Unit tests (if applicable)
└── index.ts                  # Barrel export
```

### Hooks Organization

```
hooks/
├── useFeatureData.ts         # Data fetching hooks
├── useFeatureActions.ts      # Mutation hooks
├── useFeatureState.ts        # Local state hooks
└── index.ts
```

## Shared Modules

### `modules/shared/`

Components and utilities shared across multiple features:

```
shared/
├── components/
│   ├── Layout/               # Layout components
│   ├── Navigation/           # Navigation components
│   ├── DataTable/            # Reusable data tables
│   └── Forms/                # Form components
├── hooks/
│   ├── useUser.ts            # Current user hook
│   ├── useOrganization.ts    # Organization context
│   └── usePermissions.ts     # Permission checks
└── lib/
    ├── api.ts                # API client configuration
    └── utils.ts              # Shared utilities
```

### `modules/ui/`

Low-level UI components (design system):

```
ui/
├── Button/
├── Input/
├── Select/
├── Dialog/
├── Toast/
└── ...
```

## Naming Conventions

### Files

| Type | Convention | Example |
|------|------------|---------|
| Components | PascalCase | `UserProfile.tsx` |
| Hooks | camelCase with `use` prefix | `useUserProfile.ts` |
| Context | PascalCase with `Context` suffix | `UserContext.tsx` |
| Utilities | camelCase | `formatDate.ts` |
| Constants | camelCase or SCREAMING_SNAKE_CASE | `constants.ts` |
| Types | PascalCase | `types.ts` or `UserTypes.ts` |

### Exports

Use barrel exports (`index.ts`) for clean imports:

```typescript
// modules/dashboard/components/index.ts
export { DashboardHeader } from './DashboardHeader';
export { StatsCard } from './StatsCard';
export { ActivityFeed } from './ActivityFeed';
```

```typescript
// Usage
import { DashboardHeader, StatsCard } from '@/modules/dashboard/components';
```

## Route-Module Mapping

Routes in `app/(app)/` should map to modules in `modules/`:

```
app/(app)/
├── dashboard/
│   └── page.tsx          -> modules/dashboard/
├── users/
│   ├── page.tsx          -> modules/users/
│   └── [id]/
│       └── page.tsx      -> modules/users/ (detail view)
├── settings/
│   └── page.tsx          -> modules/settings/
└── orders/
    ├── page.tsx          -> modules/orders/
    └── [id]/
        └── page.tsx      -> modules/orders/ (detail view)
```

## Scenario: Organization-Scoped Workspace Routes

### 1. Scope / Trigger

- Trigger: adding or changing protected app workspace routes, app-shell navigation, breadcrumbs, login redirects, organization switching, or settings pagination links.
- The current workspace URL must include the active organization slug when an organization is selected.

### 2. Signatures

- Canonical workspace route: `/app/[organizationSlug]/<workspacePath>`.
- Legacy-compatible route: `/app/<workspacePath>` may remain available while old links are migrated.
- Shared helpers live in `modules/shared/lib/workspace-routing.ts`:
  - `getWorkspaceHref(organizationSlug: string | undefined, path?: string): string`
  - `getWorkspacePathFromPathname(pathname: string): string`
  - `getWorkspaceSlugFromPathname(pathname: string): string | undefined`
  - `isWorkspacePathActive(pathname: string, itemPath: string): boolean`

### 3. Contracts

- `navGroups` stores workspace-local paths such as `/dashboard`, `/settings/users`, not full `/app/...` hrefs.
- `AppShell` passes the current `organization.slug` into navigation and logo links.
- `AppSidebarNav`, `AppBreadcrumbs`, settings search forms, and pagination must generate hrefs with `getWorkspaceHref(...)`.
- The `[organizationSlug]` layout must reject slug/session mismatches by redirecting to the active session organization workspace.
- Organization slugs cannot use reserved first-level workspace section keys such as `dashboard`, `settings`, `elders`, or `beds`.

### 4. Validation & Error Matrix

- Missing active organization slug -> helpers fall back to legacy `/app/<workspacePath>`.
- URL slug differs from `getCurrentAuthContext().organization.slug` -> redirect to `getWorkspaceHref(activeSlug, "/dashboard")`.
- New or updated organization slug equals a reserved workspace key -> API returns validation failure.
- A page-level redirect inside protected routes -> use `getWorkspaceHref(context.organization?.slug, targetPath)`.

### 5. Good/Base/Bad Cases

- Good: organization switch calls `POST /api/auth/organization`, then navigates to the same workspace path under the returned active organization slug.
- Base: legacy `/app/dashboard` remains renderable for compatibility, but new app-shell links point to `/app/{slug}/dashboard`.
- Bad: hard-code `/app/settings/users` in table forms or breadcrumbs; it drops users out of the organization-scoped workspace.
- Bad: infer tenant from `localStorage`; active organization remains server-session state.

### 6. Tests Required

- `pnpm lint`
- `pnpm type-check`
- `pnpm build`
- Browser assertions:
  - login/setup lands on `/app/{activeOrg.slug}/dashboard`
  - sidebar links preserve the active organization slug
  - settings search and pagination preserve the active organization slug
  - switching organization moves the URL to the new slug while preserving the workspace path
  - mismatched `/app/{wrongSlug}/...` redirects to the active organization workspace

### 7. Wrong vs Correct

#### Wrong

```tsx
<Link href="/app/settings/users">用户管理</Link>
```

#### Correct

```tsx
<Link href={getWorkspaceHref(organization.slug, "/settings/users")}>用户管理</Link>
```

## Import Path Aliases

Configure in `tsconfig.json`:

```json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"],
      "@/modules/*": ["./modules/*"],
      "@/components/*": ["./components/*"],
      "@/lib/*": ["./lib/*"]
    }
  }
}
```

## Best Practices

1. **Colocation**: Keep related files close together
2. **Single Responsibility**: Each module should have one clear purpose
3. **Explicit Dependencies**: Import what you need, avoid implicit globals
4. **Barrel Exports**: Use `index.ts` for public APIs
5. **Private by Default**: Only export what needs to be shared

## Anti-Patterns to Avoid

- Deeply nested folder structures (max 3-4 levels)
- Circular dependencies between modules
- Mixing feature code with shared utilities
- Importing internal module files directly (use barrel exports)
- Creating "utils" folders that become dumping grounds
