changeset 439:aa1f4b614b2b

Implementing CompanyView
author Dennis Concepción Martín <dennisconcepcionmartin@gmail.com>
date Sun, 20 Jun 2021 14:31:39 +0200
parents 7f2a24a774eb
children 01fa77358b82
files LazyBear.xcodeproj/project.pbxproj LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate LazyBear/LazyBearApp.swift LazyBear/Views/Company/CompanyView.swift LazyBear/Views/Company/Helpers/ChartHelper.swift LazyBear/Views/Company/Helpers/CustomRectangleBox.swift LazyBear/Views/Company/Helpers/KeyStatsHelper.swift LazyBear/Views/Global Helpers/RowShape.swift
diffstat 8 files changed, 219 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear.xcodeproj/project.pbxproj	Sun Jun 20 13:20:19 2021 +0200
+++ b/LazyBear.xcodeproj/project.pbxproj	Sun Jun 20 14:31:39 2021 +0200
@@ -10,8 +10,10 @@
 		9502BBF5267F5194003B0A59 /* CompanyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBF4267F5194003B0A59 /* CompanyView.swift */; };
 		9502BBF7267F5974003B0A59 /* CompanyResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBF6267F5974003B0A59 /* CompanyResponse.swift */; };
 		9502BBF9267F59A0003B0A59 /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBF8267F59A0003B0A59 /* Company.swift */; };
+		9502BBFB267F5EE8003B0A59 /* ChartHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBFA267F5EE8003B0A59 /* ChartHelper.swift */; };
+		9502BBFD267F63F3003B0A59 /* CustomRectangleBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBFC267F63F3003B0A59 /* CustomRectangleBox.swift */; };
+		9502BBFF267F6454003B0A59 /* KeyStatsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9502BBFE267F6454003B0A59 /* KeyStatsHelper.swift */; };
 		950857A7266BD12D005357BA /* BetterSafariView in Frameworks */ = {isa = PBXBuildFile; productRef = 950857A6266BD12D005357BA /* BetterSafariView */; };
-		950857D3266BE55F005357BA /* RowShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950857D2266BE55F005357BA /* RowShape.swift */; };
 		950B6F3D267643460029E447 /* Purchases in Frameworks */ = {isa = PBXBuildFile; productRef = 950B6F3C267643460029E447 /* Purchases */; };
 		950B6F3F267643640029E447 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 950B6F3E267643640029E447 /* StoreKit.framework */; };
 		950B6F422676454A0029E447 /* RevenueCatTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950B6F412676454A0029E447 /* RevenueCatTest.swift */; };
@@ -170,7 +172,9 @@
 		9502BBF4267F5194003B0A59 /* CompanyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyView.swift; sourceTree = "<group>"; };
 		9502BBF6267F5974003B0A59 /* CompanyResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyResponse.swift; sourceTree = "<group>"; };
 		9502BBF8267F59A0003B0A59 /* Company.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = "<group>"; };
-		950857D2266BE55F005357BA /* RowShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RowShape.swift; sourceTree = "<group>"; };
+		9502BBFA267F5EE8003B0A59 /* ChartHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartHelper.swift; sourceTree = "<group>"; };
+		9502BBFC267F63F3003B0A59 /* CustomRectangleBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRectangleBox.swift; sourceTree = "<group>"; };
+		9502BBFE267F6454003B0A59 /* KeyStatsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyStatsHelper.swift; sourceTree = "<group>"; };
 		950B6F3E267643640029E447 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
 		950B6F412676454A0029E447 /* RevenueCatTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RevenueCatTest.swift; sourceTree = "<group>"; };
 		950C36E2260FB6180081CF53 /* HapticsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticsManager.swift; sourceTree = "<group>"; };
@@ -561,14 +565,6 @@
 			path = Networking;
 			sourceTree = "<group>";
 		};
-		95893DD22613CAB5003698C5 /* Global Helpers */ = {
-			isa = PBXGroup;
-			children = (
-				950857D2266BE55F005357BA /* RowShape.swift */,
-			);
-			path = "Global Helpers";
-			sourceTree = "<group>";
-		};
 		958A735025E0170900FD7ECA /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -597,7 +593,6 @@
 				95A7C06126163943003E2EC1 /* Search */,
 				95FBE0DA2619CA6000440386 /* Profile */,
 				95E31C0B26472C8500106B98 /* Company */,
