Modules Documentation
Status & badge logic
How statuses transition and what badges render.
Complete
Opportunity status is computed at render time from `deadlineAt`, not stored as a field. The `OpportunityService.computeStatus()` method returns one of `Open` / `ClosingSoon` / `Closed` / `Rolling` — and every visual element (strip color, chip class, deadline pill) derives from that status.
The four computed statuses
- Open · green (.chip-success, bg-badge-verified)
- deadlineAt > today + 7 days. Top strip + status chip + deadline pill all render green-tinted.
- ClosingSoon · orange (.chip-orange, bg-brand-orange)
- deadlineAt ≤ today + 7 days (and still in the future). Urgent. May animate the deadline pill with a subtle pulse.
- Closed · muted grey (.chip-muted, bg-muted-foreground)
- deadlineAt < today. Card stays visible (for SEO/AEO entity history) but de-emphasized. Apply CTA hidden.
- Rolling · purple (.chip-primary, bg-primary)
- deadlineAt is NULL (no fixed deadline). Opportunity accepts applications continuously. Deadline pill shows "Rolling".
Deadline pill labels
- `or.deadline.rolling` — "Rolling deadline" / "موعد متجدّد"
- `or.deadline.closed` — "Closed" / "أُغلق"
- `or.deadline.today` — "Closes today" / "ينتهي اليوم"
- `or.deadline.inDays` — "Closes in {n} days" / "ينتهي خلال {n} أيام" (when ≤ 7 days)
- `or.deadline.on` — "Closes on {date}" / "ينتهي في {date}" (when 8-60 days)
- `or.deadline.openUntil` — "Open until {date}" / "مفتوحة حتى {date}" (when > 60 days)
