Skip to content

Commit 5266e5b

Browse files
[Bookings][Part 1] Booking details screen (#16168)
2 parents dfab840 + 93d2f67 commit 5266e5b

File tree

10 files changed

+469
-8
lines changed

10 files changed

+469
-8
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Foundation
2+
import struct Networking.Booking
3+
4+
extension BookingDetailsViewModel {
5+
struct AppointmentDetailsContent {
6+
struct Row: Identifiable {
7+
let title: String
8+
let value: String
9+
10+
var id: String {
11+
return title
12+
}
13+
}
14+
15+
let rows: [Row]
16+
17+
init(_ booking: Booking) {
18+
let durationMinutes = Int(booking.endDate.timeIntervalSince(booking.startDate) / 60)
19+
let appointmentDate = booking.startDate.formatted(date: .numeric, time: .omitted)
20+
let appointmentTimeFrame = [
21+
booking.startDate.formatted(date: .omitted, time: .shortened),
22+
booking.endDate.formatted(date: .omitted, time: .shortened)
23+
].joined(separator: " - ")
24+
25+
rows = [
26+
Row(title: Localization.appointmentDetailsDateRowTitle, value: appointmentDate),
27+
Row(title: Localization.appointmentDetailsTimeRowTitle, value: appointmentTimeFrame),
28+
Row(title: Localization.appointmentDetailsServiceTitle, value: "Women's Haircut"),
29+
Row(title: Localization.appointmentDetailsQuantityTitle, value: "1"),
30+
Row(title: Localization.appointmentDetailsDurationTitle, value: String(durationMinutes)),
31+
Row(title: Localization.appointmentDetailsCostTitle, value: booking.cost)
32+
]
33+
}
34+
}
35+
}
36+
37+
private extension BookingDetailsViewModel.AppointmentDetailsContent {
38+
enum Localization {
39+
static let appointmentDetailsDateRowTitle = NSLocalizedString(
40+
"BookingDetailsView.appointmentDetails.dateRow.title",
41+
value: "Date",
42+
comment: "Date row title in appointment details section in booking details view."
43+
)
44+
45+
static let appointmentDetailsTimeRowTitle = NSLocalizedString(
46+
"BookingDetailsView.appointmentDetails.timeRow.title",
47+
value: "Time",
48+
comment: "Time row title in appointment details section in booking details view."
49+
)
50+
51+
static let appointmentDetailsServiceTitle = NSLocalizedString(
52+
"BookingDetailsView.appointmentDetails.serviceRow.title",
53+
value: "Service",
54+
comment: "Service name row title in appointment details section in booking details view."
55+
)
56+
57+
static let appointmentDetailsQuantityTitle = NSLocalizedString(
58+
"BookingDetailsView.appointmentDetails.quantityRow.title",
59+
value: "Quantity",
60+
comment: "Quantity row title in appointment details section in booking details view."
61+
)
62+
63+
static let appointmentDetailsDurationTitle = NSLocalizedString(
64+
"BookingDetailsView.appointmentDetails.durationRow.title",
65+
value: "Duration",
66+
comment: "Duration row title in appointment details section in booking details view."
67+
)
68+
69+
static let appointmentDetailsCostTitle = NSLocalizedString(
70+
"BookingDetailsView.appointmentDetails.costRow.title",
71+
value: "Cost",
72+
comment: "Cost row title in appointment details section in booking details view."
73+
)
74+
}
75+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Foundation
2+
3+
extension BookingDetailsViewModel {
4+
struct Section: Identifiable {
5+
var id: String {
6+
return content.id
7+
}
8+
9+
let headerText: String?
10+
let footerText: String?
11+
let content: SectionContent
12+
13+
init(
14+
headerText: String? = nil,
15+
footerText: String? = nil,
16+
content: SectionContent
17+
) {
18+
self.headerText = headerText
19+
self.footerText = footerText
20+
self.content = content
21+
}
22+
}
23+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import Foundation
2+
3+
extension BookingDetailsViewModel {
4+
enum SectionContent {
5+
case header(HeaderContent)
6+
case appointmentDetails(AppointmentDetailsContent)
7+
case attendance(AttendanceContent)
8+
case payment(PaymentContent)
9+
case customer(CustomerContent)
10+
case teamMember(TeamMemberContent)
11+
}
12+
}
13+
14+
extension BookingDetailsViewModel.SectionContent: Identifiable {
15+
var id: String {
16+
switch self {
17+
case .header:
18+
return "header"
19+
case .appointmentDetails:
20+
return "appointmentDetails"
21+
case .attendance:
22+
return "attendance"
23+
case .payment:
24+
return "payment"
25+
case .customer:
26+
return "customer"
27+
case .teamMember:
28+
return "teamMember"
29+
}
30+
}
31+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Foundation
2+
import SwiftUI
3+
4+
extension BookingDetailsViewModel {
5+
enum Status {
6+
case booked, paid
7+
}
8+
}
9+
10+
extension BookingDetailsViewModel.Status {
11+
var labelText: String {
12+
switch self {
13+
case .booked:
14+
return Localization.bookingStatusBooked
15+
case .paid:
16+
return Localization.bookingStatusPaid
17+
}
18+
}
19+
20+
var labelColor: Color {
21+
switch self {
22+
case .booked:
23+
return Color(UIColor.systemGray6)
24+
case .paid:
25+
return Color(UIColor.systemGray6)
26+
}
27+
}
28+
}
29+
30+
private extension BookingDetailsViewModel.Status {
31+
enum Localization {
32+
static let bookingStatusBooked = NSLocalizedString(
33+
"BookingDetailsView.appointmentDetails.statusLabel.booked",
34+
value: "Booked",
35+
comment: "Title for the 'Booked' status label in the appointment details view."
36+
)
37+
38+
static let bookingStatusPaid = NSLocalizedString(
39+
"BookingDetailsView.appointmentDetails.statusLabel.paid",
40+
value: "Paid",
41+
comment: "Title for the 'Paid' status label in the appointment details view."
42+
)
43+
}
44+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Foundation
2+
import struct Networking.Booking
3+
4+
extension BookingDetailsViewModel {
5+
struct AttendanceContent {
6+
}
7+
8+
struct PaymentContent {
9+
}
10+
11+
struct CustomerContent {
12+
}
13+
14+
struct TeamMemberContent {
15+
}
16+
}
17+
18+
final class BookingDetailsViewModel: ObservableObject {
19+
let sections: [Section]
20+
21+
init(booking: Booking) {
22+
let headerSection = Section.init(
23+
content: .header(HeaderContent(booking))
24+
)
25+
26+
let appointmentDetailsSection = Section(
27+
headerText: Localization.appointmentDetailsSectionHeaderTitle.uppercased(),
28+
content: .appointmentDetails(AppointmentDetailsContent(booking))
29+
)
30+
31+
sections = [
32+
headerSection,
33+
appointmentDetailsSection
34+
]
35+
}
36+
}
37+
38+
private extension BookingDetailsViewModel {
39+
enum Localization {
40+
static let appointmentDetailsSectionHeaderTitle = NSLocalizedString(
41+
"BookingDetailsView.appointmentDetails.headerTitle",
42+
value: "Appointment Details",
43+
comment: "Header title for the 'Appointment Details' section in the booking details screen."
44+
)
45+
}
46+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
import struct Networking.Booking
3+
4+
extension BookingDetailsViewModel {
5+
struct HeaderContent: Hashable {
6+
let bookingDate: String
7+
let serviceName: String
8+
let customerName: String
9+
let status: [Status]
10+
11+
init(_ booking: Booking) {
12+
bookingDate = booking.startDate.formatted(date: .numeric, time: .omitted)
13+
serviceName = "Women's Haircut"
14+
customerName = "Margarita Nikolaevna"
15+
status = [.paid, .booked]
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)