diff --git a/Schedule ICTIS/ContentView.swift b/Schedule ICTIS/ContentView.swift index b141d9a..62e047c 100644 --- a/Schedule ICTIS/ContentView.swift +++ b/Schedule ICTIS/ContentView.swift @@ -41,6 +41,10 @@ struct ContentView: View { vm.group = nameGroup vm.fetchWeekSchedule(group: nameGroup) } + if let vpkStr = UserDefaults.standard.string(forKey: "vpk") { + vm.fetchWeekVPK(vpk: vpkStr) + } + print(vm.vpks) } } } diff --git a/Schedule ICTIS/LoadingScheduleView.swift b/Schedule ICTIS/LoadingScheduleView.swift index ff0004f..31c5713 100644 --- a/Schedule ICTIS/LoadingScheduleView.swift +++ b/Schedule ICTIS/LoadingScheduleView.swift @@ -13,7 +13,7 @@ struct LoadingScheduleView: View { ZStack { ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 20) { - ForEach(0..<3, id: \.self) { _ in + ForEach(0..<6, id: \.self) { _ in RoundedRectangle(cornerRadius: 20) .fill( LinearGradient( diff --git a/Schedule ICTIS/Main/Views/CreatedClassView.swift b/Schedule ICTIS/Main/Views/CreatedClassView.swift index e8b7ff8..2caf64b 100644 --- a/Schedule ICTIS/Main/Views/CreatedClassView.swift +++ b/Schedule ICTIS/Main/Views/CreatedClassView.swift @@ -13,12 +13,14 @@ struct CreatedClassView: View { var body: some View { let existingCopy = try? provider.viewContext.existingObject(with: _class.objectID) if existingCopy != nil { - HStack(spacing: 10) { + HStack(spacing: 15) { VStack { Text(getTimeString(_class.starttime)) .font(.custom("Montserrat-Regular", size: 15)) + .padding(.bottom, 1) Text(getTimeString(_class.endtime)) .font(.custom("Montserrat-Regular", size: 15)) + .padding(.top, 1) } .frame(width: 48) .padding(.top, 7) @@ -32,8 +34,9 @@ struct CreatedClassView: View { .foregroundColor(_class.important ? Color("redForImportant") : onlineOrNot(_class.online)) Text(getSubjectName(_class.subject, _class.professor, _class.auditory)) .font(.custom("Montserrat-Medium", size: 15)) - .padding(.top, 7) - .padding(.bottom, 7) + .lineSpacing(3) + .padding(.top, 9) + .padding(.bottom, 9) Spacer() } .frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230) diff --git a/Schedule ICTIS/Main/Views/MainView.swift b/Schedule ICTIS/Main/Views/MainView.swift index b54d6c0..e8e1d56 100644 --- a/Schedule ICTIS/Main/Views/MainView.swift +++ b/Schedule ICTIS/Main/Views/MainView.swift @@ -28,9 +28,6 @@ struct MainView: View { } else { ScheduleView(vm: vm, isScrolling: $isScrolling) - .onTapGesture { - isFocusedSearchBar = false - } } } .alert(isPresented: $vm.isShowingAlertForIncorrectGroup, error: vm.errorInNetwork) { error in diff --git a/Schedule ICTIS/Main/Views/ScheduleView.swift b/Schedule ICTIS/Main/Views/ScheduleView.swift index c7917a1..5a958d8 100644 --- a/Schedule ICTIS/Main/Views/ScheduleView.swift +++ b/Schedule ICTIS/Main/Views/ScheduleView.swift @@ -13,6 +13,7 @@ struct ScheduleView: View { @State private var selectedClass: ClassModel? = nil @State private var lastOffset: CGFloat = 0 @State private var scrollTimer: Timer? = nil + @State private var isShowingMyPairs = false @Binding var isScrolling: Bool var provider = ClassProvider.shared var body: some View { @@ -23,59 +24,115 @@ struct ScheduleView: View { if vm.errorInNetwork != .invalidResponse { ZStack (alignment: .top) { ScrollView(.vertical, showsIndicators: false) { - VStack (spacing: 20) { - ForEach(vm.classes.indices, id: \.self) { index in - if index != 0 && index != 1 && index == vm.selectedIndex { - let daySchedule = vm.classes[index] // Это массив строк для дня - ForEach(daySchedule.indices.dropFirst(), id: \.self) { lessonIndex in - let lesson = daySchedule[lessonIndex] // Это строка с расписанием одной пары - if !lesson.isEmpty { - HStack(spacing: 10) { - VStack { - Text(convertTimeString(vm.classes[1][lessonIndex])[0]) - .font(.custom("Montserrat-Regular", size: 15)) - .padding(.bottom, 1) - Text(convertTimeString(vm.classes[1][lessonIndex])[1]) - .font(.custom("Montserrat-Regular", size: 15)) - .padding(.top, 1) - } - .frame(width: 48) - .padding(.top, 7) - .padding(.bottom, 7) - .padding(.leading, 10) - Rectangle() - .frame(width: 2) - .frame(maxHeight: UIScreen.main.bounds.height - 18) + VStack (spacing: 30) { + VStack (alignment: .leading, spacing: 20 ) { + Text("Учебное расписание") + .font(.custom("Montserrat-Bold", size: 20)) + ForEach(vm.classes.indices, id: \.self) { index in + if index != 0 && index != 1 && index == vm.selectedIndex { + let daySchedule = vm.classes[index] // Это массив строк для дня + ForEach(daySchedule.indices.dropFirst(), id: \.self) { lessonIndex in + let lesson = daySchedule[lessonIndex] // Это строка с расписанием одной пары + if !lesson.isEmpty { + HStack(spacing: 15) { + VStack { + Text(convertTimeString(vm.classes[1][lessonIndex])[0]) + .font(.custom("Montserrat-Regular", size: 15)) + .padding(.bottom, 1) + Text(convertTimeString(vm.classes[1][lessonIndex])[1]) + .font(.custom("Montserrat-Regular", size: 15)) + .padding(.top, 1) + } + .frame(width: 48) .padding(.top, 7) .padding(.bottom, 7) - .foregroundColor(getColorForClass(lesson)) - Text(lesson) - .font(.custom("Montserrat-Medium", size: 15)) - .lineSpacing(3) - .padding(.top, 9) - .padding(.bottom, 9) - Spacer() + .padding(.leading, 10) + Rectangle() + .frame(width: 2) + .frame(maxHeight: UIScreen.main.bounds.height - 18) + .padding(.top, 7) + .padding(.bottom, 7) + .foregroundColor(getColorForClass(lesson)) + Text(lesson) + .font(.custom("Montserrat-Medium", size: 15)) + .lineSpacing(3) + .padding(.top, 9) + .padding(.bottom, 9) + Spacer() + } + .frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230) + .background(Color.white) + .cornerRadius(20) + .shadow(color: .black.opacity(0.25), radius: 4, x: 2, y: 2) } - .frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230) - .background(Color.white) - .cornerRadius(20) - .shadow(color: .black.opacity(0.25), radius: 4, x: 2, y: 2) } } } } - ForEach(classes) { _class in - if daysAreEqual(_class.day, vm.selectedDay) { - CreatedClassView(_class: _class) - .onTapGesture { - selectedClass = _class + if classes.contains(where: { daysAreEqual($0.day, vm.selectedDay) }) { + VStack(alignment: .leading, spacing: 20) { + Text("Мои пары") + .font(.custom("Montserrat-Bold", size: 20)) + ForEach(classes) { _class in + if daysAreEqual(_class.day, vm.selectedDay) { + CreatedClassView(_class: _class) + .onTapGesture { + selectedClass = _class + } } + } + } + } + if UserDefaults.standard.string(forKey: "vpk") != nil { + VStack (alignment: .leading, spacing: 20 ) { + Text("ВПК") + .font(.custom("Montserrat-Bold", size: 20)) + ForEach(vm.vpks.indices, id: \.self) { index in + if index != 0 && index != 1 && index == vm.selectedIndex { + let dayVPK = vm.vpks[index] // Это массив строк для дня + ForEach(dayVPK.indices.dropFirst(), id: \.self) { lessonIndex in + let lesson = dayVPK[lessonIndex] // Это строка с расписанием одной пары + if !lesson.isEmpty { + HStack(spacing: 15) { + VStack { + Text(convertTimeString(vm.vpks[1][lessonIndex])[0]) + .font(.custom("Montserrat-Regular", size: 15)) + .padding(.bottom, 1) + Text(convertTimeString(vm.vpks[1][lessonIndex])[1]) + .font(.custom("Montserrat-Regular", size: 15)) + .padding(.top, 1) + } + .frame(width: 48) + .padding(.top, 7) + .padding(.bottom, 7) + .padding(.leading, 10) + Rectangle() + .frame(width: 2) + .frame(maxHeight: UIScreen.main.bounds.height - 18) + .padding(.top, 7) + .padding(.bottom, 7) + .foregroundColor(getColorForClass(lesson)) + Text(lesson) + .font(.custom("Montserrat-Medium", size: 15)) + .lineSpacing(3) + .padding(.top, 9) + .padding(.bottom, 9) + Spacer() + } + .frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230) + .background(Color.white) + .cornerRadius(20) + .shadow(color: .black.opacity(0.25), radius: 4, x: 2, y: 2) + } + } + } + } } } } .frame(width: UIScreen.main.bounds.width) .padding(.bottom, 100) - .padding(.top, 30) + .padding(.top, 10) .background(GeometryReader { geometry in Color.clear.preference(key: ViewOffsetKey.self, value: geometry.frame(in: .global).minY) }) diff --git a/Schedule ICTIS/Main/Views/SearchBarView.swift b/Schedule ICTIS/Main/Views/SearchBarView.swift index 2c5f65d..c701ec0 100644 --- a/Schedule ICTIS/Main/Views/SearchBarView.swift +++ b/Schedule ICTIS/Main/Views/SearchBarView.swift @@ -28,7 +28,6 @@ struct SearchBarView: View { .onSubmit { self.isFocused = false if (!text.isEmpty) { - print(vm.errorInNetwork) vm.fetchWeekSchedule(group: text) } self.text = "" diff --git a/Schedule ICTIS/Settings/SelectingGroupView.swift b/Schedule ICTIS/Settings/SelectingGroupView.swift index f735572..fd4fc11 100644 --- a/Schedule ICTIS/Settings/SelectingGroupView.swift +++ b/Schedule ICTIS/Settings/SelectingGroupView.swift @@ -84,27 +84,29 @@ struct SelectingGroupView: View { if isFocused { ScrollView(.vertical, showsIndicators: true) { ForEach(vm.groups) { item in - VStack { - Rectangle() - .frame(height: 1) - .foregroundColor(Color("customGray1")) + if item.name.starts(with: "КТ") { //Отображаем только группы(без аудиторий и преподавателей) + VStack { + Rectangle() + .frame(height: 1) + .foregroundColor(Color("customGray1")) + .padding(.horizontal, 10) + HStack { + Text(item.name) + .foregroundColor(.black) + .font(.custom("Montserrat-SemiBold", size: 15)) + Spacer() + } .padding(.horizontal, 10) - HStack { - Text(item.name) - .foregroundColor(.black) - .font(.custom("Montserrat-SemiBold", size: 15)) - Spacer() - } - .padding(.horizontal, 10) - .padding(.top, 2) - .padding(.bottom, 2) - .frame(width: UIScreen.main.bounds.width, height: 30) - .background(Color("background")) - .onTapGesture { - UserDefaults.standard.set(item.name, forKey: "group") - vm.group = item.name - vm.fetchWeekSchedule(group: item.name) - dismiss() + .padding(.top, 2) + .padding(.bottom, 2) + .frame(width: UIScreen.main.bounds.width, height: 30) + .background(Color("background")) + .onTapGesture { + UserDefaults.standard.set(item.name, forKey: "group") + vm.group = item.name + vm.fetchWeekSchedule(group: item.name) + dismiss() + } } } } diff --git a/Schedule ICTIS/Settings/SelectingVPKView.swift b/Schedule ICTIS/Settings/SelectingVPKView.swift index 8b988ca..3003a23 100644 --- a/Schedule ICTIS/Settings/SelectingVPKView.swift +++ b/Schedule ICTIS/Settings/SelectingVPKView.swift @@ -38,7 +38,7 @@ struct SelectingVPKView: View { .onSubmit { self.isFocused = false if (!text.isEmpty) { - vm.fetchWeekSchedule(group: text) + vm.fetchWeekVPK(vpk: UserDefaults.standard.string(forKey: "vpk")) self.isLoading = true DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.isLoading = false @@ -84,27 +84,29 @@ struct SelectingVPKView: View { if isFocused { ScrollView(.vertical, showsIndicators: true) { ForEach(vm.groups) { item in - VStack { - Rectangle() - .frame(height: 1) - .foregroundColor(Color("customGray1")) + if item.name.starts(with: "ВП") || item.name.starts(with: "мВ") { + VStack { + Rectangle() + .frame(height: 1) + .foregroundColor(Color("customGray1")) + .padding(.horizontal, 10) + HStack { + Text(item.name) + .foregroundColor(.black) + .font(.custom("Montserrat-SemiBold", size: 15)) + Spacer() + } .padding(.horizontal, 10) - HStack { - Text(item.name) - .foregroundColor(.black) - .font(.custom("Montserrat-SemiBold", size: 15)) - Spacer() - } - .padding(.horizontal, 10) - .padding(.top, 2) - .padding(.bottom, 2) - .frame(width: UIScreen.main.bounds.width, height: 30) - .background(Color("background")) - .onTapGesture { - UserDefaults.standard.set(item.name, forKey: "vpk") - vm.group = item.name - vm.fetchWeekSchedule(group: item.name) - dismiss() + .padding(.top, 2) + .padding(.bottom, 2) + .frame(width: UIScreen.main.bounds.width, height: 30) + .background(Color("background")) + .onTapGesture { + UserDefaults.standard.set(item.name, forKey: "vpk") + vm.vpk = item.name + vm.fetchWeekVPK(vpk: item.name) + dismiss() + } } } } diff --git a/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift b/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift index f934041..089dad8 100644 --- a/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift +++ b/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift @@ -190,6 +190,9 @@ extension WeekViewForWeek { if vm.group != "" { vm.fetchWeekSchedule(isOtherWeek: true) } + if UserDefaults.standard.string(forKey: "vpk") != nil { + vm.fetchWeekVPK(isOtherWeek: true, vpk: UserDefaults.standard.string(forKey: "vpk")) + } weekSlider.insert(firstDate.createPrevioustWeek(), at: 0) weekSlider.removeLast() currentWeekIndex = 1 @@ -203,6 +206,9 @@ extension WeekViewForWeek { if vm.group != "" { vm.fetchWeekSchedule(isOtherWeek: true) } + if UserDefaults.standard.string(forKey: "vpk") != nil { + vm.fetchWeekVPK(isOtherWeek: true, vpk: UserDefaults.standard.string(forKey: "vpk")) + } weekSlider.append(lastDate.createNextWeek()) weekSlider.removeFirst() currentWeekIndex = weekSlider.count - 2 @@ -249,6 +255,9 @@ extension WeekViewForMonth { if vm.group != "" { vm.fetchWeekSchedule(isOtherWeek: true) } + if UserDefaults.standard.string(forKey: "vpk") != nil { + vm.fetchWeekVPK(isOtherWeek: true, vpk: UserDefaults.standard.string(forKey: "vpk")) + } } vm.selectedDay = day.date vm.updateSelectedDayIndex() @@ -287,6 +296,9 @@ extension MonthTabView { if vm.group != "" { vm.fetchWeekSchedule(isOtherWeek: true) } + if let vpkStr = UserDefaults.standard.string(forKey: "vpk") { + vm.fetchWeekVPK(vpk: vpkStr) + } } if let lastDate = monthSlider[currentMonthIndex].last?.week[6].date, @@ -300,6 +312,9 @@ extension MonthTabView { if vm.group != "" { vm.fetchWeekSchedule(isOtherWeek: true) } + if let vpkStr = UserDefaults.standard.string(forKey: "vpk") { + vm.fetchWeekVPK(vpk: vpkStr) + } } } } diff --git a/Schedule ICTIS/ViewModel/ScheduleViewModel.swift b/Schedule ICTIS/ViewModel/ScheduleViewModel.swift index 6883319..cd299c3 100644 --- a/Schedule ICTIS/ViewModel/ScheduleViewModel.swift +++ b/Schedule ICTIS/ViewModel/ScheduleViewModel.swift @@ -11,7 +11,7 @@ import Foundation final class ScheduleViewModel: ObservableObject { //MARK: Properties //Schedule - @Published var weekSchedule: Table = Table( + @Published var weekScheduleGroup: Table = Table( type: "", name: "", week: 0, @@ -34,7 +34,17 @@ final class ScheduleViewModel: ObservableObject { //Groups @Published var groups: [Choice] = [] //VPK - @Published var vpk: [[String]] = [] + @Published var vpks: [[String]] = [] + @Published var vpkHTML: String = "" + @Published var vpk: String = "" + @Published var weekScheduleVPK: Table = Table( + type: "", + name: "", + week: 0, + group: "", + table: [[]], + link: "" + ) //MARK: Methods @@ -56,10 +66,10 @@ final class ScheduleViewModel: ObservableObject { self.isNewGroup = true self.selectedDay = .init() } - self.weekSchedule = schedule.table - self.week = weekSchedule.week - self.numOfGroup = weekSchedule.group - self.classes = weekSchedule.table + self.weekScheduleGroup = schedule.table + self.week = weekScheduleGroup.week + self.numOfGroup = weekScheduleGroup.group + self.classes = weekScheduleGroup.table self.isFirstStartOffApp = false self.isShowingAlertForIncorrectGroup = false self.isLoading = false @@ -84,6 +94,47 @@ final class ScheduleViewModel: ObservableObject { } } + func fetchWeekVPK(isOtherWeek: Bool = false, vpk: String? = "default") { + isLoading = true + Task { + do { + var tempVPKS: Schedule + // В этот if мы заходим только если пользователь перелистывает недели и нам известы номер ВПК(в html формате) и номер недели, которая показывается пользователю + if isOtherWeek && vpk != nil { + tempVPKS = try await NetworkManager.shared.getScheduleForOtherWeek(self.week, self.vpkHTML) + } + // В else мы заходим в том случае, если не знаем номер недели, которую нужно отобразить и номер группы(в html формате) + else { + tempVPKS = try await NetworkManager.shared.getSchedule(vpk!) + self.vpk = vpk! + self.selectedDay = .init() + } + self.weekScheduleVPK = tempVPKS.table + self.vpkHTML = weekScheduleVPK.group + self.vpks = weekScheduleVPK.table + print(self.vpk) + self.isShowingAlertForIncorrectGroup = false + self.isLoading = false + self.errorInNetwork = .noError + } + catch { + if let error = error as? NetworkError { + switch (error) { + case .invalidResponse: + errorInNetwork = .invalidResponse + case .invalidData: + errorInNetwork = .invalidData + self.isShowingAlertForIncorrectGroup = true + default: + print("Неизвестная ошибка: \(error)") + } + isLoading = false + print("Есть ошибка: \(error)") + } + } + } + } + func fetchGroups(group: String) { Task { do {