diff --git a/Schedule ICTIS/LoadingScheduleView.swift b/Schedule ICTIS/LoadingScheduleView.swift new file mode 100644 index 0000000..ff0004f --- /dev/null +++ b/Schedule ICTIS/LoadingScheduleView.swift @@ -0,0 +1,44 @@ +// +// LoadingScheduleView.swift +// Schedule ICTIS +// +// Created by G412 on 19.02.2025. +// + +import SwiftUI + +struct LoadingScheduleView: View { + @State private var isAnimated = false + var body: some View { + ZStack { + ScrollView(.vertical, showsIndicators: false) { + VStack(spacing: 20) { + ForEach(0..<3, id: \.self) { _ in + RoundedRectangle(cornerRadius: 20) + .fill( + LinearGradient( + gradient: Gradient(colors: [ + isAnimated ? Color.gray.opacity(0.5) : Color.gray.opacity(0.2), + isAnimated ? Color.gray.opacity(0.2) : Color.gray.opacity(0.5) + ]), + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + ) + .frame(height: 65) + .padding(.horizontal, 20) + .animation(.linear(duration: 0.9).repeatForever(autoreverses: true), value: isAnimated) + } + } + .onAppear { + isAnimated.toggle() + } + .padding(.top, 30) + } + } + } +} + +#Preview { + LoadingScheduleView() +} diff --git a/Schedule ICTIS/Main/Views/LoadingView.swift b/Schedule ICTIS/LoadingView.swift similarity index 91% rename from Schedule ICTIS/Main/Views/LoadingView.swift rename to Schedule ICTIS/LoadingView.swift index e3f940e..2708e4f 100644 --- a/Schedule ICTIS/Main/Views/LoadingView.swift +++ b/Schedule ICTIS/LoadingView.swift @@ -2,7 +2,7 @@ // LoadingView.swift // Schedule ICTIS // -// Created by G412 on 11.12.2024. +// Created by Mironov Egor on 11.12.2024. // import SwiftUI diff --git a/Schedule ICTIS/Main/Views/CreatedClassView.swift b/Schedule ICTIS/Main/Views/CreatedClassView.swift index e58f960..e8b7ff8 100644 --- a/Schedule ICTIS/Main/Views/CreatedClassView.swift +++ b/Schedule ICTIS/Main/Views/CreatedClassView.swift @@ -2,7 +2,7 @@ // CreatedClassView.swift // Schedule ICTIS // -// Created by G412 on 23.12.2024. +// Created by Mironov Egor on 23.12.2024. // import SwiftUI @@ -12,7 +12,7 @@ struct CreatedClassView: View { var provider = ClassProvider.shared var body: some View { let existingCopy = try? provider.viewContext.existingObject(with: _class.objectID) - if let check = existingCopy { + if existingCopy != nil { HStack(spacing: 10) { VStack { Text(getTimeString(_class.starttime)) @@ -20,6 +20,7 @@ struct CreatedClassView: View { Text(getTimeString(_class.endtime)) .font(.custom("Montserrat-Regular", size: 15)) } + .frame(width: 48) .padding(.top, 7) .padding(.bottom, 7) .padding(.leading, 10) @@ -30,7 +31,7 @@ struct CreatedClassView: View { .padding(.bottom, 7) .foregroundColor(_class.important ? Color("redForImportant") : onlineOrNot(_class.online)) Text(getSubjectName(_class.subject, _class.professor, _class.auditory)) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Medium", size: 15)) .padding(.top, 7) .padding(.bottom, 7) Spacer() diff --git a/Schedule ICTIS/Main/Views/Fields/AuditoryFieldView.swift b/Schedule ICTIS/Main/Views/Fields/AuditoryFieldView.swift index 098b59a..8b76759 100644 --- a/Schedule ICTIS/Main/Views/Fields/AuditoryFieldView.swift +++ b/Schedule ICTIS/Main/Views/Fields/AuditoryFieldView.swift @@ -18,7 +18,7 @@ struct AuditoryFieldView: View { .padding(.leading, 12) .padding(.trailing, 14) TextField(labelForField, text: $text) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Meduim", size: 17)) .disableAutocorrection(true) .submitLabel(.done) .focused($isFocused) diff --git a/Schedule ICTIS/Main/Views/Fields/CommentFieldView.swift b/Schedule ICTIS/Main/Views/Fields/CommentFieldView.swift index 98228fd..71aa3f2 100644 --- a/Schedule ICTIS/Main/Views/Fields/CommentFieldView.swift +++ b/Schedule ICTIS/Main/Views/Fields/CommentFieldView.swift @@ -14,7 +14,7 @@ struct CommentFieldView: View { var body: some View { HStack { TextField("Комментарий", text: $textForComment) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Medium", size: 17)) .submitLabel(.done) .multilineTextAlignment(.leading) .focused($isFocused) diff --git a/Schedule ICTIS/Main/Views/Fields/ProfessorFieldView.swift b/Schedule ICTIS/Main/Views/Fields/ProfessorFieldView.swift index 240d83c..72fa104 100644 --- a/Schedule ICTIS/Main/Views/Fields/ProfessorFieldView.swift +++ b/Schedule ICTIS/Main/Views/Fields/ProfessorFieldView.swift @@ -18,7 +18,7 @@ struct ProfessorFieldView: View { .padding(.leading, 12) .padding(.trailing, 7) TextField(labelForField, text: $text) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Meduim", size: 17)) .disableAutocorrection(true) .submitLabel(.done) .focused($isFocused) diff --git a/Schedule ICTIS/Main/Views/Fields/StartEndTimeFieldView.swift b/Schedule ICTIS/Main/Views/Fields/StartEndTimeFieldView.swift index 751b0bc..afa90be 100644 --- a/Schedule ICTIS/Main/Views/Fields/StartEndTimeFieldView.swift +++ b/Schedule ICTIS/Main/Views/Fields/StartEndTimeFieldView.swift @@ -23,7 +23,7 @@ struct StartEndTimeFieldView: View { if !isTimeSelected || isIncorrectDate { Text(text) - .font(.custom("Montserrat-Regular", size: 17)) + .font(.custom("Montserrat-Meduim", size: 17)) .foregroundColor(.gray.opacity(0.5)) } else { diff --git a/Schedule ICTIS/Main/Views/Fields/SubjectFieldView.swift b/Schedule ICTIS/Main/Views/Fields/SubjectFieldView.swift index c799acf..c5f30bf 100644 --- a/Schedule ICTIS/Main/Views/Fields/SubjectFieldView.swift +++ b/Schedule ICTIS/Main/Views/Fields/SubjectFieldView.swift @@ -19,7 +19,7 @@ struct SubjectFieldView: View { .padding(.leading, 12) .padding(.trailing, 9) TextField(labelForField, text: $text) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Meduim", size: 17)) .disableAutocorrection(true) .submitLabel(.done) .focused($isFocused) @@ -33,10 +33,10 @@ struct SubjectFieldView: View { Group { if isShowingSubjectFieldRed { Text("Поле должно быть заполнено!") - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Meduim", size: 17)) .foregroundColor(.red) .frame(width: 290) - .padding(.leading, -42) + .padding(.leading, -38) } } } diff --git a/Schedule ICTIS/Main/Views/FirstLaunchScheduleView.swift b/Schedule ICTIS/Main/Views/FirstLaunchScheduleView.swift index 92e3d77..6434146 100644 --- a/Schedule ICTIS/Main/Views/FirstLaunchScheduleView.swift +++ b/Schedule ICTIS/Main/Views/FirstLaunchScheduleView.swift @@ -2,7 +2,7 @@ // FirstLaunchScheduleView.swift // Schedule ICTIS // -// Created by G412 on 06.12.2024. +// Created by Mironov Egor on 06.12.2024. // import SwiftUI diff --git a/Schedule ICTIS/Main/Views/MainView.swift b/Schedule ICTIS/Main/Views/MainView.swift index 698c965..b54d6c0 100644 --- a/Schedule ICTIS/Main/Views/MainView.swift +++ b/Schedule ICTIS/Main/Views/MainView.swift @@ -24,27 +24,25 @@ struct MainView: View { } CurrentDateView() if vm.isLoading { - LoadingView(isLoading: $vm.isLoading) + LoadingScheduleView() } else { ScheduleView(vm: vm, isScrolling: $isScrolling) + .onTapGesture { + isFocusedSearchBar = false + } } } .alert(isPresented: $vm.isShowingAlertForIncorrectGroup, error: vm.errorInNetwork) { error in - + Button("ОК") { + print("This alert") + vm.isShowingAlertForIncorrectGroup = false + vm.errorInNetwork = nil + } } message: { error in Text(error.failureReason) } .background(Color("background")) - .onTapGesture { - isFocusedSearchBar = false - } - .onAppear { - vm.group = UserDefaults.standard.string(forKey: "group") ?? "notSeted" - if vm.group != "notSeted" { - - } - } } @ViewBuilder @@ -53,14 +51,14 @@ struct MainView: View { HStack { VStack (alignment: .leading, spacing: 0) { Text(vm.selectedDay.format("EEEE")) - .font(.custom("Montserrat-SemiBold", size: 40)) + .font(.custom("Montserrat-SemiBold", size: 30)) .foregroundStyle(.black) HStack (spacing: 5) { Text(vm.selectedDay.format("dd")) - .font(.custom("Montserrat-Bold", size: 20)) + .font(.custom("Montserrat-Bold", size: 17)) .foregroundStyle(Color("grayForDate")) Text(vm.selectedDay.format("MMMM")) - .font(.custom("Montserrat-Bold", size: 20)) + .font(.custom("Montserrat-Bold", size: 17)) .foregroundStyle(Color("grayForDate")) Spacer() Button(action: { @@ -70,7 +68,7 @@ struct MainView: View { }) { HStack(spacing: 2) { Text(isShowingMonthSlider ? "Свернуть" : "Развернуть") - .font(.custom("Montserrat-Light", size: 16)) + .font(.custom("Montserrat-Regular", size: 15)) .foregroundStyle(Color.blue) Image(isShowingMonthSlider ? "arrowup" : "arrowdown") .resizable() diff --git a/Schedule ICTIS/Main/Views/NoScheduleView.swift b/Schedule ICTIS/Main/Views/NoScheduleView.swift index 0a1e2aa..ded9e01 100644 --- a/Schedule ICTIS/Main/Views/NoScheduleView.swift +++ b/Schedule ICTIS/Main/Views/NoScheduleView.swift @@ -2,7 +2,7 @@ // NoScheduleView.swift // Schedule ICTIS // -// Created by G412 on 12.12.2024. +// Created by Mironov Egor on 12.12.2024. // import SwiftUI @@ -11,9 +11,9 @@ struct NoScheduleView: View { var body: some View { VStack { ScrollView (showsIndicators: false) { - Text("Пока расписания нет") - .padding(.top, 20) - .font(.custom("Montserrat-Regular", size: 15)) + Text("Пока что расписания нет😪") + .padding(.top, 100) + .font(.custom("Montserrat-SemiBold", size: 17)) } } } diff --git a/Schedule ICTIS/Main/Views/ScheduleView.swift b/Schedule ICTIS/Main/Views/ScheduleView.swift index 21e9d3e..c7917a1 100644 --- a/Schedule ICTIS/Main/Views/ScheduleView.swift +++ b/Schedule ICTIS/Main/Views/ScheduleView.swift @@ -17,7 +17,7 @@ struct ScheduleView: View { var provider = ClassProvider.shared var body: some View { if vm.isLoading { - LoadingView(isLoading: $vm.isLoading) + LoadingScheduleView() } else { if vm.errorInNetwork != .invalidResponse { @@ -33,12 +33,13 @@ struct ScheduleView: View { HStack(spacing: 10) { VStack { Text(convertTimeString(vm.classes[1][lessonIndex])[0]) - .font(.custom("Montserrat-Medium", size: 15)) + .font(.custom("Montserrat-Regular", size: 15)) .padding(.bottom, 1) Text(convertTimeString(vm.classes[1][lessonIndex])[1]) - .font(.custom("Montserrat-Medium", size: 15)) + .font(.custom("Montserrat-Regular", size: 15)) .padding(.top, 1) } + .frame(width: 48) .padding(.top, 7) .padding(.bottom, 7) .padding(.leading, 10) @@ -49,7 +50,7 @@ struct ScheduleView: View { .padding(.bottom, 7) .foregroundColor(getColorForClass(lesson)) Text(lesson) - .font(.custom("Montserrat-Regular", size: 17)) + .font(.custom("Montserrat-Medium", size: 15)) .lineSpacing(3) .padding(.top, 9) .padding(.bottom, 9) diff --git a/Schedule ICTIS/Main/Views/SearchBarView.swift b/Schedule ICTIS/Main/Views/SearchBarView.swift index 569d458..2c5f65d 100644 --- a/Schedule ICTIS/Main/Views/SearchBarView.swift +++ b/Schedule ICTIS/Main/Views/SearchBarView.swift @@ -28,8 +28,8 @@ struct SearchBarView: View { .onSubmit { self.isFocused = false if (!text.isEmpty) { + print(vm.errorInNetwork) vm.fetchWeekSchedule(group: text) - vm.group = text } self.text = "" } @@ -53,7 +53,7 @@ struct SearchBarView: View { RoundedRectangle(cornerRadius: 10) .fill(.white) ) - if (!vm.isFirstStartOffApp && !isFocused) { + if !isFocused { Button { isShowingSheet = true } label: { diff --git a/Schedule ICTIS/Main/Views/Sheets/CreateEditClassView.swift b/Schedule ICTIS/Main/Views/Sheets/CreateEditClassView.swift index 242f411..4f25b3f 100644 --- a/Schedule ICTIS/Main/Views/Sheets/CreateEditClassView.swift +++ b/Schedule ICTIS/Main/Views/Sheets/CreateEditClassView.swift @@ -76,11 +76,11 @@ struct CreateEditClassView: View { .padding(.trailing, 5) Text("Дата") .foregroundColor(Color("grayForFields").opacity(0.5)) - .font(.custom("Montserrat-Regular", size: 18)) + .font(.custom("Montserrat-Meduim", size: 17)) Spacer() Text("\(vm._class.day, formatter: dateFormatter)") .foregroundColor(.black) - .font(.custom("Montserrat-Medium", size: 18)) + .font(.custom("Montserrat-Medium", size: 17)) .padding(.trailing, 20) } .frame(height: 40) diff --git a/Schedule ICTIS/Main/Views/TabViews/MonthTabView.swift b/Schedule ICTIS/Main/Views/TabViews/MonthTabView.swift index 3b3c652..4340c7e 100644 --- a/Schedule ICTIS/Main/Views/TabViews/MonthTabView.swift +++ b/Schedule ICTIS/Main/Views/TabViews/MonthTabView.swift @@ -18,7 +18,7 @@ struct MonthTabView: View { HStack (spacing: 34) { ForEach(MockData.daysOfWeek.indices, id: \.self) { index in Text(MockData.daysOfWeek[index]) - .font(.custom("Montserrat-SemiBold", size: 15)) + .font(.custom("Montserrat-SemiBold", size: 14)) .foregroundColor(MockData.daysOfWeek[index] == "Вс" ? Color(.red) : Color("customGray2")) .padding(.top, 13) .foregroundColor(.gray) diff --git a/Schedule ICTIS/Main/Views/TabViews/WeekViewForMonth.swift b/Schedule ICTIS/Main/Views/TabViews/WeekViewForMonth.swift index a06c29b..a108b12 100644 --- a/Schedule ICTIS/Main/Views/TabViews/WeekViewForMonth.swift +++ b/Schedule ICTIS/Main/Views/TabViews/WeekViewForMonth.swift @@ -16,7 +16,7 @@ struct WeekViewForMonth: View { ForEach(week) { day in VStack { Text(day.date.format("dd")) - .font(.custom("Montserrat-Medium", size: 15)) + .font(.custom("Montserrat-SemiBold", size: 14)) .foregroundStyle(getForegroundColor(day: day)) } .frame(width: 30, height: 30, alignment: .center) diff --git a/Schedule ICTIS/Main/Views/TabViews/WeekViewForWeek.swift b/Schedule ICTIS/Main/Views/TabViews/WeekViewForWeek.swift index 49f6b54..d7b430b 100644 --- a/Schedule ICTIS/Main/Views/TabViews/WeekViewForWeek.swift +++ b/Schedule ICTIS/Main/Views/TabViews/WeekViewForWeek.swift @@ -18,12 +18,12 @@ struct WeekViewForWeek: View { ForEach(week) { day in VStack (spacing: 1) { Text(day.date.format("E")) - .font(.custom("Montserrat-Medium", size: 16)) + .font(.custom("Montserrat-SemiBold", size: 14)) .foregroundColor(day.date.format("E") == "Вс" ? Color(.red) : isSameDate(day.date, vm.selectedDay) ? Color("customGray1") : Color("customGray3")) .padding(.top, 13) .foregroundColor(.gray) Text(day.date.format("dd")) - .font(.custom("Montserrat-Medium", size: 15)) + .font(.custom("Montserrat-Semibold", size: 14)) .foregroundStyle(isSameDate(day.date, vm.selectedDay) ? .white : .black) .padding(.bottom, 13) } diff --git a/Schedule ICTIS/MockData.swift b/Schedule ICTIS/MockData.swift index 80f9783..e191786 100644 --- a/Schedule ICTIS/MockData.swift +++ b/Schedule ICTIS/MockData.swift @@ -2,7 +2,7 @@ // MockData.swift // Schedule ICTIS // -// Created by G412 on 06.12.2024. +// Created by Mironov Egor on 06.12.2024. // import Foundation @@ -19,4 +19,6 @@ struct MockData { static let themes = ["Светлая", "Темная", "Системная"] static let languages = ["Русский", "Английский", "Китайский", "Испанский"] + + static let groups = ["КТбо2-6", "КТбо1-9", "КТбо3-3", "ВУЦ", "КТао1-1", "КТсо2-2"] } diff --git a/Schedule ICTIS/Model/GroupsModel.swift b/Schedule ICTIS/Model/GroupsModel.swift new file mode 100644 index 0000000..afc0a94 --- /dev/null +++ b/Schedule ICTIS/Model/GroupsModel.swift @@ -0,0 +1,20 @@ +// +// SubjectsModel.swift +// Schedule ICTIS +// +// Created by Mironov Egor on 19.02.2025. +// + +import Foundation + +// MARK: - Welcome +struct Welcome: Decodable { + let choices: [Choice] +} + +// MARK: - Choice +struct Choice: Decodable, Identifiable { + let name: String + let id: String + let group: String +} diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/Contents.json b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/Contents.json index 4ce8416..cfd47c3 100644 --- a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/Contents.json +++ b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "arrow.png", + "filename" : "arrowdown.svg", "idiom" : "universal", "scale" : "1x" }, diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrow.png b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrow.png deleted file mode 100644 index 68f840b..0000000 Binary files a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrow.png and /dev/null differ diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrowdown.svg b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrowdown.svg new file mode 100644 index 0000000..702229d --- /dev/null +++ b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowdown.imageset/arrowdown.svg @@ -0,0 +1,3 @@ + + + diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Contents.json b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Contents.json index 446d6be..c50124f 100644 --- a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Contents.json +++ b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Vector.png", + "filename" : "arrowup.svg", "idiom" : "universal", "scale" : "1x" }, diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Vector.png b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Vector.png deleted file mode 100644 index 4d0fca6..0000000 Binary files a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/Vector.png and /dev/null differ diff --git a/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/arrowup.svg b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/arrowup.svg new file mode 100644 index 0000000..4c077ab --- /dev/null +++ b/Schedule ICTIS/Preview Content/Assets.xcassets/arrowup.imageset/arrowup.svg @@ -0,0 +1,3 @@ + + + diff --git a/Schedule ICTIS/Settings/SelectingGroupView.swift b/Schedule ICTIS/Settings/SelectingGroupView.swift index ad4923b..f735572 100644 --- a/Schedule ICTIS/Settings/SelectingGroupView.swift +++ b/Schedule ICTIS/Settings/SelectingGroupView.swift @@ -2,7 +2,7 @@ // SelectedGroupView.swift // Schedule ICTIS // -// Created by G412 on 30.01.2025. +// Created by Mironov Egor on 30.01.2025. // import SwiftUI @@ -11,7 +11,9 @@ struct SelectingGroupView: View { @Environment(\.dismiss) private var dismiss @FocusState private var isFocused: Bool @State private var text: String = "" - @Binding var group: String + @ObservedObject var vm: ScheduleViewModel + @State private var isLoading = false + @State private var searchTask: DispatchWorkItem? var body: some View { NavigationView { VStack { @@ -23,14 +25,37 @@ struct SelectingGroupView: View { TextField("Поиск группы", text: $text) .disableAutocorrection(true) .focused($isFocused) + .onChange(of: text) { oldValue, newValue in + searchTask?.cancel() + let task = DispatchWorkItem { + if !text.isEmpty { + vm.fetchGroups(group: text) + } + } + searchTask = task + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: task) + } .onSubmit { self.isFocused = false if (!text.isEmpty) { - UserDefaults.standard.set(text, forKey: "group") - group = text + vm.fetchWeekSchedule(group: text) + self.isLoading = true + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.isLoading = false + if vm.errorInNetwork == .noError { + vm.errorInNetwork = nil + print("Зашел") + UserDefaults.standard.set(text, forKey: "group") + vm.group = text + self.text = "" + dismiss() + } + else { + vm.isShowingAlertForIncorrectGroup = true + vm.errorInNetwork = .invalidResponse + } + } } - self.text = "" - dismiss() } .submitLabel(.done) if isFocused { @@ -52,17 +77,45 @@ struct SelectingGroupView: View { RoundedRectangle(cornerRadius: 15) .fill(.white) ) - .padding(.horizontal, 10) Spacer() + if isLoading { + LoadingView(isLoading: $isLoading) + } + if isFocused { + ScrollView(.vertical, showsIndicators: true) { + ForEach(vm.groups) { item in + 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) + .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(.horizontal, 10) .background(Color("background")) - .onTapGesture { - self.isFocused = false - } + } + .onAppear { + vm.fetchGroups(group: "кт") } } } - -#Preview { - SelectingGroupView(group: .constant("КТбо2-6")) -} diff --git a/Schedule ICTIS/Settings/SelectingVPKView.swift b/Schedule ICTIS/Settings/SelectingVPKView.swift index fe40657..8b988ca 100644 --- a/Schedule ICTIS/Settings/SelectingVPKView.swift +++ b/Schedule ICTIS/Settings/SelectingVPKView.swift @@ -2,14 +2,18 @@ // SelectedVPKView.swift // Schedule ICTIS // -// Created by G412 on 30.01.2025. +// Created by Mironov Egor on 30.01.2025. // import SwiftUI struct SelectingVPKView: View { + @Environment(\.dismiss) private var dismiss @FocusState private var isFocused: Bool @State private var text: String = "" + @ObservedObject var vm: ScheduleViewModel + @State private var isLoading = false + @State private var searchTask: DispatchWorkItem? var body: some View { NavigationView { VStack { @@ -21,12 +25,37 @@ struct SelectingVPKView: View { TextField("Поиск ВПК", text: $text) .disableAutocorrection(true) .focused($isFocused) + .onChange(of: text) { oldValue, newValue in + searchTask?.cancel() + let task = DispatchWorkItem { + if !text.isEmpty { + vm.fetchGroups(group: text) + } + } + searchTask = task + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: task) + } .onSubmit { self.isFocused = false if (!text.isEmpty) { - UserDefaults.standard.set(text, forKey: "group") + vm.fetchWeekSchedule(group: text) + self.isLoading = true + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.isLoading = false + if vm.errorInNetwork == .noError { + vm.errorInNetwork = nil + print("Зашел") + UserDefaults.standard.set(text, forKey: "vpk") + vm.group = text + self.text = "" + dismiss() + } + else { + vm.isShowingAlertForIncorrectGroup = true + vm.errorInNetwork = .invalidResponse + } + } } - self.text = "" } .submitLabel(.done) if isFocused { @@ -48,17 +77,45 @@ struct SelectingVPKView: View { RoundedRectangle(cornerRadius: 15) .fill(.white) ) - .padding(.horizontal, 10) Spacer() + if isLoading { + LoadingView(isLoading: $isLoading) + } + if isFocused { + ScrollView(.vertical, showsIndicators: true) { + ForEach(vm.groups) { item in + 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) + .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(.horizontal, 10) .background(Color("background")) - .onTapGesture { - self.isFocused = false - } + } + .onAppear { + vm.fetchGroups(group: "впк") } } } - -#Preview { - SelectingVPKView() -} diff --git a/Schedule ICTIS/Settings/SettingsView.swift b/Schedule ICTIS/Settings/SettingsView.swift index 4d6f60f..8d1e1f8 100644 --- a/Schedule ICTIS/Settings/SettingsView.swift +++ b/Schedule ICTIS/Settings/SettingsView.swift @@ -2,7 +2,7 @@ // SettingsView.swift // Schedule ICTIS // -// Created by G412 on 30.01.2025. +// Created by Mironov Egor on 30.01.2025. // import SwiftUI @@ -11,6 +11,8 @@ struct SettingsView: View { @ObservedObject var vm: ScheduleViewModel @State private var selectedTheme = "Светлая" @State private var selectedLanguage = "Русский" + @AppStorage("group") private var favGroup = "" + @AppStorage("vpk") private var favVPK = "" var body: some View { NavigationView { VStack { @@ -28,17 +30,18 @@ struct SettingsView: View { }) } Section("Расписание") { - NavigationLink(destination: SelectingGroupView(group: $vm.group)) { + NavigationLink(destination: SelectingGroupView(vm: vm)) { LabeledContent { - Text(vm.group) + Text(favGroup) } label: { Text("Избранное расписание") } } - NavigationLink(destination: SelectingVPKView()) { + NavigationLink(destination: SelectingVPKView(vm: vm)) { LabeledContent { + Text(favVPK) } label: { - Text("ВПК") + Text("Избранное ВПК") } } } diff --git a/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift b/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift index a1540d5..f934041 100644 --- a/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift +++ b/Schedule ICTIS/Utilities/Extensions/View+Extensions.swift @@ -185,9 +185,11 @@ extension WeekViewForWeek { let calendar = Calendar.current if weekSlider.indices.contains(currentWeekIndex) { if let firstDate = weekSlider[currentWeekIndex].first?.date, - currentWeekIndex == 0 { + currentWeekIndex == 0 { vm.week -= 1 - vm.fetchWeekSchedule(isOtherWeek: true) + if vm.group != "" { + vm.fetchWeekSchedule(isOtherWeek: true) + } weekSlider.insert(firstDate.createPrevioustWeek(), at: 0) weekSlider.removeLast() currentWeekIndex = 1 @@ -196,9 +198,11 @@ extension WeekViewForWeek { } if let lastDate = weekSlider[currentWeekIndex].last?.date, - currentWeekIndex == (weekSlider.count - 1) { + currentWeekIndex == (weekSlider.count - 1) { vm.week += 1 - vm.fetchWeekSchedule(isOtherWeek: true) + if vm.group != "" { + vm.fetchWeekSchedule(isOtherWeek: true) + } weekSlider.append(lastDate.createNextWeek()) weekSlider.removeFirst() currentWeekIndex = weekSlider.count - 2 @@ -242,8 +246,10 @@ extension WeekViewForMonth { } print(difBetweenWeeks) vm.week += difBetweenWeeks - vm.fetchWeekSchedule(isOtherWeek: true) + if vm.group != "" { + vm.fetchWeekSchedule(isOtherWeek: true) } + } vm.selectedDay = day.date vm.updateSelectedDayIndex() } @@ -271,25 +277,29 @@ extension MonthTabView { let calendar = Calendar.current if monthSlider.indices.contains(currentMonthIndex) { if let firstDate = monthSlider[currentMonthIndex].first?.week[0].date, - currentMonthIndex == 0 { + currentMonthIndex == 0 { monthSlider.insert(firstDate.createPreviousMonth(), at: 0) monthSlider.removeLast() currentMonthIndex = 1 vm.selectedDay = calendar.date(byAdding: .weekOfYear, value: -5, to: vm.selectedDay) ?? Date.init() vm.updateSelectedDayIndex() vm.week -= 5 - vm.fetchWeekSchedule(isOtherWeek: true) + if vm.group != "" { + vm.fetchWeekSchedule(isOtherWeek: true) + } } if let lastDate = monthSlider[currentMonthIndex].last?.week[6].date, - currentMonthIndex == (monthSlider.count - 1) { + currentMonthIndex == (monthSlider.count - 1) { monthSlider.append(lastDate.createNextMonth()) monthSlider.removeFirst() currentMonthIndex = monthSlider.count - 2 vm.selectedDay = calendar.date(byAdding: .weekOfYear, value: 5, to: vm.selectedDay) ?? Date.init() vm.updateSelectedDayIndex() vm.week += 5 - vm.fetchWeekSchedule(isOtherWeek: true) + if vm.group != "" { + vm.fetchWeekSchedule(isOtherWeek: true) + } } } } diff --git a/Schedule ICTIS/Utilities/Network/NetworkManager.swift b/Schedule ICTIS/Utilities/Network/NetworkManager.swift index 9d613f9..cdb69c1 100644 --- a/Schedule ICTIS/Utilities/Network/NetworkManager.swift +++ b/Schedule ICTIS/Utilities/Network/NetworkManager.swift @@ -31,9 +31,9 @@ final class NetworkManager { func getSchedule(_ group: String) async throws -> Schedule { let newUrlForGroup = makeUrlForGroup(group) - guard let url = URL(string: newUrlForGroup) else {throw NetworkError.invalidUrl} + guard let url = URL(string: newUrlForGroup) else { throw NetworkError.invalidUrl } let (data, response) = try await URLSession.shared.data(from: url) - guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {throw NetworkError.invalidResponse} + guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { throw NetworkError.invalidResponse } do { return try decoder.decode(Schedule.self, from: data) @@ -46,9 +46,9 @@ final class NetworkManager { func getScheduleForOtherWeek(_ numOfWeek: Int, _ htmlNameOfGroup: String) async throws -> Schedule { let newUrlForWeek = makeUrlForWeek(numOfWeek, htmlNameOfGroup) print(newUrlForWeek) - guard let url = URL(string: newUrlForWeek) else {throw NetworkError.invalidUrl} + guard let url = URL(string: newUrlForWeek) else { throw NetworkError.invalidUrl } let (data, response) = try await URLSession.shared.data(from: url) - guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {throw NetworkError.invalidResponse} + guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { throw NetworkError.invalidResponse } do { return try decoder.decode(Schedule.self, from: data) @@ -57,4 +57,18 @@ final class NetworkManager { throw NetworkError.invalidData } } + + func getGroups(group: String) async throws -> Welcome { + let newUrlForGroups = makeUrlForGroup(group) + guard let url = URL(string: newUrlForGroups) else { throw NetworkError.invalidUrl } + let (data, response) = try await URLSession.shared.data(from: url) + guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { throw NetworkError.invalidResponse } + + do { + return try decoder.decode(Welcome.self, from: data) + } + catch { + throw NetworkError.invalidData + } + } } diff --git a/Schedule ICTIS/ViewModel/ScheduleViewModel.swift b/Schedule ICTIS/ViewModel/ScheduleViewModel.swift index f9442ca..6883319 100644 --- a/Schedule ICTIS/ViewModel/ScheduleViewModel.swift +++ b/Schedule ICTIS/ViewModel/ScheduleViewModel.swift @@ -10,6 +10,7 @@ import Foundation @MainActor final class ScheduleViewModel: ObservableObject { //MARK: Properties + //Schedule @Published var weekSchedule: Table = Table( type: "", name: "", @@ -30,6 +31,12 @@ final class ScheduleViewModel: ObservableObject { @Published var group: String = "" @Published var isNewGroup: Bool = false + //Groups + @Published var groups: [Choice] = [] + //VPK + @Published var vpk: [[String]] = [] + + //MARK: Methods func fetchWeekSchedule(group: String = "default", isOtherWeek: Bool = false) { isLoading = true @@ -42,10 +49,11 @@ final class ScheduleViewModel: ObservableObject { } // В else мы заходим в том случае, если не знаем номер недели, которую нужно отобразить и номер группы(в html формате) else { + print("Отладка 1") schedule = try await NetworkManager.shared.getSchedule(group) - if (!self.isFirstStartOffApp) { - self.isNewGroup = true - } + print("Отладка 2") + self.group = group + self.isNewGroup = true self.selectedDay = .init() } self.weekSchedule = schedule.table @@ -56,7 +64,7 @@ final class ScheduleViewModel: ObservableObject { self.isShowingAlertForIncorrectGroup = false self.isLoading = false self.errorInNetwork = .noError - + print("Отладка 4") } catch { if let error = error as? NetworkError { @@ -67,10 +75,33 @@ final class ScheduleViewModel: ObservableObject { errorInNetwork = .invalidData self.isShowingAlertForIncorrectGroup = true default: - print(2) + print("Неизвестная ошибка: \(error)") } isLoading = false - print(error) + print("Есть ошибка: \(error)") + } + } + } + } + + func fetchGroups(group: String) { + Task { + do { + var groups: Welcome + groups = try await NetworkManager.shared.getGroups(group: group) + self.groups = groups.choices + + } + catch { + if let error = error as? NetworkError { + switch (error) { + case .invalidData: + self.groups.removeAll() + default: + self.groups.removeAll() + print("Неизвестная ошибка: \(error)") + } + print("Есть ошибка: \(error)") } } }