ViewModel was changed and searchbar is working now. You can text your group and find your schedule
This commit is contained in:
parent
ddceec8551
commit
0f8dcea0a6
@ -13,7 +13,7 @@ struct ContentView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
switch selectedTab {
|
switch selectedTab {
|
||||||
case .schedule:
|
case .schedule:
|
||||||
ScheduleView()
|
MainView()
|
||||||
case .tasks:
|
case .tasks:
|
||||||
Text("Tasks")
|
Text("Tasks")
|
||||||
case .settings:
|
case .settings:
|
||||||
|
@ -37,6 +37,7 @@ extension Date {
|
|||||||
let startOfDate = calendar.startOfDay(for: date)
|
let startOfDate = calendar.startOfDay(for: date)
|
||||||
|
|
||||||
var week: [WeekDay] = []
|
var week: [WeekDay] = []
|
||||||
|
// Создаем дату начала и конца недели
|
||||||
let weekForDate = calendar.dateInterval(of: .weekOfMonth, for: startOfDate)
|
let weekForDate = calendar.dateInterval(of: .weekOfMonth, for: startOfDate)
|
||||||
//print("Start: \(weekForDate?.start)")
|
//print("Start: \(weekForDate?.start)")
|
||||||
//print("End: \(weekForDate?.end)")
|
//print("End: \(weekForDate?.end)")
|
||||||
@ -45,7 +46,7 @@ extension Date {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем дни для недели
|
// Создаем массив дней для недели
|
||||||
(0..<7).forEach { index in
|
(0..<7).forEach { index in
|
||||||
if let weekDay = calendar.date(byAdding: .day, value: index, to: startOfWeek) {
|
if let weekDay = calendar.date(byAdding: .day, value: index, to: startOfWeek) {
|
||||||
week.append(WeekDay(date: weekDay))
|
week.append(WeekDay(date: weekDay))
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ScheduleView: View {
|
struct MainView: View {
|
||||||
@State private var searchText: String = ""
|
@State private var searchText: String = ""
|
||||||
@State private var currentDate: Date = .init()
|
@State private var currentDate: Date = .init()
|
||||||
@State private var weekSlider: [[Date.WeekDay]] = []
|
@State private var weekSlider: [[Date.WeekDay]] = []
|
||||||
@ -18,61 +18,9 @@ struct ScheduleView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
SearchBarView(text: $searchText)
|
SearchBarView(text: $searchText, vm: vm)
|
||||||
HeaderView()
|
HeaderView()
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScheduleView(vm: vm)
|
||||||
VStack (spacing: 12) {
|
|
||||||
ForEach(vm.weekSchedule, id: \.week) { element in
|
|
||||||
let selectedDayIndex = vm.selectedIndex
|
|
||||||
if selectedDayIndex < 8 {
|
|
||||||
let schedule = element.table[selectedDayIndex]
|
|
||||||
ForEach(schedule.indices.dropFirst(), id: \.self) { index in
|
|
||||||
let lesson = schedule[index]
|
|
||||||
let firstThreeCharacters = lesson.prefix(3)
|
|
||||||
let checkEnglish = lesson.prefix(6)
|
|
||||||
if !lesson.isEmpty && index != 0 {
|
|
||||||
GeometryReader { geometry in
|
|
||||||
HStack (spacing: 8) {
|
|
||||||
VStack (alignment: .center) {
|
|
||||||
Text(convertTimeString(element.table[1][index])[0])
|
|
||||||
.font(.system(size: 15, weight: .light))
|
|
||||||
Text(convertTimeString(element.table[1][index])[1])
|
|
||||||
.font(.system(size: 15, weight: .light))
|
|
||||||
}
|
|
||||||
.padding(.top, 4)
|
|
||||||
.padding(.bottom, 4)
|
|
||||||
.padding(.leading, 8)
|
|
||||||
Rectangle()
|
|
||||||
.frame(maxHeight: geometry.size.height - 10)
|
|
||||||
.frame(width: 3)
|
|
||||||
.cornerRadius(20)
|
|
||||||
.padding(.top, 4)
|
|
||||||
.padding(.bottom, 4)
|
|
||||||
.foregroundColor(checkEnglish == "пр.Ино" || firstThreeCharacters == "лек" ? Color.blue : Color.green)
|
|
||||||
Text(lesson)
|
|
||||||
.font(.system(size: 16, weight: .regular))
|
|
||||||
.padding(.trailing, 8)
|
|
||||||
.frame(maxWidth: 280, alignment: .leading) // Выравнивание текста по левому краю
|
|
||||||
.padding(.top, 4)
|
|
||||||
.padding(.bottom, 4)
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
}
|
|
||||||
.background(Color.white)
|
|
||||||
.cornerRadius(20)
|
|
||||||
.padding(.horizontal, 10)
|
|
||||||
.frame(maxWidth: 420, maxHeight: 130)
|
|
||||||
.shadow(color: Color.black.opacity(0.1), radius: 2, x: 4, y: 4)
|
|
||||||
}
|
|
||||||
.frame(height: 70)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Text("Сегодня нет пар")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.background(Color("background"))
|
.background(Color("background"))
|
||||||
.onAppear(perform: {
|
.onAppear(perform: {
|
||||||
@ -121,10 +69,9 @@ struct ScheduleView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, 8)
|
.padding(.top, 8)
|
||||||
.padding(.leading, 20)
|
.padding(.leading, 5)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
|
|
||||||
TabView(selection: $currentWeekIndex) {
|
TabView(selection: $currentWeekIndex) {
|
||||||
ForEach(weekSlider.indices, id: \.self) { index in
|
ForEach(weekSlider.indices, id: \.self) { index in
|
||||||
@ -142,8 +89,8 @@ struct ScheduleView: View {
|
|||||||
if newValue == 0 || newValue == (weekSlider.count - 1) {
|
if newValue == 0 || newValue == (weekSlider.count - 1) {
|
||||||
createWeek = true
|
createWeek = true
|
||||||
}
|
}
|
||||||
vm.updateSelectedIndex(newValue)
|
|
||||||
}
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
@ -170,7 +117,7 @@ struct ScheduleView: View {
|
|||||||
else {
|
else {
|
||||||
Color(.white)
|
Color(.white)
|
||||||
}
|
}
|
||||||
if day.date.isToday && isSameDate(day.date, currentDate) {
|
if isSameDate(day.date, currentDate) {
|
||||||
Color("blueColor")
|
Color("blueColor")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,17 +171,8 @@ struct ScheduleView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertTimeString(_ input: String) -> [String] {
|
|
||||||
let parts = input.split(separator: "-")
|
|
||||||
if let firstPart = parts.first, let lastPart = parts.last {
|
|
||||||
return [String(firstPart), String(lastPart)]
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
ScheduleView()
|
MainView()
|
||||||
}
|
}
|
55
Schedule ICTIS/Main/ScheduleView.swift
Normal file
55
Schedule ICTIS/Main/ScheduleView.swift
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// ScheduleView.swift
|
||||||
|
// Schedule ICTIS
|
||||||
|
//
|
||||||
|
// Created by G412 on 05.12.2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ScheduleView: View {
|
||||||
|
@ObservedObject var vm: ViewModel
|
||||||
|
var body: some View {
|
||||||
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
|
VStack (spacing: 12) {
|
||||||
|
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) {
|
||||||
|
VStack {
|
||||||
|
Text(convertTimeString(vm.classes[1][lessonIndex])[0])
|
||||||
|
.font(.system(size: 15, weight: .light))
|
||||||
|
Text(convertTimeString(vm.classes[1][lessonIndex])[1])
|
||||||
|
.font(.system(size: 15, weight: .light))
|
||||||
|
}
|
||||||
|
Rectangle()
|
||||||
|
.frame(width: 2)
|
||||||
|
.frame(maxHeight: 100)
|
||||||
|
Text(lesson)
|
||||||
|
}
|
||||||
|
.background(Color.white)
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertTimeString(_ input: String) -> [String] {
|
||||||
|
let parts = input.split(separator: "-")
|
||||||
|
if let firstPart = parts.first, let lastPart = parts.last {
|
||||||
|
return [String(firstPart), String(lastPart)]
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
MainView()
|
||||||
|
}
|
@ -10,6 +10,7 @@ import SwiftUI
|
|||||||
struct SearchBarView: View {
|
struct SearchBarView: View {
|
||||||
@Binding var text: String
|
@Binding var text: String
|
||||||
@State private var isEditing = false
|
@State private var isEditing = false
|
||||||
|
@ObservedObject var vm: ViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack (spacing: 11) {
|
HStack (spacing: 11) {
|
||||||
@ -21,11 +22,15 @@ struct SearchBarView: View {
|
|||||||
TextField("Поиск группы", text: $text)
|
TextField("Поиск группы", text: $text)
|
||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.isEditing = true
|
isEditing = true
|
||||||
}
|
}
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
self.isEditing = false
|
isEditing = false
|
||||||
|
if (!text.isEmpty) {
|
||||||
|
vm.fetchWeekSchedule(text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.submitLabel(.search)
|
||||||
if isEditing {
|
if isEditing {
|
||||||
Button {
|
Button {
|
||||||
self.text = ""
|
self.text = ""
|
||||||
@ -66,9 +71,10 @@ struct SearchBarView: View {
|
|||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.padding(.top, 5)
|
.padding(.top, 5)
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
|
.accentColor(.blue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
ScheduleView()
|
MainView()
|
||||||
}
|
}
|
@ -12,8 +12,11 @@ final class NetworkManager {
|
|||||||
//MARK: Properties
|
//MARK: Properties
|
||||||
static let shared = NetworkManager()
|
static let shared = NetworkManager()
|
||||||
private let decoder = JSONDecoder()
|
private let decoder = JSONDecoder()
|
||||||
private let urlForGroup = "https://webictis.sfedu.ru/schedule-api/?query=ктбо2-6"
|
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 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 = ""
|
||||||
|
|
||||||
//MARK: Initializer
|
//MARK: Initializer
|
||||||
private init() {
|
private init() {
|
||||||
@ -21,8 +24,13 @@ final class NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//MARK: Methods
|
//MARK: Methods
|
||||||
func getSchedule() async throws -> Schedule {
|
func makeURL(_ group: String) -> String {
|
||||||
guard let url = URL(string: urlForGroup) else { throw NetworkError.invalidUrl}
|
return urlForGroup + group
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSchedule(_ group: String) async throws -> Schedule {
|
||||||
|
let newUrlForGroup = makeURL(group)
|
||||||
|
guard let url = URL(string: newUrlForGroup) else {throw NetworkError.invalidUrl}
|
||||||
let (data, response) = try await URLSession.shared.data(from: url)
|
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}
|
||||||
|
|
||||||
|
@ -10,20 +10,31 @@ import Foundation
|
|||||||
@MainActor
|
@MainActor
|
||||||
final class ViewModel: ObservableObject {
|
final class ViewModel: ObservableObject {
|
||||||
//MARK: Properties
|
//MARK: Properties
|
||||||
@Published var weekSchedule: [Table] = []
|
@Published var weekSchedule: Table = Table(
|
||||||
|
type: "",
|
||||||
|
name: "",
|
||||||
|
week: 0,
|
||||||
|
group: "",
|
||||||
|
table: [[]],
|
||||||
|
link: ""
|
||||||
|
)
|
||||||
@Published var selectedDay: Date = Date()
|
@Published var selectedDay: Date = Date()
|
||||||
@Published var selectedIndex: Int = 1
|
@Published var selectedIndex: Int = 1
|
||||||
|
@Published var classes: [[String]] = []
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
fetchWeekSchedule()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//MARK: Methods
|
//MARK: Methods
|
||||||
func fetchWeekSchedule() {
|
func fetchWeekSchedule(_ group: String) {
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
let schedule = try await NetworkManager.shared.getSchedule()
|
let schedule = try await NetworkManager.shared.getSchedule(group)
|
||||||
weekSchedule = [schedule.table]
|
weekSchedule = schedule.table
|
||||||
|
classes = weekSchedule.table
|
||||||
|
print(weekSchedule.week)
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
if let error = error as? NetworkError {
|
if let error = error as? NetworkError {
|
||||||
@ -33,12 +44,6 @@ final class ViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSelectedDaySchedule(for date: Date) -> [String]? {
|
|
||||||
guard let week = weekSchedule.first else { return nil }
|
|
||||||
let dayIndex = week.table.firstIndex { $0[0].contains(date.format("dd MMMM")) }
|
|
||||||
return dayIndex.flatMap { week.table[$0] }
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateSelectedDayIndex(_ date: Date) {
|
func updateSelectedDayIndex(_ date: Date) {
|
||||||
switch date.format("E") {
|
switch date.format("E") {
|
||||||
case "Пн":
|
case "Пн":
|
||||||
@ -59,8 +64,4 @@ final class ViewModel: ObservableObject {
|
|||||||
print(selectedIndex)
|
print(selectedIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSelectedIndex(_ index: Int) {
|
|
||||||
selectedIndex = index
|
|
||||||
print(selectedIndex)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user