11 KiB
Story 7.2: My Consultations View
Epic Reference
Epic 7: Client Dashboard
User Story
As a client, I want to view all my consultations, So that I can track upcoming appointments and review past sessions.
Dependencies
- Story 7.1: Client Dashboard Overview (navigation context)
- Epic 3: Consultation model with scopes (
approved(),pending()) - Story 3.6: Calendar file generation (.ics) for download functionality
Acceptance Criteria
Upcoming Consultations Section
- Date and time (formatted per locale)
- Consultation type (free/paid)
- Status (approved/pending)
- Payment status (for paid consultations)
- Download .ics calendar file button
Pending Requests Section
- Submitted bookings awaiting approval
- Submission date
- Problem summary preview (truncated)
- Status: "Pending Review"
Past Consultations Section
- Historical consultations
- Status (completed/cancelled/no-show)
- Date and type
Features
- Visual status indicators (badges with colors)
- Sort by date (default: newest first for past)
- Pagination if many consultations (10 per page)
- No edit/cancel capabilities (read-only)
Empty States
- "No upcoming consultations" message with link to book
- "No pending requests" message
- "No past consultations" message
Technical Notes
Files to Create/Modify
resources/views/livewire/client/consultations.blade.php- Main Volt componentroutes/web.php- Add route within client middleware group
Route Definition
// In routes/web.php, within authenticated client routes
Route::get('/client/consultations', function () {
return view('livewire.client.consultations');
})->name('client.consultations');
Volt Component Structure
<?php
use App\Models\Consultation;
use Livewire\Volt\Component;
use Livewire\WithPagination;
new class extends Component {
use WithPagination;
public function with(): array
{
$user = auth()->user();
return [
'upcoming' => $user->consultations()
->approved()
->where('scheduled_date', '>=', today())
->orderBy('scheduled_date')
->orderBy('scheduled_time')
->get(),
'pending' => $user->consultations()
->pending()
->latest()
->get(),
'past' => $user->consultations()
->whereIn('status', ['completed', 'cancelled', 'no_show'])
->orWhere(fn($q) => $q
->where('user_id', $user->id)
->approved()
->where('scheduled_date', '<', today()))
->latest('scheduled_date')
->paginate(10),
];
}
public function downloadCalendar(Consultation $consultation): \Symfony\Component\HttpFoundation\StreamedResponse
{
// Reuse .ics generation from Story 3.6
return $consultation->generateIcsDownload();
}
}; ?>
Model Scopes Required (from Epic 3)
The Consultation model should have these scopes:
scopeApproved($query)-where('status', 'approved')scopePending($query)-where('status', 'pending')
Flux UI Components to Use
<flux:badge>- Status indicators (approved=green, pending=yellow, completed=gray, cancelled=red)<flux:button>- Download calendar button<flux:heading>- Section headings<flux:text>- Consultation details
Status Badge Colors
| Status | Color | Variant |
|---|---|---|
| approved | green | variant="success" |
| pending | yellow | variant="warning" |
| completed | gray | variant="subtle" |
| cancelled | red | variant="danger" |
| no_show | red | variant="danger" |
Payment Status Display
- For paid consultations, show payment status:
- "Payment Pending" (yellow badge)
- "Payment Received" (green badge)
- For free consultations, show "Free" (blue badge)
References
docs/epics/epic-3-booking-consultation.md- Consultation model, statuses, payment handlingdocs/epics/epic-3-booking-consultation.md#story-36- .ics calendar file generationdocs/stories/story-7.1-client-dashboard-overview.md- Dashboard navigation context
Test Scenarios
Access Control
- Unauthenticated users redirected to login
- User sees only their own consultations (not other users')
Upcoming Section
- Shows approved consultations with
scheduled_date >= today - Sorted by date ascending (soonest first)
- Displays type, status, payment status correctly
- Calendar download button triggers .ics download
Pending Section
- Shows consultations with status='pending'
- Displays submission date and problem summary
- Summary truncated if too long
Past Section
- Shows completed, cancelled, no_show consultations
- Shows approved consultations with
scheduled_date < today - Sorted by date descending (newest first)
- Pagination works correctly (10 per page)
Empty States
- Empty upcoming shows appropriate message
- Empty pending shows appropriate message
- Empty past shows appropriate message
Calendar Download
- Download generates valid .ics file
- File contains correct consultation details
- Only available for approved upcoming consultations
Definition of Done
- All sections display correctly
- Calendar download works
- Status indicators clear and color-coded
- Read-only (no actions except download)
- Pagination works for past consultations
- Empty states display appropriately
- Mobile responsive
- Bilingual support
- Tests pass
Estimation
Complexity: Medium | Effort: 3-4 hours
QA Results
Review Date: 2025-12-28
Reviewed By: Quinn (Test Architect)
Code Quality Assessment
Overall: Excellent - The implementation is clean, well-structured, and follows established patterns. The Volt component correctly separates concerns with data fetching in with() and the Blade template for presentation. Proper use of Eloquent scopes and enum comparisons demonstrates adherence to the codebase's architecture.
Strengths:
- Three distinct sections (Upcoming, Pending, Past) clearly implemented
- Proper authorization via
clientmiddleware on route group - Calendar download restricted to approved consultations only (line 137 in routes/web.php)
- Locale-aware date formatting for both Arabic and English
- Consistent use of Flux UI components (
flux:badge,flux:button,flux:heading,flux:icon) - Pagination properly implemented for past consultations (10 per page)
- Empty states provide good UX with appropriate messaging and CTAs
Refactoring Performed
None required - implementation quality meets standards.
Compliance Check
- Coding Standards: ✓ Code formatted with Pint
- Project Structure: ✓ Volt component in correct location, tests in Feature directory
- Testing Strategy: ✓ 25 comprehensive Pest tests covering all acceptance criteria
- All ACs Met: ✓ All acceptance criteria verified through tests
Requirements Traceability (Given-When-Then)
| AC | Test Coverage |
|---|---|
| Upcoming: date/time formatted per locale | upcoming section shows approved consultations with future date |
| Upcoming: type (free/paid) | upcoming section displays consultation type correctly |
| Upcoming: status/payment badges | upcoming section shows payment status for paid consultations |
| Upcoming: calendar download | calendar download button is available for upcoming approved consultations |
| Pending: awaiting approval | pending section shows consultations with pending status |
| Pending: submission date | pending section shows submission date |
| Pending: truncated summary | pending section truncates long problem summary |
| Past: completed/cancelled/no-show | Tests for each status type |
| Past: sorted by date desc | past section is sorted by date descending |
| Pagination (10 per page) | past section paginates correctly |
| Empty states | Three dedicated tests for empty states |
| Read-only | consultations page is read only with no edit capabilities |
| Access control | unauthenticated user is redirected to login, user sees only their own consultations |
Improvements Checklist
- All acceptance criteria implemented
- All 25 tests pass
- Bilingual support (AR/EN) with 12 localization keys
- Mobile responsive design (flex-col sm:flex-row patterns)
- Proper authorization checks
- Consider: Add test for calendar download route (POST/GET to ensure .ics generation works end-to-end)
- Consider: Add integration test verifying locale date formatting outputs correct Arabic format
Security Review
Status: PASS
- Authorization properly enforced via
clientmiddleware at route group level - Calendar download has explicit ownership check (
$consultation->user_id === auth()->id()) - No SQL injection vectors (using Eloquent ORM throughout)
- No XSS concerns (using Blade's default escaping)
Performance Considerations
Status: PASS
- Upcoming and Pending sections use
get()which is appropriate for small result sets - Past section properly paginated (10 per page)
- Query ordering applied at database level
- No N+1 query issues detected (data accessed directly from loaded models)
Files Modified During Review
None - no refactoring required.
Gate Status
Gate: PASS → docs/qa/gates/7.2-my-consultations-view.yml
Recommended Status
✓ Ready for Done - All acceptance criteria met, 25 tests passing, clean implementation.
Dev Agent Record
Status
Ready for Review
Agent Model Used
Claude Opus 4.5
File List
| File | Action | Purpose |
|---|---|---|
resources/views/livewire/client/consultations/index.blade.php |
Modified | Updated to show three sections: Upcoming, Pending, Past consultations |
lang/en/booking.php |
Modified | Added 12 new localization keys for consultations sections |
lang/ar/booking.php |
Modified | Added Arabic translations for consultations sections |
tests/Feature/Client/ConsultationsViewTest.php |
Created | 25 feature tests covering all acceptance criteria |
Change Log
- Refactored client consultations index component from simple list to three-section view (Upcoming, Pending, Past)
- Added locale-aware date formatting for both Arabic and English
- Implemented payment status badges for paid consultations (Pending/Received)
- Added consultation type badges (Free/Paid) with appropriate colors
- Past consultations section includes pagination (10 per page)
- Calendar download button available only for upcoming approved consultations (existing route reused)
- All sections have empty state displays with appropriate messages
- Read-only view - no edit/cancel/delete actions exposed
Completion Notes
- Route already existed at
/client/consultations- no route modifications needed - CalendarService already existed with
generateDownloadResponse()method - reused via existing route - Consultation model uses
booking_date/booking_timecolumns (notscheduled_date/scheduled_timeas in story spec) - Status badge uses Flux
colorattribute (e.g.,color="green") instead ofvariantattribute - 25 tests pass covering all test scenarios
- Code formatted with
vendor/bin/pint --dirty