Comparison UI Components
Relevant source files
The following files were used as context for generating this wiki page:
The Comparison UI Components form the core user interface of the "WhereIsLifeCheaper" platform, designed to provide users with real-time, cross-country grocery and cost-of-living data. These components facilitate the visualization of complex data sets, including supermarket prices, currency exchange rates, and rental statistics across various international markets.
The system relies on a modular React architecture where the main dashboard aggregates various specialized components such as ComparisonTable, CountryCard, and RentComparison. These components consume data from a REST API that processes daily scraped information from supermarkets in countries like Turkey, Spain, Montenegro, and others. Sources: frontend/src/pages/Home.tsx:18-35, plan.md:12-25
Dashboard Architecture and Data Flow
The primary entry point for the comparison interface is the Home page, which orchestrates data fetching and state management for the UI components. It utilizes TanStack Query for efficient data retrieval and synchronization with the backend services.
Data Acquisition Flow
The following diagram illustrates how the Comparison UI retrieves and processes data for display:
The UI flow starts with user interaction (searching or selecting countries), which triggers API calls to fetch canonical comparison data. Sources: frontend/src/pages/Home.tsx:64-90, src/api/routes/canonical.ts:89-105
Component Responsibilities
| Component | Description | Primary Source |
|---|---|---|
ComparisonTable | Displays a grid of products with prices mapped across selected countries, highlighting the "best" price. | frontend/src/pages/Home.tsx:210-215 |
CountrySelector | Allows users to toggle specific countries (TR, ES, ME, UA, etc.) in and out of the comparison view. | frontend/src/pages/Home.tsx:156-177 |
CountryCard | Visualizes high-level statistics per country, including total product count and last update timestamp. | frontend/src/pages/Home.tsx:236-242 |
RentComparison | Provides a secondary cost-of-living metric focusing on median capital city rental prices. | frontend/src/pages/Home.tsx:226 |
CurrencyRatesTable | Shows the daily exchange rates used for converting local prices into a common currency (EUR). | frontend/src/pages/Home.tsx:223 |
Core Comparison Logic
The UI components leverage specific utilities and backend logic to ensure accurate comparisons across different currencies and measurement units.
Price Conversion and Normalization
To compare prices fairly, the UI utilizes a conversion utility that applies daily exchange rates. For products where weight or volume varies, the system supports "Per Unit Pricing" (e.g., price per kg or per liter). Sources: frontend/src/utils/currency.ts:57-80, src/api/routes/canonical.ts:182-205
The comparison logic identifies the cheapest country by converting all available prices to EUR and optionally using the price_per_unit field if the show_per_unit_price flag is enabled for that canonical product. Sources: frontend/src/utils/currency.ts:114-148, src/api/routes/canonical.ts:192-200
Unit Normalization Types
Supported normalizable units for comparison include:
- Weight: kg, g
- Volume: l, ml
- Count: pcs
Sources: frontend/src/utils/currency.ts:85-93
Admin and Management Components
The platform includes specialized components for data curators to manage the relationships between raw scraped products and their canonical counterparts.
Product Mapping Interface
The Mapping page is a technical interface allowing administrators to link supermarket-specific products to "Canonical Products." This is essential for the comparison UI to know that "Migros Süt" in Turkey is equivalent to "Mercadona Leche" in Spain. Sources: frontend/src/pages/admin/Mapping.tsx:20-45
Canonical Freshness Monitoring
To maintain UI accuracy, the CanonicalFreshness component tracks how recently prices were updated for mapped products. It marks products as "stale" if they have not been scanned within a defined threshold (defaulting to 7 days). Sources: frontend/src/pages/admin/CanonicalFreshness.tsx:14-25, src/api/routes/canonical.ts:60-75
This sequence ensures that data displayed in the public comparison components remains current and reliable. Sources: frontend/src/pages/admin/CanonicalFreshness.tsx:61-75, src/api/routes/canonical.ts:77-87
SEO and Metadata Integration
Comparison components are tightly integrated with an SEO hook (useSEO) to ensure that dynamic pages (like country-specific comparisons) are correctly indexed by search engines.
- Structured Data: The system generates JSON-LD schemas for
WebSite,FAQPage, andWebPage. - Dynamic Titles: Titles are updated based on the current comparison view (e.g., "Grocery Prices in Turkey | WhereIsLifeCheaper").
- Canonical URLs: Prevents duplicate content issues when users apply filters or search terms.
Sources: frontend/src/hooks/useSEO.ts:25-50, frontend/src/pages/Home.tsx:43-58
Conclusion
The Comparison UI Components bridge the gap between automated data collection and user-friendly visualization. By combining real-time supermarket data with currency normalization and administrative mapping tools, the system provides a comprehensive view of international cost-of-living differences. The modularity of these components allows the platform to scale as more countries and supermarkets are integrated into the scraping engine. Sources: plan.md:322-330, frontend/src/pages/Home.tsx:100-115