184 lines
7 KiB
Swift
184 lines
7 KiB
Swift
import SwiftUI
|
|
|
|
struct AboutScreen: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@State private var appearAnimation = false
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: 20) {
|
|
// Logo + version
|
|
VStack(spacing: 8) {
|
|
Image("PayfritLogoLight")
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fit)
|
|
.frame(width: 80, height: 80)
|
|
|
|
Text("Payfrit Works")
|
|
.font(.subheadline)
|
|
.fontWeight(.bold)
|
|
.foregroundColor(.primary)
|
|
|
|
Text("Version 1.0.0")
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.top, 16)
|
|
.scaleEffect(appearAnimation ? 1 : 0.9)
|
|
.opacity(appearAnimation ? 1 : 0)
|
|
|
|
// Intro
|
|
Text("Payfrit Works helps you manage tasks, accept cash payments, and earn money. Get notified of new tasks, complete them efficiently, and track your earnings.")
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
.multilineTextAlignment(.leading)
|
|
.padding(.horizontal, 16)
|
|
.opacity(appearAnimation ? 1 : 0)
|
|
.offset(y: appearAnimation ? 0 : 15)
|
|
|
|
// Feature cards
|
|
VStack(spacing: 12) {
|
|
featureCard(
|
|
icon: "checkmark.circle",
|
|
title: "Claim Tasks",
|
|
description: "View available tasks from businesses you work for and claim them with one tap."
|
|
)
|
|
.staggeredAppear(index: 0, appeared: appearAnimation)
|
|
|
|
featureCard(
|
|
icon: "dollarsign.circle",
|
|
title: "Accept Cash",
|
|
description: "Collect cash payments from customers with automatic change calculation."
|
|
)
|
|
.staggeredAppear(index: 1, appeared: appearAnimation)
|
|
|
|
featureCard(
|
|
icon: "antenna.radiowaves.left.and.right",
|
|
title: "Beacon Auto-Complete",
|
|
description: "Tasks complete automatically when you're near the customer's table beacon."
|
|
)
|
|
.staggeredAppear(index: 2, appeared: appearAnimation)
|
|
|
|
featureCard(
|
|
icon: "creditcard",
|
|
title: "Earn & Get Paid",
|
|
description: "Track your earnings in real-time and receive payouts to your bank account."
|
|
)
|
|
.staggeredAppear(index: 3, appeared: appearAnimation)
|
|
}
|
|
.padding(.horizontal, 16)
|
|
|
|
// Links
|
|
VStack(spacing: 8) {
|
|
Link(destination: URL(string: "https://www.payfrit.com")!) {
|
|
HStack(spacing: 10) {
|
|
Image(systemName: "globe")
|
|
.font(.subheadline)
|
|
.foregroundColor(.payfritGreen)
|
|
.frame(width: 28, height: 28)
|
|
.background(Color.payfritGreen.opacity(0.1))
|
|
.clipShape(RoundedRectangle(cornerRadius: 6, style: .continuous))
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text("Website")
|
|
.font(.caption)
|
|
.fontWeight(.medium)
|
|
.foregroundColor(.primary)
|
|
Text("www.payfrit.com")
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "arrow.up.right")
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
.padding(12)
|
|
.background(Color(.secondarySystemGroupedBackground))
|
|
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
|
|
.contentShape(Rectangle())
|
|
}
|
|
}
|
|
.padding(.horizontal, 16)
|
|
.staggeredAppear(index: 4, appeared: appearAnimation)
|
|
|
|
// Copyright
|
|
Text("\u{00A9} 2026 Payfrit. All rights reserved.")
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
.padding(.top, 4)
|
|
|
|
Spacer()
|
|
.frame(height: 20)
|
|
}
|
|
}
|
|
.background(Color(.systemGroupedBackground).ignoresSafeArea())
|
|
.navigationTitle("About Payfrit")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.onAppear {
|
|
withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) {
|
|
appearAnimation = true
|
|
}
|
|
}
|
|
}
|
|
|
|
private func featureCard(icon: String, title: String, description: String) -> some View {
|
|
HStack(spacing: 10) {
|
|
Image(systemName: icon)
|
|
.font(.subheadline)
|
|
.foregroundColor(.payfritGreen)
|
|
.frame(width: 28, height: 28)
|
|
.background(Color.payfritGreen.opacity(0.1))
|
|
.clipShape(RoundedRectangle(cornerRadius: 6, style: .continuous))
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(title)
|
|
.font(.caption)
|
|
.fontWeight(.medium)
|
|
.foregroundColor(.primary)
|
|
Text(description)
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
.padding(12)
|
|
.background(Color(.secondarySystemGroupedBackground))
|
|
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
|
|
.contentShape(Rectangle())
|
|
}
|
|
}
|
|
|
|
// MARK: - Staggered Appear Modifier
|
|
|
|
private struct StaggeredAppearModifier: ViewModifier {
|
|
let index: Int
|
|
let appeared: Bool
|
|
|
|
func body(content: Content) -> some View {
|
|
content
|
|
.opacity(appeared ? 1 : 0)
|
|
.offset(y: appeared ? 0 : 20)
|
|
.animation(
|
|
.spring(response: 0.4, dampingFraction: 0.8)
|
|
.delay(Double(index) * 0.06),
|
|
value: appeared
|
|
)
|
|
}
|
|
}
|
|
|
|
private extension View {
|
|
func staggeredAppear(index: Int, appeared: Bool) -> some View {
|
|
modifier(StaggeredAppearModifier(index: index, appeared: appeared))
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
NavigationStack {
|
|
AboutScreen()
|
|
}
|
|
}
|