From f7a0d5edc8eb8960796b86ac29916be69aa5f6ec Mon Sep 17 00:00:00 2001 From: oliverhnat Date: Sat, 13 Jan 2024 01:10:20 +0100 Subject: [PATCH] Created basic main view, dates missing --- TrashTrack.xcodeproj/project.pbxproj | 4 ++ TrashTrack/AspectVGrid.swift | 64 ++++++++++++++++++++++++++++ TrashTrack/CalendarView.swift | 26 ++++++++++- TrashTrack/DayView.swift | 11 +++-- TrashTrack/MainView.swift | 31 +++++++++----- TrashTrack/TrashModel.swift | 32 +++++++++----- 6 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 TrashTrack/AspectVGrid.swift diff --git a/TrashTrack.xcodeproj/project.pbxproj b/TrashTrack.xcodeproj/project.pbxproj index 8dd355a..7ac35c8 100644 --- a/TrashTrack.xcodeproj/project.pbxproj +++ b/TrashTrack.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 6C264FB22B51D59B002CBE12 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C264FB12B51D59B002CBE12 /* CalendarView.swift */; }; 6C264FB42B51DA90002CBE12 /* ElegantCalendar.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C264FB32B51DA90002CBE12 /* ElegantCalendar.xcassets */; }; 6C264FB62B51EFDB002CBE12 /* DayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C264FB52B51EFDB002CBE12 /* DayView.swift */; }; + 6C264FB82B5209F8002CBE12 /* AspectVGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C264FB72B5209F8002CBE12 /* AspectVGrid.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -30,6 +31,7 @@ 6C264FB12B51D59B002CBE12 /* CalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarView.swift; sourceTree = ""; }; 6C264FB32B51DA90002CBE12 /* ElegantCalendar.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = ElegantCalendar.xcassets; path = "../../../SourcePackages/checkouts/ElegantCalendar?tab=readme-ov-file#basic-usage/ElegantCalendar.xcassets"; sourceTree = BUILT_PRODUCTS_DIR; }; 6C264FB52B51EFDB002CBE12 /* DayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayView.swift; sourceTree = ""; }; + 6C264FB72B5209F8002CBE12 /* AspectVGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AspectVGrid.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,6 +68,7 @@ 6C264F9C2B51A22F002CBE12 /* TrashTrackApp.swift */, 6C264FB52B51EFDB002CBE12 /* DayView.swift */, 6C264F9E2B51A22F002CBE12 /* MainView.swift */, + 6C264FB72B5209F8002CBE12 /* AspectVGrid.swift */, 6C264FB12B51D59B002CBE12 /* CalendarView.swift */, 6C264FAA2B51A255002CBE12 /* TrashModel.swift */, 6C264FB32B51DA90002CBE12 /* ElegantCalendar.xcassets */, @@ -163,6 +166,7 @@ files = ( 6C264FB22B51D59B002CBE12 /* CalendarView.swift in Sources */, 6C264FB62B51EFDB002CBE12 /* DayView.swift in Sources */, + 6C264FB82B5209F8002CBE12 /* AspectVGrid.swift in Sources */, 6C264F9F2B51A22F002CBE12 /* MainView.swift in Sources */, 6C264FAD2B51A26F002CBE12 /* TrashModelView.swift in Sources */, 6C264FAB2B51A255002CBE12 /* TrashModel.swift in Sources */, diff --git a/TrashTrack/AspectVGrid.swift b/TrashTrack/AspectVGrid.swift new file mode 100644 index 0000000..9f5fa59 --- /dev/null +++ b/TrashTrack/AspectVGrid.swift @@ -0,0 +1,64 @@ +// +// AspectVGrid.swift +// TrashTrack +// +// Created by Oliver Hnát on 13.01.2024. +// + +import SwiftUI + +struct AspectVGrid: View where ItemView: View, Item: Identifiable { + var items: [Item] + var aspectRatio: CGFloat + var content: (Item) -> ItemView + + init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) { + self.items = items + self.aspectRatio = aspectRatio + self.content = content + } + + var body: some View { + GeometryReader { geometry in + VStack { + let width: CGFloat = widthThatFits(itemCount: items.count, in: geometry.size, itemAspectRatio: aspectRatio) + LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) { + ForEach(items) { item in + content(item).aspectRatio(aspectRatio, contentMode: .fit) + } + } + Spacer(minLength: 0) + } + } + } + + private func adaptiveGridItem(width: CGFloat) -> GridItem { + var gridItem = GridItem(.adaptive(minimum: width)) + gridItem.spacing = 0 + return gridItem + } + + private func widthThatFits(itemCount: Int, in size: CGSize, itemAspectRatio: CGFloat) -> CGFloat { + var columnCount = 1 + var rowCount = itemCount + repeat { + let itemWidth = size.width / CGFloat(columnCount) + let itemHeight = itemWidth / itemAspectRatio + if CGFloat(rowCount) * itemHeight < size.height { + break + } + columnCount += 1 + rowCount = (itemCount + (columnCount-1)) / columnCount + } while columnCount < itemCount + if columnCount > itemCount { + columnCount = itemCount + } + return floor(size.width / CGFloat(columnCount)) + } +} + +//struct AspectVGrid_Previews: PreviewProvider { +// static var previews: some View { +// AspectVGrid() +// } +//} diff --git a/TrashTrack/CalendarView.swift b/TrashTrack/CalendarView.swift index 42617ef..1b16517 100644 --- a/TrashTrack/CalendarView.swift +++ b/TrashTrack/CalendarView.swift @@ -8,11 +8,33 @@ import SwiftUI struct CalendarView: View { + var events: [TrashEvent] + let columns: [GridItem] = Array(repeating: .init(.adaptive(minimum: 50, maximum: 50)), count: 7) var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + GeometryReader { geometry in + VStack { + let width: CGFloat = geometry.size.width / 8 + LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) { + ForEach(0.. GridItem { + var gridItem = GridItem(.adaptive(minimum: width)) + gridItem.spacing = 0 + return gridItem } } #Preview { - CalendarView() + CalendarView(events: TrashModel().getTrashEvents().sorted(by: {$0.id < $1.id})) } diff --git a/TrashTrack/DayView.swift b/TrashTrack/DayView.swift index 1af7b3f..371ac2b 100644 --- a/TrashTrack/DayView.swift +++ b/TrashTrack/DayView.swift @@ -21,14 +21,13 @@ struct DayView: View { .cornerRadius(10) .scaledToFit() .frame(maxWidth: .infinity) - VStack { - Text("\(dayOfTheWeek)") - .frame(maxWidth: .infinity, alignment: .leading) - Text("\(date).") - .font(.headline) Image(systemName: image) .font(.caption) - } + .frame(maxWidth: .infinity, alignment: .trailing) + .padding(.trailing, 6) + .padding(.top, 30) + Text("\(date).") + .font(.headline) } } } diff --git a/TrashTrack/MainView.swift b/TrashTrack/MainView.swift index 03e82d8..297e938 100644 --- a/TrashTrack/MainView.swift +++ b/TrashTrack/MainView.swift @@ -10,20 +10,29 @@ import SwiftUI struct MainView: View { var model = TrashModelView() var body: some View { - VStack { - ForEach(model.getTrashEvents()) { trashEvent in - HStack { - Image(systemName: trashEvent.trash.image) - .imageScale(.large) - .foregroundStyle(.tint) - VStack { - Text(trashEvent.trash.type) - Text(trashEvent.date.ISO8601Format()) - } + GeometryReader { geometry in + VStack { + CalendarView(events: model.getTrashEvents()) + .padding() + let width: CGFloat = geometry.size.width / 2 + LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) { + DayView(image: "tree", dayOfTheWeek: "Mon", date: 31, color: .green) + .padding() + DayView(image: "newspaper", dayOfTheWeek: "Tue", date: 31, color: .blue) + .padding() + DayView(image: "waterbottle", dayOfTheWeek: "Wed", date: 31, color: .orange) + .padding() + DayView(image: "trash", dayOfTheWeek: "Thu", date: 31, color: .gray) + .padding() } } } - .padding() + } + + private func adaptiveGridItem(width: CGFloat) -> GridItem { + var gridItem = GridItem(.adaptive(minimum: width)) + gridItem.spacing = 0 + return gridItem } } diff --git a/TrashTrack/TrashModel.swift b/TrashTrack/TrashModel.swift index 5705d69..ded505e 100644 --- a/TrashTrack/TrashModel.swift +++ b/TrashTrack/TrashModel.swift @@ -26,15 +26,16 @@ struct TrashModel { init() { self.trashTypes = [ - Trash(type: "plastic", color: Color.orange, image: "waterbottle"), - Trash(type: "paper", color: Color.orange, image: "newspaper"), - Trash(type: "bio", color: Color.orange, image: "tree"), - Trash(type: "residual", color: Color.orange, image: "trash") + Trash(type: "plastic", color: .orange, image: "waterbottle"), + Trash(type: "paper", color: .blue, image: "newspaper"), + Trash(type: "bio", color: .green, image: "tree"), + Trash(type: "residual", color: .gray, image: "trash") ] self.trashEvents = [] - let numberOfEvents = 3 - for i in 0.. [TrashEvent] {