Files
ladill-mini/apps/ios/LadillMini/Core/Components/Cards.swift
T
isaaccladandCursor ea6afb80a4
Deploy Ladill Mini / deploy (push) Successful in 35s
Add Ladill Mini native Android and iOS apps.
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>
2026-06-11 22:30:35 +00:00

103 lines
3.1 KiB
Swift

import SwiftUI
struct LadillCard<Content: View>: View {
@ViewBuilder let content: Content
var body: some View {
content
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(LadillColors.surface)
.overlay(RoundedRectangle(cornerRadius: 16).stroke(LadillColors.border, lineWidth: 1))
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
struct StatCard: View {
let label: String
let value: String
var accent = false
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text(label)
.font(.ladill(size: 12, weight: .medium))
.foregroundStyle(accent ? LadillColors.indigoText : LadillColors.muted)
Text(value)
.font(.ladill(size: 22, weight: .semibold))
.foregroundStyle(accent ? LadillColors.money : LadillColors.ink)
}
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(accent ? LadillColors.indigoSoft : LadillColors.surface)
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(accent ? LadillColors.indigo.opacity(0.2) : LadillColors.border, lineWidth: 1)
)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
struct UserAvatar: View {
let name: String?
let photoURL: String?
var size: CGFloat = 40
var onTap: (() -> Void)?
var body: some View {
let content = ZStack {
Circle()
.fill(LadillColors.indigoSoft)
if let initial = name?.trimmingCharacters(in: .whitespaces).first {
Text(String(initial).uppercased())
.font(.ladill(size: size * 0.38, weight: .semibold))
.foregroundStyle(LadillColors.indigoText)
} else {
Image(systemName: "person.fill")
.font(.system(size: size * 0.4))
.foregroundStyle(LadillColors.indigoText)
}
}
.frame(width: size, height: size)
if let onTap {
Button(action: onTap) { content }.buttonStyle(.plain)
} else {
content
}
}
}
struct LoadingView: View {
var body: some View {
VStack(spacing: 12) {
ProgressView().tint(LadillColors.indigo)
Text("Loading…")
.font(.ladill(size: 14))
.foregroundStyle(LadillColors.muted)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 40)
}
}
struct ErrorView: View {
let message: String
let onRetry: () -> Void
var body: some View {
VStack(spacing: 12) {
Text(message)
.font(.ladill(size: 14))
.foregroundStyle(LadillColors.muted)
.multilineTextAlignment(.center)
Button("Try again", action: onRetry)
.font(.ladill(size: 14, weight: .semibold))
.foregroundStyle(LadillColors.indigo)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 40)
.padding(.horizontal, 20)
}
}