UI: Product Detail Page
Relevant source files
The following files were used as context for generating this wiki page:- app/Filament/Resources/ProductResource/Pages/ViewProduct.php
- resources/views/filament/resources/product-resource/pages/view.blade.php
- app/Filament/Resources/ProductResource/Widgets/ProductUrlStats.php
- app/Filament/Resources/ProductResource/Widgets/PriceHistoryChart.php
- app/Models/Product.php
- app/Filament/Resources/ProductResource.php
- resources/views/filament/pages/product/price-stat.blade.php
The Product Detail Page is a core feature of the PriceBuddy application's admin panel, providing a comprehensive, centralized view of a single tracked product. Built with FilamentPHP, this page serves as a dashboard for users to analyze price trends, manage associated store URLs, and view product metadata.
The page is structured with a tabbed interface to organize different aspects of the product's data: an overview of current prices and details, a historical view with price charts, and an optional search interface for adding new URLs. It is composed of several Livewire widgets that handle specific functionalities like displaying price statistics and rendering charts, all sourcing their data from the Product model.
Architecture and Components
The Product Detail Page is implemented as a ViewRecord page within the ProductResource. The main page class orchestrates the layout and the loading of various Livewire widgets that form the user interface.
Sources: app/Filament/Resources/ProductResource.php:199, app/Filament/Resources/ProductResource/Pages/ViewProduct.php
Page and Widget Composition
The diagram below illustrates how the ViewProduct page is composed of its Blade view and several child Livewire widgets.
This diagram shows the main ViewProduct.php class uses view.blade.php for its structure, which in turn includes several Livewire widgets for different tabs, all interacting with the Product data model.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:5-10, app/Filament/Resources/ProductResource/Pages/ViewProduct.php:18-25
Tabbed Interface
The page uses an Alpine.js-powered tab system to organize content. The active tab can be controlled by a searchQuery URL parameter, which defaults to the 'search' tab if present.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:6
| Tab | Icon | Purpose | Key Components |
|---|---|---|---|
| Overview | heroicon-m-rectangle-stack | Displays the product's current state, including the image, prices from different stores, and metadata. | ProductUrlStats widget, Product Image, Tags list. |
| History | heroicon-m-chart-bar | Visualizes the product's price changes over time. | PriceHistoryChart widget, range-chart component. |
| Search | heroicon-m-magnifying-glass | Allows users to search for and add new URLs for the product. This tab is only visible if search is enabled. | CreateViaSearchForm widget. |
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:9-35
Detailed Sections
Overview Tab
This is the default view, presenting a snapshot of the product.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:39-75
Product Image
The left side of the tab prominently displays the product's main image. It uses the primary_image attribute from the Product model, which provides a fallback to a placeholder if no image is set.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:44-48, app/Models/Product.php:211-215
Product URL Stats (ProductUrlStats Widget)
This widget is the main component of the Overview tab. It displays a series of stat cards, one for each URL associated with the product. Each card shows the store name and the latest price.
The data flow for this widget is as follows:
- The
ProductUrlStatswidget'sgetStats()method is called. - It retrieves a sorted collection of
PriceCacheDtoobjects from theProductmodel via$product->getPriceCache(). - It maps each
PriceCacheDtoto aProductUrlStatcomponent, which is a custom stat card implementation. - The first card is labeled as "(Lowest price)".
Sources: app/Filament/Resources/ProductResource/Widgets/ProductUrlStats.php:32-44, app/Models/Product.php:316-324
The following diagram shows the data flow for populating the URL stats.
Each stat card has a set of actions:
| Action | Icon | Description |
|---|---|---|
| Buy | heroicon-o-shopping-bag | Opens the product's store URL in a new tab. |
| Fetch | heroicon-o-rocket-launch | Manually triggers a price scrape for that specific URL and updates the product's price cache. |
| Delete | heroicon-o-trash | Deletes the URL from the product after confirmation. |
Sources: app/Filament/Resources/ProductResource/Widgets/ProductUrlStats.php:46-107
Metadata
Below the stats, the page displays when the product was created and a list of any associated tags. Each tag is a badge that links to the main product list, pre-filtered for that tag.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:63-72
History Tab
This tab provides tools for visualizing the product's price history.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:77-83
Price History Chart (PriceHistoryChart Widget)
This widget displays a stacked bar chart showing the product's price history over the last year.
- Type: Stacked Bar Chart
- Data Source:
Product->getAggregateRange() - Datasets:
- Min Price: The lowest price across all stores for a given day.
- Avg-Min Delta: The difference between the average and minimum price.
- Max-Avg Delta: The difference between the maximum and average price.
This composition visually represents the price range (min to max) and the average price for each day.
Sources: app/Filament/Resources/ProductResource/Widgets/PriceHistoryChart.php:26-57, app/Models/Product.php:414-438
The data preparation for this chart is shown below.
Min/Max Price History
A second chart, implemented via the <x-range-chart> Blade component, also visualizes the min/max price history.
Sources: resources/views/filament/resources/product-resource/pages/view.blade.php:80-82