This commit is contained in:
Vladimir Dubovik 2025-03-14 12:47:18 +03:00
parent 8bc7425e2a
commit 99f2bd8a74
6 changed files with 139 additions and 30 deletions

View File

@ -1,10 +1,3 @@
//
// LoadingScheduleView.swift
// Schedule ICTIS
//
// Created by G412 on 19.02.2025.
//
import SwiftUI import SwiftUI
struct LoadingScheduleView: View { struct LoadingScheduleView: View {
@ -13,27 +6,43 @@ struct LoadingScheduleView: View {
ZStack { ZStack {
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 20) { VStack(spacing: 20) {
ForEach(0..<6, id: \.self) { _ in ForEach(0..<5, id: \.self) { _ in
RoundedRectangle(cornerRadius: 20) VStack (alignment: .trailing) {
.fill( RoundedRectangle(cornerRadius: 20)
LinearGradient( .fill(
gradient: Gradient(colors: [ LinearGradient(
isAnimated ? Color.gray.opacity(0.6) : Color.gray.opacity(0.3), gradient: Gradient(colors: [
isAnimated ? Color.gray.opacity(0.3) : Color.gray.opacity(0.6) isAnimated ? Color.gray.opacity(0.6) : Color.gray.opacity(0.3),
]), isAnimated ? Color.gray.opacity(0.3) : Color.gray.opacity(0.6)
startPoint: .topLeading, ]),
endPoint: .bottomTrailing startPoint: .topLeading,
endPoint: .bottomTrailing
)
) )
) .frame(width: 45, height: 20)
.frame(height: 70) .padding(.horizontal, 20)
.padding(.horizontal, 20) .animation(.linear(duration: 0.8).repeatForever(autoreverses: true), value: isAnimated)
.animation(.linear(duration: 0.8).repeatForever(autoreverses: true), value: isAnimated) RoundedRectangle(cornerRadius: 20)
.fill(
LinearGradient(
gradient: Gradient(colors: [
isAnimated ? Color.gray.opacity(0.6) : Color.gray.opacity(0.3),
isAnimated ? Color.gray.opacity(0.3) : Color.gray.opacity(0.6)
]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(height: 70)
.padding(.horizontal, 20)
.animation(.linear(duration: 0.8).repeatForever(autoreverses: true), value: isAnimated)
}
} }
} }
.onAppear { .onAppear {
isAnimated.toggle() isAnimated.toggle()
} }
.padding(.top, 30) .padding(.top, 10)
} }
} }
} }

View File

@ -82,14 +82,15 @@ struct MainView: View {
if (!isShowingMonthSlider) { if (!isShowingMonthSlider) {
WeekTabView(vm: vm) WeekTabView(vm: vm)
.transition(.opacity) .transition(.opacity)
.animation(.easeInOut(duration: 0.25), value: isShowingMonthSlider)
} }
else { else {
MonthTabView(vm: vm) MonthTabView(vm: vm)
.transition(.opacity) .transition(.opacity)
.animation(.easeInOut(duration: 0.25), value: isShowingMonthSlider)
} }
} }
.padding(.horizontal) .padding(.horizontal)
.animation(.easeInOut(duration: 0.25), value: isShowingMonthSlider)
} }
} }
#Preview { #Preview {

View File

