Skip to content

Commit

Permalink
feat: converted timetable api to async/await
Browse files Browse the repository at this point in the history
  • Loading branch information
Chandram-Dutta committed Mar 4, 2024
1 parent 2de30c2 commit 7e3f1ed
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 99 deletions.
41 changes: 9 additions & 32 deletions VITTY/VITTY/TimeTable/Service/TimeTableAPIService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,22 @@

import Foundation

enum TimeTableAPIServiceError: Error {
case invalidUrl
}

class TimeTableAPIService {
static let shared = TimeTableAPIService()

func getTimeTable(
with username: String,
authToken: String,
completion: @escaping (Result<TimeTable, Error>) -> Void
) {
guard let url = URL(string: "\(Constants.url)timetable/\(username)") else {
completion(.failure(TimeTableAPIServiceError.invalidUrl))
return
}
authToken: String
) async throws -> TimeTable {

let url = URL(string: "\(Constants.url)timetable/\(username)")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Token \(authToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
completion(.failure(TimeTableAPIServiceError.invalidUrl))
return
}
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let timetableRaw = try decoder.decode(TimeTableRaw.self, from: data)
completion(.success(timetableRaw.data))
}
catch {
completion(.failure(error))
return
}
}
task.resume()
let data = try await URLSession.shared.data(for: request)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let timeTableRaw = try decoder.decode(TimeTableRaw.self, from: data.0)
return timeTableRaw.data
}
}
29 changes: 17 additions & 12 deletions VITTY/VITTY/TimeTable/ViewModel/TimeTableViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@
import Foundation
import SwiftData

public enum Stage {
case loading
case error
case data
}

extension TimeTableView {

@Observable
class TimeTableViewModel {

var timeTable: TimeTable?
var isLoading: Bool = false
var error: String?
var stage: Stage = .loading
var lectures = [Lecture]()
var dayNo = Date.convertToMondayWeek()

Expand All @@ -40,16 +45,16 @@ extension TimeTableView {
}
}

func fetchTimeTable(username: String, authToken: String) {
TimeTableAPIService.shared.getTimeTable(with: username, authToken: authToken) {
[weak self] result in
switch result {
case let .success(response):
self?.timeTable = response
self?.changeDay()
case let .failure(response):
print("Error: \(response)")
}
func fetchTimeTable(username: String, authToken: String) async {
do {
stage = .loading
let data = try await TimeTableAPIService.shared.getTimeTable(with: username, authToken: authToken)
timeTable = data
changeDay()
stage = .data
} catch {
print(error)
stage = .error
}
}
}
Expand Down
128 changes: 73 additions & 55 deletions VITTY/VITTY/TimeTable/Views/TimeTableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ struct TimeTableView: View {
@Environment(AuthViewModel.self) private var authViewModel
private let daysOfWeek = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

@State private var showingSheet = false

@State private var viewModel = TimeTableViewModel()
@State private var selectedLecture: Lecture? = nil

Expand All @@ -22,62 +20,84 @@ struct TimeTableView: View {
var body: some View {
NavigationStack {
ZStack {
Image("HomeBG")
Image(viewModel.lectures == [] ? "HomeNoClassesBG" : "HomeBG")
.resizable()
.ignoresSafeArea()
VStack {
ScrollView(.horizontal) {
HStack {
ForEach(daysOfWeek, id: \.self) { day in
Text(day)
.frame(width: 60, height: 54)
.background(
daysOfWeek[viewModel.dayNo] == day
? Color(Color.theme.secondary) : Color.clear
)
.onTapGesture {
withAnimation {
viewModel.dayNo = daysOfWeek.firstIndex(of: day)!
viewModel.changeDay()
}
}
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}
switch viewModel.stage {
case .loading:
VStack {
Spacer()
ProgressView()
Spacer()
}
case .error:
VStack{
Spacer()
Text("Error")
Spacer()
}
.scrollIndicators(.hidden)
.background(Color("DarkBG"))
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding(.horizontal)
List(viewModel.lectures.sorted()) { lecture in
VStack(alignment: .leading) {
Text(lecture.name)
.font(.headline)
case .data:
VStack {
ScrollView(.horizontal) {
HStack {
Text(
"\(formatTime(time: lecture.startTime)) - \(formatTime(time: lecture.endTime))"
)
Spacer()
Text("\(lecture.venue)")
ForEach(daysOfWeek, id: \.self) { day in
Text(day)
.frame(width: 60, height: 54)
.background(
daysOfWeek[viewModel.dayNo] == day
? Color(Color.theme.secondary) : Color.clear
)
.onTapGesture {
withAnimation {
viewModel.dayNo = daysOfWeek.firstIndex(of: day)!
viewModel.changeDay()
}
}
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}
.foregroundColor(Color.vprimary)
.font(.caption)
}
.onTapGesture {
selectedLecture = lecture
.scrollIndicators(.hidden)
.background(Color("DarkBG"))
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding(.horizontal)
if viewModel.lectures == [] {
Spacer()
Text("No classes today!")
.font(Font.custom("Poppins-Bold", size: 24))
Text(StringConstants.noClassQuotesOffline.randomElement()!)
} else {
List(viewModel.lectures.sorted()) { lecture in
VStack(alignment: .leading) {
Text(lecture.name)
.font(.headline)
HStack {
Text(
"\(formatTime(time: lecture.startTime)) - \(formatTime(time: lecture.endTime))"
)
Spacer()
Text("\(lecture.venue)")
}
.foregroundColor(Color.vprimary)
.font(.caption)
}
.onTapGesture {
selectedLecture = lecture
}
.listRowBackground(Color("DarkBG"))
}
.sheet(item: $selectedLecture) { lecture in
LectureDetailView(lecture: lecture)
}
.scrollContentBackground(.hidden)
}
.listRowBackground(Color("DarkBG"))
}
.sheet(item: $selectedLecture) { lecture in
LectureDetailView(lecture: lecture)
Spacer()
}
.scrollContentBackground(.hidden)
Spacer()
}

}
.navigationTitle(friend?.name ?? "Schedule")
.toolbar {

Menu {
if friend == nil {
NavigationLink {
Expand All @@ -96,13 +116,11 @@ struct TimeTableView: View {
string: "\(APIConstants.base_url)/api/v2/friends/\(friend?.username ?? "")"
)!
var request = URLRequest(url: url)

request.httpMethod = "DELETE"
request.addValue(
"Token \(authViewModel.appUser?.token ?? "")",
forHTTPHeaderField: "Authorization"
)

let task = URLSession.shared.dataTask(with: request) {
(data, response, error) in
if let error = error {
Expand All @@ -122,15 +140,15 @@ struct TimeTableView: View {
width: 40
)
}


}
}
.task {
viewModel.fetchTimeTable(
username: friend?.username ?? (authViewModel.appUser?.username ?? ""),
authToken: authViewModel.appUser?.token ?? ""
)
.onAppear {
Task {
await viewModel.fetchTimeTable (
username: friend?.username ?? (authViewModel.appUser?.username ?? ""),
authToken: authViewModel.appUser?.token ?? ""
)
}
}
}

Expand Down

0 comments on commit 7e3f1ed

Please sign in to comment.