Streaks¶
Status
UI live (mock data). wp_fruitplug_streaks exists; the PWA streaks dashboard is shipped at /account/streaks and renders a mock 4-week streak until GET /fruitplug/v1/streaks/me is wired up.
Fruit Plug rewards customers for ordering once a week. One completed order inside the current ISO week = +1 to current_length. Skip a week, current_length resets to 0; best_length never decreases.
Tier ladder¶
| Tier | Weeks in a row | PWA reward (planned) |
|---|---|---|
| Bronze | 1–3 | Free delivery on first sub box |
| Silver | 4–7 | 5% discount code emailed |
| Gold | 12–25 | Free Japanese Selection upsell on the next box |
| Platinum | 26+ | Monthly premium fruit drop + early access to limited boxes |
Thresholds live in apps/web/lib/streaks.ts as STREAK_TIERS so the UI, docs, and eventual WP response all agree on the numbers.
Data flow¶
flowchart LR
A[daily cron<br/>fruitplug_daily_streaks] --> B{user has<br/>completed order<br/>this ISO week?}
B -- yes --> C[current_length++<br/>best_length = max]
B -- no --> D[current_length = 0]
C --> E[(wp_fruitplug_streaks)]
D --> E
E --> F[GET /fruitplug/v1/streaks/me]
F --> G[apps/web/lib/streaks.ts<br/>getStreakState]
G --> H[/account/streaks/]
PWA surfaces¶
/account/streaks— hero with current length + best-ever, 12-week calendar grid (Checkdot = ordered,Circledot = missed), tier-ladder cards, streak-rewards list./accounthero — will surface tier badge + "X-week streak" copy once the live endpoint is wired.- Header drawer — planned: small amber "streak" badge next to the user's name.
Planned WP endpoint¶
GET /wp-json/fruitplug/v1/streaks/me (requires login)
{
"user_id": 42,
"current_length": 4,
"best_length": 7,
"tier": "silver",
"last_week_iso": "2026-W16",
"recent_weeks": [
{ "iso": "2026-W05", "ordered": true },
{ "iso": "2026-W06", "ordered": false }
],
"rewards": [
{ "threshold": 1, "claimed_at": "2026-03-28T00:00:00Z" },
{ "threshold": 4, "claimed_at": "2026-04-18T00:00:00Z" },
{ "threshold": 12, "claimed_at": null },
{ "threshold": 26, "claimed_at": null }
]
}
The recent_weeks array is ordered oldest → newest so the PWA can render the grid left-to-right without a sort.