Skip to content

Commit 0920a2e

Browse files
authored
Merge pull request #421 from joreilly/dependency_updates
Junie generated UI for Android client
2 parents 19dffe9 + a6a2fb3 commit 0920a2e

File tree

8 files changed

+1152
-219
lines changed

8 files changed

+1152
-219
lines changed

PeopleInSpaceSwiftUI/PeopleInSpaceSwiftUI/ContentView.swift

Lines changed: 221 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,61 @@ struct PeopleListScreen: View {
2424

2525
var body: some View {
2626
NavigationStack(path: $path) {
27-
VStack {
27+
ZStack {
28+
// Background color to match details screen
29+
Color(.systemGroupedBackground)
30+
.edgesIgnoringSafeArea(.all)
31+
2832
Observing(viewModel.uiState) { playerListUIState in
2933
switch onEnum(of: playerListUIState) {
3034
case .loading:
31-
ProgressView()
32-
.progressViewStyle(CircularProgressViewStyle())
35+
VStack(spacing: 16) {
36+
ProgressView()
37+
.progressViewStyle(CircularProgressViewStyle())
38+
Text("Loading astronauts...")
39+
.font(.headline)
40+
.foregroundColor(.secondary)
41+
}
3342
case .error(let error):
34-
Text("Error: \(error)")
43+
VStack(spacing: 16) {
44+
Image(systemName: "exclamationmark.triangle")
45+
.font(.largeTitle)
46+
.foregroundColor(.orange)
47+
Text("Error: \(error)")
48+
.font(.headline)
49+
.foregroundColor(.primary)
50+
.multilineTextAlignment(.center)
51+
52+
Button(action: {
53+
// Refresh action
54+
viewModel = PersonListViewModel()
55+
}) {
56+
Label("Try Again", systemImage: "arrow.clockwise")
57+
.padding()
58+
.background(Color.blue)
59+
.foregroundColor(.white)
60+
.cornerRadius(8)
61+
}
62+
}
63+
.padding()
3564
case .success(let success):
36-
List(success.result, id: \.name) { person in
37-
NavigationLink(value: person) {
38-
PersonView(person: person)
65+
ScrollView {
66+
LazyVStack(spacing: 12) {
67+
ForEach(success.result, id: \.name) { person in
68+
NavigationLink(value: person) {
69+
PersonView(person: person)
70+
.padding(.horizontal)
71+
.background(
72+
RoundedRectangle(cornerRadius: 12)
73+
.fill(Color(.systemBackground))
74+
.shadow(color: Color.black.opacity(0.05), radius: 5, x: 0, y: 2)
75+
)
76+
.padding(.horizontal)
77+
}
78+
.buttonStyle(PlainButtonStyle())
79+
}
3980
}
81+
.padding(.vertical)
4082
}
4183
}
4284
}
@@ -45,7 +87,17 @@ struct PeopleListScreen: View {
4587
PersonDetailsScreen(person: person)
4688
}
4789
.navigationBarTitle(Text("People In Space"))
48-
.navigationBarTitleDisplayMode(.inline)
90+
.navigationBarTitleDisplayMode(.large)
91+
.toolbar {
92+
ToolbarItem(placement: .navigationBarTrailing) {
93+
Button(action: {
94+
// Refresh action
95+
viewModel = PersonListViewModel()
96+
}) {
97+
Image(systemName: "arrow.clockwise")
98+
}
99+
}
100+
}
49101
}
50102
}
51103
}
@@ -54,21 +106,52 @@ struct PersonView: View {
54106
let person: Assignment
55107

56108
var body: some View {
57-
HStack {
109+
HStack(spacing: 16) {
110+
// Person image with improved styling
58111
AsyncImage(url: URL(string: person.personImageUrl ?? "")) { image in
59-
image.resizable()
60-
.aspectRatio(contentMode: .fit)
112+
image.resizable()
113+
.aspectRatio(contentMode: .fill)
114+
.clipShape(Circle())
115+
.overlay(Circle().stroke(Color.gray.opacity(0.2), lineWidth: 1))
61116
} placeholder: {
62-
ProgressView()
117+
Circle()
118+
.fill(Color.gray.opacity(0.2))
119+
.overlay(
120+
ProgressView()
121+
.progressViewStyle(CircularProgressViewStyle(tint: .gray))
122+
)
63123
}
64-
.frame(width: 64, height: 64)
65-
124+
.frame(width: 70, height: 70)
125+
.shadow(color: .gray.opacity(0.3), radius: 3, x: 0, y: 1)
66126

67-
VStack(alignment: .leading) {
68-
Text(person.name).font(.headline)
69-
Text(person.craft).font(.subheadline)
127+
// Person information with improved typography and layout
128+
VStack(alignment: .leading, spacing: 6) {
129+
Text(person.name)
130+
.font(.headline)
131+
.foregroundColor(.primary)
132+
133+
Text(person.craft)
134+
.font(.subheadline)
135+
.foregroundColor(.secondary)
136+
137+
// Add a subtle bio preview if available
138+
if let bio = person.personBio, !bio.isEmpty {
139+
Text(bio.prefix(50) + (bio.count > 50 ? "..." : ""))
140+
.font(.caption)
141+
.foregroundColor(.secondary)
142+
.lineLimit(1)
143+
}
70144
}
145+
146+
Spacer()
147+
148+
// Add a chevron to indicate navigation
149+
Image(systemName: "chevron.right")
150+
.font(.caption)
151+
.foregroundColor(.gray)
71152
}
153+
.padding(.vertical, 8)
154+
.contentShape(Rectangle())
72155
}
73156
}
74157

@@ -78,22 +161,131 @@ struct PersonDetailsScreen: View {
78161

79162
var body: some View {
80163
ScrollView {
81-
VStack(alignment: .center, spacing: 32) {
82-
Text(person.name).font(.title)
164+
VStack(alignment: .center, spacing: 0) {
165+
// Header with astronaut name and craft
166+
VStack(spacing: 8) {
167+
Text(person.name)
168+
.font(.largeTitle)
169+
.fontWeight(.bold)
170+
.foregroundColor(.primary)
171+
.multilineTextAlignment(.center)
172+
173+
Text("Currently on \(person.craft)")
174+
.font(.headline)
175+
.foregroundColor(.secondary)
176+
.padding(.bottom, 16)
177+
}
178+
.padding(.top, 24)
179+
.padding(.horizontal)
83180

84-
AsyncImage(url: URL(string: person.personImageUrl ?? "")) { image in
85-
image.resizable()
86-
.aspectRatio(contentMode: .fit)
87-
} placeholder: {
88-
ProgressView()
181+
// Astronaut image with enhanced styling
182+
ZStack {
183+
RoundedRectangle(cornerRadius: 16)
184+
.fill(Color.gray.opacity(0.1))
185+
.frame(height: 300)
186+
187+
AsyncImage(url: URL(string: person.personImageUrl ?? "")) { image in
188+
image.resizable()
189+
.aspectRatio(contentMode: .fit)
190+
.frame(height: 300)
191+
.clipShape(RoundedRectangle(cornerRadius: 16))
192+
} placeholder: {
193+
VStack {
194+
ProgressView()
195+
.progressViewStyle(CircularProgressViewStyle())
196+
Text("Loading image...")
197+
.font(.caption)
198+
.foregroundColor(.secondary)
199+
.padding(.top, 8)
200+
}
201+
}
202+
.frame(height: 300)
89203
}
90-
.frame(width: 240, height: 240)
91-
92-
Text(person.personBio ?? "").font(.body)
93-
Spacer()
204+
.padding(.horizontal)
205+
.padding(.bottom, 24)
206+
207+
// Bio section with card styling
208+
if let bio = person.personBio, !bio.isEmpty {
209+
VStack(alignment: .leading, spacing: 16) {
210+
Text("Biography")
211+
.font(.title2)
212+
.fontWeight(.bold)
213+
.foregroundColor(.primary)
214+
215+
Text(bio)
216+
.font(.body)
217+
.foregroundColor(.primary)
218+
.fixedSize(horizontal: false, vertical: true)
219+
.lineSpacing(6)
220+
}
221+
.padding(24)
222+
.background(
223+
RoundedRectangle(cornerRadius: 16)
224+
.fill(Color(.systemBackground))
225+
.shadow(color: Color.black.opacity(0.1), radius: 10, x: 0, y: 5)
226+
)
227+
.padding(.horizontal)
228+
} else {
229+
VStack(alignment: .center, spacing: 8) {
230+
Image(systemName: "info.circle")
231+
.font(.largeTitle)
232+
.foregroundColor(.secondary)
233+
Text("No biography available")
234+
.font(.headline)
235+
.foregroundColor(.secondary)
236+
}
237+
.frame(maxWidth: .infinity)
238+
.padding(24)
239+
.background(
240+
RoundedRectangle(cornerRadius: 16)
241+
.fill(Color.gray.opacity(0.1))
242+
)
243+
.padding(.horizontal)
244+
}
245+
246+
// Additional information section
247+
VStack(alignment: .leading, spacing: 16) {
248+
Text("Additional Information")
249+
.font(.title2)
250+
.fontWeight(.bold)
251+
.foregroundColor(.primary)
252+
253+
HStack {
254+
VStack(alignment: .leading, spacing: 8) {
255+
Label("Spacecraft", systemImage: "airplane.circle.fill")
256+
.font(.headline)
257+
Text(person.craft)
258+
.font(.body)
259+
.foregroundColor(.secondary)
260+
}
261+
.frame(maxWidth: .infinity, alignment: .leading)
262+
263+
Divider()
264+
.frame(height: 40)
265+
266+
VStack(alignment: .leading, spacing: 8) {
267+
Label("Mission", systemImage: "star.circle.fill")
268+
.font(.headline)
269+
Text("Active")
270+
.font(.body)
271+
.foregroundColor(.green)
272+
}
273+
.frame(maxWidth: .infinity, alignment: .leading)
274+
}
275+
}
276+
.padding(24)
277+
.background(
278+
RoundedRectangle(cornerRadius: 16)
279+
.fill(Color(.systemBackground))
280+
.shadow(color: Color.black.opacity(0.1), radius: 10, x: 0, y: 5)
281+
)
282+
.padding(.horizontal)
283+
.padding(.top, 16)
284+
.padding(.bottom, 32)
94285
}
95-
.padding()
96286
}
287+
.background(Color(.systemGroupedBackground).edgesIgnoringSafeArea(.all))
288+
.navigationBarTitleDisplayMode(.inline)
97289
}
98290
}
99291

0 commit comments

Comments
 (0)