@ -17,7 +17,7 @@ struct ListOfGroupsView: View {
var body: some View { var body: some View {
ScrollView(.vertical, showsIndicators: true) { ScrollView(.vertical, showsIndicators: true) {
ForEach(serchGroupsVM.groups) { item in ForEach(serchGroupsVM.groups) { item in
if item.name.starts(with: "ВПК") { if item.name.starts(with: "ВПК") || item.name.starts(with: "мВПК") {
VStack { VStack {
Rectangle() Rectangle()
.frame(height: 1) .frame(height: 1)

View File

@ -95,7 +95,7 @@ struct SelectingGroupView: View {
if isLoading { if isLoading {
LoadingView(isLoading: $isLoading) LoadingView(isLoading: $isLoading)
} }
if isFocused { //if isFocused {
ScrollView(.vertical, showsIndicators: true) { ScrollView(.vertical, showsIndicators: true) {
ForEach(serchGroupsVM.groups) { item in ForEach(serchGroupsVM.groups) { item in
if item.name.starts(with: "КТ") { //Отображаем только группы(без аудиторий и преподавателей) if item.name.starts(with: "КТ") { //Отображаем только группы(без аудиторий и преподавателей)
@ -133,7 +133,7 @@ struct SelectingGroupView: View {
} }
} }
} }
} //}
} }
.padding(.horizontal, 10) .padding(.horizontal, 10)
.background(Color("background")) .background(Color("background"))

View File

@ -94,9 +94,7 @@ struct SelectingVPKView: View {
if isLoading { if isLoading {
LoadingView(isLoading: $isLoading) LoadingView(isLoading: $isLoading)
} }
if isFocused { ListOfGroupsView(vm: vm, serchGroupsVM: serchGroupsVM, firstFavVPK: firstFavVPK, secondFavVPK: secondFavVPK, thirdFavVPK: thirdFavVPK)
ListOfGroupsView(vm: vm, serchGroupsVM: serchGroupsVM, firstFavVPK: firstFavVPK, secondFavVPK: secondFavVPK, thirdFavVPK: thirdFavVPK)
}
} }
.padding(.horizontal, 10) .padding(.horizontal, 10)
.background(Color("background")) .background(Color("background"))

View File

@ -17,7 +17,11 @@ final class SearchGroupsViewModel: ObservableObject {
var groups: Welcome var groups: Welcome
groups = try await NetworkManager.shared.getGroups(group: group) groups = try await NetworkManager.shared.getGroups(group: group)
self.groups = groups.choices self.groups = groups.choices
if (group == "кт") {
self.sortGroups()
} else {
self.sortVPK()
}
} }
catch { catch {
if let error = error as? NetworkError { if let error = error as? NetworkError {
@ -33,4 +37,101 @@ final class SearchGroupsViewModel: ObservableObject {
} }
} }
} }
// Метод сортировки
func sortGroups() {
groups.sort { (group1, group2) in
// Извлекаем компоненты из названия групп
let components1 = extractComponents(from: group1.name)
let components2 = extractComponents(from: group2.name)
// Сравниваем сначала по номеру курса (первая цифра после букв)
if components1.courseNumber != components2.courseNumber {
return components1.courseNumber < components2.courseNumber
}
// Если номера курсов равны, сравниваем по номеру группы (число после дефиса)
return components1.groupNumber < components2.groupNumber
}
}
// Вспомогательная структура для хранения извлеченных компонентов
private struct GroupComponents {
let courseNumber: Int
let groupNumber: Int
}
// Метод для извлечения числовых компонентов из названия группы
private func extractComponents(from name: String) -> GroupComponents {
// Находим индекс дефиса
guard let hyphenIndex = name.firstIndex(of: "-") else {
return GroupComponents(courseNumber: 0, groupNumber: 0)
}
// Извлекаем часть до дефиса (буквы и номер курса)
let prefix = String(name[..<hyphenIndex])
// Извлекаем часть после дефиса (номер группы)
let suffix = String(name[name.index(after: hyphenIndex)...])
// Извлекаем цифры из prefix
let courseNumberString = prefix.trimmingCharacters(in: CharacterSet.letters)
let courseNumber = Int(courseNumberString) ?? 0
// Преобразуем suffix в число
let groupNumber = Int(suffix) ?? 0
return GroupComponents(courseNumber: courseNumber, groupNumber: groupNumber)
}
// Метод сортировки для ВПК групп
func sortVPK() {
groups.sort { (group1, group2) in
let components1 = extractVPKComponents(from: group1.name)
let components2 = extractVPKComponents(from: group2.name)
// Сравниваем по типу (мВПК после ВПК)
if components1.isMinor != components2.isMinor {
return !components1.isMinor // ВПК идет перед мВПК
}
// Сравниваем по первому номеру
if components1.firstNumber != components2.firstNumber {
return components1.firstNumber < components2.firstNumber
}
// Если первые номера равны, сравниваем по второму номеру (если есть)
// Используем nil coalescing для случаев, когда второго номера нет
return (components1.secondNumber ?? Int.max) < (components2.secondNumber ?? Int.max)
}
}
// Вспомогательная структура для хранения компонентов ВПК
private struct VPKComponents {
let isMinor: Bool // true для мВПК, false для ВПК
let firstNumber: Int
let secondNumber: Int?
}
// Метод для извлечения компонентов из названия ВПК группы
private func extractVPKComponents(from name: String) -> VPKComponents {
let isMinor = name.hasPrefix("мВПК")
// Убираем префикс и разбиваем по дефису
let cleanName = isMinor ? name.replacingOccurrences(of: "мВПК-", with: "") : name.replacingOccurrences(of: "ВПК ", with: "")
let components = cleanName.split(separator: "-")
// Извлекаем первый номер
let firstNumberString = String(components[0]).trimmingCharacters(in: .whitespaces)
let firstNumber = Int(firstNumberString) ?? 0
// Извлекаем второй номер, если он есть
let secondNumber: Int?
if components.count > 1 {
secondNumber = Int(components[1]) ?? 0
} else {
secondNumber = nil
}
return VPKComponents(isMinor: isMinor, firstNumber: firstNumber, secondNumber: secondNumber)
}
} }