Remove PRD files and add prd/ to .gitignore

This commit is contained in:
Justin Edmund 2025-09-03 16:24:16 -07:00
parent 1d9bd18848
commit d75eb0afb1
5 changed files with 3 additions and 857 deletions

3
.gitignore vendored
View file

@ -87,3 +87,6 @@ typings/
.DS_Store .DS_Store
*.tsbuildinfo *.tsbuildinfo
codebase.md codebase.md
# PRDs
prd/

View file

@ -1,209 +0,0 @@
# App Router Migration PRD
## Overview
Complete migration from Next.js Pages Router to App Router by updating all components to use `next/navigation` instead of `next/router`.
## Migration Requirements
### Router API Changes
- `useRouter()` from `next/router``useRouter()` from `next/navigation`
- `router.query``useSearchParams()` hook
- `router.pathname``usePathname()` hook
- `router.asPath` → combination of `usePathname()` + `useSearchParams()`
- `router.push()` → stays the same
- `router.replace()` → stays the same
- `router.back()` → stays the same
- `router.reload()``router.refresh()`
- `router.prefetch()` → stays the same
- `router.beforePopState()` → not available in App Router (needs alternative)
- `router.events` → not available in App Router (needs alternative)
### Import Updates Required
All imports need to change from:
```tsx
import { useRouter } from 'next/router'
```
To:
```tsx
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
```
## Files to Migrate
### App Directory Files (Already using next/navigation - 6 files)
These files already use `next/navigation` but should be verified:
- [ ] `/app/teams/TeamsPageClient.tsx`
- [ ] `/app/saved/SavedPageClient.tsx`
- [ ] `/app/p/[party]/PartyPageClient.tsx`
- [ ] `/app/new/NewPartyClient.tsx`
- [ ] `/app/components/Header.tsx`
- [ ] `/app/[username]/ProfilePageClient.tsx`
### Pages Directory Files (1 file)
- [ ] `/pages/about.tsx` - Needs migration to app router or update imports
### Component Files - Auth (3 files)
- [x] `/components/auth/LoginModal/index.tsx`
- [x] `/components/auth/SignupModal/index.tsx`
- [x] `/components/auth/AccountModal/index.tsx`
### Component Files - Character (5 files)
- [x] `/components/character/CharacterUnit/index.tsx`
- [x] `/components/character/CharacterModal/index.tsx`
- [x] `/components/character/CharacterHovercard/index.tsx`
- [x] `/components/character/CharacterConflictModal/index.tsx`
- [x] `/components/character/CharacterResult/index.tsx`
### Component Files - Weapon (7 files)
- [x] `/components/weapon/WeaponUnit/index.tsx`
- [x] `/components/weapon/WeaponModal/index.tsx`
- [x] `/components/weapon/WeaponKeySelect/index.tsx`
- [x] `/components/weapon/WeaponHovercard/index.tsx`
- [x] `/components/weapon/WeaponConflictModal/index.tsx`
- [x] `/components/weapon/WeaponResult/index.tsx`
- [x] `/components/weapon/WeaponLabelIcon/index.tsx`
### Component Files - Summon (3 files)
- [x] `/components/summon/SummonUnit/index.tsx`
- [x] `/components/summon/SummonHovercard/index.tsx`
- [x] `/components/summon/SummonResult/index.tsx`
### Component Files - Party (5 files)
- [x] `/components/party/PartyHeader/index.tsx`
- [x] `/components/party/PartyHead/index.tsx`
- [x] `/components/party/PartyFooter/index.tsx`
- [x] `/components/party/PartyDropdown/index.tsx`
- [x] `/components/party/Party/index.tsx`
### Component Files - Job (7 files)
- [x] `/components/job/JobSkillItem/index.tsx`
- [x] `/components/job/JobSection/index.tsx`
- [x] `/components/job/JobDropdown/index.tsx`
- [x] `/components/job/JobAccessoryPopover/index.tsx`
- [x] `/components/job/JobAccessoryItem/index.tsx`
- [x] `/components/job/JobSkillResult/index.tsx`
- [x] `/components/job/JobImage/index.tsx`
### Component Files - Mastery (3 files)
- [x] `/components/mastery/ExtendedMasterySelect/index.tsx`
- [x] `/components/mastery/AxSelect/index.tsx`
- [x] `/components/mastery/AwakeningSelectWithInput/index.tsx`
### Component Files - Reps (4 files)
- [x] `/components/reps/GridRep/index.tsx`
- [x] `/components/reps/CharacterRep/index.tsx`
- [x] `/components/reps/WeaponRep/index.tsx`
- [x] `/components/reps/SummonRep/index.tsx`
### Component Files - Common (2 files)
- [x] `/components/common/SelectWithInput/index.tsx`
- [x] `/components/common/Editor/index.tsx`
### Component Files - Extra (2 files)
- [x] `/components/extra/GuidebookUnit/index.tsx`
- [x] `/components/extra/GuidebookResult/index.tsx`
### Component Files - Other (11 files)
- [x] `/components/toasts/UpdateToast/index.tsx`
- [x] `/components/search/SearchModal/index.tsx`
- [x] `/components/raids/RaidCombobox/index.tsx`
- [x] `/components/filters/FilterModal/index.tsx`
- [x] `/components/MentionList/index.tsx`
- [x] `/components/Layout/index.tsx`
- [x] `/components/LanguageSwitch/index.tsx`
- [x] `/components/Header/index.tsx`
- [x] `/components/ElementToggle/index.tsx`
- [x] `/components/about/ChangelogUnit/index.tsx`
- [x] `/components/HovercardHeader/index.tsx`
### Utility Files (1 file)
- [x] `/utils/changeLanguage.tsx`
## Total Files to Migrate: 59
## Migration Steps for Each File
1. **Analyze current usage**
- Check how `router` is being used
- Identify which properties/methods are accessed
- Note any router.events listeners
2. **Update imports**
- Change from `next/router` to `next/navigation`
- Add additional hooks if needed (`usePathname`, `useSearchParams`)
3. **Update router usage**
- Replace `router.query` with `useSearchParams()`
- Replace `router.pathname` with `usePathname()`
- Update any other router property access
4. **Handle edge cases**
- Router events (need alternative approach)
- beforePopState (need alternative approach)
- Dynamic route params (use `useParams()`)
5. **Test the component**
- Ensure navigation still works
- Check query parameter handling
- Verify dynamic routes
## Special Considerations
### Router Events
Files using `router.events` will need special handling as this is not available in App Router. Common patterns:
- Route change start/complete events → Use loading.tsx or Suspense
- Route change error → Use error boundaries
### Query Parameters
When migrating `router.query`:
```tsx
// Old (Pages Router)
const { id, filter } = router.query
// New (App Router)
const searchParams = useSearchParams()
const id = searchParams.get('id')
const filter = searchParams.get('filter')
```
### Dynamic Route Parameters
For dynamic segments like `[id]`:
```tsx
// Old (Pages Router)
const { id } = router.query
// New (App Router)
import { useParams } from 'next/navigation'
const params = useParams()
const id = params.id
```
### Programmatic Navigation
```tsx
// Both routers (mostly the same)
router.push('/path')
router.replace('/path')
router.back()
// Refresh (different)
// Old: router.reload()
// New: router.refresh()
```
## Post-Migration Cleanup
After all files are migrated:
1. [ ] Remove `/pages` directory (except `/pages/api` if still needed)
2. [ ] Remove Pages Router specific configuration
3. [ ] Update `_app.tsx` dependencies if any remain
4. [ ] Test all routes thoroughly
5. [ ] Update any documentation
## Success Criteria
- [x] All components use `next/navigation` imports
- [x] No references to `next/router` remain in components (only in pages/about.tsx which still needs migration)
- [x] All navigation functionality works as before
- [x] No console errors about "NextRouter was not mounted"
- [x] App runs successfully with `npm run dev`
- [ ] Build completes with `npm run build` (to be tested)

