gitbay/Views/Discovery/ProfileView.swift

5411753023a5e2958f17b523903abce380941107
gitbay-ios/gitbay/Views/Discovery/ProfileView.swift history · blame · raw

78 lines · 3306 bytes

 1import SwiftUI
 2
 3/// A user or organization: `profile show` plus their reachable repos.
 4struct ProfileView: View {
 5
 6    @State private var model: ProfileViewModel
 7
 8    init(client: GitbayClient, name: String) {
 9        _model = State(initialValue: ProfileViewModel(client: client, name: name))
10    }
11
12    var body: some View {
13        List {
14            if let profile = model.state.value {
15                Section {
16                    VStack(alignment: .leading, spacing: 6) {
17                        HStack(spacing: 8) {
18                            Image(systemName: profile.kind == "org"
19                                ? "building.2" : "person.crop.circle")
20                                .font(.title2)
21                                .foregroundStyle(.secondary)
22                            Text(profile.name)
23                                .font(.title3.weight(.semibold))
24                            Text(profile.kind)
25                                .font(.caption2)
26                                .padding(.horizontal, 6)
27                                .padding(.vertical, 1)
28                                .background(.quaternary, in: Capsule())
29                        }
30                        if let description = profile.description, !description.isEmpty {
31                            Text(description)
32                                .font(.subheadline)
33                                .foregroundStyle(.secondary)
34                        }
35                        if let website = profile.website, let url = URL(string: website) {
36                            Link(website, destination: url)
37                                .font(.caption)
38                                .lineLimit(1)
39                        }
40                    }
41                    .padding(.vertical, 4)
42                }
43
44                if profile.kind == "org" {
45                    Section {
46                        NavigationLink(value: OrgRoute.org(profile.name)) {
47                            Label("Members & Teams", systemImage: "person.3")
48                        }
49                    }
50                }
51
52                if !model.repos.isEmpty {
53                    Section("Repositories") {
54                        ForEach(model.repos) { repo in
55                            NavigationLink(value: RepoRoute.repo(repo.path)) {
56                                VStack(alignment: .leading, spacing: 2) {
57                                    Text(repo.name)
58                                        .font(.subheadline.weight(.medium))
59                                    if let description = repo.description, !description.isEmpty {
60                                        Text(description)
61                                            .font(.caption)
62                                            .foregroundStyle(.secondary)
63                                            .lineLimit(1)
64                                    }
65                                }
66                            }
67                        }
68                    }
69                }
70            }
71        }
72        .overlay { LoadStateOverlay(state: model.state) }
73        .navigationTitle(model.name)
74        .navigationBarTitleDisplayMode(.inline)
75        .task { await model.load() }
76        .refreshable { await model.load() }
77    }
78}