changeset 278:47ad897925b6

Minor UI updates ChartViews
author Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com>
date Fri, 19 Mar 2021 16:34:38 +0100
parents 91a653756a16
children 6b20a0109829
files LazyBear/Functions/Haptics.swift LazyBear/Functions/StringToDate.swift LazyBear/Models/HistoricalPriceModel.swift LazyBear/UI/ChartView.swift LazyBear/UI/CompanyView.swift LazyBear/UI/IndicatorPoint.swift LazyBear/UI/LineView.swift LazyBear/UI/PriceChartIndicator.swift
diffstat 8 files changed, 126 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear/Functions/Haptics.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/Functions/Haptics.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -9,6 +9,7 @@
 import CoreHaptics
 
 class Haptics {
+    
     func simpleSuccess() {
         let generator = UINotificationFeedbackGenerator()
         generator.notificationOccurred(.success)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Functions/StringToDate.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -0,0 +1,21 @@
+//
+//  DateToString.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 19/3/21.
+//
+
+import SwiftUI
+
+func convertStringToDate(_ stringDate: String) -> String {
+    // Convert string to date
+    let dateFormatter = DateFormatter()
+    dateFormatter.dateFormat = "yy-MM-dd"
+    let date = dateFormatter.date(from: stringDate)
+    
+    // Format date to the final format
+    dateFormatter.dateStyle = .long
+    let finalDate = dateFormatter.string(from: date!)
+    
+    return finalDate
+}
--- a/LazyBear/Models/HistoricalPriceModel.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/Models/HistoricalPriceModel.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -9,10 +9,11 @@
 
 struct HistoricalPriceModel: Codable {
     var date: String
+    var minute: String? // Intraday data only
     var close: Double
     var volume: Int
-    var change: Double
-    var changePercent: Double
-    var changeOverTime: Double
+    var change: Double? // Not intraday data only
+    var changePercent: Double? // Not intraday data only
+    var changeOverTime: Double? // Not intraday data only
 
 }
--- a/LazyBear/UI/ChartView.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/UI/ChartView.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -17,42 +17,110 @@
     @State var selectedPeriod = 2
     
     // Line View
+    @State private var orientation: UIDeviceOrientation = UIDevice.current.orientation
     @State var showingChartIndicator = false
     @State var pointInPath: CGPoint = .zero
     @State var indexValue = Int()
     
+    
     var body: some View {
+        let prices = historicalPrices.map { $0.close }
+        let dates = historicalPrices.map { $0.date }
+        let minutes = historicalPrices.map {$0.minute }
         
         VStack {
-            let prices = historicalPrices.map { $0.close }
-            let dates = historicalPrices.map { $0.date }
             ZStack {
                 if showingChartIndicator {
-                    PriceChartIndicator(prices: prices, dates: dates, indexValue: $indexValue)
+                    PriceChartIndicator(prices: prices, dates: dates, minutes: minutes, indexValue: $indexValue)
                 } else {
                     DateSelection(period: period, selectedperiod: $selectedPeriod)
                         .padding(.horizontal)
                         .onChange(of: selectedPeriod, perform: { (value) in
-                            let url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: period[value])
+                            let url = rangeEndpointSelector(value)
                             request(url: url, model: [HistoricalPriceModel].self) { self.historicalPrices = $0 }
                         })
                 }
             }
             .frame(height: 40)
             
+            let (width, height) = lineViewSize()
             if !historicalPrices.isEmpty {
-                LineView(width: deviceSize.width, height: deviceSize.width/3, normalizedData: normalize(prices), showingChartIndicator: $showingChartIndicator, pointInPath: $pointInPath, indexValue: $indexValue)
-                    .frame(width: deviceSize.width, height: deviceSize.width / 3)
+                LineView(colour: lineViewColour(prices) ,width: width, height: height, normalizedData: normalize(prices), showingChartIndicator: $showingChartIndicator, pointInPath: $pointInPath, indexValue: $indexValue)
+                    .frame(width: width, height: height)
                     .rotationEffect(.degrees(180), anchor: .center)
                     .rotation3DEffect(.degrees(180), axis: (x: 0.0, y: 1.0, z: 0.0))
                     .padding([.top, .bottom])
+                    // Detect changes on device orientation and upodate view
+                    .onReceive(NotificationCenter.Publisher(center: .default, name: UIDevice.orientationDidChangeNotification)) { _ in
+                              self.orientation = UIDevice.current.orientation
+                            }
             }
         }
         .onAppear {
             let url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: "3m")
             request(url: url, model: [HistoricalPriceModel].self) { self.historicalPrices = $0 }
         }
-
+    }
+    
+    private enum HistoricalInterval {
+        case oneWeek
+        case oneMonth
+    }
+    
+    private func selected(interval: HistoricalInterval) -> String {
+        switch interval {
+        case .oneWeek:
+            return "5dm"
+        case .oneMonth:
+            return "1mm"
+        }
+    }
+    
+    private func rangeEndpointSelector(_ value: Int) -> String {
+        var url = ""
+        
+        
+        if selectedPeriod == 0 {  // 1 week
+            url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: selected(interval: .oneWeek))
+        } else if selectedPeriod == 1 {  // 1 month
+            url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: selected(interval: .oneMonth))
+        } else {  // The rest
+            url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: period[value])
+        }
+        
+        return url
+    }
+    
+    private func lineViewColour(_ prices: [Double]) -> Color {
+        var colour = Color(.systemGreen)
+        
+        let firstPrice = prices[0]
+        let lastPrice = prices.last
+        
+        if lastPrice! < firstPrice {
+            colour = Color(.systemRed)
+        }
+        
+        return colour
+    }
+    
+    private func lineViewSize() -> (CGFloat, CGFloat) {
+        var divisor: CGFloat = 3
+        
+        // if running on iPad
+        if UIDevice.current.userInterfaceIdiom == .pad {
+            divisor = 6
+        }
+        
+        var width = deviceSize.width
+        var height = deviceSize.width / divisor
+        
+        if orientation.isLandscape {
+            width = deviceSize.height
+            height = deviceSize.height / divisor
+        }
+        
+        return (width, height)
     }
 }
 
