changeset 424:6dd97877f575

Improve code, reorganize files
author Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com>
date Sun, 13 Jun 2021 19:40:42 +0200
parents bdfdf3a1b34e
children 4effac4733b0
files LazyBear/Views/Company/Chart.swift LazyBear/Views/Company/Helpers/CompanyHeader.swift LazyBear/Views/Company/Helpers/StatsView.swift LazyBear/Views/Global Helpers/Extensive List/ExtensiveList.swift LazyBear/Views/Global Helpers/Extensive List/Helpers/ToolbarMenu.swift LazyBear/Views/Global Helpers/PriceView.swift LazyBear/Views/Global Helpers/RowShape.swift LazyBear/Views/Global Helpers/StockItem.swift LazyBear/Views/Global Helpers/StockRow.swift LazyBear/Views/Home/Helpers/CurrencyItem.swift LazyBear/Views/Home/Helpers/CurrencyListItem.swift LazyBear/Views/Home/Helpers/CurrencyRow.swift LazyBear/Views/Home/Helpers/CurrencySheet.swift LazyBear/Views/Home/Helpers/CurrencySheetRow.swift LazyBear/Views/Home/Helpers/StockItem.swift LazyBear/Views/Home/Helpers/StockRow.swift LazyBear/Views/Home/Helpers/StockSheet.swift LazyBear/Views/Home/Helpers/StockSheetRow.swift LazyBear/Views/Home/HomeView.swift LazyBear/Views/Profile/ProfileView.swift
diffstat 20 files changed, 366 insertions(+), 565 deletions(-) [+]
line wrap: on
line diff
--- a/LazyBear/Views/Company/Chart.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Company/Chart.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -36,19 +36,19 @@
                         VStack {
                             HStack {
                                 if let quote = company.chartData.quote![symbol.uppercased()] {
-                                    let latestPrice = quote.latestPrice ?? 0
-                                    let changePercent = quote.changePercent ?? 0
-                                    let priceViewStyle = PriceViewStyle(  /// Define PriceView style
-                                        horizontalAlignment: .leading,
-                                        verticalAlignment: .center,
-                                        orientation: .HStack,
-                                        priceFont: .title3,
-                                        priceFontWeight: .semibold,
-                                        percentFont: .body,
-                                        percentFontWeight: .semibold,
-                                        showBackground: true
-                                    )
-                                    PriceView(latestPrice: latestPrice, changePercent: changePercent, style: priceViewStyle)
+                                    if let latestPrice = quote.latestPrice, let changePercent = quote.changePercent {
+                                        HStack(alignment: .center) {
+                                            Text("\(latestPrice, specifier: "%.2f")")
+                                                .foregroundColor(changePercent < 0 ? .red: .green)
+                                                .fontWeight(.semibold)
+
+                                            Text("\(changePercent * 100, specifier: "%.2f")%")
+                                                .foregroundColor(changePercent < 0 ? .red: .green)
+                                                .font(.callout)
+                                                .fontWeight(.semibold)
+                                        }
+                                        .padding(.top)
+                                    }
                                 }
                                 Spacer()
                                 
--- a/LazyBear/Views/Company/Helpers/CompanyHeader.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Company/Helpers/CompanyHeader.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -20,7 +20,7 @@
             Spacer()
             
             Button(action: { showViewSelector = true }) {
-                Text("Views ")
+                Text("See more ")
                 Image(systemName: "chevron.down")
             }
         }
--- a/LazyBear/Views/Company/Helpers/StatsView.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Company/Helpers/StatsView.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -29,6 +29,7 @@
                             Spacer()
                             Text(unwrappedValue)
                                 .font(.callout)
+                                .lineLimit(1)
                         }
                     }
                 }
