mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 14:35:17 -05:00
169 lines
3.2 KiB
Markdown
169 lines
3.2 KiB
Markdown
---
|
|
description: Migrate a React component from thrillwiki-87 to Vue/Nuxt
|
|
---
|
|
|
|
# Migrate Component Workflow
|
|
|
|
Convert a React component from thrillwiki-87 (the authoritative source) to Vue 3 Composition API for the Nuxt 4 project.
|
|
|
|
## Step 1: Locate Source Component
|
|
|
|
Find the React component in thrillwiki-87:
|
|
```bash
|
|
# React components are in:
|
|
/Volumes/macminissd/Projects/thrillwiki-87/src/components/
|
|
```
|
|
|
|
Common component directories:
|
|
- `auth/` - Authentication components
|
|
- `parks/` - Park-related components
|
|
- `rides/` - Ride-related components
|
|
- `forms/` - Form components
|
|
- `moderation/` - Moderation queue components
|
|
- `ui/` - Base UI primitives (shadcn-ui)
|
|
- `common/` - Shared utilities
|
|
- `layout/` - Layout components
|
|
|
|
## Step 2: Analyze React Component
|
|
|
|
Extract these patterns from the source:
|
|
|
|
```tsx
|
|
// Props interface
|
|
interface ComponentProps {
|
|
prop1: string
|
|
prop2?: number
|
|
}
|
|
|
|
// State hooks
|
|
const [value, setValue] = useState<Type>(initial)
|
|
|
|
// Effects
|
|
useEffect(() => { /* logic */ }, [deps])
|
|
|
|
// Event handlers
|
|
const handleClick = () => { /* logic */ }
|
|
|
|
// Render return
|
|
return <JSX />
|
|
```
|
|
|
|
## Step 3: Translate to Vue 3
|
|
|
|
### Props
|
|
```tsx
|
|
// React
|
|
interface Props { name: string; count?: number }
|
|
```
|
|
↓
|
|
```vue
|
|
<!-- Vue -->
|
|
<script setup lang="ts">
|
|
defineProps<{
|
|
name: string
|
|
count?: number
|
|
}>()
|
|
</script>
|
|
```
|
|
|
|
### State
|
|
```tsx
|
|
// React
|
|
const [value, setValue] = useState<string>('')
|
|
```
|
|
↓
|
|
```vue
|
|
<!-- Vue -->
|
|
<script setup lang="ts">
|
|
const value = ref<string>('')
|
|
</script>
|
|
```
|
|
|
|
### Effects
|
|
```tsx
|
|
// React
|
|
useEffect(() => {
|
|
fetchData()
|
|
}, [id])
|
|
```
|
|
↓
|
|
```vue
|
|
<!-- Vue -->
|
|
<script setup lang="ts">
|
|
watch(() => id, () => {
|
|
fetchData()
|
|
}, { immediate: true })
|
|
</script>
|
|
```
|
|
|
|
### Events
|
|
```tsx
|
|
// React
|
|
onClick={() => onSelect(item)}
|
|
```
|
|
↓
|
|
```vue
|
|
<!-- Vue -->
|
|
@click="emit('select', item)"
|
|
```
|
|
|
|
## Step 4: Map UI Components
|
|
|
|
Translate shadcn-ui to Nuxt UI:
|
|
|
|
| shadcn-ui | Nuxt UI |
|
|
|-----------|---------|
|
|
| `<Button>` | `<UButton>` |
|
|
| `<Card>` | `<UCard>` |
|
|
| `<Dialog>` | `<UModal>` |
|
|
| `<Input>` | `<UInput>` |
|
|
| `<Select>` | `<USelect>` |
|
|
| `<Tabs>` | `<UTabs>` |
|
|
| `<Badge>` | `<UBadge>` |
|
|
|
|
## Step 5: Update API Calls
|
|
|
|
Replace Supabase with Django API:
|
|
|
|
```tsx
|
|
// React (Supabase)
|
|
const { data } = await supabase.from('parks').select('*')
|
|
```
|
|
↓
|
|
```vue
|
|
<!-- Vue (Django) -->
|
|
<script setup lang="ts">
|
|
const { data } = await useApi<Park[]>('/parks/')
|
|
</script>
|
|
```
|
|
|
|
## Step 6: Place in Nuxt Structure
|
|
|
|
Target paths:
|
|
```
|
|
frontend/app/components/
|
|
├── auth/ # Auth components
|
|
├── cards/ # Card components
|
|
├── common/ # Shared utilities
|
|
├── modals/ # Modal dialogs
|
|
├── rides/ # Ride components
|
|
└── ui/ # Base UI components
|
|
```
|
|
|
|
## Step 7: Verify Parity
|
|
|
|
- [ ] All props from source are present
|
|
- [ ] All state variables ported
|
|
- [ ] All event handlers work
|
|
- [ ] Styling matches (Tailwind classes)
|
|
- [ ] Loading states present
|
|
- [ ] Error states handled
|
|
- [ ] Dark mode works
|
|
|
|
## Example Migration
|
|
|
|
**Source**: `thrillwiki-87/src/components/parks/ParkCard.tsx`
|
|
**Target**: `frontend/app/components/cards/ParkCard.vue`
|
|
|
|
Check existing target. If it exists, compare and add missing features. If not, create new.
|