From 4b6352b8fd36782cd418eab5bc8006eb5a4ea43c Mon Sep 17 00:00:00 2001 From: Trey t Date: Mon, 25 Nov 2024 09:48:44 -0800 Subject: [PATCH] filter view all workout filter view is its own view all workout filter view is the top of all workout view --- iphone/Werkout_ios/APIModels/Workout.swift | 38 ++++++ .../AllWorkouts/AllWorkoutsListView.swift | 120 +++--------------- .../Werkout_ios/Views/Login/LoginView.swift | 14 ++ .../Werkout_ios/subview/FilterAllView.swift | 90 +++++++++++++ 4 files changed, 157 insertions(+), 105 deletions(-) create mode 100644 iphone/Werkout_ios/subview/FilterAllView.swift diff --git a/iphone/Werkout_ios/APIModels/Workout.swift b/iphone/Werkout_ios/APIModels/Workout.swift index 54894e2..dccece6 100644 --- a/iphone/Werkout_ios/APIModels/Workout.swift +++ b/iphone/Werkout_ios/APIModels/Workout.swift @@ -61,3 +61,41 @@ struct Workout: Codable, Identifiable, Equatable { allSupersetExecercise = try container.decodeIfPresent([SupersetExercise].self, forKey: .allSupersetExecercise) } } + +extension Array where Element == Workout { + func filterWorkouts(searchString: String, filteredRegisterdUser: RegisteredUser?) -> [Workout] { + var matchingWorkouts = [Workout]() + + if (!searchString.isEmpty && searchString.count > 0) { + matchingWorkouts = self.filter({ + if $0.name.lowercased().contains(searchString.lowercased()) { + return true + } + + if let equipment = $0.equipment?.joined(separator: "").lowercased(), + equipment.contains(searchString.lowercased()) { + return true + } + + if let muscles = $0.muscles?.joined(separator: "").lowercased(), + muscles.contains(searchString.lowercased()) { + return true + } + + return false + }) + } + + if matchingWorkouts.isEmpty { + matchingWorkouts.append(contentsOf: self) + } + + if let filteredRegisterdUser = filteredRegisterdUser { + matchingWorkouts = matchingWorkouts.filter({ + $0.registeredUser == filteredRegisterdUser + }) + } + + return matchingWorkouts + } +} diff --git a/iphone/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift b/iphone/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift index 7545781..619c2ea 100644 --- a/iphone/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift +++ b/iphone/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift @@ -7,17 +7,17 @@ import SwiftUI +enum SortType: String, CaseIterable { + case name = "Name" + case date = "Date" +} + struct AllWorkoutsListView: View { - enum SortType: String, CaseIterable { - case name = "Name" - case date = "Date" - } - @State var searchString: String = "" @Binding var uniqueWorkoutUsers: [RegisteredUser]? @State private var filteredRegisterdUser: RegisteredUser? - let workouts: [Workout] + @State var workouts: [Workout] let selectedWorkout: ((Workout) -> Void) @State var filteredWorkouts = [Workout]() var refresh: (() -> Void) @@ -29,6 +29,13 @@ struct AllWorkoutsListView: View { Text((filteredRegisterdUser.firstName ?? "NA") + "'s Workouts") } + FilterAllView(searchString: $searchString, + uniqueWorkoutUsers: $uniqueWorkoutUsers, + filteredRegisterdUser: $filteredRegisterdUser, + filteredWorkouts: $filteredWorkouts, + workouts: $workouts, + currentSort: $currentSort) + ScrollView { LazyVStack(spacing: 20) { ForEach(filteredWorkouts, id:\.id) { workout in @@ -44,111 +51,14 @@ struct AllWorkoutsListView: View { .refreshable { refresh() } - - HStack { - TextField("Filter" ,text: $searchString) - .padding() - .textFieldStyle(OvalTextFieldStyle()) - - if let uniqueWorkoutUsers = uniqueWorkoutUsers { - Menu(content: { - ForEach(uniqueWorkoutUsers, id: \.self) { index in - Button(action: { - filteredRegisterdUser = index - filteredWorkouts = filterWorkouts() - }, label: { - Text((index.firstName ?? "") + " -" + (index.lastName ?? "")) - }) - } - - Button(action: { - filteredRegisterdUser = nil - filteredWorkouts = filterWorkouts() - }, label: { - Text("All") - }) - - }, label: { - Image(systemName: filteredRegisterdUser == nil ? "person.2" : "person.2.fill") - .padding(.trailing) - }) - } - - Menu(content: { - ForEach(SortType.allCases, id: \.self) { index in - Button(action: { - sortWorkouts(sortType: index) - }, label: { - Text(index.rawValue) - }) - } - }, label: { - Image(systemName: "list.number") - .padding(.trailing) - }) - } } .onChange(of: searchString) { newValue in - filteredWorkouts = filterWorkouts() + filteredWorkouts = workouts.filterWorkouts(searchString: searchString, filteredRegisterdUser: filteredRegisterdUser) } .onAppear{ - filteredWorkouts = filterWorkouts() + filteredWorkouts = workouts.filterWorkouts(searchString: searchString, filteredRegisterdUser: filteredRegisterdUser) } } - - func sortWorkouts(sortType: SortType) { - if currentSort == sortType { - filteredWorkouts = filteredWorkouts.reversed() - return - } - switch sortType { - case .name: - filteredWorkouts = filteredWorkouts.sorted(by: { - $0.name < $1.name - }) - case .date: - filteredWorkouts = filteredWorkouts.sorted(by: { - $0.createdAt ?? Date() < $1.createdAt ?? Date() - }) - } - currentSort = sortType - } - - func filterWorkouts() -> [Workout] { - var matchingWorkouts = [Workout]() - - if (!searchString.isEmpty && searchString.count > 0) { - matchingWorkouts = workouts.filter({ - if $0.name.lowercased().contains(searchString.lowercased()) { - return true - } - - if let equipment = $0.equipment?.joined(separator: "").lowercased(), - equipment.contains(searchString.lowercased()) { - return true - } - - if let muscles = $0.muscles?.joined(separator: "").lowercased(), - muscles.contains(searchString.lowercased()) { - return true - } - - return false - }) - } - - if matchingWorkouts.isEmpty { - matchingWorkouts.append(contentsOf: workouts) - } - - if let filteredRegisterdUser = filteredRegisterdUser { - matchingWorkouts = matchingWorkouts.filter({ - $0.registeredUser == filteredRegisterdUser - }) - } - - return matchingWorkouts - } } struct AllWorkoutsListView_Previews: PreviewProvider { diff --git a/iphone/Werkout_ios/Views/Login/LoginView.swift b/iphone/Werkout_ios/Views/Login/LoginView.swift index 3327a65..67108b0 100644 --- a/iphone/Werkout_ios/Views/Login/LoginView.swift +++ b/iphone/Werkout_ios/Views/Login/LoginView.swift @@ -14,6 +14,11 @@ struct LoginView: View { let completion: (() -> Void) @State var doingNetworkShit: Bool = false + @State var errorTitle = "" + @State var errorMessage = "" + @State var hasError: Bool = false + + var body: some View { VStack { TextField("Email", text: $email) @@ -65,6 +70,11 @@ struct LoginView: View { .edgesIgnoringSafeArea(.all) .scaledToFill() ) + .alert(errorTitle, isPresented: $hasError, actions: { + + }, message: { + + }) } func login() { @@ -78,6 +88,10 @@ struct LoginView: View { if success { completion() dismiss() + } else { + errorTitle = "error logging in" + errorMessage = "invalid credentials" + hasError = true } }) } diff --git a/iphone/Werkout_ios/subview/FilterAllView.swift b/iphone/Werkout_ios/subview/FilterAllView.swift new file mode 100644 index 0000000..09a0b59 --- /dev/null +++ b/iphone/Werkout_ios/subview/FilterAllView.swift @@ -0,0 +1,90 @@ +// +// FilterAllView.swift +// Werkout_ios +// +// Created by Trey Tartt on 11/25/24. +// + +import SwiftUI + +struct FilterAllView: View { + @Binding var searchString: String + @Binding var uniqueWorkoutUsers: [RegisteredUser]? + @Binding var filteredRegisterdUser: RegisteredUser? + @Binding var filteredWorkouts: [Workout] + @Binding var workouts: [Workout] + @Binding var currentSort: SortType? + + var body: some View { + HStack { + TextField("Filter" ,text: $searchString) + .padding(.horizontal) + .textFieldStyle(.roundedBorder) + + if let uniqueWorkoutUsers = uniqueWorkoutUsers { + Menu(content: { + ForEach(uniqueWorkoutUsers, id: \.self) { index in + Button(action: { + filteredRegisterdUser = index + filteredWorkouts = workouts.filterWorkouts(searchString: searchString, + filteredRegisterdUser: filteredRegisterdUser) + }, label: { + Text((index.firstName ?? "") + " -" + (index.lastName ?? "")) + }) + } + + Button(action: { + filteredRegisterdUser = nil + filteredWorkouts = workouts.filterWorkouts(searchString: searchString,filteredRegisterdUser: filteredRegisterdUser) + }, label: { + Text("All") + }) + + }, label: { + Image(systemName: filteredRegisterdUser == nil ? "person.2" : "person.2.fill") + .padding(.trailing) + }) + } + + Menu(content: { + ForEach(SortType.allCases, id: \.self) { index in + Button(action: { + sortWorkouts(sortType: index) + }, label: { + Text(index.rawValue) + }) + } + }, label: { + Image(systemName: "list.number") + .padding(.trailing) + }) + } + } + + func sortWorkouts(sortType: SortType) { + if currentSort == sortType { + filteredWorkouts = filteredWorkouts.reversed() + return + } + switch sortType { + case .name: + filteredWorkouts = filteredWorkouts.sorted(by: { + $0.name < $1.name + }) + case .date: + filteredWorkouts = filteredWorkouts.sorted(by: { + $0.createdAt ?? Date() < $1.createdAt ?? Date() + }) + } + currentSort = sortType + } +} + +#Preview { + FilterAllView(searchString: .constant(""), + uniqueWorkoutUsers: .constant(nil), + filteredRegisterdUser: .constant(nil), + filteredWorkouts: .constant(PreviewData.allWorkouts()), + workouts: .constant(PreviewData.allWorkouts()), + currentSort: .constant(nil)) +}