Skip to content

Commit

Permalink
Report set up (#31)
Browse files Browse the repository at this point in the history
Cough Report 

## ♻️ Current situation & Problem
The current app is lacking a cough report to provide trend summaries and
insights for both user and doctors. This implements a new tab to view
weekly monthly changes in cough with a graph interface to view cough
frequency.


## ⚙️ Release Notes 

- Created daily, monthly, and weekly cough report cards
- Increase/decrease in cough, peak times in coughs
- Added button to view graph trends of daily weekly monthly coughs
*Note: Currently uses fake cough data


## ✅ Testing
N/A

## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md).

---------

Co-authored-by: MiguelAFH <[email protected]>
  • Loading branch information
jennleww and MiguelAFH authored Mar 5, 2025
1 parent 029893f commit 5238df6
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CoughSync.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@

/* Begin PBXFileSystemSynchronizedRootGroup section */
0665A4212D5C2D180055D1B2 /* CoughVisualization */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = CoughVisualization; sourceTree = "<group>"; };
0665A4852D6E602C0055D1B2 /* Report */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Report; sourceTree = "<group>"; };
252FC3102D5DC6520043712C /* CoughDetection */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = CoughDetection; sourceTree = "<group>"; };
252FC3112D5DC7760043712C /* CoughView */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = CoughView; sourceTree = "<group>"; };
4913AC9F2D5C4CF40030C90D /* Models */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Models; sourceTree = "<group>"; };
Expand Down Expand Up @@ -323,6 +324,7 @@
2F4E23822989D51F0013F3D9 /* CoughSyncTestingSetup.swift */,
A9720E412ABB68B300872D23 /* Account */,
2FE5DC2729EDD38D004B9AB4 /* Contacts */,
0665A4852D6E602C0055D1B2 /* Report */,
0665A4212D5C2D180055D1B2 /* CoughVisualization */,
A9A3DCC62C75CB8D00FC9B69 /* Firestore */,
2FE5DC2829EDD398004B9AB4 /* Onboarding */,
Expand Down Expand Up @@ -396,6 +398,7 @@
);
fileSystemSynchronizedGroups = (
0665A4212D5C2D180055D1B2 /* CoughVisualization */,
0665A4852D6E602C0055D1B2 /* Report */,
252FC3102D5DC6520043712C /* CoughDetection */,
252FC3112D5DC7760043712C /* CoughView */,
4913AC9F2D5C4CF40030C90D /* Models */,
Expand Down
9 changes: 6 additions & 3 deletions CoughSync/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
@_spi(TestingSupport) import SpeziAccount
import SwiftUI


struct HomeView: View {
enum Tabs: String {
case dashboard
case schedule
case coughTracking
case coughDetection
case coughReport
}

@AppStorage(StorageKeys.homeTabSelection) private var selectedTab = Tabs.dashboard
Expand All @@ -35,11 +35,15 @@ struct HomeView: View {
}
.customizationID("home.schedule")


Tab("Cough Tracking", systemImage: "waveform.path.ecg", value: .coughTracking) {
CoughTrackerView()
}
.customizationID("home.coughtracking")

Tab("Cough Report", systemImage: "chart.bar.doc.horizontal", value: .coughReport) {
CoughReportView()
}
.customizationID("home.coughreport")

if FeatureFlags.debugDetector {
Tab("Cough Detection", systemImage: "speaker.wave.3.fill", value: .coughDetection) {
Expand All @@ -59,7 +63,6 @@ struct HomeView: View {
}
}


#if DEBUG
#Preview {
var details = AccountDetails()
Expand Down
24 changes: 24 additions & 0 deletions CoughSync/Report/CoughReportData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// This source file is part of the CoughSync based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Foundation

enum CoughReportData {
// Fake data for now (replace with actual logic later)
static func getDailyCoughs() -> [Int] {
(0..<7).map { _ in Int.random(in: 10...50) } // 7 days of cough counts
}

static func getWeeklyCoughs() -> [Int] {
(0..<4).map { _ in Int.random(in: 50...200) } // 4 weeks of cough counts
}

static func getMonthlyCoughs() -> [Int] {
(0..<12).map { _ in Int.random(in: 200...800) } // 12 months of cough counts
}
}
61 changes: 61 additions & 0 deletions CoughSync/Report/FrequencyView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// This source file is part of the CoughSync based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Charts
import SwiftUI

struct FrequencyView: View {
let dailyCoughs = CoughReportData.getDailyCoughs()
let weeklyCoughs = CoughReportData.getWeeklyCoughs()
let monthlyCoughs = CoughReportData.getMonthlyCoughs()

var body: some View {
NavigationStack {
GeometryReader { geometry in
ScrollView {
VStack(spacing: 15) {
Text("Cough Trends")
.font(.largeTitle.bold())
.padding(.top)

CoughTrendChart(
title: "Daily Coughs (Past Week)",
data: dailyCoughs,
xLabels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
chartHeight: geometry.size.height * 0.3 // Limits chart height
)

CoughTrendChart(
title: "Weekly Coughs (Past Month)",
data: weeklyCoughs,
xLabels: ["Week 1", "Week 2", "Week 3", "Week 4"],
chartHeight: geometry.size.height * 0.3
)

CoughTrendChart(
title: "Monthly Coughs (Past Year)",
data: monthlyCoughs,
xLabels: [
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
],
chartHeight: geometry.size.height * 0.3
)
}
.padding()
}
.safeAreaInset(edge: .bottom) { Color.clear.frame(height: 60) } // Prevents tab bar overlap
}
.navigationBarTitleDisplayMode(.inline)
}
}
}

#Preview {
FrequencyView()
}
61 changes: 61 additions & 0 deletions CoughSync/Report/ReportCard.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// This source file is part of the CoughSync based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//

// ReportCard.swift
// CoughSync
//

import SwiftUI

struct ReportCard: View {
let title: String
let percentage: Double
let peakTime: String

private var percentageText: String {
percentage >= 0 ? "+\(String(format: "%.1f", percentage))%" : "\(String(format: "%.1f", percentage))%"
}

private var percentageColor: Color {
percentage >= 0 ? .orange : .blue
}

var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text(title)
.font(.title2.bold())
.foregroundColor(.primary)

HStack {
Text("Coughs Change: ")
.foregroundColor(.primary)
Text(percentageText)
.fontWeight(.bold)
.foregroundColor(percentageColor)
}

HStack {
Image(systemName: "clock.fill")
.foregroundColor(.gray)
.accessibilityLabel("Clock icon")
Text("Peak Time: \(peakTime)")
.font(.body)
.foregroundColor(.primary)
}
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(RoundedRectangle(cornerRadius: 14).fill(.ultraThinMaterial))

.padding(.horizontal)
}
}

#Preview {
ReportCard(title: "Daily Report", percentage: 12.5, peakTime: "8:00 PM - 10:00 PM")
}
41 changes: 41 additions & 0 deletions CoughSync/Report/ReportView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// This source file is part of the CoughSync based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//

