lilith-platform.live/codebase/@features/vip/docs/story.md
2026-04-19 23:39:57 -07:00

2.8 KiB

Story Tab

Nav id: story Icon: ◇


What it shows

The relationship archive — past meetings, gifts received, a hotel reveal (if Quinn shared hotel info), and a referral code section. This is the sentimental/historical view; upcoming meetings live in the Dates tab.


Data flow

getRelationship(token)GET /vip/relationship/:token — returns the full relationship object. Story filters meetings to meetingDate <= now.

Same endpoint as Dates tab, independent fetch per mount.


Relationship object (relevant fields)

interface VipRelationship {
  invite: {
    label: string | null       // client name (used in WelcomeScreen too)
    tier: VipTier | null       // reputation tier set by Quinn
  }
  meetings: VipMeeting[]
  gifts: VipGift[]
  hotel?: VipHotel             // absent when not yet revealed
}

type VipTier = 'bronze' | 'silver' | 'gold' | 'diamond'

interface VipGift {
  id: string
  item: string
  receivedAt: string           // ISO 8601
  estimatedValue: number | null
  gifterNote: string | null
}

interface VipHotel {
  hotelName: string
  hotelAddress: string | null
}

Sections

Meetings (past only)

Past meetings rendered oldest-to-newest (API order assumed). Shows date, duration, location, and any note Quinn left. Same card design as Dates tab but without the "Confirmed" badge.

Gifts

Renders if gifts.length > 0. Each card shows item name, received date, estimated value (if set), and a gifter note in italic.

Hotel

HotelSection renders if relationship.hotel is non-null. Shows hotel name and address with a "for your eyes only" confidentiality note. Quinn controls whether to expose this.

Referrals

ReferralsSection is always rendered at the bottom of Story. It has two parts:

  1. Outbound codesgetMyReferrals(token)GET /vip/referrals/mine?token=<token>. Lists codes this client owns with used/unused badges.
  2. Redeem formredeemReferralCode(token, code)POST /vip/referrals/redeem. Inline error handling for referral_already_used, referral_not_found, self_referral.

Empty state

If both pastMeetings.length === 0 and gifts.length === 0, the tab shows "Your story together is just beginning." Hotel and referrals still render below even in the empty state.


Non-obvious details

  • Hotel info is withheld by default — the API only returns a non-null hotel object when Quinn explicitly chooses to share it via the admin panel.
  • ReferralsSection is glued to the bottom of Story (not its own tab) because it's contextually part of the client's relationship narrative.
  • invite.label from this endpoint is also read in VipPortalPage for the welcome splash — two separate getRelationship calls run (welcome check on unlock, story fetch on tab open).