Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the Timeline to Appointments #35

Merged
merged 6 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions PICS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
8644E6842B72046B001218D0 /* GettingThere.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644E6832B72046B001218D0 /* GettingThere.swift */; };
8644E6872B7204A7001218D0 /* AppointmentBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644E6862B7204A7001218D0 /* AppointmentBlock.swift */; };
8644E69B2B722708001218D0 /* Appointments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8644E69A2B722708001218D0 /* Appointments.swift */; };
8649094A2B8AB65600054C9A /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 864909492B8AB65600054C9A /* TimelineView.swift */; };
864909422B8AA1C300054C9A /* TrailMakingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 864909412B8AA1C300054C9A /* TrailMakingTest.swift */; };
9733CFC62A8066DE001B7ABC /* SpeziOnboarding in Frameworks */ = {isa = PBXBuildFile; productRef = 2FE5DC8029EDD91D004B9AB4 /* SpeziOnboarding */; };
9739A0C62AD7B5730084BEA5 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = 9739A0C52AD7B5730084BEA5 /* FirebaseStorage */; };
Expand Down Expand Up @@ -172,6 +173,7 @@
8644E6832B72046B001218D0 /* GettingThere.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingThere.swift; sourceTree = "<group>"; };
8644E6862B7204A7001218D0 /* AppointmentBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppointmentBlock.swift; sourceTree = "<group>"; };
8644E69A2B722708001218D0 /* Appointments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appointments.swift; sourceTree = "<group>"; };
864909492B8AB65600054C9A /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; };
864909412B8AA1C300054C9A /* TrailMakingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrailMakingTest.swift; sourceTree = "<group>"; };
A403A52D2B705A8C003CFA5C /* HealthVisualizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthVisualizationTests.swift; sourceTree = "<group>"; };
A480C7BF2B6D5A3700B29A07 /* HKVisualization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HKVisualization.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -423,6 +425,7 @@
8644E6862B7204A7001218D0 /* AppointmentBlock.swift */,
8644E6832B72046B001218D0 /* GettingThere.swift */,
8644E67A2B6C75B1001218D0 /* MapView.swift */,
864909492B8AB65600054C9A /* TimelineView.swift */,
);
path = Appointment;
sourceTree = "<group>";
Expand Down Expand Up @@ -710,6 +713,7 @@
8644E6872B7204A7001218D0 /* AppointmentBlock.swift in Sources */,
5661552E2AB854C000209B80 /* PackageHelper.swift in Sources */,
27FA29902A388E9B009CAC45 /* ModalView.swift in Sources */,
8649094A2B8AB65600054C9A /* TimelineView.swift in Sources */,
2FE5DC2629EDD38A004B9AB4 /* Contacts.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
1 change: 0 additions & 1 deletion PICS/Appointment/AppointmentBlock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//
// SPDX-License-Identifier: MIT
//

import Foundation
import SwiftUI

Expand Down
5 changes: 5 additions & 0 deletions PICS/Appointment/AppointmentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ struct AppointmentView: View {
VStack(alignment: .leading) {
AppointmentBlock(date: formattedDate(appt1), time: formattedTime(appt1))
AppointmentBlock(date: formattedDate(appt2), time: formattedTime(appt2))
.padding(.bottom)
Text("Your Timeline")
.foregroundColor(.black)
.italic()
TimelineView(appt1: appt1, appt2: appt2)
}
.padding()

Expand Down
1 change: 0 additions & 1 deletion PICS/Appointment/Appointments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//
// SPDX-License-Identifier: MIT
//

import Foundation
import SwiftUI

Expand Down
138 changes: 138 additions & 0 deletions PICS/Appointment/TimelineView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//
// This source file is part of the PICS based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//
import Foundation
import SwiftUI

struct CurrentLocation: Shape {
let date1: Date
let date2: Date
let now: Date

init(date1: Date, date2: Date, now: Date) {
self.date1 = date1
self.date2 = date2
self.now = now
}

func path(in rect: CGRect) -> Path {
var path = Path()

let arrowWidth = rect.width
let arrowHeight = rect.height / 2

let circleRadius: CGFloat = 7
let positions: [CGFloat] = [1, 2, 3, 4, 5].map { CGFloat($0) / 6 }

for position in positions {
print(position)
akanshyabhat marked this conversation as resolved.
Show resolved Hide resolved
let circleRect = CGRect(
x: arrowWidth * position - circleRadius,
y: arrowHeight / 2 - circleRadius,
width: circleRadius * 2,
height: circleRadius * 2
)
if (now < date1 && position == 1 / 6) ||
(now == date1 && position == 2 / 6) ||
(now > date1 && now < date2 && position == 3 / 6) ||
(now == date2 && position == 4 / 6) ||
(now > date2 && position == 5 / 6 ) {
path.addEllipse(in: circleRect)
}
}

return path
}
}

struct BidirectionalArrow: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()

let arrowWidth = rect.width
let arrowHeight = rect.height / 2

// Draw the main arrow line
path.move(to: CGPoint(x: 0, y: arrowHeight / 2))
path.addLine(to: CGPoint(x: arrowWidth, y: arrowHeight / 2))


let circleRadius: CGFloat = 5

let circleRect1 = CGRect(
x: arrowWidth * 1 / 3 - circleRadius,
y: arrowHeight / 2 - circleRadius,
width: circleRadius * 2,
height: circleRadius * 2
)
path.addEllipse(in: circleRect1)

let circleRect2 = CGRect(
x: arrowWidth * 2 / 3 - circleRadius,
y: arrowHeight / 2 - circleRadius,
width: circleRadius * 2,
height: circleRadius * 2
)
path.addEllipse(in: circleRect2)

// Draw the right arrowhead lines
path.move(to: CGPoint(x: arrowWidth - arrowHeight / 2, y: arrowHeight / 4))
path.addLine(to: CGPoint(x: arrowWidth, y: arrowHeight / 2))
path.addLine(to: CGPoint(x: arrowWidth - arrowHeight / 2, y: arrowHeight * 3 / 4))
path.closeSubpath()

// Draw the left arrowhead lines
path.move(to: CGPoint(x: arrowHeight / 2, y: arrowHeight / 4))
path.addLine(to: CGPoint(x: 0, y: arrowHeight / 2))
path.addLine(to: CGPoint(x: arrowHeight / 2, y: arrowHeight * 3 / 4))
path.closeSubpath()

return path
}
}


struct TimelineView: View {
let appt1: Date
let appt2: Date

var body: some View {
let calendar = Calendar.current
let currentDate = Date()

let components1 = calendar.dateComponents([.year, .month, .day], from: appt1)
let components2 = calendar.dateComponents([.year, .month, .day], from: appt2)
let components3 = calendar.dateComponents([.year, .month, .day], from: currentDate)

if let date1 = calendar.date(from: components1), let date2 = calendar.date(from: components2), let now = calendar.date(from: components3) {
VStack {
BidirectionalArrow()
.fill(Color.black)
.stroke(Color.black, lineWidth: 2)
.frame(width: 361, height: 25)
.overlay(
CurrentLocation(date1: date1, date2: date2, now: now)
.fill(Color.accentColor)
)
HStack(spacing: 0) {
Spacer()
Text("Appointment 1")
.padding(.leading, 45)
Spacer()
Text("Appointment 2")
.padding(.trailing, 40)
Spacer()
}
.font(.system(size: 12))
.foregroundColor(.black)
}
} else {
Text("Failed to get dates")
.foregroundColor(.red)

Check warning on line 135 in PICS/Appointment/TimelineView.swift

View check run for this annotation

Codecov / codecov/patch

PICS/Appointment/TimelineView.swift#L134-L135

Added lines #L134 - L135 were not covered by tests
}
}
}
12 changes: 12 additions & 0 deletions PICS/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
}
}
}
},
"Appointment 1" : {

},
"Appointment 2" : {

},
"APPOINTMENTS_NAVIGATION_TITLE" : {
"extractionState" : "manual",
Expand Down Expand Up @@ -272,6 +278,9 @@
}
}
}
},
"Failed to get dates" : {

},
"GETTING_HERE_HEADING" : {
"extractionState" : "manual",
Expand Down Expand Up @@ -962,6 +971,9 @@
}
}
}
},
"Your Timeline" : {

},
"ZIP_CITY" : {
"extractionState" : "manual",
Expand Down
Loading