Skip to content

Commit

Permalink
Points shop fix (#626)
Browse files Browse the repository at this point in the history
* should display simple list of redeemed items

- hopefully it works but can't check it
- if it does work it may need to be reset everytime a new qr code is scanned so likely reset the array after success case

* Fixed API call to redeem cart

* Success/error popup on scanning

* Remove events from points shop scanner

---------

Co-authored-by: anushkasankaran <[email protected]>
  • Loading branch information
yashjagtap23 and anushkasankaran authored Feb 20, 2025
1 parent 59b2b8b commit 211e00e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 50 deletions.
15 changes: 14 additions & 1 deletion HIAPI/Models/CartItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,22 @@ public struct CartItemContainer: Decodable, APIReturnable {
}
}

public struct RedeemReturnItem: Codable, APIReturnable {
public let userId: String?
public let items: [RedeemItem]? // Return items upon success
public let error: String?
public let message: String?
}

public struct RedeemItem: Codable, APIReturnable {
public let itemId: String
public let name: String
public let quantity: Int
}

public struct CartReturnItem: Codable, APIReturnable {
public let items: [String: Int]? // Return items upon success
public let userId: String?
public let items: [String: Int]? // Return items upon success
public let error: String?
public let message: String?
}
Expand Down
6 changes: 0 additions & 6 deletions HIAPI/Models/Item.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,3 @@ public struct Item: Codable, Hashable {
public let imageURL: String

}

public struct RedeemItem: Codable, APIReturnable {
public let itemName: String? // Return itemName upon success
public let success: Bool
public let error: String?
}
14 changes: 2 additions & 12 deletions HIAPI/Services/ShopService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,13 @@ public final class ShopService: BaseService {
return APIRequest<CartItemContainer>(service: self, endpoint: "shop/cart/", headers: headers, method: .GET)
}

public static func redeemPrize(itemId: String, itemInstance: String, userToken: String) -> APIRequest<RedeemItem> {
let jsonBody: [String: Any] = [
"itemId": itemId,
"instance": itemInstance
]
let headers: HTTPParameters = ["Authorization": userToken]

return APIRequest<RedeemItem>(service: self, endpoint: "shop/item/buy/", body: jsonBody, headers: headers, method: .POST)
}

