Monorepo for Tangled
0

Configure Feed

Select the types of activity you want to include in your feed.

appview/db: add handlers for onboarding flow

Signed-off-by: oppiliappan <me@oppi.li>

oppiliappan (Jul 7, 2026, 3:55 PM +0100) 93d553bd 161c85b9

+90
+90
appview/db/onboarding.go
··· 1 + package db 2 + 3 + import ( 4 + "database/sql" 5 + "log" 6 + "time" 7 + 8 + "tangled.org/core/appview/models" 9 + ) 10 + 11 + // GetOnboarding returns the onboarding record for a did, or (nil, nil) if none exists. 12 + func GetOnboarding(e Execer, did string) (*models.Onboarding, error) { 13 + query := `select did, step, status, created, updated from onboarding where did = ?` 14 + row := e.QueryRow(query, did) 15 + 16 + var o models.Onboarding 17 + var status string 18 + var created, updated string 19 + err := row.Scan(&o.Did, &o.Step, &status, &created, &updated) 20 + if err == sql.ErrNoRows { 21 + return nil, nil 22 + } 23 + if err != nil { 24 + return nil, err 25 + } 26 + 27 + o.Status = models.OnboardingStatus(status) 28 + if t, err := time.Parse(time.RFC3339, created); err == nil { 29 + o.Created = t 30 + } 31 + if t, err := time.Parse(time.RFC3339, updated); err == nil { 32 + o.Updated = t 33 + } 34 + 35 + return &o, nil 36 + } 37 + 38 + func UpsertOnboarding(e Execer, o *models.Onboarding) error { 39 + query := ` 40 + insert into onboarding (did, step, status, updated) 41 + values (?, ?, ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now')) 42 + on conflict(did) do update set 43 + step = excluded.step, 44 + status = excluded.status, 45 + updated = excluded.updated 46 + ` 47 + _, err := e.Exec(query, o.Did, o.Step, string(o.Status)) 48 + return err 49 + } 50 + 51 + // AdvanceOnboardingStep moves the stored step forward to the given step. It is 52 + // monotonic: it never decreases the step, so navigating back to an earlier page 53 + // and re-submitting does not regress recorded progress. 54 + func AdvanceOnboardingStep(e Execer, did string, step int) error { 55 + _, err := e.Exec( 56 + `update onboarding set step = ?, updated = strftime('%Y-%m-%dT%H:%M:%SZ', 'now') where did = ? and step < ?`, 57 + step, did, step, 58 + ) 59 + return err 60 + } 61 + 62 + func CompleteOnboarding(e Execer, did string) error { 63 + _, err := e.Exec( 64 + `update onboarding set status = ?, step = ?, updated = strftime('%Y-%m-%dT%H:%M:%SZ', 'now') where did = ?`, 65 + string(models.OnboardingCompleted), models.OnboardingStepDone, did, 66 + ) 67 + return err 68 + } 69 + 70 + func SkipOnboarding(e Execer, did string) error { 71 + _, err := e.Exec( 72 + `update onboarding set status = ?, updated = strftime('%Y-%m-%dT%H:%M:%SZ', 'now') where did = ?`, 73 + string(models.OnboardingSkipped), did, 74 + ) 75 + return err 76 + } 77 + 78 + // IsOnboarding reports whether a did has an in-progress onboarding record. 79 + func IsOnboarding(e Execer, did string) (bool, error) { 80 + var exists bool 81 + err := e.QueryRow( 82 + `select exists(select 1 from onboarding where did = ? and status = 'in_progress')`, 83 + did, 84 + ).Scan(&exists) 85 + if err != nil { 86 + log.Println("failed to check onboarding status", err) 87 + return false, err 88 + } 89 + return exists, nil 90 + }