diff --git a/Schedule ICTIS/ContentView.swift b/Schedule ICTIS/ContentView.swift index b8f1dbb..dc78bb7 100644 --- a/Schedule ICTIS/ContentView.swift +++ b/Schedule ICTIS/ContentView.swift @@ -8,20 +8,18 @@ import SwiftUI struct ContentView: View { - @State private var isActiveTabBar: TabModel = .schedule - @State private var isTabBarHidden: Bool = false + @State private var selectedTab: TabModel = .schedule var body: some View { - VStack { - TabView(selection: $isActiveTabBar) { + ZStack { + switch selectedTab { + case .schedule: ScheduleView() - .tag(TabModel.schedule) + case .tasks: Text("Tasks") - .tag(TabModel.tasks) + case .settings: Text("Settings") - .tag(TabModel.settings) } - CustomTabBarView(isActiveTabBar: $isActiveTabBar) - .padding(.bottom, 10) + CustomTabBarView(selectedTab: $selectedTab) } .background(.secondary.opacity(0.15)) } diff --git a/Schedule ICTIS/CustomTabBarView.swift b/Schedule ICTIS/CustomTabBarView.swift index 1c09548..9326ef9 100644 --- a/Schedule ICTIS/CustomTabBarView.swift +++ b/Schedule ICTIS/CustomTabBarView.swift @@ -10,42 +10,53 @@ import SwiftUI struct CustomTabBarView: View { var isActiveForeground: Color = .white var isActiveBackground: Color = Color("blueColor") - @Binding var isActiveTabBar: TabModel + @Binding var selectedTab: TabModel // @NameSpace private var animation var body: some View { - HStack(spacing: 0) { - ForEach(TabModel.allCases, id: \.rawValue) { tab in - Button { - isActiveTabBar = tab - } label: { - HStack(spacing: 5) { - Image(systemName: tab.rawValue) - .font(.title) - .frame(width: 80, height: 35) - } - .foregroundStyle(isActiveTabBar == tab ? isActiveForeground : Color("blueColor")) - .padding(.vertical, 7) - .padding(.leading, 15) - .padding(.trailing, 15) - .background { - if isActiveTabBar == tab { - Capsule() - .fill(isActiveBackground) + VStack { + Spacer() + HStack(spacing: 0) { + content + } + .animation(.smooth(duration: 0.3, extraBounce: 0), value: selectedTab) + .padding(6) + .background(.clear) + .mask(RoundedRectangle(cornerRadius: 24, style: .continuous)) + + // .background( + // background + // .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: 5)) + // .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: -5)), + // in: .capsule + // ) + } + .ignoresSafeArea(.keyboard, edges: .bottom) + } + + var content: some View { + ForEach(TabModel.allCases, id: \.rawValue) { tab in + Button { + selectedTab = tab + } label: { + VStack { + Image(systemName: tab.rawValue) + .font(.title) + .frame(width: 80, height: 35) + } + .foregroundStyle(selectedTab == tab ? isActiveForeground : Color("blueColor")) + .padding(.vertical, 7) + .padding(.leading, 15) + .padding(.trailing, 15) + .background { + if selectedTab == tab { + Capsule() + .fill(isActiveBackground) // .matchedGeometryEffect(id: "ACTIVETAB", in: animation) - } } } - .buttonStyle(.plain) } + .buttonStyle(.plain) } - .padding(.horizontal, 5) - .animation(.smooth(duration: 0.3, extraBounce: 0), value: isActiveTabBar) -// .background( -// background -// .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: 5)) -// .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: -5)), -// in: .capsule -// ) } } diff --git a/Schedule ICTIS/Helpers/Date+Extensions.swift b/Schedule ICTIS/Helpers/Date+Extensions.swift new file mode 100644 index 0000000..b08d964 --- /dev/null +++ b/Schedule ICTIS/Helpers/Date+Extensions.swift @@ -0,0 +1,43 @@ +// +// Date+Extensions.swift +// Schedule ICTIS +// +// Created by G412 on 14.11.2024. +// + +import SwiftUI + + +extension Date { + func format(_ format: String, locale: Locale = Locale(identifier: "ru_RU")) -> String { + let formatter = DateFormatter() + formatter.dateFormat = format + formatter.locale = locale + return formatter.string(from: self) + } + + func fetchWeek(_ date: Date = .init()) -> [WeekDay] { + let calendar = Calendar.current + let startOfDate = calendar.startOfDay(for: date) + + var week: [WeekDay] = [] + let weekForDate = calendar.dateInterval(of: .weekOfMonth, for: startOfDate) + + guard let startOfWeek = weekForDate?.start else { + return [] + } + + (0..<7).forEach { index in + if let weekDay = calendar.date(byAdding: .day, value: index, to: startOfWeek) { + week.append(.init(date: weekDay)) + } + } + + return week + } + + struct WeekDay: Identifiable { + var id: UUID = .init() + var date: Date + } +} diff --git a/Schedule ICTIS/ScheduleView.swift b/Schedule ICTIS/ScheduleView.swift index 59f78b4..ca7ce55 100644 --- a/Schedule ICTIS/ScheduleView.swift +++ b/Schedule ICTIS/ScheduleView.swift @@ -9,12 +9,72 @@ import SwiftUI struct ScheduleView: View { @State private var searchText: String = "" + @State private var currentDate: Date = .init() + @State private var weekSlider: [[Date.WeekDay]] = [] + @State private var currentWeekIndex: Int = 0 var body: some View { VStack { SearchBarView(text: $searchText) + HeaderView() Spacer() } - .background(.secondary.opacity(0.15)) + .background(.secondary.opacity(0.1)) + .onAppear(perform: { + if weekSlider.isEmpty { + let currentWeek = Date().fetchWeek() + weekSlider.append(currentWeek) + } + }) + + } + + @ViewBuilder + func HeaderView() -> some View { + VStack (alignment: .leading, spacing: 6) { + HStack (spacing: 5) { + Text(currentDate.format("YYYY")) + .foregroundStyle(.blue) + Text(currentDate.format("MMMM")) + .foregroundStyle(.blue) + } + .font(.title.bold()) +// Text(currentDate.formatted(date: .complete, time: .omitted)) +// .font(.title.bold()) + + TabView(selection: $currentWeekIndex) { + ForEach(weekSlider.indices, id: \.self) { index in + let week = weekSlider[index] + WeekView(week) + .tag(index) + } + } + .tabViewStyle(.page(indexDisplayMode: .never)) + .frame(height: 90) + } + } + + @ViewBuilder + func WeekView(_ week: [Date.WeekDay]) -> some View { + HStack (spacing: 14) { + ForEach(week) { day in + VStack (spacing: 4) { + Text(day.date.format("E")) + .font(.callout) + .fontWeight(.medium) + .textScale(.secondary) + .padding(.top, 6) + .foregroundColor(.gray) + Text(day.date.format("dd")) + .font(.callout) + .fontWeight(.bold) + .textScale(.secondary) + .padding(.bottom, 6) + } + .frame(maxWidth: 40, maxHeight: 55, alignment: .center) + .background(Color.white) + .cornerRadius(10) + } + } } } diff --git a/Schedule ICTIS/SearchBarView.swift b/Schedule ICTIS/SearchBarView.swift index 5a78c8b..aacf58e 100644 --- a/Schedule ICTIS/SearchBarView.swift +++ b/Schedule ICTIS/SearchBarView.swift @@ -1,10 +1,3 @@ -// -// SearchBarView.swift -// Schedule ICTIS -// -// Created by G412 on 13.11.2024. -// - import SwiftUI struct SearchBarView: View { @@ -13,34 +6,41 @@ struct SearchBarView: View { var body: some View { HStack { - TextField("Ввести номер группы", text: $text) - .padding(7) - .padding(.horizontal, 25) - .background(.white) - .cornerRadius(8) - .overlay( - HStack { - Image(systemName: "magnifyingglass") - .foregroundColor(.gray) - .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) - .padding(.leading, 8) - - if isEditing { - Button(action: { - self.text = "" - self.isEditing = false - UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) - }) { - Image(systemName: "multiply.circle.fill") - .foregroundColor(.gray) - .padding(.trailing, 8) - } - } + HStack { + Image(systemName: "magnifyingglass") + .foregroundColor(Color.gray) + .padding(.leading, 10) + TextField("Ввести номер группы", text: $text) + .disableAutocorrection(true) + .frame(width: 270, height: 45) + .overlay( + Group { + if isEditing { + Button { + self.text = "" + self.isEditing = false + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + } label: { + Image(systemName: "xmark.circle.fill") + .padding(.trailing, 30) + .offset(x: 10) + .foregroundColor(.gray) + } + } + }, alignment: .trailing + ) + .onTapGesture { + self.isEditing = true } - ) - .onTapGesture { - self.isEditing = true - } + .onSubmit { + self.isEditing = false + } + } + .background( + RoundedRectangle(cornerRadius: 10) + .fill(.white) + ) + Spacer() Button { } label: { @@ -54,8 +54,8 @@ struct SearchBarView: View { .foregroundStyle(.white) .scaledToFit() .frame(width: 16) + } } - } } .padding(.horizontal) }