Commit
This commit is contained in:
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array/>
|
||||
</plist>
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ICTIS_logo.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
|
BIN
Schedule-ICTIS/Assets.xcassets/AppIcon.appiconset/ICTIS_logo.png
Normal file
BIN
Schedule-ICTIS/Assets.xcassets/AppIcon.appiconset/ICTIS_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
21
Schedule-ICTIS/Assets.xcassets/ICTIS_logo.imageset/Contents.json
vendored
Normal file
21
Schedule-ICTIS/Assets.xcassets/ICTIS_logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ICTIS_logo.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
Schedule-ICTIS/Assets.xcassets/ICTIS_logo.imageset/ICTIS_logo.png
vendored
Normal file
BIN
Schedule-ICTIS/Assets.xcassets/ICTIS_logo.imageset/ICTIS_logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
21
Schedule-ICTIS/Assets.xcassets/arrowRight.imageset/Contents.json
vendored
Normal file
21
Schedule-ICTIS/Assets.xcassets/arrowRight.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "arrowRight.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
3
Schedule-ICTIS/Assets.xcassets/arrowRight.imageset/arrowRight.svg
vendored
Normal file
3
Schedule-ICTIS/Assets.xcassets/arrowRight.imageset/arrowRight.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 6L15 12L9 18" stroke="#8B8B8B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 212 B |
21
Schedule-ICTIS/Assets.xcassets/arrowdown.imageset/Contents.json
vendored
Normal file
21
Schedule-ICTIS/Assets.xcassets/arrowdown.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "arrowdown.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
3
Schedule-ICTIS/Assets.xcassets/arrowdown.imageset/arrowdown.svg
vendored
Normal file
3
Schedule-ICTIS/Assets.xcassets/arrowdown.imageset/arrowdown.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 1L7 7L1 1" stroke="#007AFF" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 191 B |
21
Schedule-ICTIS/Assets.xcassets/arrowup.imageset/Contents.json
vendored
Normal file
21
Schedule-ICTIS/Assets.xcassets/arrowup.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "arrowup.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
3
Schedule-ICTIS/Assets.xcassets/arrowup.imageset/arrowup.svg
vendored
Normal file
3
Schedule-ICTIS/Assets.xcassets/arrowup.imageset/arrowup.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L7 1L13 7" stroke="#007AFF" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 191 B |
21
Schedule-ICTIS/Assets.xcassets/upDownArrows.imageset/Contents.json
vendored
Normal file
21
Schedule-ICTIS/Assets.xcassets/upDownArrows.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "upDownArrows.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
4
Schedule-ICTIS/Assets.xcassets/upDownArrows.imageset/upDownArrows.svg
vendored
Normal file
4
Schedule-ICTIS/Assets.xcassets/upDownArrows.imageset/upDownArrows.svg
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="14" height="18" viewBox="0 0 14 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L7 1L13 7" stroke="#878787" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M13 11L7 17L1 11" stroke="#878787" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 320 B |
@ -34,6 +34,18 @@ struct ContentView: View {
|
||||
}
|
||||
TabBarView(selectedTab: $selectedTab)
|
||||
}
|
||||
.alert(isPresented: $vm.isShowingAlertForIncorrectSingleGroup, error: vm.errorInNetworkForSingleGroup) { error in
|
||||
Button("ОК") {
|
||||
print("This alert")
|
||||
vm.isShowingAlertForIncorrectSingleGroup = false
|
||||
vm.errorInNetworkForSingleGroup = nil
|
||||
}
|
||||
} message: { error in
|
||||
Text(error.failureReason)
|
||||
}
|
||||
.onAppear {
|
||||
vm.fillFilteringGroups()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
<string>Montserrat-BlackItalic.ttf</string>
|
||||
<string>Montserrat-Bold.ttf</string>
|
||||
<string>Montserrat-BoldItalic.ttf</string>
|
||||
<string>Monsterrat-ExtraBold.ttf</string>
|
||||
<string>Montserrat-ExtraBold.ttf</string>
|
||||
<string>Montserrat-ExtraBoldItalic.ttf</string>
|
||||
<string>Montserrat-ExtraLight.ttf</string>
|
||||
<string>Montserrat-ExtraLightItalic.ttf</string>
|
||||
|
@ -9,43 +9,69 @@ import SwiftUI
|
||||
|
||||
struct FilterGroupsView: View {
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@ObservedObject var networkMonitor: NetworkMonitor
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
LazyHStack(spacing: 12) {
|
||||
ForEach(vm.filteringGroups, id: \.self) { group in
|
||||
VStack {
|
||||
Text(group)
|
||||
.foregroundColor(Color("customGray3"))
|
||||
.font(.custom("Montserrat-Medium", fixedSize: 14))
|
||||
.padding(.horizontal, 15)
|
||||
.padding(.vertical, 7)
|
||||
}
|
||||
.background(Color.white)
|
||||
.overlay (
|
||||
Group {
|
||||
if vm.showOnlyChoosenGroup == group {
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(Color("blueColor"), lineWidth: 3)
|
||||
}
|
||||
}
|
||||
)
|
||||
// Кнопка добавления новой группы
|
||||
NavigationLink(destination: SelectingGroupView(vm: vm, networkMonitor: networkMonitor)) {
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.frame(width: 28, height: 28)
|
||||
.foregroundStyle(.white)
|
||||
.cornerRadius(20)
|
||||
.onTapGesture {
|
||||
Image(systemName: "plus")
|
||||
.foregroundColor(Color("customGray3"))
|
||||
.font(.system(size: 12))
|
||||
}
|
||||
}
|
||||
|
||||
if vm.filteringGroups.count == 2 {
|
||||
ForEach(vm.filteringGroups.dropFirst(), id: \.self) { group in
|
||||
GroupItem(group: group, isSelected: vm.showOnlyChoosenGroup == group) {
|
||||
vm.showOnlyChoosenGroup = group
|
||||
}
|
||||
}
|
||||
} else if vm.filteringGroups.count > 2 {
|
||||
ForEach(vm.filteringGroups, id: \.self) { group in
|
||||
GroupItem(group: group, isSelected: vm.showOnlyChoosenGroup == group) {
|
||||
vm.showOnlyChoosenGroup = group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
.frame(height: 40)
|
||||
.onAppear {
|
||||
vm.updateFilteringGroups()
|
||||
}
|
||||
.padding(.bottom, 4)
|
||||
}
|
||||
}
|
||||
|
||||
// Вынесенный компонент для элемента группы
|
||||
struct GroupItem: View {
|
||||
let group: String
|
||||
let isSelected: Bool
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Text(group)
|
||||
.foregroundColor(Color("customGray3"))
|
||||
.font(.custom("Montserrat-Medium", fixedSize: 14))
|
||||
.padding(.horizontal, 15)
|
||||
.padding(.vertical, 7)
|
||||
.background(Color.white)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(isSelected ? Color("blueColor") : Color.clear, lineWidth: 3)
|
||||
)
|
||||
.cornerRadius(20)
|
||||
.onTapGesture(perform: action)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
@Previewable @ObservedObject var vm = ScheduleViewModel()
|
||||
FilterGroupsView(vm: vm)
|
||||
@Previewable @ObservedObject var networkMonitor = NetworkMonitor()
|
||||
FilterGroupsView(vm: vm, networkMonitor: networkMonitor)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ struct MainView: View {
|
||||
@FocusState private var isFocusedSearchBar: Bool
|
||||
@State private var isScrolling: Bool = false
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
SearchBarView(isFocused: _isFocusedSearchBar, vm: vm, isShowingMonthSlider: $isShowingMonthSlider)
|
||||
.onChange(of: isScrolling, initial: false) { oldValue, newValue in
|
||||
@ -22,7 +23,7 @@ struct MainView: View {
|
||||
}
|
||||
}
|
||||
CurrentDateView()
|
||||
FilterGroupsView(vm: vm)
|
||||
FilterGroupsView(vm: vm, networkMonitor: networkMonitor)
|
||||
if vm.isLoading {
|
||||
LoadingScheduleView()
|
||||
}
|
||||
@ -41,6 +42,7 @@ struct MainView: View {
|
||||
}
|
||||
.background(Color("background"))
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func CurrentDateView() -> some View {
|
||||
|
@ -31,8 +31,9 @@ struct SearchBarView: View {
|
||||
if (!text.isEmpty) {
|
||||
vm.fetchWeekForSingleGroup(groupName: text)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
guard vm.errorInNetwork == .noError else {
|
||||
vm.isShowingAlertForIncorrectGroup = true
|
||||
guard vm.errorInNetworkForSingleGroup == .noError else {
|
||||
vm.isShowingAlertForIncorrectSingleGroup = true
|
||||
self.text = ""
|
||||
return
|
||||
}
|
||||
vm.removeFromSchedule(group: vm.searchingGroup)
|
||||
@ -40,7 +41,7 @@ struct SearchBarView: View {
|
||||
vm.searchingGroup = text
|
||||
vm.nameToHtml[text] = ""
|
||||
print("Ключи: \(vm.nameToHtml.keys)")
|
||||
vm.updateFilteringGroups()
|
||||
vm.addGroupToFilteringArray(group: text)
|
||||
vm.fetchWeekSchedule()
|
||||
self.text = ""
|
||||
}
|
||||
@ -77,12 +78,10 @@ struct SearchBarView: View {
|
||||
Rectangle()
|
||||
.frame(width: 40, height: 40)
|
||||
.foregroundStyle(Color("blueColor"))
|
||||
.cornerRadius(15)
|
||||
.cornerRadius(10)
|
||||
Image(systemName: "plus")
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
.scaledToFit()
|
||||
.frame(width: 16)
|
||||
.foregroundColor(.white)
|
||||
.font(.system(size: 22))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,6 @@ extension JsonClassModel {
|
||||
|
||||
let groupsToDelete = try context.fetch(fetchRequest)
|
||||
|
||||
print("Пары для удаления: \(groupsToDelete)")
|
||||
|
||||
for group in groupsToDelete {
|
||||
do {
|
||||
try ClassProvider.shared.delete(group, in: context)
|
||||
|
@ -9,6 +9,7 @@ import SwiftUI
|
||||
import CoreData
|
||||
|
||||
struct FavGroupsView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@ObservedObject var networkMonitor: NetworkMonitor
|
||||
@FetchRequest(fetchRequest: FavouriteGroupModel.all()) private var favGroups // Список групп сохраненных в CoreData
|
||||
@ -39,28 +40,39 @@ struct FavGroupsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
}
|
||||
.navigationBarBackButtonHidden(true) // Скрываем стандартную кнопку "Назад"
|
||||
.background(Color("background"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button(action: {
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Настройки")
|
||||
}
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
// Кнопка в правой части
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
if favGroups.count < 10 {
|
||||
NavigationLink(destination: SelectingGroupView(vm: vm, networkMonitor: networkMonitor)) {
|
||||
HStack {
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.frame(width: 40, height: 40)
|
||||
.foregroundStyle(Color("blueColor"))
|
||||
.cornerRadius(10)
|
||||
Image(systemName: "plus")
|
||||
.foregroundColor(.white)
|
||||
.font(.system(size: 22))
|
||||
.padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
.background(Color("blueColor"))
|
||||
.cornerRadius(10)
|
||||
.padding(.trailing, 20)
|
||||
.font(.system(size: 18))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 90)
|
||||
}
|
||||
.background(Color("background"))
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct FavVPKView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@ObservedObject var vm: ScheduleViewModel
|
||||
@ObservedObject var networkMonitor: NetworkMonitor
|
||||
@FetchRequest(fetchRequest: FavouriteVpkModel.all()) private var favVpk // Список ВПК сохраненных в CoreData
|
||||
@ -38,28 +39,39 @@ struct FavVPKView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
}
|
||||
.navigationBarBackButtonHidden(true) // Скрываем стандартную кнопку "Назад"
|
||||
.background(Color("background"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button(action: {
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Настройки")
|
||||
}
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
// Кнопка в правой части
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
if favVpk.count < 5 {
|
||||
NavigationLink(destination: SelectingVPKView(vm: vm, networkMonitor: networkMonitor)) {
|
||||
HStack {
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.frame(width: 40, height: 40)
|
||||
.foregroundStyle(Color("blueColor"))
|
||||
.cornerRadius(10)
|
||||
Image(systemName: "plus")
|
||||
.foregroundColor(.white)
|
||||
.font(.system(size: 22))
|
||||
.padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
||||
}
|
||||
.background(Color("blueColor"))
|
||||
.cornerRadius(10)
|
||||
.padding(.trailing, 20)
|
||||
.font(.system(size: 18))
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 90)
|
||||
}
|
||||
.background(Color("background"))
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ struct ListOfGroupsView: View {
|
||||
try saveGroup(name: item.name)
|
||||
saveScheduleForVpkToMemory(withName: item.name)
|
||||
vm.nameToHtml[item.name] = ""
|
||||
vm.updateFilteringGroups()
|
||||
vm.addGroupToFilteringArray(group: item.name)
|
||||
vm.fetchWeekSchedule()
|
||||
dismiss()
|
||||
} catch {
|
||||
|
@ -45,30 +45,29 @@ struct SelectingGroupView: View {
|
||||
self.isFocused = false
|
||||
guard !text.isEmpty else { return }
|
||||
|
||||
vm.fetchWeekForSingleGroup(groupName: text)
|
||||
self.isLoading = true
|
||||
vm.fetchWeekForSingleGroup(groupName: text)
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
guard vm.errorInNetwork == .noError else {
|
||||
vm.isShowingAlertForIncorrectGroup = true
|
||||
if vm.errorInNetworkForSingleGroup != .noError {
|
||||
return
|
||||
}
|
||||
|
||||
vm.errorInNetwork = nil
|
||||
vm.errorInNetworkForSingleGroup = nil
|
||||
let formattedText = transformStringToFormat(text)
|
||||
|
||||
do {
|
||||
try saveGroup(name: formattedText)
|
||||
saveScheduleForGroupToMemory(withName: formattedText)
|
||||
vm.nameToHtml[formattedText] = ""
|
||||
vm.updateFilteringGroups()
|
||||
vm.addGroupToFilteringArray(group: formattedText)
|
||||
vm.fetchWeekSchedule()
|
||||
self.isLoading = false
|
||||
self.text = ""
|
||||
dismiss()
|
||||
} catch {
|
||||
print("Ошибка сохранения: \(error.localizedDescription)")
|
||||
vm.isShowingAlertForIncorrectGroup = true
|
||||
vm.isShowingAlertForIncorrectSingleGroup = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,7 +88,7 @@ struct SelectingGroupView: View {
|
||||
}
|
||||
.frame(height: 40)
|
||||
.background (
|
||||
RoundedRectangle(cornerRadius: 15)
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
.fill(.white)
|
||||
)
|
||||
Spacer()
|
||||
@ -121,7 +120,7 @@ struct SelectingGroupView: View {
|
||||
try saveGroup(name: item.name)
|
||||
saveScheduleForGroupToMemory(withName: item.name)
|
||||
vm.nameToHtml[item.name] = ""
|
||||
vm.updateFilteringGroups()
|
||||
vm.addGroupToFilteringArray(group: item.name)
|
||||
vm.fetchWeekSchedule()
|
||||
self.isLoading = false
|
||||
self.text = ""
|
||||
@ -144,6 +143,21 @@ struct SelectingGroupView: View {
|
||||
.onAppear {
|
||||
serchGroupsVM.fetchGroups(group: "кт")
|
||||
}
|
||||
.navigationBarBackButtonHidden(true) // Скрываем стандартную кнопку "Назад"
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button(action: {
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Назад")
|
||||
}
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,30 +45,29 @@ struct SelectingVPKView: View {
|
||||
self.isFocused = false
|
||||
guard !text.isEmpty else { return }
|
||||
|
||||
vm.fetchWeekForSingleGroup(groupName: text)
|
||||
self.isLoading = true
|
||||
vm.fetchWeekForSingleGroup(groupName: text)
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
guard vm.errorInNetwork == .noError else {
|
||||
vm.isShowingAlertForIncorrectGroup = true
|
||||
guard vm.errorInNetworkForSingleGroup == .noError else {
|
||||
return
|
||||
}
|
||||
|
||||
vm.errorInNetwork = nil
|
||||
vm.errorInNetworkForSingleGroup = nil
|
||||
let formattedText = transformStringToFormat(text)
|
||||
|
||||
do {
|
||||
try saveGroup(name: formattedText)
|
||||
saveScheduleForVpkToMemory(withName: formattedText)
|
||||
vm.nameToHtml[formattedText] = ""
|
||||
vm.updateFilteringGroups()
|
||||
vm.addGroupToFilteringArray(group: formattedText)
|
||||
vm.fetchWeekSchedule()
|
||||
self.isLoading = false
|
||||
self.text = ""
|
||||
dismiss()
|
||||
} catch {
|
||||
print("Ошибка сохранения: \(error.localizedDescription)")
|
||||
vm.isShowingAlertForIncorrectGroup = true
|
||||
vm.isShowingAlertForIncorrectSingleGroup = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,6 +106,21 @@ struct SelectingVPKView: View {
|
||||
.onAppear {
|
||||
serchGroupsVM.fetchGroups(group: "ВПК")
|
||||
}
|
||||
.navigationBarBackButtonHidden(true) // Скрываем стандартную кнопку "Назад"
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button(action: {
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "chevron.left")
|
||||
Text("Назад")
|
||||
}
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ struct SettingsView: View {
|
||||
@State private var selectedTheme = "Светлая"
|
||||
@State private var selectedLanguage = "Русский"
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
ScrollView (.vertical, showsIndicators: false) {
|
||||
VStack (alignment: .leading) {
|
||||
|
@ -21,7 +21,7 @@ enum NetworkError: String, Error, LocalizedError {
|
||||
case .invalidResponse:
|
||||
"InvalidResponse"
|
||||
case .invalidData:
|
||||
"Проверьте номер группы"
|
||||
"Проверьте имя группы"
|
||||
case .timeout:
|
||||
"Ошибка сети"
|
||||
case .noError:
|
@ -17,7 +17,7 @@ final class ScheduleViewModel: ObservableObject {
|
||||
@Published var classesGroups: [[ClassInfo]] = []
|
||||
@Published var searchingGroup = ""
|
||||
@Published var filteringGroups: [String] = ["Все"]
|
||||
@Published var showOnlyChoosenGroup: String = "Все"
|
||||
@Published var showOnlyChoosenGroup: String = ""
|
||||
|
||||
//Schedule
|
||||
@Published var weekScheduleGroup: Table = Table(
|
||||
@ -34,7 +34,9 @@ final class ScheduleViewModel: ObservableObject {
|
||||
|
||||
@Published var isFirstStartOffApp = true
|
||||
@Published var isShowingAlertForIncorrectGroup: Bool = false
|
||||
@Published var isShowingAlertForIncorrectSingleGroup: Bool = false
|
||||
@Published var errorInNetwork: NetworkError?
|
||||
@Published var errorInNetworkForSingleGroup: NetworkError?
|
||||
@Published var isLoading: Bool = false
|
||||
@Published var isNewGroup: Bool = false
|
||||
|
||||
@ -141,25 +143,25 @@ final class ScheduleViewModel: ObservableObject {
|
||||
|
||||
// Обновляем данные
|
||||
self.classesForSingleGroup = singleSchedule
|
||||
self.isShowingAlertForIncorrectGroup = false
|
||||
self.isShowingAlertForIncorrectSingleGroup = false
|
||||
self.isLoading = false
|
||||
self.errorInNetwork = .noError
|
||||
self.errorInNetworkForSingleGroup = .noError
|
||||
|
||||
} catch {
|
||||
if let urlError = error as? URLError, urlError.code == .timedOut {
|
||||
errorInNetwork = .timeout
|
||||
errorInNetworkForSingleGroup = .timeout
|
||||
print("Ошибка: превышено время ожидания ответа от сервера")
|
||||
} else if let error = error as? NetworkError {
|
||||
switch error {
|
||||
case .invalidResponse:
|
||||
errorInNetwork = .invalidResponse
|
||||
errorInNetworkForSingleGroup = .invalidResponse
|
||||
case .invalidData:
|
||||
errorInNetwork = .invalidData
|
||||
errorInNetworkForSingleGroup = .invalidData
|
||||
print("FetchSingle: InvalidData")
|
||||
self.isShowingAlertForIncorrectGroup = true
|
||||
default:
|
||||
print("Неизвестная ошибка: \(error)")
|
||||
}
|
||||
self.isShowingAlertForIncorrectSingleGroup = true
|
||||
print("Есть ошибка: \(error)")
|
||||
}
|
||||
isLoading = false
|
||||
@ -229,12 +231,34 @@ final class ScheduleViewModel: ObservableObject {
|
||||
classesGroups[i].remove(at: j)
|
||||
}
|
||||
}
|
||||
|
||||
self.filteringGroups = self.filteringGroups.filter {$0 != group}
|
||||
|
||||
if group == self.showOnlyChoosenGroup || self.filteringGroups.count == 2 {
|
||||
selectShowingGroup()
|
||||
}
|
||||
}
|
||||
|
||||
func updateFilteringGroups() {
|
||||
self.filteringGroups = ["Все"]
|
||||
func selectShowingGroup() {
|
||||
if self.filteringGroups.count == 2 {
|
||||
self.showOnlyChoosenGroup = self.filteringGroups[1]
|
||||
} else if self.filteringGroups.count < 2 {
|
||||
self.showOnlyChoosenGroup = ""
|
||||
}
|
||||
else {
|
||||
self.showOnlyChoosenGroup = "Все"
|
||||
}
|
||||
}
|
||||
|
||||
func addGroupToFilteringArray(group: String) {
|
||||
self.filteringGroups.append(group)
|
||||
}
|
||||
|
||||
func fillFilteringGroups() {
|
||||
let keys = self.nameToHtml.keys
|
||||
print(keys)
|
||||
self.filteringGroups.append(contentsOf: keys)
|
||||
|
||||
selectShowingGroup()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user