View file

@ -1,246 +0,0 @@
# Fix App Router Caching Issues PRD
## Overview
Fix critical runtime errors in the App Router implementation related to viewport metadata configuration and dynamic data access within cached functions. These fixes are designed to work with Next.js 14 while preparing for migration to Next.js 15.
## Current Issues
### Issue 1: Viewport Metadata Warning
**Error:** "Unsupported metadata viewport is configured in metadata export. Please move it to viewport export instead."
**Root Cause:**
- Viewport configuration is incorrectly placed in the `metadata` export in `app/layout.tsx`
- Next.js 13+ App Router requires viewport to be a separate export
**Impact:** Warning on every page load, potential SEO and mobile rendering issues
### Issue 2: Dynamic Data in Cached Functions
**Error:** "Route /new used 'cookies' inside a function cached with 'unstable_cache(...)'. Accessing Dynamic data sources inside a cache scope is not supported."
**Root Cause:**
- Data fetching functions in `app/lib/data.ts` use `unstable_cache` wrapper
- Inside cached functions, `fetchFromApi()` calls `getAuthToken()` which accesses `cookies()`
- Next.js doesn't allow dynamic data sources (cookies, headers) inside cached scopes
**Impact:** Pages fail to load, API calls fail, poor user experience
## Files to be Modified
### Core Files Requiring Changes
#### 1. `/app/layout.tsx`
**Changes needed:**
- Remove `viewport` property from `metadata` export (line 16)
- Add new `viewport` export with proper format
- Fix import conflict with Radix UI's Viewport component
#### 2. `/app/lib/data.ts`
**Changes needed:**
- Remove `unstable_cache` wrapper from all 10 functions:
- `getTeams()` (lines 30-52)
- `getTeam()` (lines 58-69)
- `getUserInfo()` (lines 73-84)
- `getRaidGroups()` (lines 88-99)
- `getVersion()` (lines 103-114)
- `getFavorites()` (lines 118-129)
- `getJobs()` (lines 133-151)
- `getJob()` (lines 155-166)
- `getJobSkills()` (lines 170-182)
- `getJobAccessories()` (lines 186-197)
- Remove `unstable_cache` import from line 1
### Pages That Use These Functions (Testing Required)
#### 3. `/app/new/page.tsx`
- Uses: `getRaidGroups()` (line 14)
- Test: Page loads, raid groups populate
#### 4. `/app/teams/page.tsx`
- Uses: `getTeams()`
- Test: Teams list loads with filters
#### 5. `/app/saved/page.tsx`
- Uses: `getFavorites()`
- Test: Saved teams display correctly
#### 6. `/app/p/[party]/page.tsx`
- Uses: `getTeam()`
- Test: Individual party pages load
#### 7. `/app/[username]/page.tsx`
- Uses: `getUserInfo()`, `getTeams()`
- Test: User profiles load with their teams
### Supporting Files (No changes, but related)
#### 8. `/app/lib/api-utils.ts`
- Contains `getAuthToken()` that causes the issue
- No changes needed, just awareness
## Next.js 15 Migration Context
### Key Next.js 15 Changes
1. **Caching Behavior**
- Fetch requests no longer cached by default
- `unstable_cache` being deprecated in favor of `use cache` directive
- More explicit cache control
2. **Async Request APIs**
- `cookies()`, `headers()`, and `params` become async
- Better separation between static and dynamic data
3. **Request Deduplication**
- Automatic deduplication of identical requests
- No need for manual caching in many cases
### Migration Strategy
Our fixes should align with Next.js 15's philosophy:
- Remove implicit caching
- Rely on framework's built-in optimizations
- Prepare for async request APIs
## Proposed Solution
### Solution for Viewport Issue
Move viewport configuration to a separate export in `app/layout.tsx`:
```typescript
// Remove from metadata
export const metadata: Metadata = {
title: 'granblue.team',
description: 'Create, save, and share Granblue Fantasy party compositions',
// viewport: 'viewport-fit=cover, width=device-width, initial-scale=1.0', // REMOVE
}
// Add as separate export
export const viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
}
```
### Solution for Caching Issue
Remove `unstable_cache` wrapper from all data fetching functions. This aligns with Next.js 15's default behavior and eliminates the dynamic data issue.
**Before:**
```typescript
export async function getRaidGroups() {
const key = ['getRaidGroups'];
const run = unstable_cache(async () => {
try {
const data = await fetchFromApi('/raids/groups');
return data;
} catch (error) {
console.error('Failed to fetch raid groups', error);
throw error;
}
}, key, { revalidate: 300 });
return run();
}
```
**After:**
```typescript
export async function getRaidGroups() {
try {
const data = await fetchFromApi('/raids/groups');
return data;
} catch (error) {
console.error('Failed to fetch raid groups', error);
throw error;
}
}
```
### Rationale
1. **Simplicity** - Removes complexity of cache management
2. **Next.js 15 Ready** - Aligns with new caching defaults
3. **No Dynamic Data Issues** - Cookies can be accessed freely
4. **Performance** - Next.js automatically deduplicates requests within same render
5. **Maintainability** - Less code to maintain and debug
## Implementation Tasks
### Phase 1: Immediate Fixes (Next.js 14)
#### File: `/app/layout.tsx`
- [ ] Remove viewport from metadata export (line 16)
- [ ] Add viewport as separate export
- [ ] Rename Radix Toast Viewport import to avoid naming conflict
#### File: `/app/lib/data.ts`
- [ ] Remove `import { unstable_cache } from 'next/cache'` (line 1)
- [ ] Remove `unstable_cache` wrapper from `getTeams()` (lines 30-52)
- [ ] Remove `unstable_cache` wrapper from `getTeam()` (lines 58-69)
- [ ] Remove `unstable_cache` wrapper from `getUserInfo()` (lines 73-84)
- [ ] Remove `unstable_cache` wrapper from `getRaidGroups()` (lines 88-99)
- [ ] Remove `unstable_cache` wrapper from `getVersion()` (lines 103-114)
- [ ] Remove `unstable_cache` wrapper from `getFavorites()` (lines 118-129)
- [ ] Remove `unstable_cache` wrapper from `getJobs()` (lines 133-151)
- [ ] Remove `unstable_cache` wrapper from `getJob()` (lines 155-166)
- [ ] Remove `unstable_cache` wrapper from `getJobSkills()` (lines 170-182)
- [ ] Remove `unstable_cache` wrapper from `getJobAccessories()` (lines 186-197)
#### Testing
- [ ] Test `/new` page loads without errors (uses getRaidGroups)
- [ ] Test `/teams` page functionality (uses getTeams)
- [ ] Test `/saved` page functionality (uses getFavorites)
- [ ] Test `/p/[party]` pages load (uses getTeam)
- [ ] Test `/[username]` profile pages (uses getUserInfo, getTeams)
- [ ] Verify API calls work with authentication
- [ ] Check console for any remaining warnings
### Phase 2: Next.js 15 Migration Prep
- [ ] Document any performance impacts from removing caching
- [ ] Identify truly static data that might benefit from explicit caching
- [ ] Plan implementation of `use cache` directive for Next.js 15
- [ ] Prepare for async `cookies()` and `headers()` migration
### Phase 3: Next.js 15 Migration
- [ ] Update to Next.js 15
- [ ] Convert `cookies()` calls to async where needed
- [ ] Implement `use cache` directive for static data if needed
- [ ] Remove any remaining `unstable_cache` imports
- [ ] Test full application functionality
## Success Criteria
### Immediate (Phase 1)
- [ ] No viewport metadata warnings in console
- [ ] No "cookies inside cached function" errors
- [ ] All pages load successfully
- [ ] API calls work with and without authentication
- [ ] No regression in functionality
### Long-term (Phase 3)
- [ ] Successfully running on Next.js 15
- [ ] Optimal caching strategy implemented
- [ ] Clean codebase without deprecated APIs
- [ ] Performance metrics maintained or improved
## Risks and Mitigations
### Risk: Performance Impact
**Mitigation:**
- Next.js automatically deduplicates requests in same render cycle
- Monitor performance metrics before/after change
- Can implement selective caching if needed
### Risk: Increased API Load
**Mitigation:**
- Most data fetching happens server-side with deduplication
- API should handle load or implement server-side caching
- Can add Redis/memory cache if needed
## Timeline
- Phase 1: Immediate (1-2 hours)
- Phase 2: Before Next.js 15 migration (documentation only)
- Phase 3: During Next.js 15 migration sprint
## Notes
- This approach prioritizes simplicity and forward compatibility
- Aligns with Next.js team's recommended patterns
- Reduces technical debt before major version upgrade
- Makes codebase more maintainable and predictable
- Total of 2 core files need modification, 5 pages need testing

