From e7510aef68d5c74ea094f075b6c8b36eec3dfb80 Mon Sep 17 00:00:00 2001 From: Vladimir Dubovik Date: Fri, 6 Dec 2024 18:25:17 +0300 Subject: [PATCH] LotsOfChanges --- .../blueForOnline.colorset/Contents.json | 38 +++++++++++++++++++ .../greenForOffline.colorset/Contents.json | 38 +++++++++++++++++++ Schedule ICTIS/ContentView.swift | 3 +- .../Main/FirstLaunchScheduleView.swift | 28 ++++++++++++++ Schedule ICTIS/Main/MainView.swift | 30 ++++++++++----- Schedule ICTIS/Main/ScheduleView.swift | 37 ++++++++++++++---- Schedule ICTIS/Main/SearchBarView.swift | 3 +- Schedule ICTIS/MockData.swift | 21 ++++++++++ Schedule ICTIS/Network/NetworkManager.swift | 28 ++++++++++---- Schedule ICTIS/ViewModel/ViewModel.swift | 26 ++++++++----- 10 files changed, 217 insertions(+), 35 deletions(-) create mode 100644 Schedule ICTIS/Assets.xcassets/blueForOnline.colorset/Contents.json create mode 100644 Schedule ICTIS/Assets.xcassets/greenForOffline.colorset/Contents.json create mode 100644 Schedule ICTIS/Main/FirstLaunchScheduleView.swift create mode 100644 Schedule ICTIS/MockData.swift diff --git a/Schedule ICTIS/Assets.xcassets/blueForOnline.colorset/Contents.json b/Schedule ICTIS/Assets.xcassets/blueForOnline.colorset/Contents.json new file mode 100644 index 0000000..213c5b9 --- /dev/null +++ b/Schedule ICTIS/Assets.xcassets/blueForOnline.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0x7A", + "red" : "0x00" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Schedule ICTIS/Assets.xcassets/greenForOffline.colorset/Contents.json b/Schedule ICTIS/Assets.xcassets/greenForOffline.colorset/Contents.json new file mode 100644 index 0000000..7aba1dd --- /dev/null +++ b/Schedule ICTIS/Assets.xcassets/greenForOffline.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x0A", + "green" : "0x97", + "red" : "0x00" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Schedule ICTIS/ContentView.swift b/Schedule ICTIS/ContentView.swift index eb11f8b..dd68dca 100644 --- a/Schedule ICTIS/ContentView.swift +++ b/Schedule ICTIS/ContentView.swift @@ -9,11 +9,12 @@ import SwiftUI struct ContentView: View { @State private var selectedTab: TabBarModel = .schedule + @StateObject var vm = ViewModel() var body: some View { ZStack { switch selectedTab { case .schedule: - MainView() + MainView(vm: vm) case .tasks: Text("Tasks") case .settings: diff --git a/Schedule ICTIS/Main/FirstLaunchScheduleView.swift b/Schedule ICTIS/Main/FirstLaunchScheduleView.swift new file mode 100644 index 0000000..b3d591c --- /dev/null +++ b/Schedule ICTIS/Main/FirstLaunchScheduleView.swift @@ -0,0 +1,28 @@ +// +// FirstLaunchScheduleView.swift +// Schedule ICTIS +// +// Created by G412 on 06.12.2024. +// + +import SwiftUI + +struct FirstLaunchScheduleView: View { + var body: some View { + VStack (alignment: .center) { + Spacer() + HStack { + Image(systemName: "pencil") + .font(.title) + Text("Введите свою группу") + .font(.system(size: 20, weight: .bold, design: .default)) + } + .foregroundColor(Color("blueColor")) + Spacer() + } + } +} + +#Preview { + FirstLaunchScheduleView() +} diff --git a/Schedule ICTIS/Main/MainView.swift b/Schedule ICTIS/Main/MainView.swift index 8fdcca6..5586f95 100644 --- a/Schedule ICTIS/Main/MainView.swift +++ b/Schedule ICTIS/Main/MainView.swift @@ -9,40 +9,47 @@ import SwiftUI struct MainView: View { @State private var searchText: String = "" - @State private var currentDate: Date = .init() + @State private var currentDate: Date = Date() @State private var weekSlider: [[Date.WeekDay]] = [] @State private var currentWeekIndex: Int = 1 @State private var createWeek: Bool = false @State private var isShowingMonthSlider: Bool = false - @StateObject var vm = ViewModel() + @State private var isFirstAppearence = true + @ObservedObject var vm: ViewModel var body: some View { VStack { SearchBarView(text: $searchText, vm: vm) - HeaderView() - ScheduleView(vm: vm) + CurrentDateView() + if (vm.isFirstStartOffApp) { + FirstLaunchScheduleView() + } + else { + ScheduleView(vm: vm) + } } .background(Color("background")) .onAppear(perform: { + currentDate = vm.selectedDay + vm.updateSelectedDayIndex(currentDate) if weekSlider.isEmpty { let currentWeek = Date().fetchWeek() - + if let firstDate = currentWeek.first?.date { weekSlider.append(firstDate.createPrevioustWeek()) } - + weekSlider.append(currentWeek) - + if let lastDate = currentWeek.last?.date { weekSlider.append(lastDate.createNextWeek()) } } - vm.updateSelectedDayIndex(currentDate) }) } @ViewBuilder - func HeaderView() -> some View { + func CurrentDateView() -> some View { VStack (alignment: .leading, spacing: 6) { HStack { VStack (alignment: .leading, spacing: 0) { @@ -147,6 +154,7 @@ struct MainView: View { .onPreferenceChange(OffsetKey.self) { value in if value.rounded() == 15 && createWeek { paginateWeek() + createWeek = false } } @@ -158,6 +166,7 @@ struct MainView: View { if weekSlider.indices.contains(currentWeekIndex) { if let firstDate = weekSlider[currentWeekIndex].first?.date, currentWeekIndex == 0 { + vm.fetchWeekSchedule("new week", -1) weekSlider.insert(firstDate.createPrevioustWeek(), at: 0) weekSlider.removeLast() currentWeekIndex = 1 @@ -165,6 +174,7 @@ struct MainView: View { if let lastDate = weekSlider[currentWeekIndex].last?.date, currentWeekIndex == (weekSlider.count - 1) { + vm.fetchWeekSchedule("new week", 1) weekSlider.append(lastDate.createNextWeek()) weekSlider.removeFirst() currentWeekIndex = weekSlider.count - 2 @@ -174,5 +184,5 @@ struct MainView: View { } #Preview { - MainView() + ContentView() } diff --git a/Schedule ICTIS/Main/ScheduleView.swift b/Schedule ICTIS/Main/ScheduleView.swift index 27d5149..6c7a803 100644 --- a/Schedule ICTIS/Main/ScheduleView.swift +++ b/Schedule ICTIS/Main/ScheduleView.swift @@ -11,34 +11,48 @@ struct ScheduleView: View { @ObservedObject var vm: ViewModel var body: some View { ScrollView(.vertical, showsIndicators: false) { - VStack (spacing: 12) { + 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: 6) { + HStack(spacing: 10) { VStack { Text(convertTimeString(vm.classes[1][lessonIndex])[0]) - .font(.system(size: 15, weight: .light)) + .font(.system(size: 15, weight: .regular)) Text(convertTimeString(vm.classes[1][lessonIndex])[1]) - .font(.system(size: 15, weight: .light)) + .font(.system(size: 15, weight: .regular)) } + .padding(.top, 7) + .padding(.bottom, 7) + .padding(.leading, 10) Rectangle() .frame(width: 2) - .frame(maxHeight: 100) + .frame(maxHeight: UIScreen.main.bounds.height - 18) + .padding(.top, 7) + .padding(.bottom, 7) + .foregroundColor(onlineOrOffline(lesson) ? Color("greenForOffline") : Color("blueForOnline")) Text(lesson) + .font(.system(size: 18, weight: .regular)) + .padding(.top, 7) + .padding(.bottom, 7) + Spacer() } + .frame(maxWidth: UIScreen.main.bounds.width - 40, maxHeight: 230) .background(Color.white) - .padding(.horizontal) + .cornerRadius(20) } } } } } + .padding(.bottom, 100) + .padding(.top, 10) } } + //ктбо2-6 func convertTimeString(_ input: String) -> [String] { let parts = input.split(separator: "-") @@ -48,8 +62,17 @@ struct ScheduleView: View { return [] } } + + func onlineOrOffline(_ str: String) -> Bool { + if (MockData.onlineClasses.contains(str)) { + return false + } + else { + return true + } + } } #Preview { - MainView() + ContentView() } diff --git a/Schedule ICTIS/Main/SearchBarView.swift b/Schedule ICTIS/Main/SearchBarView.swift index 5c289ce..6bc6815 100644 --- a/Schedule ICTIS/Main/SearchBarView.swift +++ b/Schedule ICTIS/Main/SearchBarView.swift @@ -27,6 +27,7 @@ struct SearchBarView: View { .onSubmit { isEditing = false if (!text.isEmpty) { + vm.isFirstStartOffApp = false vm.fetchWeekSchedule(text) } } @@ -76,5 +77,5 @@ struct SearchBarView: View { } #Preview { - MainView() + ContentView() } diff --git a/Schedule ICTIS/MockData.swift b/Schedule ICTIS/MockData.swift new file mode 100644 index 0000000..76785cd --- /dev/null +++ b/Schedule ICTIS/MockData.swift @@ -0,0 +1,21 @@ +// +// MockData.swift +// Schedule ICTIS +// +// Created by G412 on 06.12.2024. +// + +import Foundation + + +struct MockData { + static let onlineClasses: [String] = [ + "пр.Академический курс иностранного языка Янкаускас Е. С. LMS", + "пр.Академический курс иностранного языка Янкаускас Е. С. LMS-3", + "пр.Введение в инженерную деятельность 1 п/г Михайлова В. Д. LMS 2 п/г Романенко К. С. 3 п/г Козловский А. В. 4 п/г Компаниец В. С. 5 п/г Олейников К. А. 6 п/г Прудников В. А. 7 п/г Петров Д. А. 8 п/г Григорян К. С.", + "пр.Иностранный язык Иностранный язык LMS", + "лек.Операционные системы 1 п/г Шкурко А. Н. Г-309 АКТРУ 2 п/г Дроздов С. Н. Г-333 3 п/г Нужнов Е. В. Г-301 Operating systems(Операционные системы) 4 п/г Самойлов А. Н. LMS", + "пр.Введение в инженерную деятельность 1 п/г Плёнкин А. П. LMS-1 2 п/г Кучеров С. А. 3 п/г Шкурко А. Н. 4 п/г Механцев Б. Е.", + "лек.Операционные системы 1 п/г Шкурко А. Н. Г-309 АКТРУ 2 п/г Дроздов С. Н. Г-333 3 п/г Нужнов Е. В. Г-301 Operating systems(Операционные системы) 4 п/г Самойлов А. Н. LMS" + ] +} diff --git a/Schedule ICTIS/Network/NetworkManager.swift b/Schedule ICTIS/Network/NetworkManager.swift index 1609ab3..93e8353 100644 --- a/Schedule ICTIS/Network/NetworkManager.swift +++ b/Schedule ICTIS/Network/NetworkManager.swift @@ -8,15 +8,12 @@ import Foundation final class NetworkManager { - + //"https://webictis.sfedu.ru/schedule-api/?group=51.html&week=15" //MARK: Properties static let shared = NetworkManager() private let decoder = JSONDecoder() private let urlForGroup = "https://webictis.sfedu.ru/schedule-api/?query=" - private let urlForWeek = "https://webictis.sfedu.ru/schedule-api/?group=51.html&week=15" - private var groupString: String = "" - private var numOfGroup: String = "" - private var numOfWeek: String = "" + private let urlForWeek = "https://webictis.sfedu.ru/schedule-api/?group=" //MARK: Initializer private init() { @@ -24,16 +21,33 @@ final class NetworkManager { } //MARK: Methods - func makeURL(_ group: String) -> String { + func makeUrlForGroup(_ group: String) -> String { return urlForGroup + group } + func makeUrlForWeek(_ numOfWeek: Int, _ htmlNameOfGroup: String) -> String { + return urlForWeek + htmlNameOfGroup + "&" + String(numOfWeek) + } + func getSchedule(_ group: String) async throws -> Schedule { - let newUrlForGroup = makeURL(group) + let newUrlForGroup = makeUrlForGroup(group) 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} + do { + return try decoder.decode(Schedule.self, from: data) + } + catch { + throw NetworkError.invalidData + } + } + func getScheduleForOtherWeek(_ numOfWeek: Int, _ htmlNameOfGroup: String) async throws -> Schedule { + let newUrlForWeek = makeUrlForWeek(numOfWeek, htmlNameOfGroup) + 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} + do { return try decoder.decode(Schedule.self, from: data) } diff --git a/Schedule ICTIS/ViewModel/ViewModel.swift b/Schedule ICTIS/ViewModel/ViewModel.swift index ce54557..0366ce2 100644 --- a/Schedule ICTIS/ViewModel/ViewModel.swift +++ b/Schedule ICTIS/ViewModel/ViewModel.swift @@ -18,23 +18,30 @@ final class ViewModel: ObservableObject { table: [[]], link: "" ) - @Published var selectedDay: Date = Date() + @Published var selectedDay: Date = .init() @Published var selectedIndex: Int = 1 @Published var classes: [[String]] = [] - - init() { - - } - + @Published var week: Int = 0 + @Published var numOfGroup: String = "" + @Published var isFirstStartOffApp = true //MARK: Methods - func fetchWeekSchedule(_ group: String) { + func fetchWeekSchedule(_ group: String = "new week", _ num: Int = 0) { Task { do { - let schedule = try await NetworkManager.shared.getSchedule(group) + let schedule: Schedule + if (group == "new week") { + schedule = try await NetworkManager.shared.getScheduleForOtherWeek(week + num, numOfGroup) + } + else{ + schedule = try await NetworkManager.shared.getSchedule(group) + } weekSchedule = schedule.table + week = weekSchedule.week + numOfGroup = weekSchedule.group + print(week) + print(numOfGroup) classes = weekSchedule.table - print(weekSchedule.week) } catch { if let error = error as? NetworkError { @@ -45,6 +52,7 @@ final class ViewModel: ObservableObject { } func updateSelectedDayIndex(_ date: Date) { + selectedDay = date switch date.format("E") { case "Пн": selectedIndex = 2