Deploy Ladill Mini / deploy (push) Successful in 35s
Ship full-featured mobile clients with auth, payments, QRs, push notifications, and iOS polish including Figtree typography, app icons, and QR previews. Co-authored-by: Cursor <cursoragent@cursor.com>
333 lines
8.8 KiB
Swift
333 lines
8.8 KiB
Swift
import Foundation
|
|
|
|
struct Envelope<T: Decodable>: Decodable { let data: T }
|
|
|
|
struct PagedEnvelope<T: Decodable>: Decodable {
|
|
let data: [T]
|
|
let meta: PageMeta?
|
|
}
|
|
|
|
struct PageMeta: Decodable {
|
|
let currentPage: Int?
|
|
let lastPage: Int?
|
|
let perPage: Int?
|
|
let total: Int?
|
|
}
|
|
|
|
struct LoginRequest: Encodable {
|
|
let email: String
|
|
let password: String
|
|
let deviceName = "Ladill Mini iOS"
|
|
}
|
|
|
|
struct LoginResult: Decodable {
|
|
let token: String
|
|
let user: User
|
|
}
|
|
|
|
struct RegisterRequest: Encodable {
|
|
let name: String
|
|
let email: String
|
|
let password: String
|
|
let passwordConfirmation: String
|
|
let company: String?
|
|
let address: String
|
|
let city: String
|
|
let state: String
|
|
let country: String
|
|
let zipcode: String
|
|
let phoneCc: String
|
|
let phone: String
|
|
let mobileCc: String?
|
|
let mobile: String?
|
|
let terms: Bool
|
|
let deviceName = "Ladill Mini iOS"
|
|
}
|
|
|
|
struct User: Decodable {
|
|
let id: Int64
|
|
let publicId: String?
|
|
let name: String?
|
|
let email: String?
|
|
let avatarUrl: String?
|
|
let actingAccount: Account?
|
|
}
|
|
|
|
struct Account: Decodable {
|
|
let id: Int64
|
|
let publicId: String?
|
|
let name: String?
|
|
let email: String?
|
|
}
|
|
|
|
struct Overview: Decodable {
|
|
let currency: String?
|
|
let todayTakingsMinor: Int64?
|
|
let todayCount: Int?
|
|
let paymentQrCount: Int?
|
|
let walletBalanceMinor: Int64?
|
|
let recentPayments: [Payment]?
|
|
}
|
|
|
|
struct Payment: Decodable, Identifiable {
|
|
let id: Int64
|
|
let reference: String?
|
|
let amountMinor: Int64?
|
|
let merchantAmountMinor: Int64?
|
|
let platformFeeMinor: Int64?
|
|
let currency: String?
|
|
let status: String?
|
|
let payerName: String?
|
|
let payerEmail: String?
|
|
let payerPhone: String?
|
|
let payerNote: String?
|
|
let qrCodeId: Int64?
|
|
let qrLabel: String?
|
|
let paidAt: String?
|
|
let createdAt: String?
|
|
}
|
|
|
|
struct PaymentQr: Decodable, Identifiable {
|
|
let id: Int64
|
|
let label: String
|
|
let businessName: String?
|
|
let branchLabel: String?
|
|
let currency: String?
|
|
let shortCode: String?
|
|
let publicUrl: String?
|
|
let isActive: Bool?
|
|
let scansTotal: Int?
|
|
let previewUrl: String?
|
|
let createdAt: String?
|
|
let updatedAt: String?
|
|
}
|
|
|
|
struct CreatePaymentQrRequest: Encodable {
|
|
let label: String
|
|
let businessName: String
|
|
let branchLabel: String?
|
|
}
|
|
|
|
struct UpdatePaymentQrRequest: Encodable {
|
|
var label: String?
|
|
var businessName: String?
|
|
var branchLabel: String?
|
|
var isActive: Bool?
|
|
}
|
|
|
|
struct Payouts: Decodable {
|
|
let currency: String?
|
|
let totalRevenueMinor: Int64?
|
|
let walletBalanceMinor: Int64?
|
|
let accountWalletUrl: String?
|
|
}
|
|
|
|
struct AccountSettings: Decodable {
|
|
let profile: ProfileInfo
|
|
let notifications: NotificationPrefs
|
|
}
|
|
|
|
struct ProfileInfo: Decodable {
|
|
let name: String?
|
|
let email: String?
|
|
let phone: String?
|
|
let phoneCc: String?
|
|
}
|
|
|
|
struct NotificationPrefs: Codable {
|
|
var notifyEmail: String?
|
|
var productUpdates: Bool?
|
|
var notifyRegistrations: Bool?
|
|
var notifyPayouts: Bool?
|
|
}
|
|
|
|
struct UpdateSettingsRequest: Encodable {
|
|
let notifyEmail: String?
|
|
let productUpdates: Bool
|
|
let notifyRegistrations: Bool
|
|
let notifyPayouts: Bool
|
|
}
|
|
|
|
struct UpdateProfileRequest: Encodable {
|
|
let name: String
|
|
let phoneCc: String?
|
|
let phone: String?
|
|
}
|
|
|
|
struct AvatarResult: Decodable { let avatarUrl: String? }
|
|
|
|
struct ChangePasswordRequest: Encodable {
|
|
let currentPassword: String
|
|
let password: String
|
|
let passwordConfirmation: String
|
|
}
|
|
|
|
struct MessageResponse: Decodable { let message: String? }
|
|
|
|
struct AfiaChatRequest: Encodable {
|
|
let message: String
|
|
let history: [AfiaChatTurn]
|
|
}
|
|
|
|
struct AfiaChatTurn: Encodable {
|
|
let role: String
|
|
let text: String
|
|
}
|
|
|
|
struct AfiaChatResponse: Decodable {
|
|
let reply: String?
|
|
let message: String?
|
|
}
|
|
|
|
struct WalletInfo: Decodable {
|
|
let currency: String?
|
|
let balanceMinor: Int64?
|
|
let spentMinor: Int64?
|
|
let creditedMinor: Int64?
|
|
}
|
|
|
|
struct TopupRequest: Encodable { let amount: Double }
|
|
|
|
struct CheckoutUrl: Decodable { let checkoutUrl: String }
|
|
|
|
struct PayoutAccountWrapper: Decodable { let payoutAccount: PayoutAccount? }
|
|
|
|
struct PayoutAccount: Decodable {
|
|
let accountType: String?
|
|
let accountName: String?
|
|
let accountNumber: String?
|
|
let bankCode: String?
|
|
let bankName: String?
|
|
let currency: String?
|
|
}
|
|
|
|
struct UpdatePayoutAccountRequest: Encodable {
|
|
let accountType: String
|
|
let accountName: String
|
|
let accountNumber: String
|
|
let bankCode: String
|
|
let bankName: String
|
|
let currency: String
|
|
}
|
|
|
|
struct Bank: Decodable, Identifiable {
|
|
var id: String { code }
|
|
let name: String
|
|
let code: String
|
|
}
|
|
|
|
struct WithdrawRequest: Encodable { let amount: Double }
|
|
|
|
struct Withdrawal: Decodable, Identifiable {
|
|
let id: Int64
|
|
let amountGhs: Double?
|
|
let status: String?
|
|
let createdAt: String?
|
|
}
|
|
|
|
struct SupportTicket: Decodable, Identifiable {
|
|
let id: Int64
|
|
let ticketRef: String?
|
|
let subject: String?
|
|
let status: String?
|
|
let priority: String?
|
|
let hasReply: Bool?
|
|
let createdAt: String?
|
|
let message: String?
|
|
let reply: String?
|
|
let repliedAt: String?
|
|
}
|
|
|
|
struct CreateTicketRequest: Encodable {
|
|
let subject: String
|
|
let message: String
|
|
let priority: String
|
|
}
|
|
|
|
struct NotificationsListResponse: Decodable {
|
|
let data: [AppNotification]
|
|
let unreadCount: Int?
|
|
}
|
|
|
|
struct AppNotification: Decodable, Identifiable {
|
|
let id: String
|
|
let type: String?
|
|
let title: String
|
|
let message: String
|
|
let icon: String?
|
|
let milestone: String?
|
|
let url: String?
|
|
let readAt: String?
|
|
let createdAt: String?
|
|
|
|
var isRead: Bool { readAt != nil }
|
|
}
|
|
|
|
struct UnreadCountEnvelope: Decodable { let unreadCount: Int? }
|
|
|
|
struct PushTokenRequest: Encodable {
|
|
let token: String
|
|
let platform = "ios"
|
|
let deviceName = "Ladill Mini iOS"
|
|
}
|
|
|
|
struct Country: Identifiable, Hashable {
|
|
var id: String { code }
|
|
let code: String
|
|
let name: String
|
|
let dialCode: String
|
|
let states: [String]
|
|
}
|
|
|
|
enum Countries {
|
|
static let all: [Country] = [
|
|
Country(code: "GH", name: "Ghana", dialCode: "233", states: [
|
|
"Ahafo", "Ashanti", "Bono", "Bono East", "Central", "Eastern", "Greater Accra",
|
|
"North East", "Northern", "Oti", "Savannah", "Upper East", "Upper West", "Volta",
|
|
"Western", "Western North",
|
|
]),
|
|
Country(code: "NG", name: "Nigeria", dialCode: "234", states: [
|
|
"Abia", "Abuja FCT", "Adamawa", "Akwa Ibom", "Anambra", "Bauchi", "Bayelsa", "Benue",
|
|
"Borno", "Cross River", "Delta", "Ebonyi", "Edo", "Ekiti", "Enugu", "Gombe", "Imo",
|
|
"Jigawa", "Kaduna", "Kano", "Katsina", "Kebbi", "Kogi", "Kwara", "Lagos", "Nasarawa",
|
|
"Niger", "Ogun", "Ondo", "Osun", "Oyo", "Plateau", "Rivers", "Sokoto", "Taraba",
|
|
"Yobe", "Zamfara",
|
|
]),
|
|
Country(code: "KE", name: "Kenya", dialCode: "254", states: [
|
|
"Baringo", "Bomet", "Bungoma", "Busia", "Elgeyo-Marakwet", "Embu", "Garissa",
|
|
"Homa Bay", "Isiolo", "Kajiado", "Kakamega", "Kericho", "Kiambu", "Kilifi",
|
|
"Kirinyaga", "Kisii", "Kisumu", "Kitui", "Kwale", "Laikipia", "Lamu", "Machakos",
|
|
"Makueni", "Mandera", "Marsabit", "Meru", "Migori", "Mombasa", "Murang'a", "Nairobi",
|
|
"Nakuru", "Nandi", "Narok", "Nyamira", "Nyandarua", "Nyeri", "Samburu", "Siaya",
|
|
"Taita-Taveta", "Tana River", "Tharaka-Nithi", "Trans Nzoia", "Turkana",
|
|
"Uasin Gishu", "Vihiga", "Wajir", "West Pokot",
|
|
]),
|
|
Country(code: "ZA", name: "South Africa", dialCode: "27", states: [
|
|
"Eastern Cape", "Free State", "Gauteng", "KwaZulu-Natal", "Limpopo", "Mpumalanga",
|
|
"North West", "Northern Cape", "Western Cape",
|
|
]),
|
|
Country(code: "GB", name: "United Kingdom", dialCode: "44", states: [
|
|
"England", "Northern Ireland", "Scotland", "Wales",
|
|
]),
|
|
Country(code: "US", name: "United States", dialCode: "1", states: [
|
|
"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
|
|
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
|
|
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
|
|
"Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
|
|
"New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
|
|
"North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
|
|
"South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
|
|
"Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming",
|
|
]),
|
|
]
|
|
|
|
static var `default`: Country { all[0] }
|
|
}
|
|
|
|
enum LoadState<T> {
|
|
case idle
|
|
case loading
|
|
case success(T)
|
|
case failure(String)
|
|
}
|