---
name: migrate-screen
description: Migrate a variant screen from pages/variant_screens/ to features/ with BaseController + BasePageView
disable-model-invocation: true
argument-hint: "<screen_name> e.g. feed_details_screen, spaces_details_screen"
---

# Migrate Screen to Features

Migrate `$ARGUMENTS` from `pages/variant_screens/` to `features/` using `BaseController` + `BasePageView`.

## Step 1: Study existing patterns

Read 2 already-migrated feature screens to understand the pattern:

**Reference implementations:**
- `features/feed_details/` — non-SDUI detail page with BaseController
- `features/chat_details/` — non-SDUI detail page with BaseController
- `features/course/course_details/` — SDUI page with SduiPageController
- `features/profile/` — non-SDUI page with BaseController

**Choose the right base class:**
- If the screen has a page function in `appza_pages.dart` → use `SduiPageController` + `BasePageView`
- If the screen loads its own data (not SDUI) → use `BaseController` + `BasePageView`

## Step 2: Investigate the old screen

1. Read the old controller (extends `VariantBaseController` or `VariantBaseController with SomeMixin`)
2. Read the old screen (extends `VariantBaseView`)
3. Read variant screen files (e.g., `variants/screen_1/`)
4. Identify: data loading, state management, action methods, navigation arguments
5. Check how many variants exist — if only 1, no variant routing needed

## Step 3: Create the controller

In `features/<screen_name>/`:

### BaseController pattern:
```dart
class <Name>Controller extends BaseController {
  @override
  bool get hasArg => true/false;

  @override
  Map<String, Type> get requiredArguments => {...};

  @override
  void processArguments(Map<String, dynamic> args) { ... }

  @override
  Future<void> initializePage() async { ... }

  @override
  ({PageState pageState, String errorMessage}) validatePageState() { ... }
}
```

### SduiPageController pattern:
```dart
class <Name>Controller extends SduiPageController {
  @override
  bool get hasArg => true;

  @override
  Map<String, Type> get requiredArguments => {...};

  @override
  void processArguments(Map<String, dynamic> args) { ... }

  @override
  Future<PageResult> fetchPageConfig() => somePageFunction(...);

  @override
  ({String errorMessage, PageState pageState}) validatePageState() { ... }
}
```

## Step 4: Create the screen

```dart
class <Name>Screen extends BasePageView<<Name>Controller> {
  <Name>Screen({super.key}) : super(controller: <Name>Controller());

  @override
  Widget buildLoadingView(BuildContext context) {
    // Port shimmer from old screen if it had one
  }

  @override
  Widget buildContent(BuildContext context) {
    // Port UI from old variant screen
  }
}
```

## Step 5: Update all imports

1. Grep for all imports of the old screen path
2. Update each to the new feature path
3. Check navigation calls (`Get.to`, `Get.toNamed`) that reference the old screen

## Step 6: Verify

1. `fvm flutter analyze` — zero new errors
2. Grep for remaining references to old path (only self-references should remain)
3. Provide manual test steps
4. Check loading UX matches old behavior (shimmer, instant, etc.)

## Rules
- Use `BaseController` + `BasePageView` — NOT `GetxController` + `StatelessWidget`, NOT `VariantBaseController/View`
- Use API service classes for all API calls
- Use `colorPrint` for debug traces
- Match old loading UX (shimmer if old had shimmer, instant if old was instant)
- Dispose TextEditingControllers, ScrollControllers in `onClose()`
- Do NOT delete old files yet — that's `/cleanup-old-code`
- Commit after migration
