video_translate/docs/plans/2026-03-21-upload-three-card-row.md
2026-03-21 14:04:23 +08:00

178 lines
4.8 KiB
Markdown

# Upload Three-Card Row Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Refactor the upload page so "Upload source video", "Mode & Workflow", and "Language & Dubbing" appear as three first-row cards on desktop, with "Subtitle Defaults" moved to the next row.
**Architecture:** Keep the existing upload, trim, subtitle-default, and TTS state behavior intact while changing only the desktop grid composition. The main work is in `src/components/UploadScreen.tsx`, supported by focused test updates in `src/components/UploadScreen.test.tsx`. Existing compact header behavior in `src/App.tsx` can remain unchanged unless minor spacing adjustments are needed after the grid refactor.
**Tech Stack:** React 19, TypeScript, Tailwind CSS v4 utilities, Vitest, React Testing Library
---
### Task 1: Lock the three-card first row with a failing test
**Files:**
- Modify: `src/components/UploadScreen.test.tsx`
- Reference: `src/components/UploadScreen.tsx`
**Step 1: Write the failing test**
Add a test that describes the new first-row structure:
```tsx
it('renders upload, mode, and language cards as first-row regions', () => {
renderUploadScreen();
expect(screen.getByTestId('upload-dropzone-card')).toBeInTheDocument();
expect(screen.getByTestId('mode-card')).toBeInTheDocument();
expect(screen.getByTestId('language-card')).toBeInTheDocument();
expect(screen.getByTestId('subtitle-defaults-card')).toBeInTheDocument();
});
```
**Step 2: Run test to verify it fails**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx
```
Expected: FAIL because the mode/language/subtitle cards do not expose the new structural markers yet.
**Step 3: Write minimal implementation**
Add the minimum `data-testid` hooks needed in `src/components/UploadScreen.tsx` for the four card regions.
**Step 4: Run test to verify it passes**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx
```
Expected: PASS for the new first-row region assertion.
**Step 5: Commit**
```bash
git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx
git commit -m "test: lock upload three-card first row"
```
### Task 2: Refactor the upload workbench grid
**Files:**
- Modify: `src/components/UploadScreen.tsx`
- Modify: `src/components/UploadScreen.test.tsx`
- Reference: `src/index.css`
**Step 1: Write the failing test**
Add one more test that preserves the compact language grid after the layout move:
```tsx
it('keeps the language card controls intact after moving into the first row', () => {
renderUploadScreen();
expect(screen.getByTestId('language-card')).toContainElement(screen.getByTestId('tts-language-grid'));
expect(screen.getByRole('button', { name: 'Generate Translated Video' })).toBeInTheDocument();
});
```
**Step 2: Run test to verify it fails**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx
```
Expected: FAIL until the language card is promoted into its own first-row region.
**Step 3: Write minimal implementation**
Reshape `src/components/UploadScreen.tsx` into a desktop-first two-row grid:
- first row:
- upload card
- mode card
- language card
- second row:
- subtitle defaults card
Keep the language card self-contained with:
- subtitle language context
- TTS language grid
- generate button
Keep the subtitle card in the second row with preview and sliders unchanged functionally.
**Step 4: Run test to verify it passes**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx
```
Expected: PASS for the new structure and existing interaction tests.
**Step 5: Commit**
```bash
git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx
git commit -m "feat: move language card into first row"
```
### Task 3: Full verification
**Files:**
- Modify: `src/components/UploadScreen.tsx`
- Modify: `src/components/UploadScreen.test.tsx`
- Optionally modify: `src/App.tsx`
**Step 1: Write the failing test**
If any final regression gap appears after Task 2, add the smallest targeted test for it before final polish.
**Step 2: Run test to verify it fails**
Run:
```bash
node ./node_modules/vitest/vitest.mjs run src/components/UploadScreen.test.tsx src/App.test.tsx
```
Expected: FAIL only if a real regression remains.
**Step 3: Write minimal implementation**
Apply only the final layout polish needed to satisfy the failing regression.
**Step 4: Run test to verify it passes**
Run:
```bash
npm.cmd test
npm.cmd run lint
npm.cmd run build
```
Expected:
- all tests PASS
- typecheck PASS
- build PASS
**Step 5: Commit**
```bash
git add src/components/UploadScreen.tsx src/components/UploadScreen.test.tsx src/App.tsx src/App.test.tsx
git commit -m "test: verify upload three-card row layout"
```