Login and Home

This commit is contained in:
Daniel Arantes Loverde
2026-02-04 16:55:29 -03:00
parent 78daaf1927
commit 33fc111459
90 changed files with 1707 additions and 303 deletions

View File

@@ -0,0 +1,44 @@
import SwiftUI
struct PrimaryButton: View {
let title: String
var fullWidth: Bool = true
let action: @MainActor @Sendable () -> Void
var body: some View {
Button(action: { action() }) {
Text(title)
.font(AppTypography.button)
.tracking(AppTypography.buttonLetterSpacing)
.foregroundStyle(AppColors.textInverse)
.frame(maxWidth: fullWidth ? .infinity : nil)
.frame(height: 56)
.background(AppColors.primary)
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous))
}
.buttonStyle(.plain)
}
}
struct SecondaryButton: View {
let title: String
var fullWidth: Bool = true
let action: @MainActor @Sendable () -> Void
var body: some View {
Button(action: { action() }) {
Text(title)
.font(AppTypography.button)
.tracking(AppTypography.buttonLetterSpacing)
.foregroundStyle(AppColors.primary)
.frame(maxWidth: fullWidth ? .infinity : nil)
.frame(height: 56)
.background(AppColors.backgroundLight)
.overlay(
RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)
.stroke(AppColors.primary.opacity(0.3), lineWidth: 1)
)
}
.buttonStyle(.plain)
}
}

View File

@@ -0,0 +1,44 @@
import SwiftUI
struct SearchField: View {
var placeholder: String
@Binding var text: String
var body: some View {
HStack(spacing: 12) {
Image(systemName: "magnifyingglass")
.foregroundStyle(AppColors.secondary)
TextField(placeholder, text: $text)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
}
.padding(.horizontal, 16)
.frame(height: 52)
.background(AppColors.backgroundLight)
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)
.stroke(AppColors.secondary.opacity(0.15), lineWidth: 1)
)
}
}
struct PillButton: View {
let title: String
let isActive: Bool
var body: some View {
Text(title)
.font(AppTypography.caption)
.tracking(AppTypography.captionLetterSpacing)
.foregroundStyle(isActive ? AppColors.textInverse : AppColors.secondary)
.padding(.horizontal, 14)
.padding(.vertical, 8)
.background(isActive ? AppColors.primary : AppColors.backgroundLight)
.clipShape(Capsule())
.overlay(
Capsule()
.stroke(AppColors.secondary.opacity(0.15), lineWidth: isActive ? 0 : 1)
)
}
}

View File

@@ -0,0 +1,131 @@
import SwiftUI
struct FeaturedStoreCard: View {
let store: FeaturedStoreCardModel
var body: some View {
VStack(alignment: .leading, spacing: 12) {
ZStack(alignment: .topLeading) {
RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)
.fill(AppColors.brandSoft)
.frame(height: 120)
.overlay(
Circle()
.fill(AppColors.surface)
.frame(width: 64, height: 64)
.overlay(
Image(systemName: store.iconName)
.font(.title2)
.foregroundStyle(AppColors.primary)
)
)
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(action: {}) {
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)
}
.padding(10)
}
}
Text(store.name)
.font(AppTypography.heading3)
.foregroundStyle(AppColors.textPrimary)
.lineLimit(1)
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)
}
Text(store.category)
.font(.caption)
.foregroundStyle(AppColors.textMuted)
}
.padding(14)
.background(AppColors.surface)
.clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous))
}
}
struct FeaturedStoreCardModel: Identifiable {
let id = UUID()
let name: String
let rating: Double
let reviews: String
let distance: String
let category: String
let promoText: String?
let isFavorite: Bool
let iconName: 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 = UUID()
let title: String
let subtitle: String
let colors: [Color]
}