reviewd epic 7 stories
This commit is contained in:
@@ -3,6 +3,10 @@
|
||||
## Epic Reference
|
||||
**Epic 7:** Client Dashboard
|
||||
|
||||
## Dependencies
|
||||
- **Story 7.5:** New Booking Interface (provides booking page where indicator displays)
|
||||
- **Story 3.3:** Availability Calendar (calendar component to integrate with)
|
||||
|
||||
## User Story
|
||||
As a **client**,
|
||||
I want **to see my booking status and limits clearly**,
|
||||
@@ -11,25 +15,46 @@ So that **I understand when I can book consultations**.
|
||||
## Acceptance Criteria
|
||||
|
||||
### Display Locations
|
||||
- [ ] Dashboard widget
|
||||
- [ ] Booking page
|
||||
- [ ] Dashboard widget showing booking status
|
||||
- [ ] Booking page status banner
|
||||
|
||||
### Status Messages
|
||||
- [ ] "You can book a consultation today"
|
||||
- [ ] "You already have a booking for today"
|
||||
- [ ] "You have a pending request for [date]"
|
||||
- [ ] "You can book a consultation today" (when no booking exists for today)
|
||||
- [ ] "You already have a booking for today" (when pending/approved booking exists for today)
|
||||
- [ ] "You have a pending request for [date]" (shows first pending request date)
|
||||
|
||||
### Calendar Integration
|
||||
- [ ] Calendar shows booked days as unavailable
|
||||
- [ ] Visual indicator for user's booked dates
|
||||
- [ ] Pass `bookedDates` array to availability calendar component
|
||||
- [ ] Calendar marks user's booked dates as unavailable (distinct styling)
|
||||
- [ ] Visual indicator differentiates "user already booked" from "no slots available"
|
||||
|
||||
### Information
|
||||
- [ ] Clear messaging about 1-per-day limit
|
||||
- [ ] Bilingual messages
|
||||
- [ ] Bilingual messages (Arabic/English)
|
||||
|
||||
### Edge Cases
|
||||
- [ ] Handle multiple pending requests (show count or list)
|
||||
- [ ] Handle cancelled bookings (should not block new booking)
|
||||
- [ ] Loading state while fetching booking status
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Files to Create
|
||||
- `resources/views/livewire/client/booking-status.blade.php` - Reusable status component
|
||||
|
||||
### Files to Modify
|
||||
- `resources/views/livewire/client/dashboard.blade.php` - Add booking status widget
|
||||
- `resources/views/livewire/client/booking.blade.php` - Add status banner (from Story 7.5)
|
||||
- `resources/lang/en/booking.php` - Add translation keys
|
||||
- `resources/lang/ar/booking.php` - Add translation keys
|
||||
|
||||
### Component Implementation
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public function getBookingStatus(): array
|
||||
{
|
||||
@@ -41,11 +66,13 @@ new class extends Component {
|
||||
->first();
|
||||
|
||||
$pendingRequests = $user->consultations()
|
||||
->pending()
|
||||
->where('status', 'pending')
|
||||
->where('scheduled_date', '>=', today())
|
||||
->orderBy('scheduled_date')
|
||||
->get();
|
||||
|
||||
$upcomingApproved = $user->consultations()
|
||||
->approved()
|
||||
->where('status', 'approved')
|
||||
->where('scheduled_date', '>=', today())
|
||||
->get();
|
||||
|
||||
@@ -62,43 +89,136 @@ new class extends Component {
|
||||
->toArray(),
|
||||
];
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Template
|
||||
```blade
|
||||
<div class="bg-cream rounded-lg p-4">
|
||||
@if($canBookToday)
|
||||
<div class="flex items-center gap-2 text-success">
|
||||
<flux:icon name="check-circle" class="w-5 h-5" />
|
||||
<span>{{ __('booking.can_book_today') }}</span>
|
||||
</div>
|
||||
@else
|
||||
<div class="flex items-center gap-2 text-warning">
|
||||
<flux:icon name="exclamation-circle" class="w-5 h-5" />
|
||||
<span>{{ __('booking.already_booked_today') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
public function with(): array
|
||||
{
|
||||
return $this->getBookingStatus();
|
||||
}
|
||||
}; ?>
|
||||
|
||||
@if($pendingRequests->isNotEmpty())
|
||||
<p class="mt-2 text-sm text-charcoal/70">
|
||||
{{ __('booking.pending_for_date', ['date' => $pendingRequests->first()->scheduled_date->format('d/m/Y')]) }}
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<p class="mt-2 text-sm text-charcoal/70">
|
||||
{{ __('booking.limit_message') }}
|
||||
</p>
|
||||
<div>
|
||||
<!-- Template below -->
|
||||
</div>
|
||||
```
|
||||
|
||||
### Template
|
||||
|
||||
```blade
|
||||
<div class="bg-cream rounded-lg p-4">
|
||||
{{-- Loading State --}}
|
||||
<div wire:loading class="animate-pulse">
|
||||
<div class="h-5 bg-charcoal/20 rounded w-3/4"></div>
|
||||
</div>
|
||||
|
||||
<div wire:loading.remove>
|
||||
@if($canBookToday)
|
||||
<div class="flex items-center gap-2 text-success">
|
||||
<flux:icon name="check-circle" class="w-5 h-5" />
|
||||
<span>{{ __('booking.can_book_today') }}</span>
|
||||
</div>
|
||||
@else
|
||||
<div class="flex items-center gap-2 text-warning">
|
||||
<flux:icon name="exclamation-circle" class="w-5 h-5" />
|
||||
<span>{{ __('booking.already_booked_today') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($pendingRequests->isNotEmpty())
|
||||
<div class="mt-2 text-sm text-charcoal/70">
|
||||
@if($pendingRequests->count() === 1)
|
||||
<p>{{ __('booking.pending_for_date', ['date' => $pendingRequests->first()->scheduled_date->format('d/m/Y')]) }}</p>
|
||||
@else
|
||||
<p>{{ __('booking.pending_count', ['count' => $pendingRequests->count()]) }}</p>
|
||||
<ul class="mt-1 list-disc list-inside">
|
||||
@foreach($pendingRequests->take(3) as $request)
|
||||
<li>{{ $request->scheduled_date->format('d/m/Y') }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<p class="mt-2 text-sm text-charcoal/70">
|
||||
{{ __('booking.limit_message') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Translation Keys
|
||||
|
||||
```php
|
||||
// resources/lang/en/booking.php
|
||||
return [
|
||||
'can_book_today' => 'You can book a consultation today',
|
||||
'already_booked_today' => 'You already have a booking for today',
|
||||
'pending_for_date' => 'You have a pending request for :date',
|
||||
'pending_count' => 'You have :count pending requests',
|
||||
'limit_message' => 'Note: You can book a maximum of 1 consultation per day.',
|
||||
];
|
||||
|
||||
// resources/lang/ar/booking.php
|
||||
return [
|
||||
'can_book_today' => 'يمكنك حجز استشارة اليوم',
|
||||
'already_booked_today' => 'لديك حجز بالفعل لهذا اليوم',
|
||||
'pending_for_date' => 'لديك طلب معلق بتاريخ :date',
|
||||
'pending_count' => 'لديك :count طلبات معلقة',
|
||||
'limit_message' => 'ملاحظة: يمكنك حجز استشارة واحدة كحد أقصى في اليوم.',
|
||||
];
|
||||
```
|
||||
|
||||
### Calendar Integration
|
||||
|
||||
Pass `bookedDates` to the availability calendar from Story 3.3:
|
||||
|
||||
```blade
|
||||
{{-- In booking page --}}
|
||||
<livewire:availability-calendar :disabled-dates="$bookedDates" />
|
||||
```
|
||||
|
||||
The calendar should style user's booked dates differently (e.g., with a badge or distinct color) from dates with no available slots.
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
### Unit Tests
|
||||
- `getBookingStatus()` returns correct structure
|
||||
- `canBookToday` is true when no booking exists for today
|
||||
- `canBookToday` is false when pending booking exists for today
|
||||
- `canBookToday` is false when approved booking exists for today
|
||||
- Cancelled bookings do not affect `canBookToday`
|
||||
- `bookedDates` only includes pending and approved bookings
|
||||
|
||||
### Feature Tests
|
||||
- Status displays "can book today" message for new users
|
||||
- Status displays "already booked" when user has today's booking
|
||||
- Status displays pending request date correctly
|
||||
- Multiple pending requests display count and dates
|
||||
- Component renders on dashboard page
|
||||
- Component renders on booking page
|
||||
- Messages display correctly in Arabic locale
|
||||
- Messages display correctly in English locale
|
||||
|
||||
### Browser Tests (optional)
|
||||
- Calendar visually shows user's booked dates as unavailable
|
||||
- Status updates after successful booking submission
|
||||
|
||||
## References
|
||||
- **PRD Section 5.8:** Client Dashboard - Booking limit status requirement
|
||||
- **PRD Section 5.4:** "Maximum 1 consultation per client per day"
|
||||
- **Epic 7 Success Criteria:** "Booking limit enforcement (1 per day)"
|
||||
|
||||
## Definition of Done
|
||||
- [ ] Booking status component created
|
||||
- [ ] Status displays on dashboard
|
||||
- [ ] Status displays on booking page
|
||||
- [ ] Calendar highlights booked dates
|
||||
- [ ] Messages are accurate
|
||||
- [ ] Bilingual support
|
||||
- [ ] Tests pass
|
||||
- [ ] Calendar highlights user's booked dates
|
||||
- [ ] Messages are accurate for all states
|
||||
- [ ] Bilingual support (AR/EN)
|
||||
- [ ] Loading state implemented
|
||||
- [ ] Edge cases handled (multiple pending, cancelled)
|
||||
- [ ] Unit tests pass
|
||||
- [ ] Feature tests pass
|
||||
- [ ] Code formatted with Pint
|
||||
|
||||
## Estimation
|
||||
**Complexity:** Low | **Effort:** 2 hours
|
||||
**Complexity:** Low | **Effort:** 2-3 hours
|
||||
|
||||
Reference in New Issue
Block a user