Coffee Bean Review Dashboard¶
Goal¶
Build a custom dashboard page (not a CRUD controller) that displays cards with pre-filtered links to the existing CoffeeBeanCrudController, organized by status and other useful filters.
Problem¶
The team needs an easy way to access different coffee bean reviews filtered by status without having to manually set filters each time. They want "prefilled filters" - quick access links that take them directly to filtered views.
Solution¶
Create a custom dashboard route with a dedicated template that shows: - Status-based filter cards (OK, Partial Data, Invalid Data, Extraction Failed, Discarded) - Each card displays the count and a "View All" link with pre-filled status filter - Additional filter sections for Availability and Origin Type
Implementation Steps¶
1. Clean Up Incorrect Implementation¶
- Delete
src/Controller/Admin/CoffeeBeanReviewCrudController.php - This CRUD controller approach was wrong - we don't need another CRUD interface
- Delete or keep
templates/admin/review/crud/index.html.twig - The availability toggle template - might be useful later, or can be removed
2. Add Review Dashboard Method to DashboardController¶
File: src/Controller/Admin/DashboardController.php
Add a new route method:
#[Route('/admin/review-dashboard', name: 'admin_review_dashboard')]
public function reviewDashboard(): Response
{
// Query database for status counts
$statusCounts = $this->entityManager
->getRepository(CoffeeBean::class)
->createQueryBuilder('cb')
->select('cb.status, COUNT(cb.id) as count')
->groupBy('cb.status')
->getQuery()
->getResult();
// Convert to associative array for template
$counts = [];
foreach ($statusCounts as $row) {
$counts[$row['status']->value] = $row['count'];
}
// Ensure AdminContext exists (required for FrankenPHP)
$request = $this->container->get('request_stack')->getCurrentRequest();
if ($this->adminContextProvider->getContext() === null && $request) {
$adminContext = $this->adminContextFactory->create($request, $this, null);
$request->attributes->set(EA::CONTEXT_REQUEST_ATTRIBUTE, $adminContext);
}
return $this->render('admin/review_dashboard.html.twig', [
'status_counts' => $counts,
]);
}
3. Create Review Dashboard Template¶
File: templates/admin/review_dashboard.html.twig
Structure:
- Extends @EasyAdmin/layout.html.twig
- Status cards section (4 columns, each card shows count + link)
- Availability filter section (2 buttons: Available/Unavailable)
- Origin Type filter section (2 buttons: Single Origin/Blend)
Filter URL Pattern:
{{ ea_url()
.setController('App\\Controller\\Admin\\CoffeeBeanCrudController')
.setAction('index')
.set('filters[status][comparison]', '=')
.set('filters[status][value][]', 'ok')
}}
Status Values:
- ok - OK Beans
- partial_data - Partial Data
- invalid_data - Invalid Data
- extraction_failed - Extraction Failed
- discarded - Discarded
Additional Filters:
- Availability: filters[available][value][] = 'true' or 'false'
- Origin Type: filters[originType][value][] = 'Single Origin' or 'Blend'
4. Update Menu in DashboardController¶
File: src/Controller/Admin/DashboardController.php
In configureMenuItems(), add:
yield MenuItem::section('Coffee Bean Management');
yield MenuItem::linkToRoute('Review Dashboard', 'fa fa-clipboard-list', 'admin_review_dashboard');
yield MenuItem::linkToCrud('Coffee Beans', 'fa fa-coffee', CoffeeBean::class);
// ... rest of menu items
Expected Result¶
Users will see a dashboard page with: - Status Cards: Visual cards showing count for each status with "View All" buttons - Quick Filters: Pre-configured filter links for common use cases (Available beans, Single Origin, etc.) - Direct Navigation: All links go to the main CoffeeBeanCrudController with filters pre-applied
This gives the team "prefilled filters" without creating duplicate CRUD interfaces.
Technical Notes¶
Filter Syntax Reference¶
- ChoiceFilter:
filters[fieldName][comparison]='='andfilters[fieldName][value][]= enum value - BooleanFilter:
filters[fieldName][comparison]='='andfilters[fieldName][value][]='true'/'false' - EntityFilter:
filters[fieldName][comparison]='='andfilters[fieldName][value][]= entity ID
AdminContext Requirement¶
Always ensure AdminContext exists when rendering EasyAdmin templates (see DashboardController pattern, required for FrankenPHP compatibility).
Twig Function¶
Use ea_url() in templates instead of PHP AdminUrlGenerator - more elegant and template-friendly.
Dependencies¶
- Existing
CoffeeBeanCrudControllerwith all its filters - Existing
DashboardControllerstructure - EasyAdmin layout templates
- Bootstrap CSS (already in use)
Follow-up Possibilities¶
- Add more filter combinations as the team identifies common workflows
- Add date range filters (e.g., "Beans added this week")
- Add roaster-based filter cards
- Add search functionality directly on the dashboard