4 plans across 3 waves to expand from 7 to 17 rclone backends: - Plan 01 (W1): Registry refactoring, BackendType derivation, 10 new entries - Plan 02 (W2): OAuthInstructions, GdriveAuthToggle, BackendIcons components - Plan 03 (W2): BackendSelectionStep UX overhaul with categories, search, icons - Plan 04 (W3): RemoteConfigStep wiring for all new backends + visual verify Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 13-add-remaining-rclone-remotes | 03 | execute | 2 |
|
|
true |
|
|
Purpose: With 17 backends (up from 7), a flat grid is unusable. Categories group by IT-pro mental model, search enables quick access, icons aid visual scanning. Output: Refactored BackendSelectionStep.tsx, updated BackendCard.tsx, new test cases.
<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/13-add-remaining-rclone-remotes/13-CONTEXT.md @.planning/phases/13-add-remaining-rclone-remotes/13-RESEARCH.md @.planning/phases/13-add-remaining-rclone-remotes/13-01-SUMMARY.mdFrom src/schemas/registry.ts (after Plan 01):
export type BackendCategory = 'cloud-object-storage' | 'cloud-drives' | 'protocol-based';
export type BackendType = keyof typeof BACKEND_REGISTRY;
// Each entry has: displayName, description, category, fields
From src/components/icons/BackendIcons.tsx (from Plan 02):
interface IconProps { className?: string; }
export const BACKEND_ICONS: Partial<Record<BackendType, React.FC<IconProps>>>;
From src/components/ui/TextFieldMD3.tsx:
interface TextFieldMD3Props {
id: string;
label: string;
registration: UseFormRegisterReturn;
error?: FieldError;
required?: boolean;
helpText?: string;
// ... more props
}
From src/components/ui/BackendCard.tsx (current):
interface BackendCardProps {
name: string;
description: string;
selected?: boolean;
onClick: () => void;
}
-
Refactor BackendSelectionStep to add category grouping and search:
a. Add search state:
const [searchQuery, setSearchQuery] = useState('')b. Add search bar ABOVE the backend cards (below the remote name input). Use a plain
<input>styled with MD3 tokens (NOT TextFieldMD3 — it uses placeholder=" " which conflicts with a search placeholder). Style it as:className="w-full px-4 py-2.5 rounded-xl border border-outline bg-surface-container text-on-surface placeholder:text-on-surface-variant/50 focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Search backends..."Use
onChange={(e) => setSearchQuery(e.target.value)}— no debounce needed for 17 items.c. Add category constants:
const CATEGORY_ORDER: BackendCategory[] = ['cloud-object-storage', 'cloud-drives', 'protocol-based']; const CATEGORY_LABELS: Record<BackendCategory, string> = { 'cloud-object-storage': 'Cloud Object Storage', 'cloud-drives': 'Cloud Drives', 'protocol-based': 'Protocol-based', };d. Add matchesSearch function that checks displayName, description, category label, and field labels:
function matchesSearch(entry: { displayName: string; description: string; category: BackendCategory; fields: { label: string }[] }, query: string): boolean { const q = query.toLowerCase(); return entry.displayName.toLowerCase().includes(q) || entry.description.toLowerCase().includes(q) || CATEGORY_LABELS[entry.category].toLowerCase().includes(q) || entry.fields.some(f => f.label.toLowerCase().includes(q)); }e. Replace the flat
data-testid="backend-cards"grid with category sections:{CATEGORY_ORDER.map(cat => { const backends = Object.entries(BACKEND_REGISTRY) .filter(([, e]) => e.category === cat) .filter(([, e]) => !searchQuery || matchesSearch(e, searchQuery)); if (backends.length === 0) return null; return ( <section key={cat} className="mb-6"> <h3 className="text-lg font-semibold text-on-surface mb-3">{CATEGORY_LABELS[cat]}</h3> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> {backends.map(([type, entry]) => ( <BackendCard key={type} name={entry.displayName} description={entry.description} selected={state.remote.backendType === type} onClick={() => handleCardClick(type as BackendType)} icon={BACKEND_ICONS[type as BackendType] ? React.createElement(BACKEND_ICONS[type as BackendType]!, { className: 'w-6 h-6' }) : undefined} /> ))} </div> </section> ); })}f. Keep the existing remote name TextFieldMD3 and RemoteNamePreview at the top. Keep the Next button at the bottom. Keep form validation logic unchanged.
g. Keep
data-testid="backend-cards"on a wrapping div around all category sections so existing tests that query within it still work. -
Import BACKEND_ICONS from '../icons/BackendIcons' and BackendCategory from '../../schemas/registry'. npx tsc --noEmit 2>&1 | tail -10 && npx vitest run src/components/wizard/BackendSelectionStep.test.tsx --reporter=verbose 2>&1 | tail -30 BackendSelectionStep renders 17 backends grouped by category with search bar. BackendCard shows icon when provided. Existing tests pass.
For search tests:
- Find the search input by placeholder "Search backends..."
- Use
fireEvent.change()oruserEvent.type()to enter search text - Assert on presence/absence of backend card text and category headings
For category tests:
- Assert "Cloud Object Storage", "Cloud Drives", "Protocol-based" headings are present
- After filtering, assert missing headings are NOT in the document
Write tests first (RED), verify they fail, then ensure Task 1 implementation makes them pass (GREEN). npx vitest run src/components/wizard/BackendSelectionStep.test.tsx --reporter=verbose 6 new test cases pass covering search filtering, category heading visibility, cross-field search matching, and full backend card rendering.
- `npx vitest run` — full suite green - `npx tsc --noEmit` — no type errors - BackendSelectionStep renders categories, search works, icons display - No empty category headings when search filters out all backends in a category<success_criteria>
- 17 backends rendered in 3 category sections with headings
- Search bar filters instantly across displayName, description, category, field labels
- Empty categories hidden (conditional rendering, not CSS)
- Backend cards show inline SVG icons
- Existing remote name validation unchanged
- All tests pass (existing + 6 new) </success_criteria>