Login and Home
This commit is contained in:
88
pedi-foods/Sources/PediFoods/Services/ApiService.swift
Normal file
88
pedi-foods/Sources/PediFoods/Services/ApiService.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
import Foundation
|
||||
|
||||
struct ApiEnvelope<T: Decodable>: Decodable {
|
||||
let error: Bool
|
||||
let code: String?
|
||||
let message: String?
|
||||
let result: T?
|
||||
}
|
||||
|
||||
final class ApiService {
|
||||
private let client: ApiClient
|
||||
private var tokenStore: TokenStore
|
||||
|
||||
init(client: ApiClient = ApiClient(), tokenStore: TokenStore = DefaultTokenStore()) {
|
||||
self.client = client
|
||||
self.tokenStore = tokenStore
|
||||
}
|
||||
|
||||
// MARK: - Auth
|
||||
|
||||
func requestOtp(email: String) async throws -> ApiEnvelope<EmptyResult> {
|
||||
let body = try JSONEncoder().encode(["email": email])
|
||||
let req = ApiRequest(path: "/api/customer/login", method: "POST", module: .customer, requiresAuth: false, body: body)
|
||||
return try await client.send(req)
|
||||
}
|
||||
|
||||
func validateOtp(email: String, otp: String) async throws -> ApiEnvelope<LoginResult> {
|
||||
let body = try JSONEncoder().encode(["email": email, "otp": otp])
|
||||
let req = ApiRequest(path: "/api/customer/login", method: "POST", module: .customer, requiresAuth: false, body: body)
|
||||
let response: ApiEnvelope<LoginResult> = try await client.send(req)
|
||||
if let token = response.result?.token {
|
||||
tokenStore.jwt = token
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func profile() async throws -> ApiEnvelope<CustomerProfile> {
|
||||
let req = ApiRequest(path: "/api/customer/profile", method: "GET", module: .customer, requiresAuth: true)
|
||||
return try await client.send(req)
|
||||
}
|
||||
|
||||
// MARK: - Stores
|
||||
|
||||
func listStores(lat: Double, lng: Double, category: String? = nil, search: String? = nil) async throws -> ApiEnvelope<[StoreSummary]> {
|
||||
var items = [
|
||||
URLQueryItem(name: "lat", value: String(lat)),
|
||||
URLQueryItem(name: "lng", value: String(lng))
|
||||
]
|
||||
if let category {
|
||||
items.append(URLQueryItem(name: "category", value: category))
|
||||
}
|
||||
if let search {
|
||||
items.append(URLQueryItem(name: "search", value: search))
|
||||
}
|
||||
let req = ApiRequest(path: "/api/app/stores", method: "GET", module: .app, requiresAuth: true, queryItems: items)
|
||||
return try await client.send(req)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DTOs
|
||||
|
||||
struct EmptyResult: Decodable {}
|
||||
|
||||
struct LoginResult: Decodable {
|
||||
let token: String
|
||||
let customer: CustomerProfile?
|
||||
}
|
||||
|
||||
struct CustomerProfile: Decodable {
|
||||
let id: String
|
||||
let name: String
|
||||
let email: String
|
||||
let phoneNumber: String?
|
||||
}
|
||||
|
||||
struct StoreSummary: Decodable {
|
||||
let id: String
|
||||
let name: String
|
||||
let logo: String?
|
||||
let cover: String?
|
||||
let category: String?
|
||||
let rating: Double?
|
||||
let deliveryTime: String?
|
||||
let deliveryFee: Double?
|
||||
let distance: Double?
|
||||
let isOpen: Bool?
|
||||
let statusLabel: String?
|
||||
}
|
||||
Reference in New Issue
Block a user