docs: add UI/UX redesign implementation plan
11 tasks across 5 phases: 1. Foundation: Router, shared utils, color palette 2. Filter Bar: Replace sidebar with horizontal filter bar 3. Property Cards: Visual redesign with better hierarchy 4. Polish: Error boundary, cleanup 5. Verification: End-to-end visual check
This commit is contained in:
parent
6f8eb8a0ba
commit
706a60c741
1 changed files with 482 additions and 0 deletions
482
docs/plans/2026-02-28-ui-redesign-implementation.md
Normal file
482
docs/plans/2026-02-28-ui-redesign-implementation.md
Normal file
|
|
@ -0,0 +1,482 @@
|
||||||
|
# UI/UX Redesign Implementation Plan
|
||||||
|
|
||||||
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||||
|
|
||||||
|
**Goal:** Redesign the realestate-crawler frontend from sidebar-filter layout to horizontal-filter-bar layout with React Router, redesigned property cards, refined visual system, and tabbed listing detail.
|
||||||
|
|
||||||
|
**Architecture:** Replace the sidebar FilterPanel with a horizontal FilterBar component. Add react-router-dom for URL-based navigation and deep linking. Extract shared utilities to eliminate duplication. Refine the color palette from plain shadcn neutral to a teal-accented property search theme. All changes are frontend-only — no backend API changes needed.
|
||||||
|
|
||||||
|
**Tech Stack:** React 19, TypeScript, Tailwind CSS 4, shadcn/ui, react-router-dom, Mapbox GL, Vite
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Foundation (Router + Shared Utils + Color System)
|
||||||
|
|
||||||
|
### Task 1: Install react-router-dom
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/package.json`
|
||||||
|
|
||||||
|
**Step 1: Install the dependency**
|
||||||
|
|
||||||
|
Run: `cd /Users/viktorbarzin/code/realestate-crawler/frontend && npm install react-router-dom`
|
||||||
|
|
||||||
|
**Step 2: Verify installation**
|
||||||
|
|
||||||
|
Run: `grep react-router-dom package.json`
|
||||||
|
Expected: `"react-router-dom": "^7..."`
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/viktorbarzin/code/realestate-crawler
|
||||||
|
git add frontend/package.json frontend/package-lock.json
|
||||||
|
git commit -m "chore: add react-router-dom dependency"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Extract shared utility functions
|
||||||
|
|
||||||
|
Currently `formatDuration`, `formatCurrency`, `formatDate`, `TravelModeIcon`, and `isTerminalStatus` are duplicated across PropertyCard.tsx, ListingDetail.tsx, MobileBottomSheet.tsx, StatsBar.tsx, TaskIndicator.tsx, TaskProgressDrawer.tsx, useTaskProgress.ts, and App.tsx.
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `frontend/src/utils/format.ts`
|
||||||
|
- Create: `frontend/src/utils/taskUtils.ts`
|
||||||
|
- Modify: `frontend/src/components/PropertyCard.tsx` — remove local formatDuration/formatCurrency/formatDate, import from utils
|
||||||
|
- Modify: `frontend/src/components/ListingDetail.tsx` — same
|
||||||
|
- Modify: `frontend/src/components/MobileBottomSheet.tsx` — same
|
||||||
|
- Modify: `frontend/src/components/StatsBar.tsx` — remove local formatCurrency, import from utils
|
||||||
|
- Modify: `frontend/src/App.tsx` — remove local isTerminalStatus, import from utils
|
||||||
|
- Modify: `frontend/src/components/TaskIndicator.tsx` — remove local isTerminalStatus/taskStateToResult, import
|
||||||
|
- Modify: `frontend/src/components/TaskProgressDrawer.tsx` — remove local isTerminalStatus/taskStateToResult, import
|
||||||
|
- Modify: `frontend/src/hooks/useTaskProgress.ts` — remove local isTerminalStatus, import
|
||||||
|
|
||||||
|
**Step 1: Create `frontend/src/utils/format.ts`**
|
||||||
|
|
||||||
|
Extract these functions by reading them from PropertyCard.tsx (lines ~18-55) and consolidating:
|
||||||
|
- `formatCurrency(value: number): string` — formats as £X,XXX
|
||||||
|
- `formatDuration(seconds: number): string` — formats as Xmin / Xhr Xmin
|
||||||
|
- `formatDate(dateStr: string): string` — formats as "3d ago" / "2w ago" etc.
|
||||||
|
- `formatPricePerSqm(price: number, sqm: number | null): string | null`
|
||||||
|
|
||||||
|
**Step 2: Create `frontend/src/utils/taskUtils.ts`**
|
||||||
|
|
||||||
|
Extract from App.tsx and TaskIndicator.tsx:
|
||||||
|
- `isTerminalStatus(status: string): boolean`
|
||||||
|
- `taskStateToResult(ts: TaskState): TaskResult`
|
||||||
|
|
||||||
|
**Step 3: Update all importing files** to use the shared utils instead of local definitions. Search for each function name and replace local definitions with imports.
|
||||||
|
|
||||||
|
**Step 4: Run tests**
|
||||||
|
|
||||||
|
Run: `cd /Users/viktorbarzin/code/realestate-crawler/frontend && npx vitest run`
|
||||||
|
Expected: All existing tests pass
|
||||||
|
|
||||||
|
**Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/utils/format.ts frontend/src/utils/taskUtils.ts frontend/src/components/ frontend/src/App.tsx frontend/src/hooks/
|
||||||
|
git commit -m "refactor: extract shared utility functions to eliminate duplication"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: Update color palette in index.css
|
||||||
|
|
||||||
|
Replace the achromatic neutral palette with a teal-accented property search palette.
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/index.css:44-77` (the `:root` block)
|
||||||
|
|
||||||
|
**Step 1: Update the `:root` CSS variables**
|
||||||
|
|
||||||
|
Change the `:root` block to use teal-accented colors. Key changes:
|
||||||
|
- `--primary`: change from `oklch(0.205 0 0)` (pure black) to a dark slate `oklch(0.208 0.042 265.755)` (slate 900 with hint of blue)
|
||||||
|
- `--accent`: change from neutral gray to teal `oklch(0.627 0.14 175.5)` (teal 600)
|
||||||
|
- `--ring`: update to teal ring color
|
||||||
|
- Add custom properties for deal indicators:
|
||||||
|
- `--color-deal-good: oklch(0.696 0.17 162.48)` (emerald 500)
|
||||||
|
- `--color-deal-above: oklch(0.795 0.184 86.047)` (amber 500)
|
||||||
|
|
||||||
|
Also add these to the `@theme inline` block:
|
||||||
|
```css
|
||||||
|
--color-deal-good: var(--deal-good);
|
||||||
|
--color-deal-above: var(--deal-above);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Verify Vite HMR picks up the changes**
|
||||||
|
|
||||||
|
The running Vite dev server should hot-reload. Check the browser at localhost:5173.
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/index.css
|
||||||
|
git commit -m "style: update color palette to teal-accented property search theme"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: Set up React Router with URL-based filter state
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/main.tsx` — wrap App in BrowserRouter
|
||||||
|
- Create: `frontend/src/hooks/useFilterParams.ts` — hook that syncs filter state with URL search params
|
||||||
|
- Modify: `frontend/src/App.tsx` — use useFilterParams instead of local useState for queryParameters and viewMode
|
||||||
|
|
||||||
|
**Step 1: Update main.tsx**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
// Wrap <App /> in <BrowserRouter>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Create useFilterParams hook**
|
||||||
|
|
||||||
|
This hook:
|
||||||
|
- Reads filter values from URL search params on mount
|
||||||
|
- Returns `[filterValues, setFilterValues]` where setFilterValues updates both state and URL
|
||||||
|
- Reads `viewMode` from the URL pathname (`/map`, `/split`, `/list`, `/saved`)
|
||||||
|
- Falls back to DEFAULT_FILTER_VALUES for missing params
|
||||||
|
- Handles the `/callback` route for auth
|
||||||
|
|
||||||
|
Key URL params: `type`, `minPrice`, `maxPrice`, `minBeds`, `maxBeds`, `minSqm`, `maxSqm`, `minPriceSqm`, `maxPriceSqm`, `furnish`, `district`, `lastSeenDays`, `availableFrom`, `sort`, `metric`
|
||||||
|
|
||||||
|
**Step 3: Update App.tsx**
|
||||||
|
|
||||||
|
- Import `useFilterParams` and `useNavigate` from react-router-dom
|
||||||
|
- Replace `useState<ParameterValues | null>(null)` for queryParameters with the hook
|
||||||
|
- Replace `useState<ViewMode>('map')` for viewMode with URL-derived state
|
||||||
|
- Keep the `/callback` route check but use React Router's Routes/Route
|
||||||
|
|
||||||
|
**Step 4: Test that the app still renders with the router**
|
||||||
|
|
||||||
|
Navigate to `http://localhost:5173/map` in the browser and verify it loads.
|
||||||
|
|
||||||
|
**Step 5: Run tests**
|
||||||
|
|
||||||
|
Run: `cd /Users/viktorbarzin/code/realestate-crawler/frontend && npx vitest run`
|
||||||
|
Fix any tests that break due to missing router context (wrap test renders in `<MemoryRouter>`).
|
||||||
|
|
||||||
|
**Step 6: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/main.tsx frontend/src/hooks/useFilterParams.ts frontend/src/App.tsx
|
||||||
|
git commit -m "feat: add React Router with URL-based filter state and deep linking"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Filter Bar (Replace Sidebar)
|
||||||
|
|
||||||
|
### Task 5: Create the FilterBar component
|
||||||
|
|
||||||
|
This is the core layout change. Create a new horizontal FilterBar that replaces the sidebar FilterPanel.
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `frontend/src/components/FilterBar.tsx`
|
||||||
|
- Create: `frontend/src/components/FilterChips.tsx`
|
||||||
|
|
||||||
|
**Step 1: Create FilterBar.tsx**
|
||||||
|
|
||||||
|
A horizontal bar with:
|
||||||
|
- Compact dropdown selectors for: Price Range (min-max), Bedrooms (min-max), Min Size
|
||||||
|
- A "More Filters" button that opens a Popover with: Max Size, Price/m² range, Furnishing toggles, District input, Available From date, Last Seen Days, POI travel time filters
|
||||||
|
- Right-aligned action buttons: "Show Listings" (primary) and "Scrape New" (secondary)
|
||||||
|
- Uses the same Zod schema and react-hook-form as the current FilterPanel
|
||||||
|
- Emits the same `onSubmit(action, parameters)` callback
|
||||||
|
|
||||||
|
The bar layout: `flex items-center gap-2 px-4 h-10 bg-muted/50 border-b`
|
||||||
|
|
||||||
|
Use shadcn Popover for dropdown selectors (not full Select components — we want compact inline triggers).
|
||||||
|
|
||||||
|
**Step 2: Create FilterChips.tsx**
|
||||||
|
|
||||||
|
A component that renders active filter values as removable chips:
|
||||||
|
```tsx
|
||||||
|
<div className="flex flex-wrap gap-1 px-4 py-1 border-b bg-muted/30">
|
||||||
|
{chips.map(chip => (
|
||||||
|
<span key={chip.key} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-accent/10 text-accent text-xs font-medium">
|
||||||
|
{chip.label}
|
||||||
|
<button onClick={() => onRemove(chip.key)}><X className="h-3 w-3" /></button>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Only renders when there are active non-default filters.
|
||||||
|
|
||||||
|
**Step 3: Run tests**
|
||||||
|
|
||||||
|
Run: `npx vitest run`
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/components/FilterBar.tsx frontend/src/components/FilterChips.tsx
|
||||||
|
git commit -m "feat: create horizontal FilterBar and FilterChips components"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 6: Integrate FilterBar into App.tsx layout
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/App.tsx` — replace FilterPanel sidebar with FilterBar
|
||||||
|
- Modify: `frontend/src/components/Header.tsx` — add Rent/Buy toggle, remove elements that moved
|
||||||
|
|
||||||
|
**Step 1: Update the desktop layout in App.tsx**
|
||||||
|
|
||||||
|
Replace the current desktop layout structure:
|
||||||
|
```
|
||||||
|
sidebar (FilterPanel w-80) + main content
|
||||||
|
```
|
||||||
|
With:
|
||||||
|
```
|
||||||
|
FilterBar (full-width, below header)
|
||||||
|
FilterChips (full-width, conditional)
|
||||||
|
main content (full-width)
|
||||||
|
StatusBar (full-width)
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the `<FilterPanel>` render from the desktop layout. Keep it for mobile as a sheet/modal (or replace with FilterBar in a full-screen modal).
|
||||||
|
|
||||||
|
**Step 2: Update Header.tsx**
|
||||||
|
|
||||||
|
- Add Rent/Buy toggle tabs to the header (currently in FilterPanel)
|
||||||
|
- The toggle should call the filter update function to switch listing_type
|
||||||
|
|
||||||
|
**Step 3: Move VisualizationCard "Color by" control into StatsBar**
|
||||||
|
|
||||||
|
The metric selector (Color by dropdown) currently sits below the filter panel. Move it into the StatsBar component, next to the view mode toggle.
|
||||||
|
|
||||||
|
**Step 4: Update mobile layout**
|
||||||
|
|
||||||
|
Replace the mobile filter Sheet (sidebar slide-in) with a full-screen Dialog/modal containing the FilterBar fields stacked vertically with a sticky "Apply Filters" button at the bottom.
|
||||||
|
|
||||||
|
**Step 5: Verify in browser**
|
||||||
|
|
||||||
|
Navigate to localhost:5173 and verify:
|
||||||
|
- Filter bar appears below header
|
||||||
|
- Map takes full viewport width
|
||||||
|
- Filters work correctly
|
||||||
|
- Mobile filter opens as modal
|
||||||
|
|
||||||
|
**Step 6: Run tests**
|
||||||
|
|
||||||
|
Run: `npx vitest run`
|
||||||
|
|
||||||
|
**Step 7: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/App.tsx frontend/src/components/Header.tsx frontend/src/components/StatsBar.tsx
|
||||||
|
git commit -m "feat: integrate FilterBar into layout, remove sidebar, full-width map"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Property Cards Redesign
|
||||||
|
|
||||||
|
### Task 7: Redesign PropertyCard component
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/components/PropertyCard.tsx`
|
||||||
|
|
||||||
|
**Step 1: Redesign the full card variant**
|
||||||
|
|
||||||
|
Update the card layout to match the design:
|
||||||
|
- Larger image carousel (16:10 aspect ratio via `aspect-[16/10]`)
|
||||||
|
- Heart and external link buttons overlaid on the image (absolute positioned, top-right)
|
||||||
|
- Price as the dominant element below image (`text-xl font-bold tracking-tight`)
|
||||||
|
- Deal indicator as a colored dot + text (using new `--color-deal-good` / `--color-deal-above` CSS vars)
|
||||||
|
- Key metrics on one line with middle dots: `2 bed · 65 m² · £38/m²`
|
||||||
|
- Location below metrics
|
||||||
|
- POI travel times as compact inline badges with mode icons
|
||||||
|
- Agency + freshness de-emphasized at bottom
|
||||||
|
|
||||||
|
**Step 2: Update compact card variant**
|
||||||
|
|
||||||
|
Ensure PropertyCardCompact also follows the new visual hierarchy (price dominant, location secondary).
|
||||||
|
|
||||||
|
**Step 3: Verify in browser**
|
||||||
|
|
||||||
|
Check both full and compact card rendering.
|
||||||
|
|
||||||
|
**Step 4: Run tests**
|
||||||
|
|
||||||
|
Run: `npx vitest run -- --grep PropertyCard`
|
||||||
|
|
||||||
|
**Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/components/PropertyCard.tsx frontend/src/components/PropertyCardCompact.tsx
|
||||||
|
git commit -m "style: redesign PropertyCard with better visual hierarchy"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 8: Redesign ListingDetail with tabbed sections
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/components/ListingDetail.tsx`
|
||||||
|
- Modify: `frontend/src/components/ListingDetailSheet.tsx`
|
||||||
|
|
||||||
|
**Step 1: Update ListingDetailSheet to be larger**
|
||||||
|
|
||||||
|
Change the drawer to take 60% viewport width on desktop (currently `sm:!max-w-lg` → `sm:!max-w-2xl`) and 90vh on mobile.
|
||||||
|
|
||||||
|
**Step 2: Add tabbed sections to ListingDetail**
|
||||||
|
|
||||||
|
Use shadcn Tabs component to organize content into:
|
||||||
|
- **Overview** tab: Key features list + full description (default active)
|
||||||
|
- **Travel** tab: POI distances table with all travel modes
|
||||||
|
- **Price History** tab: Price history timeline (currently inline)
|
||||||
|
- **Details** tab: Property attributes grid (type, furnishing, council tax, lease, service charge, available from)
|
||||||
|
|
||||||
|
Keep the photo gallery and header (price, metrics, actions) above the tabs.
|
||||||
|
|
||||||
|
**Step 3: Verify in browser**
|
||||||
|
|
||||||
|
Open a listing detail sheet and verify tabs work.
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/components/ListingDetail.tsx frontend/src/components/ListingDetailSheet.tsx
|
||||||
|
git commit -m "feat: redesign listing detail with tabbed sections"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Polish & Cleanup
|
||||||
|
|
||||||
|
### Task 9: Add Error Boundary
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `frontend/src/components/ErrorBoundary.tsx`
|
||||||
|
- Modify: `frontend/src/main.tsx` — wrap App in ErrorBoundary
|
||||||
|
|
||||||
|
**Step 1: Create a simple error boundary**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { Component, type ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface Props { children: ReactNode; }
|
||||||
|
interface State { hasError: boolean; error: Error | null; }
|
||||||
|
|
||||||
|
export class ErrorBoundary extends Component<Props, State> {
|
||||||
|
state: State = { hasError: false, error: null };
|
||||||
|
static getDerivedStateFromError(error: Error) { return { hasError: true, error }; }
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-center min-h-screen">
|
||||||
|
<div className="text-center p-8 max-w-md">
|
||||||
|
<h1 className="text-xl font-bold mb-2">Something went wrong</h1>
|
||||||
|
<p className="text-muted-foreground mb-4">{this.state.error?.message}</p>
|
||||||
|
<button onClick={() => window.location.reload()} className="px-4 py-2 bg-primary text-primary-foreground rounded-md">
|
||||||
|
Reload
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Wrap App in main.tsx**
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/components/ErrorBoundary.tsx frontend/src/main.tsx
|
||||||
|
git commit -m "feat: add error boundary to prevent white-screen crashes"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 10: Clean up deprecated FilterPanel references
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Optionally delete or mark deprecated: `frontend/src/components/FilterPanel.tsx`
|
||||||
|
- Clean up any remaining references to FilterPanel in App.tsx
|
||||||
|
- Remove unused sidebar CSS variables from index.css if no longer needed
|
||||||
|
|
||||||
|
**Step 1: Remove FilterPanel from imports and usage in App.tsx**
|
||||||
|
|
||||||
|
If FilterPanel is no longer used anywhere (replaced by FilterBar), remove the import and any dead code.
|
||||||
|
|
||||||
|
**Step 2: Run final test suite**
|
||||||
|
|
||||||
|
Run: `npx vitest run`
|
||||||
|
Expected: All tests pass
|
||||||
|
|
||||||
|
**Step 3: Build check**
|
||||||
|
|
||||||
|
Run: `npx tsc -b && npx vite build`
|
||||||
|
Expected: No type errors, successful build
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A
|
||||||
|
git commit -m "chore: clean up deprecated FilterPanel references"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Verification
|
||||||
|
|
||||||
|
### Task 11: End-to-end visual verification
|
||||||
|
|
||||||
|
**Step 1: Start the full dev environment**
|
||||||
|
|
||||||
|
Start backend services (Docker compose or local) and the frontend.
|
||||||
|
|
||||||
|
**Step 2: Log in and verify all views**
|
||||||
|
|
||||||
|
- Map view: hexgrid renders, clicking cells shows popups
|
||||||
|
- Filter bar: all dropdowns work, chips appear/remove correctly
|
||||||
|
- URL state: changing filters updates URL, refreshing preserves filters
|
||||||
|
- Split view: map + list side by side
|
||||||
|
- List view: redesigned cards with correct hierarchy
|
||||||
|
- Listing detail: tabbed sections work
|
||||||
|
- Mobile: bottom sheet, filter modal, swipe review
|
||||||
|
- Saved view: liked listings display correctly
|
||||||
|
|
||||||
|
**Step 3: Take screenshots of before/after**
|
||||||
|
|
||||||
|
Use Chrome CDP at localhost:9222 to capture final state.
|
||||||
|
|
||||||
|
**Step 4: Final commit with any fixes**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary of Files Changed
|
||||||
|
|
||||||
|
| Action | File |
|
||||||
|
|--------|------|
|
||||||
|
| Create | `frontend/src/utils/format.ts` |
|
||||||
|
| Create | `frontend/src/utils/taskUtils.ts` |
|
||||||
|
| Create | `frontend/src/hooks/useFilterParams.ts` |
|
||||||
|
| Create | `frontend/src/components/FilterBar.tsx` |
|
||||||
|
| Create | `frontend/src/components/FilterChips.tsx` |
|
||||||
|
| Create | `frontend/src/components/ErrorBoundary.tsx` |
|
||||||
|
| Modify | `frontend/package.json` (add react-router-dom) |
|
||||||
|
| Modify | `frontend/src/main.tsx` (router + error boundary) |
|
||||||
|
| Modify | `frontend/src/index.css` (color palette) |
|
||||||
|
| Modify | `frontend/src/App.tsx` (layout restructure, router integration) |
|
||||||
|
| Modify | `frontend/src/components/Header.tsx` (Rent/Buy toggle) |
|
||||||
|
| Modify | `frontend/src/components/StatsBar.tsx` (add metric selector) |
|
||||||
|
| Modify | `frontend/src/components/PropertyCard.tsx` (visual redesign) |
|
||||||
|
| Modify | `frontend/src/components/PropertyCardCompact.tsx` (visual updates) |
|
||||||
|
| Modify | `frontend/src/components/ListingDetail.tsx` (tabbed layout) |
|
||||||
|
| Modify | `frontend/src/components/ListingDetailSheet.tsx` (larger drawer) |
|
||||||
|
| Modify | `frontend/src/components/TaskIndicator.tsx` (use shared utils) |
|
||||||
|
| Modify | `frontend/src/components/TaskProgressDrawer.tsx` (use shared utils) |
|
||||||
|
| Modify | `frontend/src/components/MobileBottomSheet.tsx` (use shared utils) |
|
||||||
|
| Modify | `frontend/src/hooks/useTaskProgress.ts` (use shared utils) |
|
||||||
|
| Deprecate | `frontend/src/components/FilterPanel.tsx` |
|
||||||
Loading…
Add table
Add a link
Reference in a new issue