Skip to content

Commit

Permalink
Merge pull request #510 from pennlabs/subletting-endpoints
Browse files Browse the repository at this point in the history
Add Subletting! 😃
  • Loading branch information
JHawk0224 authored Mar 12, 2024
2 parents c6297f5 + 58beb96 commit 0e53725
Show file tree
Hide file tree
Showing 41 changed files with 3,807 additions and 231 deletions.
119 changes: 108 additions & 11 deletions PennMobile.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct DiningVenueDetailLocationView: View {
var body: some View {
Map(coordinateRegion: $region, annotationItems: [venue]) { venue in
MapMarker(coordinate: PennCoordinate.shared.getCoordinates(for: venue))
}.clipShape(RoundedRectangle(cornerRadius: /*@START_MENU_TOKEN@*/25.0/*@END_MENU_TOKEN@*/))
}.clipShape(RoundedRectangle(cornerRadius: 25.0))
.frame(height: mapHeight)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct DiningVenueDetailMenuView: View {
.padding([.top, .bottom])
}
.sheet(isPresented: $showMenu) {
MenuWebView(url: URL(string: DiningVenue.menuUrlDict[id] ?? "https://university-of-pennsylvania.cafebonappetit.com/")!)
WebView(url: URL(string: DiningVenue.menuUrlDict[id] ?? "https://university-of-pennsylvania.cafebonappetit.com/")!)
}
if menus.count > 0 {
Picker("Menu", selection: self.$menuIndex) {
Expand Down Expand Up @@ -100,7 +100,7 @@ struct DiningVenueDetailMenuView_Previews: PreviewProvider {
}
}

struct MenuWebView: UIViewRepresentable {
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct DiningStationRow: View {
VStack {
ForEach(diningStation.items, id: \.self) { diningStationItem in
DiningStationItemRow(isExpanded: false, for: diningStationItem)
.padding([.leading, .trailing])
.padding(.horizontal)
if diningStationItem != diningStation.items.last {
Line()
.stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
Expand Down
3 changes: 3 additions & 0 deletions PennMobile/General/Protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ extension ShowsAlertForError {

case .failure(.authenticationError):
self.showAlert(withMsg: "Unable to access your courses.\nPlease login again.", title: "Login Error", completion: authenticationError)

case .failure(.alreadyExists):
self.showAlert(withMsg: "Something went wrong. It seems to already exist.", title: "Uh oh!", completion: other)

case .failure(.other):
self.showAlert(withMsg: "Unable to access your courses.\nPlease login again.", title: "Login Error", completion: authenticationError)
Expand Down
175 changes: 111 additions & 64 deletions PennMobile/General/SwiftUI Views/CustomPopupView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,84 +12,131 @@ import PennMobileShared
// Global state for the popup
class PopupManager: ObservableObject {
@Published var isShown: Bool = false
@Published var disableBackground: Bool = false
@Published var image: Image = Image(systemName: "star")
@Published var title: String = ""
@Published var message: String = ""
@Published var button1: String = ""
@Published var button2: String = ""
@Published var action1: () -> Void = {}
@Published var action2: () -> Void = {}
// Add more properties as needed for buttons and actions
@Published var button1: String?
@Published var button2: String?
@Published var action1: (() -> Void)?
@Published var action2: (() -> Void)?
@Published var autoHide: Bool = true

public init() {
isShown = false
image = Image(systemName: "star")
title = ""
message = ""
autoHide = true
}

public init(image: Image? = nil, title: String, message: String, button1: String? = nil, action1: (() -> Void)? = nil, button2: String? = nil, action2: (() -> Void)? = nil, autoHide: Bool = true) {
isShown = false
set(image: image, title: title, message: message, button1: button1, action1: action1, button2: button2, action2: action2, autoHide: autoHide)
}

public func show() {
withAnimation {
self.isShown = true
}
}

public func hide() {
withAnimation {
self.isShown = false
}
}

public func set(image: Image? = nil, title: String, message: String, button1: String? = nil, action1: (() -> Void)? = nil, button2: String? = nil, action2: (() -> Void)? = nil, autoHide: Bool? = nil) {
withAnimation {
self.image = image ?? Image(systemName: "star")
self.title = title
self.message = message
self.button1 = button1
self.button2 = button2
self.action1 = action1
self.action2 = action2
if let autoHide {
self.autoHide = autoHide
}
}
}
}

// Popup View
struct CustomPopupView: View {
@Binding var isShown: Bool
var image: Image?
var title: String
var message: String
var button1: String?
var button2: String?
var action1: () -> Void
var action2: () -> Void
@ObservedObject var popupManager: PopupManager

var body: some View {
if isShown {
ZStack {
// Scrim
Color.black
.opacity(0.2)
.edgesIgnoringSafeArea(.all)

VStack(spacing: 18) {
// Optional image
image?
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
.foregroundColor(Color("navigation"))
Text(title).font(.headline)
Text(message)
.font(.subheadline)
.multilineTextAlignment(.leading)
Button(action: action1) {
Text(button1 != nil ? button1! : "Confirm")
.foregroundColor(.white)
.padding()
.frame(maxWidth: 300)
.background(RoundedRectangle(cornerRadius: 50).fill(Color("navigation")))
ZStack {
// Scrim
Color.black
.opacity(0.2)
.edgesIgnoringSafeArea(.all)

VStack(spacing: 18) {
// Optional image
popupManager.image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
.foregroundColor(Color("navigation"))
Text(popupManager.title)
.font(.headline)
Text(popupManager.message)
.font(.subheadline)
.multilineTextAlignment(.leading)
Button(action: {
if popupManager.autoHide {
popupManager.hide()
} else {
popupManager.autoHide = true
}
.padding(.horizontal, 24)
if button2 != nil {
Button(action: action2) {
Text(button2!)
}
if popupManager.action1 != nil {
popupManager.action1!()
}
}) {
Text(popupManager.button1 ?? "Confirm")
.foregroundColor(.white)
.padding()
.frame(maxWidth: 300)
.background(RoundedRectangle(cornerRadius: 50).fill(Color("navigation")))
}
.frame(maxWidth: 280)
.padding(.horizontal, 24)
.padding(.vertical, 32)
.background(Color("uiCardBackground"))
.cornerRadius(12)
.shadow(color: Color.black.opacity(0.15), radius: 20, x: 0, y: 3)
if popupManager.button2 != nil {
Button(action: {
if popupManager.autoHide {
popupManager.hide()
} else {
popupManager.autoHide = true
}
if popupManager.action2 != nil {
popupManager.action2!()
}
}) {
Text(popupManager.button2!)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.frame(maxWidth: 280)
.padding(.horizontal, 24)
.padding(.vertical, 32)
.background(Color("uiCardBackground"))
.cornerRadius(12)
.shadow(color: Color.black.opacity(0.15), radius: 20, x: 0, y: 3)
}

.edgesIgnoringSafeArea(.all)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
}
}

struct CustomPopupView_Previews: PreviewProvider, View {
@State private var isShown = true

var body: some View {
CustomPopupView(isShown: $isShown, title: "Sample title", message: "This is a sample message. Text text text text text text.",
button1: "See My Listings",
button2: "Cancel",
action1: {isShown = false},
action2: {isShown = false}
)
}

static var previews: some View {
Self()
}
#Preview {
@StateObject var popupManager = PopupManager(
title: "Sample title",
message: "This is a sample message.",
button1: "See My Listings",
button2: "Cancel")
popupManager.show()

return CustomPopupView(popupManager: popupManager)
}
48 changes: 48 additions & 0 deletions PennMobile/General/UserDefaults + Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Foundation
import WebKit
import PennMobileShared
import OrderedCollections

// MARK: UserDefaultsKeys
extension UserDefaults {
Expand Down Expand Up @@ -45,6 +46,9 @@ extension UserDefaults {
case firstDollarsBalance
case firstSwipesBalance
case tabPreferences
case subletDrafts
case subletFilterData
case subletAmenities
}

func clearAll() {
Expand Down Expand Up @@ -629,3 +633,47 @@ extension UserDefaults {
return [.dining, .gsr, .laundry]
}
}

// MARK: - Subletting
extension UserDefaults {
func setSubletDrafts(_ drafts: [SubletDraft]) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(drafts) {
UserDefaults.standard.set(encoded, forKey: UserDefaultsKeys.subletDrafts.rawValue)
}
}

func getSubletDrafts() -> [SubletDraft]? {
if let decodedData = UserDefaults.standard.data(forKey: UserDefaultsKeys.subletDrafts.rawValue) {
let decoder = JSONDecoder()
return try? decoder.decode([SubletDraft].self, from: decodedData)
}
return nil
}

func setSubletFilterData(_ data: MarketplaceFilterData) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(data) {
UserDefaults.standard.set(encoded, forKey: UserDefaultsKeys.subletFilterData.rawValue)
}
}

func getSubletFilterData() -> MarketplaceFilterData? {
if let decodedData = UserDefaults.standard.data(forKey: UserDefaultsKeys.subletFilterData.rawValue) {
let decoder = JSONDecoder()
return try? decoder.decode(MarketplaceFilterData.self, from: decodedData)
}
return nil
}

func setSubletAmenities(_ data: OrderedSet<String>) {
UserDefaults.standard.set(Array(data), forKey: UserDefaultsKeys.subletAmenities.rawValue)
}

func getSubletAmenities() -> OrderedSet<String>? {
if let data = UserDefaults.standard.value(forKey: UserDefaultsKeys.subletAmenities.rawValue) as? [String] {
return OrderedSet(data)
}
return nil
}
}
2 changes: 1 addition & 1 deletion PennMobile/Home/Fitness/FitnessView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct ListRowModifier: ViewModifier {
func body(content: Content) -> some View {
Group {
content
.padding([.leading, .trailing])
.padding(.horizontal)
Divider()
}
}
Expand Down
38 changes: 38 additions & 0 deletions PennMobile/Home/Map/AddressMapView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// AddressMapView.swift
// PennMobile
//
// Created by Jordan H on 3/2/24.
// Copyright © 2024 PennLabs. All rights reserved.
//

import SwiftUI
import MapKit

struct AddressMapView: View {
var address: String?
@State private var region: MKCoordinateRegion = PennCoordinate.shared.getDefaultRegion(at: .far)
@State private var location: CLLocationCoordinate2D?

var body: some View {
Map(coordinateRegion: $region, annotationItems: location != nil ? [location!] : []) { location in
MapMarker(coordinate: location)
}
.onAppear {
if address != nil {
let geocoder = CLGeocoder()
let regionHint = CLCircularRegion(center: region.center, radius: 5000, identifier: "regionHint")
geocoder.geocodeAddressString(address!, in: regionHint) { (placemarks, _) in
if let placemark = placemarks?.first, let location = placemark.location {
self.region.center = location.coordinate
self.location = location.coordinate
}
}
}
}
}
}

#Preview {
AddressMapView(address: "101 S 39th St")
}
Loading

0 comments on commit 0e53725

Please sign in to comment.