q
This commit is contained in:
parent
d3f448e288
commit
b65b061d95
@ -8,20 +8,18 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@State private var isActiveTabBar: TabModel = .schedule
|
@State private var selectedTab: TabModel = .schedule
|
||||||
@State private var isTabBarHidden: Bool = false
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
ZStack {
|
||||||
TabView(selection: $isActiveTabBar) {
|
switch selectedTab {
|
||||||
|
case .schedule:
|
||||||
ScheduleView()
|
ScheduleView()
|
||||||
.tag(TabModel.schedule)
|
case .tasks:
|
||||||
Text("Tasks")
|
Text("Tasks")
|
||||||
.tag(TabModel.tasks)
|
case .settings:
|
||||||
Text("Settings")
|
Text("Settings")
|
||||||
.tag(TabModel.settings)
|
|
||||||
}
|
}
|
||||||
CustomTabBarView(isActiveTabBar: $isActiveTabBar)
|
CustomTabBarView(selectedTab: $selectedTab)
|
||||||
.padding(.bottom, 10)
|
|
||||||
}
|
}
|
||||||
.background(.secondary.opacity(0.15))
|
.background(.secondary.opacity(0.15))
|
||||||
}
|
}
|
||||||
|
@ -10,42 +10,53 @@ import SwiftUI
|
|||||||
struct CustomTabBarView: View {
|
struct CustomTabBarView: View {
|
||||||
var isActiveForeground: Color = .white
|
var isActiveForeground: Color = .white
|
||||||
var isActiveBackground: Color = Color("blueColor")
|
var isActiveBackground: Color = Color("blueColor")
|
||||||
@Binding var isActiveTabBar: TabModel
|
@Binding var selectedTab: TabModel
|
||||||
// @NameSpace private var animation
|
// @NameSpace private var animation
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 0) {
|
VStack {
|
||||||
ForEach(TabModel.allCases, id: \.rawValue) { tab in
|
Spacer()
|
||||||
Button {
|
HStack(spacing: 0) {
|
||||||
isActiveTabBar = tab
|
content
|
||||||
} label: {
|
}
|
||||||
HStack(spacing: 5) {
|
.animation(.smooth(duration: 0.3, extraBounce: 0), value: selectedTab)
|
||||||
Image(systemName: tab.rawValue)
|
.padding(6)
|
||||||
.font(.title)
|
.background(.clear)
|
||||||
.frame(width: 80, height: 35)
|
.mask(RoundedRectangle(cornerRadius: 24, style: .continuous))
|
||||||
}
|
|
||||||
.foregroundStyle(isActiveTabBar == tab ? isActiveForeground : Color("blueColor"))
|
// .background(
|
||||||
.padding(.vertical, 7)
|
// background
|
||||||
.padding(.leading, 15)
|
// .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: 5))
|
||||||
.padding(.trailing, 15)
|
// .shadow(.drop(color: .black.opacity(0.08), radius: 5, x: 5, y: -5)),
|
||||||
.background {
|
// in: .capsule
|
||||||
if isActiveTabBar == tab {
|
// )
|
||||||
Capsule()
|
}
|
||||||
.fill(isActiveBackground)
|
.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)
|
// .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
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
Schedule ICTIS/Helpers/Date+Extensions.swift
Normal file
43
Schedule ICTIS/Helpers/Date+Extensions.swift
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -9,12 +9,72 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ScheduleView: View {
|
struct ScheduleView: View {
|
||||||
@State private var searchText: String = ""
|
@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 {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
SearchBarView(text: $searchText)
|
SearchBarView(text: $searchText)
|
||||||
|
HeaderView()
|
||||||
Spacer()
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
//
|
|
||||||
// SearchBarView.swift
|
|
||||||
// Schedule ICTIS
|
|
||||||
//
|
|
||||||
// Created by G412 on 13.11.2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct SearchBarView: View {
|
struct SearchBarView: View {
|
||||||
@ -13,34 +6,41 @@ struct SearchBarView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
TextField("Ввести номер группы", text: $text)
|
HStack {
|
||||||
.padding(7)
|
Image(systemName: "magnifyingglass")
|
||||||
.padding(.horizontal, 25)
|
.foregroundColor(Color.gray)
|
||||||
.background(.white)
|
.padding(.leading, 10)
|
||||||
.cornerRadius(8)
|
TextField("Ввести номер группы", text: $text)
|
||||||
.overlay(
|
.disableAutocorrection(true)
|
||||||
HStack {
|
.frame(width: 270, height: 45)
|
||||||
Image(systemName: "magnifyingglass")
|
.overlay(
|
||||||
.foregroundColor(.gray)
|
Group {
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
if isEditing {
|
||||||
.padding(.leading, 8)
|
Button {
|
||||||
|
self.text = ""
|
||||||
if isEditing {
|
self.isEditing = false
|
||||||
Button(action: {
|
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||||
self.text = ""
|
} label: {
|
||||||
self.isEditing = false
|
Image(systemName: "xmark.circle.fill")
|
||||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
.padding(.trailing, 30)
|
||||||
}) {
|
.offset(x: 10)
|
||||||
Image(systemName: "multiply.circle.fill")
|
.foregroundColor(.gray)
|
||||||
.foregroundColor(.gray)
|
}
|
||||||
.padding(.trailing, 8)
|
}
|
||||||
}
|
}, alignment: .trailing
|
||||||
}
|
)
|
||||||
|
.onTapGesture {
|
||||||
|
self.isEditing = true
|
||||||
}
|
}
|
||||||
)
|
.onSubmit {
|
||||||
.onTapGesture {
|
self.isEditing = false
|
||||||
self.isEditing = true
|
}
|
||||||
}
|
}
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.fill(.white)
|
||||||
|
)
|
||||||
|
Spacer()
|
||||||
Button {
|
Button {
|
||||||
|
|
||||||
} label: {
|
} label: {
|
||||||
@ -54,8 +54,8 @@ struct SearchBarView: View {
|
|||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 16)
|
.frame(width: 16)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user