Models
All data models are Codable structs in StaccatoCoffee/Models/. They map directly to Supabase database tables using CodingKeys for snake_case conversion.
Profile
File: Models/Profile.swift
| Property | Type | DB Column | Description |
|---|---|---|---|
id | String | id | UUID, references auth.users |
email | String | email | User email |
fullName | String? | full_name | Display name |
phone | String? | phone | Phone number |
avatarUrl | String? | avatar_url | Profile image URL |
birthday | String? | birthday | Birthday string |
role | UserRole | role | customer, employee, or admin |
createdAt | Date | created_at | Account creation date |
updatedAt | Date | updated_at | Last update |
Computed Properties:
displayName—fullNameor email prefix or “Coffee Lover”firstName— First word offullNameisStaff—role == .employee || role == .adminisAdmin—role == .admin
MenuItem
File: Models/MenuItem.swift
| Property | Type | DB Column | Description |
|---|---|---|---|
id | String | id | UUID |
categoryId | String | category_id | FK to menu_categories |
name | String | name | Item name |
description | String? | description | Item description |
basePrice | Int | base_price | Price in cents |
imageUrl | String? | image_url | Item image |
starsToRedeem | Int | stars_to_redeem | Stars needed to redeem for free |
isFeatured | Bool | is_featured | Shown on home page |
isAvailable | Bool | is_available | Currently available |
sortOrder | Int | sort_order | Display order |
nutritionInfo | NutritionInfo? | nutrition_info | JSONB nutrition data |
Computed: starsEarned — (basePrice * 2) / 100 (2 stars per dollar)
Related Types
MenuCategory: id, name, slug, description, imageUrl, sortOrder, isActive
MenuItemWithModifiers: Extends MenuItem with category: MenuCategory and modifierGroups: [ModifierGroupWithModifiers]
ModifierGroup: id, name, slug, isRequired, minSelections, maxSelections, sortOrder
- Computed:
isSingleSelect—maxSelections == 1
Modifier: id, groupId, name, priceAdjustment (cents), isDefault, isAvailable, sortOrder
Order
File: Models/Order.swift
| Property | Type | DB Column | Description |
|---|---|---|---|
id | String | id | UUID |
locationId | String | location_id | FK to locations |
userId | String? | user_id | FK to auth.users |
orderNumber | String | order_number | e.g., “SC-A042” |
status | OrderStatus | status | Current status |
assignedTo | String? | assigned_to | Staff who claimed |
claimedAt | Date? | claimed_at | When claimed |
subtotal | Int | subtotal | In cents |
tax | Int | tax | In cents |
discount | Int | discount | In cents |
tip | Int | tip | In cents |
total | Int | total | In cents |
starsEarned | Int | stars_earned | Stars awarded |
paymentMethod | String? | payment_method | Payment type |
squarePaymentId | String? | square_payment_id | Square payment ref |
squareOrderId | String? | square_order_id | Square order ref |
idempotencyKey | String? | idempotency_key | Duplicate prevention |
version | Int | version | Optimistic locking |
OrderStatus
enum OrderStatus: String, Codable {
case pending
case inProgress = "in_progress"
case ready
case completed
case cancelled
}OrderItem
id, orderId, menuItemId, name, quantity, unitPrice, totalPrice, notes
OrderItemModifier
id, orderItemId, modifierId, name, priceAdjustment
CartItem
File: Models/CartItem.swift
| Property | Type | Description |
|---|---|---|
id | String | UUID |
menuItemId | String | Reference to menu item |
name | String | Item name |
basePrice | Int | Base price in cents |
quantity | Int | Quantity (mutable) |
modifiers | [CartItemModifier] | Selected modifiers |
notes | String? | Special instructions |
Computed Properties:
totalPrice—(basePrice + modifierTotal) * quantityunitPriceWithModifiers—basePrice + modifierTotalstarsEarned—(unitPriceWithModifiers * 2) / 100totalStars—starsEarned * quantity
LoyaltyAccount
File: Models/LoyaltyAccount.swift
| Property | Type | DB Column | Description |
|---|---|---|---|
id | String | id | UUID |
userId | String | user_id | FK to auth.users |
starsBalance | Int | stars_balance | Current redeemable stars |
lifetimeStars | Int | lifetime_stars | Total ever earned |
tier | LoyaltyTier | tier | green, gold, platinum |
tierExpiry | Date? | tier_expiry | When tier expires |
LoyaltyTier
| Case | Required Stars | Color |
|---|---|---|
.green | 0 | #22C55E |
.gold | 300 | #EAB308 |
.platinum | 600 | #94A3B8 |
Reward
File: Models/Reward.swift
| Property | Type | DB Column | Description |
|---|---|---|---|
id | String | id | UUID |
name | String | name | Reward name |
description | String? | description | Description |
starsRequired | Int | stars_required | Cost in stars |
rewardType | RewardType | reward_type | Type of reward |
rewardValue | RewardValue? | reward_value | JSONB value config |
minTier | LoyaltyTier | min_tier | Minimum tier required |
isActive | Bool | is_active | Currently available |