View file

@ -1,159 +0,0 @@
# Product Requirements Document: Fix "Element type is invalid" Error
## Problem Statement
After implementing the Party component interface fixes, pages still fail to load with the error:
```
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined
```
This error occurs when React tries to render a component that is `undefined`, typically due to:
- Incorrect imports
- Missing exports
- Incompatible APIs between Pages Router and App Router
- SVG import issues
## Investigation Findings
### Components Verified as Working
**Party Component** (`/components/party/Party/index.tsx`)
- Has proper 'use client' directive
- All imports exist and are correct
- Proper default export
- All child components properly imported
✅ **Grid Components**
- WeaponGrid, SummonGrid, CharacterGrid all have proper exports
- All their child components exist and work
✅ **Common Components**
- Button, Overlay, SegmentedControl have proper exports
- Alert component exists and works
✅ **SVG Icons**
- All SVG files exist with proper content
- Icons: Edit.svg, Remix.svg, Save.svg, Private.svg, Unlisted.svg, Check.svg, Ellipsis.svg
### Root Cause Analysis
#### Primary Issue: next/head in Client Components
The most critical issue is components using `next/head` which is incompatible with App Router:
**How this causes the error:**
1. `next/head` is a Pages Router API
2. In App Router context, `next/head` exports become `undefined`
3. When components try to render `<Head>`, they render `undefined`
4. React throws "Element type is invalid: got undefined"
#### Secondary Issues
1. **Import path inconsistencies** - Some components use 'types' instead of '~types'
2. **Potential SVG import issues** - Some SVG imports might need `.default` accessor
3. **Missing error boundaries** - No way to catch and debug component errors
## Files That Need Changes
### Critical Files (Using next/head)
- [ ] `/components/party/PartyHead/index.tsx` - Uses `import Head from 'next/head'`
- [ ] `/components/head/NewHead/index.tsx` - Uses `import Head from 'next/head'`
- [ ] `/components/head/ProfileHead/index.tsx` - Uses `import Head from 'next/head'`
- [ ] `/components/head/SavedHead/index.tsx` - Uses `import Head from 'next/head'`
- [ ] `/components/head/TeamsHead/index.tsx` - Uses `import Head from 'next/head'`
- [ ] `/components/about/AboutHead/index.tsx` - Uses `import Head from 'next/head'`
### Files Already Using next/head (Need Verification)
These files in pages directory are okay since they're Pages Router:
- `/pages/_app.tsx` - Pages Router, can use next/head
- `/pages/*.tsx` - All pages files can use next/head
### Components That Import Head Components
- [ ] Check if any App Router pages import the head components above
- [ ] Verify PartyHead is not being used anywhere
## Implementation Plan
### Phase 1: Remove/Replace next/head Usage
#### Option A: Remove Head Components (Recommended for unused components)
For components that are not actively used in App Router:
1. Delete the component file entirely
2. Remove any imports of these components
3. Metadata should be handled in page.tsx files instead
#### Option B: Convert to Client-Safe Components
For components that need to be preserved:
1. Remove `import Head from 'next/head'`
2. Remove `<Head>` wrapper
3. Return only the content that should be rendered in the component
4. Move metadata to the parent page.tsx file
### Phase 2: Fix Import Issues
1. Ensure all imports use correct paths ('~types' not 'types')
2. Verify SVG imports work correctly
3. Check for circular dependencies
### Phase 3: Add Error Boundaries
1. Create an ErrorBoundary component
2. Wrap Party component to catch errors
3. Add logging for better debugging
## Task List
### Immediate Actions
1. **Investigate PartyHead usage**
- Check if PartyHead is imported anywhere
- If not used, delete it
- If used, convert to App Router compatible component
2. **Remove unused head components**
- Delete NewHead (not used, metadata in page.tsx)
- Delete ProfileHead (not used, metadata in page.tsx)
- Delete SavedHead (not used, metadata in page.tsx)
- Delete TeamsHead (not used, metadata in page.tsx)
- Delete AboutHead (check usage first)
3. **Fix PartyHead if needed**
- Remove next/head import
- Convert to regular component
- Move metadata logic to parent
4. **Verify all imports**
- Check all components for correct import paths
- Fix any SVG import issues
- Resolve any circular dependencies
5. **Test thoroughly**
- Test /new page
- Test /p/[party] pages
- Test all other App Router pages
## Success Criteria
- No "Element type is invalid" errors
- All pages load successfully
- Party component renders correctly
- Tab navigation works
- All interactive features function
## Risk Mitigation
1. **Backup current state** - Commit current changes before modifications
2. **Test incrementally** - Fix and test one component at a time
3. **Use error boundaries** - Add error handling to isolate issues
4. **Maintain rollback plan** - Keep track of changes for easy reversion
## Expected Outcome
After implementing these fixes:
1. The "Element type is invalid" error will be resolved
2. All App Router pages will load correctly
3. The Party component will function as expected
4. Better error handling will be in place for future debugging
## Timeline
- Phase 1: 30 minutes (remove/fix head components)
- Phase 2: 15 minutes (fix imports)
- Phase 3: 15 minutes (add error boundaries)
- Testing: 15 minutes
- Total: ~1.25 hours
## Notes
- The head components were likely created during initial development for Pages Router
- In App Router, metadata should be handled via the metadata export in page.tsx files
- Many of these head components appear to be unused since metadata is already defined in the App Router pages
- Removing unused components will simplify the codebase and prevent future issues

