This commit is contained in:
Daniel Arantes Loverde
2026-07-07 15:11:31 -03:00
parent 8b9ebdcb44
commit e51c99973f
293 changed files with 457 additions and 4919 deletions

View File

@@ -0,0 +1,173 @@
import SwiftUI
struct FeaturedStoreCard: View {
let store: FeaturedStoreCardModel
var onFavoriteToggle: (() -> Void)? = nil
var body: some View {
VStack(alignment: .leading, spacing: 12) {
ZStack(alignment: .topLeading) {
mediaBlock
if let promo = store.promoText {
Text(promo)
.font(AppTypography.caption)
.foregroundStyle(AppColors.textInverse)
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(Color.red)
.clipShape(Capsule())
.padding(10)
}
HStack {
Spacer()
Button {
onFavoriteToggle?()
} label: {
Image(systemName: store.isFavorite ? "heart.fill" : "heart")
.foregroundStyle(store.isFavorite ? Color.red : AppColors.textMuted)
.padding(8)
.background(AppColors.surface)
.clipShape(Circle())
.shadow(color: AppShadow.soft.color, radius: AppShadow.soft.radius, y: AppShadow.soft.y)
}
.buttonStyle(.borderless)
.accessibilityLabel(store.isFavorite ? "Remover loja dos favoritos" : "Adicionar loja aos favoritos")
.padding(10)
}
}
Text(store.name)
.font(AppTypography.heading3)
.foregroundStyle(AppColors.textPrimary)
if store.isOpen {
HStack(spacing: 6) {
Image(systemName: "star.fill")
.font(.caption)
.foregroundStyle(Color(hex: "#F5B335"))
Text(String(format: "%.1f", store.rating))
.font(.caption)
.foregroundStyle(AppColors.textPrimary)
Text("(\(store.reviews))")
.font(.caption)
.foregroundStyle(AppColors.textMuted)
Text("·")
.font(.caption)
.foregroundStyle(AppColors.textMuted)
Text(store.distance)
.font(.caption)
.foregroundStyle(AppColors.textMuted)
}
} else {
Text(store.statusLabel?.isEmpty == false ? (store.statusLabel ?? "Fechado") : "Fechado")
.font(AppTypography.heading3)
.foregroundStyle(AppColors.textPrimary)
}
Text(store.category)
.font(.caption)
.foregroundStyle(AppColors.textMuted)
}
.padding(14)
.background(AppColors.surface)
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous))
.saturation(store.isOpen ? 1 : 0)
.opacity(store.isOpen ? 1 : 0.9)
}
private var mediaBlock: some View {
ZStack {
RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)
.fill(AppColors.brandSoft)
mediaImage
}
.frame(height: 120)
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous))
}
@ViewBuilder
private var mediaImage: some View {
AsyncStoreImage(imageURL: store.imageURL)
}
private var storeIconPlaceholder: some View {
ZStack {
Image("placeholder-product")
.resizable()
.scaledToFill()
.opacity(0.7)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.clipped()
Circle()
.fill(AppColors.surface.opacity(0.92))
.frame(width: 64, height: 64)
.overlay(
Image(systemName: store.iconName)
.font(.title2)
.foregroundStyle(AppColors.primary)
)
}
}
}
struct FeaturedStoreCardModel: Identifiable {
let id: String
let name: String
let rating: Double
let reviews: String
let distance: String
let deliveryFee: Double?
let category: String
let promoText: String?
let isFavorite: Bool
let iconName: String
let imageURL: String?
let logoURL: String?
let coverURL: String?
let isOpen: Bool
let statusLabel: String?
}
struct SpecialOfferCard: View {
let model: SpecialOfferCardModel
var body: some View {
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous)
.fill(
LinearGradient(
colors: model.colors,
startPoint: .leading,
endPoint: .trailing
)
)
Circle()
.fill(Color.white.opacity(0.18))
.frame(width: 120, height: 120)
.offset(x: 140, y: 10)
VStack(alignment: .leading, spacing: 8) {
Text(model.title)
.font(AppTypography.heading2)
.foregroundStyle(AppColors.textInverse)
Text(model.subtitle)
.font(AppTypography.body)
.foregroundStyle(AppColors.textInverse.opacity(0.85))
}
.padding(20)
}
.shadow(color: AppShadow.soft.color, radius: AppShadow.soft.radius, y: AppShadow.soft.y)
}
}
struct SpecialOfferCardModel: Identifiable {
let id: String
let title: String
let subtitle: String
let colors: [Color]
}