public static func redeemCart(qrCode: String, userToken: String) -> APIRequest<CartReturnItem> {
public static func redeemCart(qrCode: String, userToken: String) -> APIRequest<RedeemReturnItem> {
let jsonBody: [String: Any] = [
"QRCode": qrCode
]
let headers: HTTPParameters = ["Authorization": userToken]

return APIRequest<CartReturnItem>(service: self, endpoint: "shop/cart/redeem/", body: jsonBody, headers: headers, method: .POST)
return APIRequest<RedeemReturnItem>(service: self, endpoint: "shop/cart/redeem/", body: jsonBody, headers: headers, method: .POST)
}

public static func addToCart(itemId: String, userToken: String) -> APIRequest<CartReturnItem> {
Expand Down
81 changes: 50 additions & 31 deletions HackIllinois/ViewControllers/HIScanPointsShopViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,18 @@ extension HIScanPointsShopViewController {
containerView.constrain(to: view, trailingInset: 0, leadingInset: 0)
containerView.addSubview(previewView)
setupCaptureSession()
if user.roles.contains(.STAFF) {
let observable = HIStaffButtonViewObservable()
observable.$selectedEventId.sink { eventID in
self.selectedEventID = eventID
}.store(in: &cancellables)
let staffButtonController = UIHostingController(rootView: HIStaffButtonView(observable: observable))
addChild(staffButtonController)
staffButtonController.view.backgroundColor = .clear
staffButtonController.view.frame = CGRect(x: 0, y: 100, width: Int(view.frame.maxX), height: 600)
view.addSubview(staffButtonController.view)
}
// if user.roles.contains(.STAFF) {
// let observable = HIStaffButtonViewObservable()
// observable.$selectedEventId.sink { eventID in
// self.selectedEventID = eventID
// }.store(in: &cancellables)
//
// let staffButtonController = UIHostingController(rootView: HIStaffButtonView(observable: observable))
// addChild(staffButtonController)
// staffButtonController.view.backgroundColor = .clear
// staffButtonController.view.frame = CGRect(x: 0, y: 100, width: Int(view.frame.maxX), height: 600)
// view.addSubview(staffButtonController.view)
// }
}
view.addSubview(closeButton)
closeButton.addTarget(self, action: #selector(didSelectCloseButton(_:)), for: .touchUpInside)
Expand Down Expand Up @@ -198,31 +199,38 @@ extension HIScanPointsShopViewController: AVCaptureMetadataOutputObjectsDelegate
}
}

func handlePointsShopAlert(status: String, itemName: String) {
print(status)
func handlePointsShopAlert(code: Int, description: String, items: [RedeemItem]) {
print("Shop alert with code: \(code)")
var alertTitle = ""
var alertMessage = ""
var error = true
switch status {
case "Success":
alertTitle = "\n\nPrize Obtained!"
alertMessage = "\nYou have successfully redeemed \(itemName) at the Points Shop!"
switch code {
case 0:
alertTitle = "\n\nSuccess!"
if items.isEmpty {
alertMessage += "\nAttendee cart is empty."
} else {
alertMessage = "\nAttendee has successfully redeemed:\n"
for item in items {
alertMessage += "\n\(item.name): \(item.quantity)"
}
}
error = false
case "invalidHTTPReponse(code: 404, description: \"forbidden\")":
case 404:
alertTitle = "\n\nError!"
alertMessage = "\nUser has no attendee profile."
alertMessage = "\nShop item is not found."
self.respondingToQRCodeFound = true
case "invalidHTTPReponse(code: 404, description: \"not found\")":
alertTitle = "\n\nError!"
alertMessage = "\nItem with itemId not found or already purchased."
case 402:
alertTitle = "\n\nInsufficient Funds!"
alertMessage = "\nAttendee does not have enough points to purchase."
self.respondingToQRCodeFound = true
case "invalidHTTPReponse(code: 400, description: \"bad request\")":
case 400:
alertTitle = "\n\nError!"
alertMessage = "\nYou have insufficient funds."
alertMessage = "\nInsufficient quantity in shop or QR is invalid/expired. Have attendee go back to cart and regenrate QR code."
self.respondingToQRCodeFound = true
default:
alertTitle = "\n\nError!"
alertMessage = "\nSomething isn't quite right. Double check your coins amount and make sure you have the correct QR code."
alertMessage = "\nSomething isn't quite right. API returned: \(description)"
self.respondingToQRCodeFound = true
}
// Create custom alert for points shop
Expand Down Expand Up @@ -270,22 +278,25 @@ extension HIScanPointsShopViewController: AVCaptureMetadataOutputObjectsDelegate
guard respondingToQRCodeFound else { return }
let meta = metadataObjects.first as? AVMetadataMachineReadableCodeObject
let code = meta?.stringValue ?? ""
let query = extractQueryValue(from: code)
guard let user = HIApplicationStateController.shared.user else { return }
respondingToQRCodeFound = false
HIAPI.ShopService.redeemCart(qrCode: code, userToken: user.token)
HIAPI.ShopService.redeemCart(qrCode: query ?? "", userToken: user.token)
.onCompletion { result in
do {
let (codeResult, _) = try result.get()
let status = codeResult.error
let itemName = "Hello"
NSLog(status ?? "Success")
DispatchQueue.main.async {
self.handlePointsShopAlert(status: status ?? "Success", itemName: itemName)
self.handlePointsShopAlert(code: 0, description: "", items: codeResult.items ?? [])
}
} catch APIRequestError.invalidHTTPReponse(code: let code, description: let description) {
NSLog("Error info \(code): \(description)")
DispatchQueue.main.async {
self.handlePointsShopAlert(code: code, description: "", items: [])
}
} catch {
NSLog("Error info: \(error)")
DispatchQueue.main.async { [self] in
self.handlePointsShopAlert(status: "\(error)", itemName: "")
self.handlePointsShopAlert(code: -1, description: "unable to parse API error response", items: [])
}
}
sleep(2)
Expand All @@ -294,6 +305,14 @@ extension HIScanPointsShopViewController: AVCaptureMetadataOutputObjectsDelegate
.launch()
}

func extractQueryValue(from url: String) -> String? {
guard let components = URLComponents(string: url),
let queryItem = components.queryItems?.first(where: { $0.name == "qr" }) else {
return nil
}
return queryItem.value
}

func decode(_ token: String) -> [String: AnyObject]? {
let string = token.components(separatedBy: ".")
if string.count == 1 { return nil }
Expand Down

0 comments on commit 211e00e

Please sign in to comment.