View file

@ -1,243 +0,0 @@
# Product Requirements Document: Fix Party Component Interface Mismatch
## Problem Statement
During the App Router migration, the client components (`NewPartyClient` and `PartyPageClient`) were created with an incorrect interface for the `Party` component. This causes an "Element type is invalid" error preventing pages from loading.
## Root Cause Analysis
### What Went Wrong
1. **Interface Mismatch**: The Party component expects props like `selectedTab`, `raidGroups`, and `handleTabChanged`, but client components are passing `party`, `isNew`, and `onSave`
2. **Incomplete Migration**: During the Pages-to-App Router migration, new client wrapper components were created without matching the existing Party component's interface
3. **Missing Context**: The migration didn't account for the Party component being a complete, self-contained system that handles its own state management
### Current Party Component Architecture
The Party component is a comprehensive system that:
- Manages its own save/create/update logic via internal functions (`createParty()` and `updateParty()`)
- Uses global `appState` from Valtio for state management
- Handles tab switching between Character/Weapon/Summon grids
- Manages edit permissions and authentication
- Contains PartyHeader, PartySegmentedControl, Grid components, and PartyFooter
### Expected Interface
```typescript
interface Props {
new?: boolean
team?: Party
selectedTab: GridType
raidGroups: RaidGroup[]
handleTabChanged: (value: string) => void
pushHistory?: (path: string) => void
}
```
### Current (Incorrect) Usage
```typescript
// In NewPartyClient.tsx
<Party
party={appState.parties[0] || { name: t('new_party'), element: 1 }}
isNew={true}
onSave={handleSave}
/>
// In PartyPageClient.tsx
<Party
party={party}
onRemix={handleRemix}
onDelete={handleDelete}
/>
```
## Solution Options
### Option 1: Fix Client Components (Recommended)
Update the client wrapper components to match the Party component's expected interface.
**Pros:**
- Maintains existing Party component architecture
- Minimal changes required
- Preserves all existing functionality
- Lower risk of breaking existing features
**Cons:**
- Client components need to manage additional state
### Option 2: Create Adapter Components
Create intermediate adapter components that translate between the two interfaces.
**Pros:**
- Keeps existing client component logic
- Provides flexibility for future changes
**Cons:**
- Adds complexity
- Extra layer of abstraction
- Performance overhead
### Option 3: Refactor Party Component
Change the Party component to accept the simpler interface the client components expect.
**Pros:**
- Simpler client components
- More explicit prop passing
**Cons:**
- Major refactoring required
- Risk of breaking existing functionality
- Would need to extract and relocate save/update logic
- Affects multiple components
## Implementation Plan (Option 1 - Recommended)
### Phase 1: Fix Critical Props Interface
#### Task List
- [x] Remove unstable_cache from data.ts (completed)
- [x] Fix viewport metadata in layout.tsx (completed)
- [x] Fix Radix Toast import (completed)
- [ ] Fix NewPartyClient props interface
- [ ] Fix PartyPageClient props interface
- [ ] Add selectedTab state management to both components
- [ ] Implement handleTabChanged functions
- [ ] Add pushHistory navigation wrapper
- [ ] Ensure raidGroups are passed correctly
- [ ] Remove next/head usage from Head components
#### Files to Modify
##### Critical Files (Must Change)
```typescript
/app/new/NewPartyClient.tsx
- Add: useState for selectedTab (default: GridType.Weapon)
- Add: handleTabChanged function
- Change: party → team prop
- Change: isNew → new prop
- Remove: onSave prop (Party handles internally)
- Add: raidGroups prop from parent
- Add: pushHistory function using router.push
/app/p/[party]/PartyPageClient.tsx
- Add: useState for selectedTab (default: GridType.Weapon)
- Add: handleTabChanged function
- Change: party → team prop
- Remove: onRemix and onDelete props (Party handles internally)
- Add: raidGroups prop from parent
- Add: pushHistory function using router.push
/app/new/page.tsx
- Verify: raidGroups are fetched correctly
- Ensure: raidGroups are passed to NewPartyClient
/app/p/[party]/page.tsx
- Add: Fetch raidGroups data
- Pass: raidGroups to PartyPageClient
```
##### Head Component Cleanup
```typescript
/components/head/NewHead/index.tsx
- Remove entirely (metadata handled in page.tsx)
/components/head/ProfileHead/index.tsx
- Remove entirely (metadata handled in page.tsx)
/components/head/SavedHead/index.tsx
- Remove entirely (metadata handled in page.tsx)
/components/head/TeamsHead/index.tsx
- Remove entirely (metadata handled in page.tsx)
/components/party/PartyHead/index.tsx
- Refactor to not use next/head
- Or remove if not needed in App Router
```
### Phase 2: Restore Toast Viewport
```typescript
/app/layout.tsx
- Uncomment and fix ToastViewport component
- Ensure proper import from @radix-ui/react-toast
```
## Testing Requirements
### Functional Tests
1. **Page Loading**
- [ ] /new page loads without errors
- [ ] /p/[party] pages load without errors
- [ ] No "Element type is invalid" errors in console
2. **Party Creation**
- [ ] Can create a new party
- [ ] Party name can be edited
- [ ] Party description can be added
- [ ] Save functionality works
3. **Party Editing**
- [ ] Can edit existing party
- [ ] Changes persist after save
- [ ] Edit permissions work correctly
4. **Tab Navigation**
- [ ] Can switch between Characters tab
- [ ] Can switch to Weapons tab
- [ ] Can switch to Summons tab
- [ ] Tab state persists during editing
5. **State Management**
- [ ] appState updates correctly
- [ ] Valtio state management works
- [ ] No state inconsistencies
### Browser Testing
- [ ] Chrome/Edge
- [ ] Firefox
- [ ] Safari
## Success Criteria
- No runtime errors on party pages
- All party creation/editing functionality works
- Tab navigation functions correctly
- Pages load successfully in development and production
- Metadata is properly rendered for SEO
- No console warnings about invalid props
## Risk Mitigation
1. **Testing Strategy**
- Test each change incrementally
- Verify functionality after each component update
- Use development server for immediate feedback
2. **Rollback Plan**
- Create focused commits for each component
- Keep changes minimal and isolated
- Document any discovered issues
3. **Communication**
- Document any unexpected behavior
- Note any additional required changes
- Update PRD if scope changes
## Timeline
- **Phase 1**: Immediate (blocking issue)
- Estimated: 1-2 hours
- Priority: Critical
- **Phase 2**: Follow-up
- Estimated: 30 minutes
- Priority: Medium
## Dependencies
- GridType enum from utils/enums.tsx
- RaidGroup type definitions
- Valtio state management
- Next.js App Router navigation
## Open Questions
1. Should PartyHead component be refactored or removed?
2. Are there other pages using the Party component that need updates?
3. Should we add TypeScript interfaces for better type safety?
## Notes
- The Party component is well-designed as a self-contained system
- The issue is purely an interface mismatch, not a design flaw
- This pattern (self-contained components) might be worth documenting for future migrations