banyaro-ios/BanYaroGo/Views/SettingsView.swift
rene bfd327bd40 Settings: echtes Profil via /api/auth/me (Rolle, Founder, Abo, Avatar)
Login liefert nur {token, name, is_premium}. Für Admin-/Founder-/Tier-Info
holen wir nach Login (und beim Erscheinen von MainTabView) /api/auth/me und
zeigen ein echtes Profil mit Avatar, Email, Rolle und nur dann Premium-Status,
wenn das relevant ist.
2026-05-30 09:37:12 +02:00

114 lines
3.7 KiB
Swift

import SwiftUI
struct SettingsView: View {
@Environment(AuthSession.self) private var auth
var body: some View {
NavigationStack {
Form {
Section {
HStack(spacing: 14) {
avatarView
.frame(width: 60, height: 60)
.clipShape(Circle())
VStack(alignment: .leading, spacing: 2) {
Text(displayName)
.font(.headline)
if let email = auth.profile?.email {
Text(email)
.font(.footnote)
.foregroundStyle(.secondary)
}
}
}
.padding(.vertical, 4)
}
Section("Account") {
LabeledContent("Rolle", value: rolleLabel)
if auth.profile?.isFounder == true {
LabeledContent("Founder", value: founderLabel)
}
if auth.profile?.isPartner == true {
LabeledContent("Partner", value: "Ja")
}
if let tier = auth.profile?.subscriptionTier, !tier.isEmpty {
LabeledContent("Abo", value: tier.capitalized)
}
LabeledContent("Premium", value: premiumValue ? "Ja" : "Nein")
}
if let wohnort = auth.profile?.wohnort, !wohnort.isEmpty {
Section("Ort") {
Text(wohnort)
}
}
Section {
Button("Abmelden", role: .destructive) {
auth.logout()
}
}
Section("Über") {
Text("Ban Yaro Go ist die native iOS-Ergänzung zur banyaro.app PWA. Phase 1: deine Touren ansehen.")
.font(.footnote)
.foregroundStyle(.secondary)
}
}
.navigationTitle("Mehr")
.refreshable { await auth.loadProfile() }
}
}
private var displayName: String {
auth.profile?.name ?? auth.userName ?? ""
}
private var premiumValue: Bool {
auth.profile?.isPremium ?? auth.isPremium
}
private var rolleLabel: String {
switch auth.profile?.rolle?.lowercased() {
case "admin": return "Admin"
case "moderator": return "Moderator"
case nil: return ""
default: return "Mitglied"
}
}
private var founderLabel: String {
if let n = auth.profile?.founderNumber { return "#\(n)" }
return "Ja"
}
@ViewBuilder
private var avatarView: some View {
if let path = auth.profile?.avatarUrl, !path.isEmpty,
let url = avatarURL(path) {
AsyncImage(url: url) { phase in
switch phase {
case .success(let img): img.resizable().scaledToFill()
default: avatarPlaceholder
}
}
} else {
avatarPlaceholder
}
}
private var avatarPlaceholder: some View {
ZStack {
Color.accentColor.opacity(0.2)
Image(systemName: "person.crop.circle.fill")
.font(.system(size: 36))
.foregroundStyle(Color.accentColor)
}
}
private func avatarURL(_ path: String) -> URL? {
if path.hasPrefix("http") { return URL(string: path) }
return URL(string: "https://banyaro.app\(path)")
}
}