- SwiftUI + async/await architecture - Barcode scanning with AVFoundation - Product display with score ring, NOVA badge, nutrition - Alternatives with sort/filter - Auth (login/register) - Favorites & history - Account management - Dark theme - Connected to food.payfrit.com API (Open Food Facts proxy) Co-Authored-By: Claude <noreply@anthropic.com>
129 lines
4.4 KiB
Markdown
129 lines
4.4 KiB
Markdown
# PayfritFood - iOS App
|
|
|
|
Native Swift/SwiftUI iOS app for scanning food products, viewing health scores, and finding healthier alternatives.
|
|
|
|
**Bundle ID**: `com.payfrit.food`
|
|
**Display Name**: Payfrit Food
|
|
**API Base**: `https://food.payfrit.com/api`
|
|
|
|
## Build & Deploy
|
|
|
|
```bash
|
|
# Build for device
|
|
cd ~/payfrit-food-ios && xcodebuild -project PayfritFood.xcodeproj -scheme PayfritFood -destination 'id=00008030-000244863413C02E' -allowProvisioningUpdates build
|
|
|
|
# Install to phone
|
|
xcrun devicectl device install app --device 00008030-000244863413C02E ~/Library/Developer/Xcode/DerivedData/PayfritFood-*/Build/Products/Debug-iphoneos/PayfritFood.app
|
|
|
|
# Launch app
|
|
xcrun devicectl device process launch --device 00008030-000244863413C02E com.payfrit.food
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
PayfritFood/
|
|
├── PayfritFoodApp.swift # App entry point
|
|
├── Info.plist # App config, permissions
|
|
├── Assets.xcassets/ # App icons, colors
|
|
│
|
|
├── Models/
|
|
│ ├── Product.swift # Product with score, NOVA, nutrition
|
|
│ ├── Alternative.swift # Alternative product with links
|
|
│ ├── UserProfile.swift # User profile
|
|
│ └── ScanHistory.swift # Scan history item
|
|
│
|
|
├── ViewModels/
|
|
│ └── AppState.swift # Central state (@MainActor ObservableObject)
|
|
│
|
|
├── Services/
|
|
│ ├── APIService.swift # Actor-based API client
|
|
│ ├── AuthStorage.swift # Keychain token storage
|
|
│ ├── BarcodeScanner.swift # AVFoundation barcode scanning
|
|
│ └── LocationService.swift # CoreLocation for distance
|
|
│
|
|
└── Views/
|
|
├── RootView.swift # Tab navigation
|
|
├── ScanTab/
|
|
│ ├── ScanScreen.swift # Camera + manual entry
|
|
│ └── ManualEntrySheet.swift
|
|
├── ProductTab/
|
|
│ ├── ProductScreen.swift # Product detail
|
|
│ ├── ScoreRing.swift # Animated score circle
|
|
│ ├── NOVABadge.swift # NOVA 1-4 badge
|
|
│ ├── DietaryPills.swift # Dietary tags
|
|
│ ├── NutritionSection.swift
|
|
│ └── IngredientsSection.swift
|
|
├── AlternativesTab/
|
|
│ ├── AlternativesScreen.swift
|
|
│ ├── FilterChips.swift
|
|
│ ├── AlternativeCard.swift
|
|
│ └── SponsoredCard.swift
|
|
├── FavoritesTab/
|
|
│ └── FavoritesScreen.swift
|
|
├── HistoryTab/
|
|
│ └── HistoryScreen.swift
|
|
├── AccountTab/
|
|
│ ├── AccountScreen.swift
|
|
│ ├── LoginSheet.swift
|
|
│ └── RegisterSheet.swift
|
|
└── Components/
|
|
└── ProductCard.swift
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### State Management
|
|
- **AppState** (`@MainActor ObservableObject`): Single source of truth
|
|
- Authentication: userId, userToken, userProfile, isPremium
|
|
- Current product and alternatives
|
|
- Navigation state (selectedTab, showLoginSheet, etc.)
|
|
|
|
### API Service
|
|
- **APIService** (Swift actor): Thread-safe singleton
|
|
- Base URL: `https://food.payfrit.com/api`
|
|
- Auth via `Authorization: Bearer {token}` header
|
|
|
|
### Key Endpoints
|
|
- `POST /auth/login` - Login with email/password
|
|
- `POST /auth/register` - Register new user
|
|
- `POST /product/lookup` - Lookup product by barcode
|
|
- `GET /product/{id}/alternatives` - Get healthier alternatives
|
|
- `GET /favorites` - Get user favorites
|
|
- `GET /history` - Get scan history
|
|
|
|
## Features
|
|
|
|
### Barcode Scanning
|
|
- AVFoundation with AVCaptureMetadataOutput
|
|
- Supported formats: EAN-8, EAN-13, UPC-A, UPC-E, Code-128
|
|
- Manual entry fallback
|
|
|
|
### Product Display
|
|
- Animated score ring (0-100)
|
|
- NOVA badge (1-4 processing level)
|
|
- Dietary pills (vegan, gluten-free, etc.)
|
|
- Expandable nutrition facts
|
|
- Expandable ingredients list
|
|
|
|
### Alternatives
|
|
- Sort by: Rating, Price, Distance, Processing Level
|
|
- Filter chips: Dietary (vegan, GF, etc.), Availability (delivery, pickup)
|
|
- Sponsored cards with action links (premium users see no sponsored content)
|
|
|
|
### User Features
|
|
- Favorites (requires auth)
|
|
- Scan history (requires auth)
|
|
- Account: export data, logout, delete account
|
|
- Premium: removes sponsored content
|
|
|
|
## Permissions
|
|
- **Camera**: Barcode scanning
|
|
- **Location**: Find nearby stores
|
|
|
|
## Dependencies
|
|
- None (uses only system frameworks)
|
|
|
|
## iOS Version
|
|
- Minimum: iOS 16.0
|
|
- SwiftUI + async/await + URLSession
|