178 lines
4.8 KiB
Markdown
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"
|
|
```
|