--- a/LazyBear/UI/CompanyView.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/UI/CompanyView.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -37,7 +37,7 @@
         .onAppear { companyOption.view = .stock }
         .toolbar {
             ToolbarItem(placement: .principal) {
-                Button(action: { self.hudManager.showAction.toggle() }) {
+                Button(action: { self.hudManager.showAction.toggle(); haptics.simpleSuccess() }) {
                     HStack {
                         if companyOption.view == .stock {
                             Text("Stock")
--- a/LazyBear/UI/IndicatorPoint.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/UI/IndicatorPoint.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -8,10 +8,14 @@
 import SwiftUI
 
 struct IndicatorPoint: View {
+    @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)])
+    var userSettings: FetchedResults<UserSettings>
+    
     var body: some View {
+        let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent")
         Circle()
             .frame(width: 20, height: 20)
-            .foregroundColor(.blue)
+            .foregroundColor(colour)
     }
 }
 
--- a/LazyBear/UI/LineView.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/UI/LineView.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -8,6 +8,7 @@
 import SwiftUI
 
 struct LineView: View {
+    var colour: Color
     var width: CGFloat
     var height: CGFloat
     var normalizedData: [Double]
@@ -17,8 +18,13 @@
     @Binding var showingChartIndicator: Bool
     @Binding var pointInPath: CGPoint
     @Binding var indexValue: Int
+    
+    @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)])
+    var userSettings: FetchedResults<UserSettings>
 
     var body: some View {
+        let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent")
+        
         // Substract 2 to skip the first and the last item
         let widthBetweenPoints = Double(width) / Double(normalizedData.count - 2)
         let initialPoint = normalizedData[0] * Double(height)
@@ -40,7 +46,7 @@
                         pathPoints.append(path.currentPoint!)
                     }
                 }
-                .stroke(self.showingChartIndicator ? Color.blue: Color.green, lineWidth: 2)
+                .stroke(self.showingChartIndicator ? colour: self.colour, lineWidth: 2)
                 
                 if showingChartIndicator {
                     IndicatorPoint()
@@ -99,7 +105,7 @@
         GeometryReader { geo in
             VStack {
                 let normalizedData: [Double] = [0, 0.1, 0.15, 0.2, 0.3, 0.4, 0.35, 0.38, 0.5, 0.55, 0.6, 0.57, 0.8, 1]
-                LineView(width: geo.size.width, height: geo.size.width / 2, normalizedData: normalizedData, showingChartIndicator: .constant(false), pointInPath: .constant(.zero), indexValue: .constant(0))
+                LineView(colour: Color(.systemGreen), width: geo.size.width, height: geo.size.width / 2, normalizedData: normalizedData, showingChartIndicator: .constant(false), pointInPath: .constant(.zero), indexValue: .constant(0))
             }
         }
     }
--- a/LazyBear/UI/PriceChartIndicator.swift	Thu Mar 18 17:23:37 2021 +0100
+++ b/LazyBear/UI/PriceChartIndicator.swift	Fri Mar 19 16:34:38 2021 +0100
@@ -10,14 +10,22 @@
 struct PriceChartIndicator: View {
     var prices: [Double]
     var dates: [String]
+    var minutes: [String?]
     @Binding var indexValue: Int
+    @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)])
+    var userSettings: FetchedResults<UserSettings>
     
     var body: some View {
+        let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent")
         HStack {
             Group {
-                Text(dates[indexValue])
+                let date = convertStringToDate(dates[indexValue])
+                Text(date)
+                if let minute = minutes[indexValue] {
+                    Text(minute)
+                }
                 Text("\(prices[indexValue], specifier: "%.2f")")
-                    .foregroundColor(.blue)
+                    .foregroundColor(colour)
             }
             .font(.subheadline)
         }
@@ -26,6 +34,6 @@
 
 struct PriceChartIndicator_Previews: PreviewProvider {
     static var previews: some View {
-        PriceChartIndicator(prices: [100, 50], dates: ["10-10-2020", "11-10-2020"], indexValue: .constant(0))
+        PriceChartIndicator(prices: [100, 50], dates: ["10-10-2020", "11-10-2020"], minutes: ["9:02", "9:03"], indexValue: .constant(0))
     }
 }