--- a/LazyBear/Views/Global Helpers/Extensive List/ExtensiveList.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-//
-//  ExtensiveList.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 14/4/21.
-//
-
-import SwiftUI
-
-struct ExtensiveList: View {
-    var listName: String
-    var list: [String: QuoteModel]?
-    var intradayPrices: [String: [Double]]?
-    var latestCurrencies: [String: CurrencyModel]?
-    var addOnDelete: Bool
-    
-    @Environment(\.presentationMode) private var presentationMode
-    @Environment(\.managedObjectContext) private var moc
-    @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: [])
-    var watchlistCompany: FetchedResults<WatchlistCompany>
-    
-    @State private var isEditMode: EditMode = .inactive
-    @State private var showRenameListAction = false
-    @State private var showDeleteListAlert = false
-    @State private var showSearchView = false
-    
-    var body: some View {
-        NavigationView {
-            ZStack {
-                VStack {
-                    if let list = list {
-                        List {
-                            ForEach(Array(list.keys.sorted()), id: \.self) { companySymbol in
-                                    StockItem(symbol: companySymbol,
-                                              company: list[companySymbol]!,
-                                              intradayPrices: intradayPrices?[companySymbol],
-                                              orientation: .horizontal,
-                                              hidePriceView: self.isEditMode == .active  // Hide on EditMode
-                                    )
-                                
-                            }
-                            .onDelete(perform: addOnDelete ? deleteCompany: nil)
-                        }
-                    }
-                    
-                    if let latestCurrencies = latestCurrencies {
-                        List(Array(latestCurrencies.keys.sorted()), id: \.self) { currencySymbol in
-                            CurrencyListItem(currencySymbol: currencySymbol, currency: latestCurrencies[currencySymbol]!)
-                            
-                        }
-                    }
-                }
-                
-                // Blur background
-                Color(.black)
-                    .edgesIgnoringSafeArea(.all)
-                    .opacity(showRenameListAction ? 0.2: 0)
-                    .animation(.easeInOut)
-                    .onTapGesture { showRenameListAction = false }
-                
-                // Show rename Action Sheet
-                TextfieldAlert(listName: listName, showRenameAction: $showRenameListAction, presentationMode: presentationMode)
-                    .offset(y: showRenameListAction ? 0: 700)
-                    .animation(.easeInOut)
-            }
-            // Show delete list alert
-            .alert(isPresented: $showDeleteListAlert) {
-                Alert(
-                    title: Text("Are you sure you want to delete this list?"),
-                    message: Text("This action can't be undo"),
-                    primaryButton: .destructive(Text("Delete")) { deleteList() },
-                    secondaryButton: .cancel()
-                )
-            }
-            .navigationTitle(listName)
-            .navigationBarTitleDisplayMode(.inline)
-            .toolbar {
-                ToolbarItem(placement: .cancellationAction) {
-                    if addOnDelete {
-                        EditButton()
-                    } else {
-                        Button(action: { presentationMode.wrappedValue.dismiss() }) {
-                            Image(systemName: "multiply")
-                                .imageScale(.large)
-                        }
-                    }
-                }
-                ToolbarItem(placement: .navigationBarTrailing) {
-                    if addOnDelete {
-                        ToolbarMenu(showRenameListAction: $showRenameListAction, showDeleteListAlert: $showDeleteListAlert)
-                    }
-                }
-            }
-            .environment(\.editMode, self.$isEditMode)  // Always after Toolbar
-        }
-    }
-    
-    /*
-     Delete company from watchlist
-     */
-    private func deleteCompany(at offsets: IndexSet) {
-        for index in offsets {
-            let company = watchlistCompany[index]
-            moc.delete(company)
-        }
-        do {
-            try moc.save()
-            print("Company deleted")
-        } catch {
-            print(error.localizedDescription)
-        }
-    }
-    
-    /*
-     Remove entire list if it's not the last one. It can't be zero watchlists
-     */
-    private func deleteList() {
-        let selectedWatchlist = watchlistCompany.filter({ $0.watchlist == listName })
-        for company in selectedWatchlist {
-            moc.delete(company)
-        }
-        do {
-            try moc.save()
-            print("List deleted")
-            presentationMode.wrappedValue.dismiss()  // Dismiss view
-        } catch {
-            print(error.localizedDescription)
-        }
-    }
-}
-
-struct ExtensiveList_Previews: PreviewProvider {
-    static var previews: some View {
-        ExtensiveList(listName: "List name", addOnDelete: false)
-    }
-}
--- a/LazyBear/Views/Global Helpers/Extensive List/Helpers/ToolbarMenu.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-//
-//  ToolbarMenu.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 25/4/21.
-//
-
-import SwiftUI
-
-struct ToolbarMenu: View {
-    @Binding var showRenameListAction: Bool
-    @Binding var showDeleteListAlert: Bool
-    
-    @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: [])
-    var watchlistCompany: FetchedResults<WatchlistCompany>
-    
-    var body: some View {
-        Menu {
-            Section {
-                Button(action: { showRenameListAction = true }) {
-                    Label("Rename list", systemImage: "square.and.pencil")
-                }
-            }
-            
-            if Set(watchlistCompany.map { $0.watchlist }).count > 1 {  /// If there are only 1 watchlist -> It cannot be deleted
-                Section(header: Text("Secondary actions")) {
-                    Button(action: { showDeleteListAlert = true }) {
-                        Label("Delete list", systemImage: "trash")
-                    }
-                }
-            }
-        }
-        label: {
-            Label("Options", systemImage: "ellipsis.circle")
-                .imageScale(.large)
-        }
-    }
-}
-
-struct ToolbarMenu_Previews: PreviewProvider {
-    static var previews: some View {
-        ToolbarMenu(showRenameListAction: .constant(false), showDeleteListAlert: .constant(false))
-    }
-}
--- a/LazyBear/Views/Global Helpers/PriceView.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-//
-//  PriceView.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 3/4/21.
-//
-
-import SwiftUI
-
-struct PriceView: View {
-    var latestPrice: Double
-    var changePercent: Double
-    var style: PriceViewStyle
-    
-    var body: some View {
-        if style.orientation == .VStack {
-            VStack(alignment: style.horizontalAlignment) {
-                Price(latestPrice: latestPrice, changePercent: changePercent, style: style)
-            }
-        } else {
-            HStack(alignment: style.verticalAlignment) {
-                Price(latestPrice: latestPrice, changePercent: changePercent, style: style)
-            }
-            .if(style.showBackground) { content in
-                content
-                    .padding(10)
-                    .background(
-                        RoundedRectangle(cornerRadius: 15)
-                            .foregroundColor(Color(.tertiarySystemBackground))
-                    )
-            }
-        }
-    }
-}
-
-/*
- 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 Price: View {
-    var latestPrice: Double
-    var changePercent: Double
-    var style: PriceViewStyle
-    
-    var body: some View {
-        Text("\(latestPrice, specifier: "%.2f")")
-            .foregroundColor(changePercent < 0 ? .red: .green)
-            .font(style.priceFont)
-            .fontWeight(style.priceFontWeight)
-        
-        Text("\(changePercent*100, specifier: "%.2f")%")
-            .foregroundColor(changePercent < 0 ? .red: .green)
-            .font(style.percentFont)
-            .fontWeight(style.percentFontWeight)
-    }
-}
-
-
-struct PriceView_Previews: PreviewProvider {
-    static var previews: some View {
-        PriceView(
-            latestPrice: 120.30,
-            changePercent: 0.03,
-            style: PriceViewStyle(
-                horizontalAlignment: .leading,
-                verticalAlignment: .center,
-                orientation: .VStack,
-                priceFont: .body,
-                priceFontWeight: .semibold,
-                percentFont: .callout,
-                percentFontWeight: .semibold,
-                showBackground: true
-            )
-        )
-    }
-}
--- a/LazyBear/Views/Global Helpers/RowShape.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Global Helpers/RowShape.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -21,6 +21,20 @@
     }
 }
 
+/*
+ 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()
--- a/LazyBear/Views/Global Helpers/StockItem.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-//
-//  StockItem.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 28/3/21.
-//
-
-import SwiftUI
-import StockCharts
-
-enum OrientationView {
-    case horizontal, vertical
-}
-
-struct StockItem: View {
-    var symbol: String
-    var company: QuoteModel
-    var intradayPrices: [Double]?
-    var orientation: OrientationView
-    var hidePriceView: Bool?
-    
-    var body: some View {
-        if orientation == .vertical {
-            let verticalRow: AnyView = AnyView(
-                NavigationLink(destination: CompanyView(symbol: symbol)) {
-                    VerticalStockRow(symbol: symbol, company: company, intradayPrices: intradayPrices)
-                }
-                .buttonStyle(PlainButtonStyle())
-            )
-            return verticalRow
-        } else {
-            let horizontalRow: AnyView = AnyView(
-                NavigationLink(destination: CompanyView(symbol: symbol)) {
-                    HorizontalStockRow(symbol: symbol, company: company, intradayPrices: intradayPrices, hidePriceView: hidePriceView ?? false)
-                }
-            )
-            return horizontalRow
-        }
-    }
-}
-
-struct StockItem_Previews: PreviewProvider {
-    static var previews: some View {
-        StockItem(
-            symbol: "AAPL", company: QuoteModel(changePercent: 0.03, companyName: "apple inc", latestPrice: 130.3),
-            intradayPrices: [130.3, 132.3], orientation: .horizontal
-        )
-    }
-}
-
-
-struct VerticalStockRow: View {
-    var symbol: String
-    var company: QuoteModel
-    var intradayPrices: [Double]?
-    
-    var body: some View {
-        RoundedRectangle(cornerRadius: 20)
-            .foregroundColor(Color(.secondarySystemBackground))
-            .aspectRatio(0.8, contentMode: .fit)
-            .clipShape(RoundedRectangle(cornerRadius: 20))
-            .overlay(
-                VStack(alignment: .leading) {
-                    Group {
-                        Text(symbol.uppercased())
-                            .fontWeight(.semibold)
-                            .padding(.top)
-                        
-                        Text(company.companyName.capitalized)
-                            .font(.callout)
-                            .fontWeight(.semibold)
-                            .opacity(0.6)
-                            .lineLimit(1)
-                        
-                        let priceViewStyle = PriceViewStyle(
-                            horizontalAlignment: .leading,
-                            verticalAlignment: .center,
-                            orientation: .VStack,
-                            priceFont: .body,
-                            priceFontWeight: .semibold,
-                            percentFont: .callout,
-                            percentFontWeight: .semibold,
-                            showBackground: false
-                        )
-                        
-                        PriceView(latestPrice: company.latestPrice ?? 0,
-                                  changePercent: company.changePercent ?? 0,
-                                  style: priceViewStyle)
-                            .padding(.top)
-                            
-                    }
-                    .padding(.horizontal)
-                    
-                    Spacer()
-                     
-                    if let prices = intradayPrices {
-                        LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false)
-                            .padding(.vertical)
-                            .clipShape(RoundedRectangle(cornerRadius: 20))
-                    }
-                        
-                }
-                ,alignment: .leading
-            )
-    }
-}
-
-
-struct HorizontalStockRow: View {
-    var symbol: String
-    var company: QuoteModel
-    var intradayPrices: [Double]?
-    var hidePriceView: Bool
-    
-    var body: some View {
-        HStack {
-            VStack(alignment: .leading) {
-                Text(symbol.uppercased())
-                    .fontWeight(.semibold)
-                
-                Text(company.companyName.capitalized)
-                    .font(.callout)
-                    .fontWeight(.semibold)
-                    .opacity(0.6)
-                    .lineLimit(1)
-            }
-            
-            Spacer()
-            if !hidePriceView {
-                if let prices = intradayPrices {
-                    LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false)
-                        .frame(width: 80)
-                        .padding(.vertical, 10)
-                        .padding(.leading)
-                }
-                
-                let priceViewStyle = PriceViewStyle(
-                    horizontalAlignment: .leading,
-                    verticalAlignment: .center,
-                    orientation: .VStack,
-                    priceFont: .body,
-                    priceFontWeight: .semibold,
-                    percentFont: .callout,
-                    percentFontWeight: .semibold,
-                    showBackground: false
-                )
-                
-                PriceView(latestPrice: company.latestPrice ?? 0,
-                          changePercent: company.changePercent ?? 0,
-                          style: priceViewStyle)
-                    // Center PriceView with the other rows
-                    .frame(minWidth: 80, alignment: .trailing)
-            }
-        }
-        .padding(5)
-    }
-}
--- a/LazyBear/Views/Global Helpers/StockRow.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-//
-//  StockRow.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 28/3/21.
-//
-
-import SwiftUI
-
-
-struct StockRow: View {
-    var listName: String
-    var list: [String: QuoteModel]
-    var intradayPrices: [String: [Double]]?
-    var addOnDelete: Bool
-
-    @State private var showExtensiveList = false
-    
-    @Environment(\.managedObjectContext) private var moc
-    
-    var body: some View {
-        VStack(alignment: .leading) {
-            HStack(alignment: .bottom) {
-                VStack(alignment: .leading) {
-                    Text(listName)
-                        .font(.title3)
-                        .fontWeight(.semibold)
-                        .padding([.top, .horizontal])
-                    
-                    Text("Real-time quotes")
-                        .font(.caption)
-                        .opacity(0.5)
-                        .padding(.horizontal)
-                }
-                
-                Spacer()
-                Button("See all", action: { self.showExtensiveList = true })
-                    .buttonStyle(BorderlessButtonStyle())
-                    .padding(.horizontal)
-            }
-            
-            ScrollView(.horizontal, showsIndicators: false) {
-                HStack(spacing: 20) {
-                    ForEach(Array(list.keys.sorted()), id: \.self) { companySymbol in
-                        StockItem(symbol: companySymbol, company: list[companySymbol]!, intradayPrices: intradayPrices?[companySymbol], orientation: .vertical)
-                    }
-                }
-                .padding()
-            }
-            .frame(height: 250)
-        }
-        .padding(.bottom)
-        .sheet(isPresented: $showExtensiveList) {
-            ExtensiveList(listName: listName, list: list, intradayPrices: intradayPrices, latestCurrencies: nil, addOnDelete: addOnDelete)
-                .environment(\.managedObjectContext, self.moc)
-            
-        }
-    }
-}
-
-
-struct StockRectangleRow_Previews: PreviewProvider {
-    static var previews: some View {
-        StockRow(
-            listName: "Gainers",
-            list: ["AAPL": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 130.3)],
-            intradayPrices: ["AAPL": [130.2]], addOnDelete: false
-        )
-    }
-}
--- a/LazyBear/Views/Home/Helpers/CurrencyItem.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Home/Helpers/CurrencyItem.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -10,6 +10,7 @@
 struct CurrencyItem: View {
     var currencySymbol: String
     var currency: CurrencyModel
+    var rectangleWidth: CGFloat?
     
     var body: some View {
         RoundedRectangle(cornerRadius: 8)
--- a/LazyBear/Views/Home/Helpers/CurrencyListItem.swift	Sun Jun 13 19:40:18 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-//
-//  CurrencyListItem.swift
-//  LazyBear
-//
-//  Created by Dennis Concepción Martín on 14/4/21.
-//
-
-import SwiftUI
-
-struct CurrencyListItem: View {
-    var currencySymbol: String
-    var currency: CurrencyModel
-    
-    var body: some View {
-        HStack {
-            Text(currency.flag)
-                .padding(.trailing)
-            
-            VStack(alignment: .leading) {
-                Text("USD/\(currencySymbol)")
-                    .font(.headline)
-                
-                Text(currency.name)
-                    .font(.callout)
-            }
-            
-            Spacer()
-            Text("\(currency.rate, specifier: "%.2f")")
-                .padding(.horizontal)
-        }
-    }
-}
-
-struct CurrencyRowItem_Previews: PreviewProvider {
-    static var previews: some View {
-        CurrencyListItem(currencySymbol: "AUD", currency: CurrencyModel(flag: "🇺🇸", name: "Australian dollar", rate: 1.3116))
-    }
-}
--- a/LazyBear/Views/Home/Helpers/CurrencyRow.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Home/Helpers/CurrencyRow.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -9,8 +9,7 @@
 
 struct CurrencyRow: View {
     var latestCurrencies: [String: CurrencyModel]
-    
-    @Environment(\.managedObjectContext) private var moc
+
     @State private var showExtensiveList = false
     
     var body: some View {
@@ -44,8 +43,7 @@
             }
         }
         .sheet(isPresented: $showExtensiveList) {
-            ExtensiveList(listName: "Currencies", latestCurrencies: latestCurrencies, addOnDelete: false)
-                .environment(\.managedObjectContext, self.moc)
+            CurrencySheet(latestCurrencies: latestCurrencies)
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/CurrencySheet.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,38 @@
+//
+//  CurrencySheet.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 13/6/21.
+//
+
+import SwiftUI
+
+struct CurrencySheet: View {
+    @Environment(\.presentationMode) private var currencySheetPresentation
+    
+    var latestCurrencies: [String: CurrencyModel]
+    var body: some View {
+        NavigationView {
+            VStack {
+                List(Array(latestCurrencies.keys.sorted()), id: \.self) { currencySymbol in
+                    CurrencySheetRow(currencySymbol: currencySymbol, currency: latestCurrencies[currencySymbol]!)
+                }
+            }
+            .navigationTitle("Currencies")
+            .navigationBarTitleDisplayMode(.inline)
+            .toolbar {
+                ToolbarItem(placement: .navigationBarLeading) {
+                    Button(action: {currencySheetPresentation.wrappedValue.dismiss()}) {
+                        Image(systemName: "multiply")
+                    }
+                }
+            }
+        }
+    }
+}
+
+struct CurrencySheet_Previews: PreviewProvider {
+    static var previews: some View {
+        CurrencySheet(latestCurrencies: ["AUD": CurrencyModel(flag: "🇦🇺", name: "Australian dollar", rate: 1.2938)])
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/CurrencySheetRow.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,39 @@
+//
+//  CurrencySheetRow.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 13/6/21.
+//
+
+import SwiftUI
+
+struct CurrencySheetRow: View {
+    var currencySymbol: String
+    var currency: CurrencyModel
+    
+    var body: some View {
+        HStack {
+            Text(currency.flag)
+                .padding(.trailing)
+            
+            VStack(alignment: .leading) {
+                Text("USD/\(currencySymbol)")
+                    .font(.headline)
+                
+                Text(currency.name)
+                    .font(.callout)
+            }
+            
+            Spacer()
+            Text("\(currency.rate, specifier: "%.2f")")
+                .fontWeight(.semibold)
+                .padding(.horizontal)
+        }
+    }
+}
+
+struct CurrencySheetRow_Previews: PreviewProvider {
+    static var previews: some View {
+        CurrencySheetRow(currencySymbol: "AUD", currency: CurrencyModel(flag: "🇦🇺", name: "Australian dollar", rate: 1.2938))
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/StockItem.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,71 @@
+//
+//  StockItem.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 13/6/21.
+//
+
+import SwiftUI
+import StockCharts
+
+struct StockItem: View {
+    var symbol: String
+    var company: QuoteModel
+    var intradayPrices: [Double]?
+    
+    var body: some View {
+        RoundedRectangle(cornerRadius: 20)
+            .foregroundColor(Color(.secondarySystemBackground))
+            .aspectRatio(0.8, contentMode: .fit)
+            .clipShape(RoundedRectangle(cornerRadius: 20))
+            .overlay(
+                VStack(alignment: .leading) {
+                    Group {
+                        Text(symbol.uppercased())
+                            .fontWeight(.semibold)
+                            .padding(.top)
+                        
+                        Text(company.companyName.capitalized)
+                            .font(.callout)
+                            .fontWeight(.semibold)
+                            .opacity(0.6)
+                            .lineLimit(1)
+                        
+                        if let latestPrice = company.latestPrice, let changePercent = company.changePercent {
+                            VStack(alignment: .leading) {
+                                Text("\(latestPrice, specifier: "%.2f")")
+                                    .foregroundColor(changePercent < 0 ? .red: .green)
+                                    .fontWeight(.semibold)
+
+                                Text("\(changePercent * 100, specifier: "%.2f")%")
+                                    .foregroundColor(changePercent < 0 ? .red: .green)
+                                    .font(.callout)
+                                    .fontWeight(.semibold)
+                            }
+                            .padding(.top)
+                        }
+                    }
+                    .padding(.horizontal)
+                    
+                    Spacer()
+                     
+                    if let prices = intradayPrices {
+                        LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false)
+                            .padding(.vertical)
+                            .clipShape(RoundedRectangle(cornerRadius: 20))
+                    }
+                        
+                }
+                ,alignment: .leading
+            )
+    }
+}
+
+struct StockItem_Previews: PreviewProvider {
+    static var previews: some View {
+        StockItem(
+            symbol: "aapl",
+            company: QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3)
+        )
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/StockRow.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,76 @@
+//
+//  StockRow.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 28/3/21.
+//
+
+import SwiftUI
+
+
+struct StockRow: View {
+    var list: [String: [String: QuoteModel]]
+    var intradayPrices: [String: [Double]]?
+
+    @State private var showList = false
+    
+    var body: some View {
+        let listName = list.first!.key
+        VStack(alignment: .leading) {
+            HStack(alignment: .bottom) {
+                VStack(alignment: .leading) {
+                    Text(adaptListTitle(listName))
+                        .font(.title3)
+                        .fontWeight(.semibold)
+                        .padding([.top, .horizontal])
+                    
+                    Text("Real-time quotes")
+                        .font(.caption)
+                        .opacity(0.5)
+                        .padding(.horizontal)
+                }
+                
+                Spacer()
+                Button("See all", action: { showList = true })
+                    .buttonStyle(BorderlessButtonStyle())
+                    .padding(.horizontal)
+            }
+            
+            ScrollView(.horizontal, showsIndicators: false) {
+                HStack(spacing: 20) {
+                    let companies = list[listName]
+                    ForEach(Array(companies!.keys), id: \.self) { symbol in
+                        StockItem(symbol: symbol, company: companies![symbol]!, intradayPrices: intradayPrices![symbol])
+                    }
+                }
+                .padding()
+            }
+            .frame(height: 250)
+        }
+        .padding(.bottom)
+        .sheet(isPresented: $showList) {
+            StockSheet(listName: adaptListTitle(listName), companies: list[list.first!.key]!, intradayPrices: intradayPrices)
+        }
+    }
+    
+    /*
+     Get list keys (mostactive, losers, active) and adapt them to diplay
+     */
+    private func adaptListTitle(_ title: String) -> String {
+        if title == "mostactive" {
+            return "Most active"
+        } else {
+            return title.capitalized
+        }
+    }
+}
+
+
+struct StockRectangleRow_Previews: PreviewProvider {
+    static var previews: some View {
+        StockRow(
+            list: ["mostactive": ["AAPL": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 130.3)]],
+            intradayPrices: ["AAPL": [130.2]]
+        )
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/StockSheet.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,43 @@
+//
+//  StockSheet.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 13/6/21.
+//
+
+import SwiftUI
+
+struct StockSheet: View {
+    var listName: String
+    var companies: [String: QuoteModel]
+    var intradayPrices: [String: [Double]]?
+    
+    @Environment(\.presentationMode) private var stockSheetPresentation
+    
+    var body: some View {
+        NavigationView {
+            VStack {
+                List(Array(companies.keys.sorted()), id: \.self) { symbol in
+                    NavigationLink(destination: CompanyView(symbol: symbol)) {
+                        StockSheetRow(symbol: symbol, company: companies[symbol]!, intradayPrices: intradayPrices![symbol]!)
+                    }
+                }
+            }
+            .navigationTitle(listName)
+            .navigationBarTitleDisplayMode(.inline)
+            .toolbar {
+                ToolbarItem(placement: .navigationBarLeading) {
+                    Button(action: {stockSheetPresentation.wrappedValue.dismiss()}) {
+                        Image(systemName: "multiply")
+                    }
+                }
+            }
+        }
+    }
+}
+
+struct StockSheet_Previews: PreviewProvider {
+    static var previews: some View {
+        StockSheet(listName: "Most active", companies: ["aapl": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3)])
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LazyBear/Views/Home/Helpers/StockSheetRow.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -0,0 +1,60 @@
+//
+//  StockSheetRow.swift
+//  LazyBear
+//
+//  Created by Dennis Concepción Martín on 13/6/21.
+//
+
+import SwiftUI
+import StockCharts
+
+struct StockSheetRow: View {
+    var symbol: String
+    var company: QuoteModel
+    var intradayPrices: [Double]?
+    
+    var body: some View {
+        HStack {
+            VStack(alignment: .leading) {
+                Text(symbol.capitalized.capitalized)
+                    .fontWeight(.semibold)
+                
+                Text(company.companyName.capitalized)
+                    .font(.callout)
+                    .fontWeight(.semibold)
+                    .opacity(0.6)
+                    .lineLimit(1)
+            }
+            
+            Spacer()
+            if let prices = intradayPrices {
+                LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false)
+                    .frame(width: 80)
+                    .padding(.vertical, 10)
+                    .padding(.leading)
+            }
+            
+            if let latestPrice = company.latestPrice, let changePercent = company.changePercent {
+                VStack(alignment: .trailing) {
+                    Text("\(latestPrice, specifier: "%.2f")")
+                        .foregroundColor(changePercent < 0 ? .red: .green)
+                        .fontWeight(.semibold)
+
+                    Text("\(changePercent * 100, specifier: "%.2f")%")
+                        .foregroundColor(changePercent < 0 ? .red: .green)
+                        .font(.callout)
+                        .fontWeight(.semibold)
+                }
+            }
+        }
+    }
+}
+
+struct StockSheetRow_Previews: PreviewProvider {
+    static var previews: some View {
+        StockSheetRow(
+            symbol: "aapl",
+            company: QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3)
+        )
+    }
+}
--- a/LazyBear/Views/Home/HomeView.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Home/HomeView.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -34,7 +34,7 @@
                         let mirror = Mirror(reflecting: lists)
                         ForEach(Array(mirror.children), id: \.label) { child in
                             if let list = child.value as? [String : QuoteModel] {
-                                StockRow(listName: "\(adaptListTitle(child.label!))", list: list, intradayPrices: home.data.intradayPrices, addOnDelete: false)
+                                StockRow(list: [child.label!: list], intradayPrices: home.data.intradayPrices)
                                     .listRowInsets(EdgeInsets())
                             }
                         }