-				95893DD22613CAB5003698C5 /* Global Helpers */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -640,6 +635,9 @@
 		95E31C0E26472CB600106B98 /* Helpers */ = {
 			isa = PBXGroup;
 			children = (
+				9502BBFC267F63F3003B0A59 /* CustomRectangleBox.swift */,
+				9502BBFA267F5EE8003B0A59 /* ChartHelper.swift */,
+				9502BBFE267F6454003B0A59 /* KeyStatsHelper.swift */,
 			);
 			path = Helpers;
 			sourceTree = "<group>";
@@ -1000,8 +998,10 @@
 				950B6F422676454A0029E447 /* RevenueCatTest.swift in Sources */,
 				95672B8F25DDA54700DCBE4A /* LazyBearApp.swift in Sources */,
 				95A7C066261639E0003E2EC1 /* SearchView.swift in Sources */,
+				9502BBFD267F63F3003B0A59 /* CustomRectangleBox.swift in Sources */,
 				95A4B937263EA5C20056F036 /* WatchlistCreatorRow.swift in Sources */,
 				950D0E192618AA4900D17AD7 /* CompanyList.swift in Sources */,
+				9502BBFB267F5EE8003B0A59 /* ChartHelper.swift in Sources */,
 				952994822629CA46005F0AB0 /* SearchResponse.swift in Sources */,
 				95A07F6C26305AC6009865AA /* QuoteModel.swift in Sources */,
 				95A07F6226305A9B009865AA /* CurrencyModel.swift in Sources */,
@@ -1017,6 +1017,7 @@
 				95A07F7126305AD5009865AA /* SectorPerformanceModel.swift in Sources */,
 				9594F0402651355B00CFA8D4 /* HistoricalPricesModel.swift in Sources */,
 				95123AC026767370001BFAF3 /* StockItem.swift in Sources */,
+				9502BBFF267F6454003B0A59 /* KeyStatsHelper.swift in Sources */,
 				9519BE06267E5EC3009C6015 /* ProfileStockRow.swift in Sources */,
 				9550444626111EE5000E0BCB /* SectorItem.swift in Sources */,
 				95672B9B25DDA54800DCBE4A /* LazyBear.xcdatamodeld in Sources */,
@@ -1031,7 +1032,6 @@
 				95A4B930263E9F530056F036 /* WatchlistCreatorList.swift in Sources */,
 				95123ABA2676658E001BFAF3 /* StockSheet.swift in Sources */,
 				9562404E263C7D8800C6C511 /* WatchlistCreatorClass.swift in Sources */,
-				950857D3266BE55F005357BA /* RowShape.swift in Sources */,
 				952045152610C7C600A76362 /* ConvertEpoch.swift in Sources */,
 				952FC0BA267C9A24001406B1 /* RenameListSheet.swift in Sources */,
 				95CCFB60266E864C00C384A1 /* ConvertStringToDate.swift in Sources */,
Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- a/LazyBear/LazyBearApp.swift	Sun Jun 20 13:20:19 2021 +0200
+++ b/LazyBear/LazyBearApp.swift	Sun Jun 20 14:31:39 2021 +0200
@@ -17,7 +17,7 @@
 
     var body: some Scene {
         WindowGroup {
-            CompanyView()
+            CompanyView(symbol: "aapl", name: "aaple inc")
                 .environment(\.managedObjectContext, persistenceController.container.viewContext)
         }
     }
--- a/LazyBear/Views/Company/CompanyView.swift	Sun Jun 20 13:20:19 2021 +0200
+++ b/LazyBear/Views/Company/CompanyView.swift	Sun Jun 20 14:31:39 2021 +0200
@@ -8,19 +8,44 @@
 import SwiftUI
 
 struct CompanyView: View {
+    var symbol: String
+    var name: String
+    
     @ObservedObject var company = Company()
     
     var body: some View {
-        NavigationView {
-            VStack {
-                RowShape()
+        if company.showView {
+            NavigationView {
+                ScrollView {
+                    VStack {
+                        HStack {
+                            Text(name.capitalized)
+                                .font(.title)
+                                .fontWeight(.semibold)
+                                .lineLimit(1)
+                            
+                            Spacer()
+                        }
+                        .padding(.horizontal)
+                        
+                        ChartHelper(quote: company.data.quote, historicalPrices: company.data.historicalPrices)
+                        KeyStatsHelper(keyStats: company.data.keyStats)
+                    }
+                }
+                .background(Color(.systemGray6).edgesIgnoringSafeArea(.all))
+                .navigationTitle(symbol.uppercased())
             }
+        } else {
+            ProgressView()
+                .onAppear {
+                    company.request("https://api.lazybear.app/company/symbol=aapl", .initial)
+                }
         }
     }
 }
 
 struct CompanyView_Previews: PreviewProvider {
     static var previews: some View {
-        CompanyView()
+        CompanyView(symbol: "aapl", name: "apple inc")
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Company/Helpers/ChartHelper.swift	Sun Jun 20 14:31:39 2021 +0200
@@ -0,0 +1,49 @@
+//
+//  ChartHelper.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 20/6/21.
+//
+
+import SwiftUI
+
+struct ChartHelper: View {
+    var quote: [QuoteModel]?
+    var historicalPrices: [HistoricalPricesModel]?
+    
+    var body: some View {
+        CustomRectangleBox()
+            .frame(height: 270)
+            .padding(.horizontal)
+            .overlay(
+                VStack {
+                    if let quote = quote?.first {
+                        HStack(alignment: .center) {
+                            Text("\(quote.latestPrice ?? 0, specifier: "%.2f")")
+                                .foregroundColor(quote.changePercent ?? 0 < 0 ? .red: .green)
+                                .fontWeight(.semibold)
+
+                            Text("\(quote.changePercent ?? 0 * 100, specifier: "%.2f")%")
+                                .foregroundColor(quote.changePercent ?? 0 < 0 ? .red: .green)
+                                .font(.callout)
+                                .fontWeight(.semibold)
+                        }
+                        .padding(.top)
+                    }
+                }
+            )
+    }
+}
+
+struct ChartHelper_Previews: PreviewProvider {
+    static var previews: some View {
+        ChartHelper(
+            quote: [
+                QuoteModel(companyName: "apple inc", latestPrice: 120.3, changePercent: 0.03)
+            ],
+            historicalPrices: [
+                HistoricalPricesModel(close: 120.3, date: "2020-01-01", minute: nil)
+            ]
+        )
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Company/Helpers/CustomRectangleBox.swift	Sun Jun 20 14:31:39 2021 +0200
@@ -0,0 +1,22 @@
+//
+//  CustomRectangleBox.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 20/6/21.
+//
+
+import SwiftUI
+
+struct CustomRectangleBox: View {
+    var body: some View {
+        RoundedRectangle(cornerRadius: 15)
+            .foregroundColor(.white)
+            .shadow(color: Color(.systemGray).opacity(0.25), radius: 10, x: 0.0, y: 0.0)
+    }
+}
+
+struct CustomRectangleBox_Previews: PreviewProvider {
+    static var previews: some View {
+        CustomRectangleBox()
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Company/Helpers/KeyStatsHelper.swift	Sun Jun 20 14:31:39 2021 +0200
@@ -0,0 +1,106 @@
+//
+//  KeyStatsHelper.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 20/6/21.
+//
+
+import SwiftUI
+
+struct KeyStatsHelper: View {
+    var keyStats: KeyStatsModel?
+    
+    let displayWords: DisplayWordsModel = parseJSON("DisplayWords.json")
+    
+    var body: some View {
+        if let keyStats = keyStats {
+            ScrollView(.horizontal, showsIndicators: false) {
+                HStack(spacing: 40) {
+                    
+                    let mirror = Mirror(reflecting: keyStats)
+                    ForEach(Array(mirror.children), id: \.label) { child in  /// Iterate over each variable within the class
+                        
+                        if let unwrappedValue = unwrapAnyOptional(value: child.value) {
+                            let label = String(child.label!)
+                            
+                            Capsule()
+                                .frame(width: 250, height: 40)
+                                .foregroundColor(.white)
+                                .shadow(color: Color(.systemGray).opacity(0.25), radius: 10, x: 0.0, y: 0.0)
+                                .overlay(
+                                    HStack {
+                                        Text("\(displayWords.keyStats[label]!):")
+                                            .font(.callout)
+                                            .fontWeight(.semibold)
+                                            .lineLimit(1)
+                                        
+                                        Spacer()
+                                        Text(unwrappedValue)
+                                            .font(.callout)
+                                            .lineLimit(1)
+                                    }
+                                    .padding()
+                                )
+                        }
+                    }
+                }
+                .frame(height: 80)
+                .padding(.horizontal)
+            }
+        }
+    }
+    
+    /*
+     Unwrap optional Int, Double, String into String
+     */
+    private func unwrapAnyOptional(value: Any) -> String? {
+        if let value = value as? Int {
+            return "\(value)"
+        } else if let value = value as? Double {
+            return String(format: "%.3f", value)
+        } else {
+            return value as? String
+        }
+    }
+}
+
+struct KeyStatsHelper_Previews: PreviewProvider {
+    static var previews: some View {
+        KeyStatsHelper(keyStats:
+                KeyStatsModel(
+                    companyName: "Apple inc",
+                    employees: 123,
+                    marketcap: 123,
+                    float: 123,
+                    sharesOutstanding: 123,
+                    beta: 123.12,
+                    peRatio: 123.4,
+                    dividendYield: 123.4,
+                    ttmDividendRate: 123.4,
+                    ttmEPS: 123.4,
+                    avg10Volume: 123,
+                    avg30Volume: 123,
+                    day50MovingAvg: 123.4,
+                    day200MovingAvg: 123.4,
+                    week52Change: 123.4,
+                    week52High: 123.4,
+                    week52Low: 123.4,
+                    week52HighSplitAdjustOnly: 123.4,
+                    week52LowSplitAdjustOnly: 123.4,
+                    maxChangePercent: 123.4,
+                    ytdChangePercent: 123.4,
+                    day5ChangePercent: 123.4,
+                    day30ChangePercent: 123.4,
+                    month1ChangePercent: 123.4,
+                    month3ChangePercent: 123.4,
+                    month6ChangePercent: 123.4,
+                    year1ChangePercent: 123.4,
+                    year2ChangePercent: 123.4,
+                    year5ChangePercent: 123.4,
+                    exDividendDate: "2020-01-01",
+                    nextDividendDate: "2020-01-01",
+                    nextEarningsDate: "2020-01-01"
+            )
+        )
+    }
+}
--- a/LazyBear/Views/Global Helpers/RowShape.swift	Sun Jun 20 13:20:19 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-//
-//  RowShape.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 5/6/21.
-//
-
-import SwiftUI
-
-struct RowShape: View {
-    @Environment(\.colorScheme) var colorScheme
-    
-    var body: some View {
-        RoundedRectangle(cornerRadius: 25)
-            .foregroundColor(Color("customSecondaryBackground"))
-            .if(colorScheme == .light) { content in  /// Apply shadow only when is not dark mode
-                content
-                    .shadow(color: Color(.gray).opacity(0.15), radius: 10)
-            }
-    }
-}
-
-/*
- Apply modifiers to the passed view on some condition
- */
-extension View {
-   @ViewBuilder
-   func `if`<Content: View>(_ conditional: Bool, content: (Self) -> Content) -> some View {
-        if conditional {
-            content(self)
-        } else {
-            self
-        }
-    }
-}
-
-struct RowShape_Previews: PreviewProvider {
-    static var previews: some View {
-        RowShape()
-    }
-}