Files
spsays-bff/internal/model/sadhna.go
T
2026-08-30 02:18:53 +05:30

105 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import "time"
// SadhnaLog is one persisted row of the sadhna_logs table — the chanting
// half of a day's sādhana. The posting half is derived from the posts
// table at read time, so it has no column here.
type SadhnaLog struct {
ID string `json:"id"`
UserID string `json:"user_id"`
LogDate time.Time `json:"log_date"`
RoundsCompleted int `json:"rounds_completed"`
ChantDone bool `json:"chant_done"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// SadhnaDay is one cell of the 7-day streak strip. `Completed` is the
// conjunction the streak counts: both the chanting and the posting were
// done that calendar day.
type SadhnaDay struct {
Date string `json:"date"` // YYYY-MM-DD (UTC)
ChantDone bool `json:"chant_done"`
QuoteDone bool `json:"quote_done"`
Completed bool `json:"completed"`
}
// VineDay is one fold of the sādhana creeper — one day of practice the
// vine has wound around its pole. The creeper grows a fresh fold for each
// day of the current streak (oldest first), plus a final in-progress fold
// for an unfinished today. Rounds/Posts annotate the fold so the devotee
// sees exactly what they offered that day.
type VineDay struct {
Date string `json:"date"` // YYYY-MM-DD (UTC)
Rounds int `json:"rounds"` // rounds chanted that day
Posts int `json:"posts"` // quotes posted that day
Completed bool `json:"completed"` // both disciplines done (a full fold)
InProgress bool `json:"in_progress"` // today, not yet complete (the growing tip)
}
// SadhnaReward is one gift item in the streak-reward catalog.
type SadhnaReward struct {
ID string `json:"id"`
Key string `json:"key"`
Name string `json:"name"`
Meaning string `json:"meaning"`
ImageURL string `json:"image_url"`
Active bool `json:"active"`
Sort int `json:"sort"`
}
// SadhnaRewardGrant is a reward a user earned at a streak milestone (a
// multiple of 7 days). The full reward is embedded for direct rendering.
type SadhnaRewardGrant struct {
// Milestone is the streak day this was earned on. Nil for an admin gift,
// which isn't tied to a streak at all.
Milestone *int `json:"milestone"`
GrantedAt time.Time `json:"granted_at"`
Reward SadhnaReward `json:"reward"`
// Source is "streak" or "gift".
Source string `json:"source"`
// Opened is false while a gift is still wrapped — the gallery renders
// those blurred until the devotee opens them.
Opened bool `json:"opened"`
}
// SadhnaDashboard is the single payload the /sadhna-streak page reads. It
// folds together today's progress, the week strip, the streak counters,
// and the plant's growth state so the client renders without further
// round-trips.
type SadhnaDashboard struct {
// Today's two disciplines.
TargetRounds int `json:"target_rounds"` // user's goal (16 if unset)
RoundsCompleted int `json:"rounds_completed"` // saved progress today
ChantDone bool `json:"chant_done"` // rounds reached target
QuoteDone bool `json:"quote_done"` // posted at least one quote today
TodayCompleted bool `json:"today_completed"` // both done today
// Streak counters.
CurrentStreak int `json:"current_streak"`
LongestStreak int `json:"longest_streak"`
// Plant state. Growth is 0–100; Stage is the derived label the client
// maps to a visual; Alive is false only when growth has decayed to 0.
Growth int `json:"growth"`
Stage string `json:"stage"` // dead | sprout | seedling | sapling | young | mature
Alive bool `json:"alive"`
// The trailing 7 calendar days, oldest first, for the top strip.
Week []SadhnaDay `json:"week"`
// The creeper: one fold per day of the current streak (oldest first),
// plus a final in-progress fold for an unfinished today. Capped to the
// most recent vineMaxDays folds for payload sanity; CurrentStreak holds
// the true length.
VineDays []VineDay `json:"vine_days"`
// Rewards. NextRewardDate is the projected UTC date (YYYY-MM-DD) the next
// gift lands if the streak continues — for the calendar's gift marker.
// PendingReward is a freshly earned, not-yet-celebrated gift the client
// should celebrate now (nil when there's nothing to show).
NextRewardDate *string `json:"next_reward_date"`
PendingReward *SadhnaRewardGrant `json:"pending_reward"`
}