@@ -71,17 +71,6 @@
 
         }
     }
-    
-    /*
-     Get list keys (mostactive, losers, active) and adapt them to diplay
-     */
-    private func adaptListTitle(_ title: String) -> String {
-        if title == "mostactive" {
-            return "Most active"
-        } else {
-            return title.capitalized
-        }
-    }
 }
 
 struct HomeView_Previews: PreviewProvider {
--- a/LazyBear/Views/Profile/ProfileView.swift	Sun Jun 13 19:40:18 2021 +0200
+++ b/LazyBear/Views/Profile/ProfileView.swift	Sun Jun 13 19:40:42 2021 +0200
@@ -25,11 +25,13 @@
                      Get Watchlist names -> Create rows for each watchlist -> in each row, show companies
                      */
                     let watchlists = Set(watchlistCompanies.map { $0.watchlist })  /// Set -> avoid duplicates names
+                    
                     ForEach(Array(watchlists).sorted(), id: \.self) { listName in
-                        let symbols = watchlistCompanies.filter({ $0.watchlist == listName }).map { $0.symbol }
+                        let symbols = watchlistCompanies.filter({ $0.watchlist == listName }).map { $0.symbol }  /// Get symbols contained in specified watchlist (Core Data)
+                        
                         if let companies = profile.data.quotes {
                             let list = companies.filter({ symbols.contains($0.key) })  /// From API response select the companies within the specified watchlist
-                            StockRow(listName: listName, list: list, intradayPrices: profile.data.intradayPrices, addOnDelete: true)
+                            StockRow(list: [listName: list], intradayPrices: profile.data.intradayPrices)
                         }
                     }
                     .listRowInsets(EdgeInsets())
@@ -37,8 +39,8 @@
                         refreshList()
                     }
                 }
-                .onAppear { self.timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect() }  // Start timer
-                .onDisappear { self.timer.upstream.connect().cancel() }  // Stop timer
+                .onAppear { self.timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect() }  /// Start timer
+                .onDisappear { self.timer.upstream.connect().cancel() }  /// Stop timer
                 .onReceive(timer) { _ in
                     if !showCreateNewWatchlist {
                         prepareUrl(.streaming)