---
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.
