mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 09:25:18 -05:00
lol
This commit is contained in:
183
.agent/workflows/migrate-page.md
Normal file
183
.agent/workflows/migrate-page.md
Normal file
@@ -0,0 +1,183 @@
|
||||
---
|
||||
description: Migrate a React page from thrillwiki-87 to Nuxt 4
|
||||
---
|
||||
|
||||
# Migrate Page Workflow
|
||||
|
||||
Port a React page from thrillwiki-87 (the authoritative source) to a Nuxt 4 page.
|
||||
|
||||
## Step 1: Locate Source Page
|
||||
|
||||
Find the React page in thrillwiki-87:
|
||||
```bash
|
||||
/Volumes/macminissd/Projects/thrillwiki-87/src/pages/
|
||||
```
|
||||
|
||||
Key pages:
|
||||
- `Index.tsx` - Homepage
|
||||
- `Parks.tsx` - Parks listing
|
||||
- `ParkDetail.tsx` - Individual park (36KB - complex)
|
||||
- `Rides.tsx` - Rides listing
|
||||
- `RideDetail.tsx` - Individual ride (54KB - most complex)
|
||||
- `Profile.tsx` - User profile (51KB - complex)
|
||||
- `Search.tsx` - Global search
|
||||
- `AdminDashboard.tsx` - Admin panel
|
||||
|
||||
## Step 2: Analyze Page Structure
|
||||
|
||||
Extract from React page:
|
||||
|
||||
```tsx
|
||||
// Route params
|
||||
const { id } = useParams()
|
||||
|
||||
// Data fetching
|
||||
const { data, isLoading, error } = useQuery(...)
|
||||
|
||||
// SEO
|
||||
// (usually react-helmet or similar)
|
||||
|
||||
// Page layout structure
|
||||
return (
|
||||
<Layout>
|
||||
<Tabs>...</Tabs>
|
||||
<Content>...</Content>
|
||||
</Layout>
|
||||
)
|
||||
```
|
||||
|
||||
## Step 3: Create Nuxt Page
|
||||
|
||||
### Route Params
|
||||
```tsx
|
||||
// React
|
||||
const { parkSlug } = useParams()
|
||||
```
|
||||
↓
|
||||
```vue
|
||||
<!-- Nuxt -->
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
const parkSlug = route.params.park_slug as string
|
||||
</script>
|
||||
```
|
||||
|
||||
### Data Fetching
|
||||
```tsx
|
||||
// React (React Query)
|
||||
const { data, isLoading } = useQuery(['park', id], () => fetchPark(id))
|
||||
```
|
||||
↓
|
||||
```vue
|
||||
<!-- Nuxt -->
|
||||
<script setup lang="ts">
|
||||
const { data, pending } = await useAsyncData(
|
||||
`park-${parkSlug}`,
|
||||
() => useParksApi().getPark(parkSlug)
|
||||
)
|
||||
</script>
|
||||
```
|
||||
|
||||
### SEO Meta
|
||||
```tsx
|
||||
// React (Helmet)
|
||||
<Helmet>
|
||||
<title>{park.name} | ThrillWiki</title>
|
||||
</Helmet>
|
||||
```
|
||||
↓
|
||||
```vue
|
||||
<!-- Nuxt -->
|
||||
<script setup lang="ts">
|
||||
useSeoMeta({
|
||||
title: () => `${data.value?.name} | ThrillWiki`,
|
||||
description: () => data.value?.description
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Page Meta
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth'], // if authentication required
|
||||
layout: 'default'
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## Step 4: Port Page Sections
|
||||
|
||||
Common patterns:
|
||||
|
||||
### Tabs Structure
|
||||
```tsx
|
||||
// React
|
||||
<Tabs defaultValue="overview">
|
||||
<TabsList>
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="overview">...</TabsContent>
|
||||
</Tabs>
|
||||
```
|
||||
↓
|
||||
```vue
|
||||
<!-- Nuxt -->
|
||||
<UTabs :items="tabs" v-model="activeTab">
|
||||
<template #default="{ item }">
|
||||
<component :is="item.component" v-bind="item.props" />
|
||||
</template>
|
||||
</UTabs>
|
||||
```
|
||||
|
||||
### Loading States
|
||||
```tsx
|
||||
// React
|
||||
{isLoading ? <Skeleton /> : <Content />}
|
||||
```
|
||||
↓
|
||||
```vue
|
||||
<!-- Nuxt -->
|
||||
<template>
|
||||
<div v-if="pending">
|
||||
<USkeleton class="h-48" />
|
||||
</div>
|
||||
<div v-else-if="data">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Step 5: Target Location
|
||||
|
||||
Nuxt pages use file-based routing:
|
||||
|
||||
| React Route | Nuxt File Path |
|
||||
|-------------|----------------|
|
||||
| `/parks` | `pages/parks/index.vue` |
|
||||
| `/parks/:slug` | `pages/parks/[park_slug]/index.vue` |
|
||||
| `/parks/:slug/rides/:ride` | `pages/parks/[park_slug]/rides/[ride_slug].vue` |
|
||||
| `/manufacturers/:id` | `pages/manufacturers/[slug].vue` |
|
||||
|
||||
## Step 6: Verify Feature Parity
|
||||
|
||||
Compare source page with target:
|
||||
- [ ] All tabs/sections present
|
||||
- [ ] All data displayed
|
||||
- [ ] All actions work (edit, delete, etc.)
|
||||
- [ ] Responsive layout matches
|
||||
- [ ] Loading states present
|
||||
- [ ] Error handling works
|
||||
- [ ] SEO meta correct
|
||||
|
||||
## Reference: Page Complexity
|
||||
|
||||
| Page | Source Size | Priority |
|
||||
|------|-------------|----------|
|
||||
| RideDetail.tsx | 54KB | High |
|
||||
| Profile.tsx | 51KB | High |
|
||||
| AdminSettings.tsx | 44KB | Medium |
|
||||
| ParkDetail.tsx | 36KB | High |
|
||||
| Auth.tsx | 29KB | Medium |
|
||||
| Parks.tsx | 22KB | High |
|
||||
| Rides.tsx | 20KB | High |
|
||||
Reference in New Issue
Block a user