import SwiftUI

struct CoughReportView: View {
var body: some View {
NavigationStack {
VStack(spacing: 20) {
Text("Cough Report")
.font(.largeTitle.bold())

ScrollView {
VStack(spacing: 15) {
ReportCard(title: "Daily Report", percentage: 12.5, peakTime: "8:00 PM - 10:00 PM")
ReportCard(title: "Weekly Report", percentage: -8.3, peakTime: "Wednesday 9:00 AM - 11:00 AM")
ReportCard(title: "Monthly Report", percentage: 5.2, peakTime: "January 15 at 7:00 PM - 9:00 PM")

NavigationLink(destination: FrequencyView()) {
Text("View Cough Frequency Trends →")
.font(.headline)
.foregroundColor(.blue)
}
.padding(.top, 10)
}
.padding()
}
}
.navigationBarTitleDisplayMode(.inline)
}
}
}

#Preview {
CoughReportView()
}
52 changes: 52 additions & 0 deletions CoughSync/Report/TrendChart.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// This source file is part of the CoughSync based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2025 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Charts
import SwiftUI


struct CoughTrendChart: View {
let title: String
let data: [Int]
let xLabels: [String]
let chartHeight: CGFloat // New parameter for dynamic height

var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text(title)
.font(.title2.bold())

Chart {
ForEach(Array(data.enumerated()), id: \.offset) { index, value in
LineMark(
x: .value("Time", xLabels[index]),
y: .value("Coughs", value)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(.blue)
}
}
.frame(height: chartHeight) // Use dynamic height
.chartYAxis {
AxisMarks(position: .leading)
}
}
.padding()
.background(RoundedRectangle(cornerRadius: 14).fill(.ultraThinMaterial))
.padding(.horizontal)
}
}

#Preview {
CoughTrendChart(
title: "Daily Coughs (Past Week)",
data: [10, 20, 30, 40, 50, 30, 20],
xLabels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
chartHeight: 200
)
}
21 changes: 21 additions & 0 deletions CoughSync/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
},
"Check In" : {

},
"Clock icon" : {

},
"Close" : {
"localizations" : {
Expand Down Expand Up @@ -123,6 +126,9 @@
},
"Cough Difference: %lld" : {

},
"Cough Report" : {

},
"Cough Sync" : {

Expand All @@ -132,12 +138,21 @@
},
"Cough Tracking" : {

},
"Cough Trends" : {

},
"Coughing Tracking" : {

},
"coughs" : {

},
"Coughs" : {

},
"Coughs Change: " : {

},
"Coughs Today: %lld" : {

Expand Down Expand Up @@ -381,6 +396,9 @@
}
}
}
},
"Peak Time: %@" : {

},
"Please complete the questionnaire to personalize your experience." : {

Expand Down Expand Up @@ -506,6 +524,9 @@
}
}
}
},
"View Cough Frequency Trends →" : {

},
"WELCOME_AREA1_DESCRIPTION" : {
"localizations" : {
Expand Down
3 changes: 2 additions & 1 deletion CoughSync/SharedContext/FeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ enum FeatureFlags {
/// Requires ``disableFirebase`` to be `false`.
static let setupTestAccount = CommandLine.arguments.contains("--setupTestAccount")

static let debugDetector = CommandLine.arguments.contains("--debugDetector")
// static let debugDetector = CommandLine.arguments.contains("--debugDetector")
static let debugDetector = true
}

0 comments on commit 5238df6

Please sign in to comment.