182 lines
6.8 KiB
Swift
182 lines
6.8 KiB
Swift
//
|
||
// MonthTabView.swift
|
||
// Schedule ICTIS
|
||
//
|
||
// Created by Mironov Egor on 10.12.2024.
|
||
//
|
||
|
||
import SwiftUI
|
||
|
||
struct MonthTabView: View {
|
||
@State private var currentMonthIndex: Int = 1
|
||
@State private var monthSlider: [[Date.MonthWeek]] = []
|
||
@State private var createMonth: Bool = false
|
||
@State private var currentWeekIndex: Int = 0
|
||
@ObservedObject var vm: ScheduleViewModel
|
||
var body: some View {
|
||
VStack {
|
||
HStack (spacing: 34) {
|
||
ForEach(MockData.daysOfWeek.indices, id: \.self) { index in
|
||
Text(MockData.daysOfWeek[index])
|
||
.font(.system(size: 15, weight: .semibold))
|
||
.foregroundColor(MockData.daysOfWeek[index] == "Вс" ? Color(.red) : Color("customGray2"))
|
||
.padding(.top, 13)
|
||
.foregroundColor(.gray)
|
||
}
|
||
}
|
||
.padding(.top, 14)
|
||
TabView(selection: $currentMonthIndex) {
|
||
ForEach(monthSlider.indices, id: \.self) { index in
|
||
let month = monthSlider[index]
|
||
MonthView(month)
|
||
.tag(index)
|
||
}
|
||
}
|
||
.padding(.top, -25)
|
||
.padding(.bottom, -10)
|
||
.padding(.horizontal, -15)
|
||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||
}
|
||
.onAppear(perform: {
|
||
vm.updateSelectedDayIndex()
|
||
if monthSlider.isEmpty {
|
||
let currentMonth = Date().fetchMonth(vm.selectedDay)
|
||
|
||
if let firstDate = currentMonth.first?.week[0].date {
|
||
monthSlider.append(firstDate.createPreviousMonth())
|
||
}
|
||
|
||
monthSlider.append(currentMonth)
|
||
|
||
if let lastDate = currentMonth.last?.week[6].date {
|
||
monthSlider.append(lastDate.createNextMonth())
|
||
}
|
||
}
|
||
})
|
||
.onChange(of: currentMonthIndex, initial: false) { oldValue, newValue in
|
||
if newValue == 0 || newValue == (monthSlider.count - 1) {
|
||
createMonth = true
|
||
}
|
||
}
|
||
}
|
||
|
||
@ViewBuilder
|
||
func MonthView(_ month: [Date.MonthWeek]) -> some View {
|
||
VStack (spacing: 10) {
|
||
ForEach(month.indices, id: \.self) { index in
|
||
let week = month[index].week
|
||
WeekView(week)
|
||
}
|
||
}
|
||
.background {
|
||
GeometryReader {
|
||
let minX = $0.frame(in: .global).minX
|
||
|
||
Color.clear
|
||
.preference(key: OffsetKey.self, value: minX)
|
||
.onPreferenceChange(OffsetKey.self) { value in
|
||
if (abs(value.rounded()) - 20) < 5 && createMonth {
|
||
paginateMonth()
|
||
|
||
createMonth = false
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
@ViewBuilder
|
||
func WeekView(_ week: [Date.WeekDay]) -> some View {
|
||
HStack (spacing: 23) {
|
||
ForEach(week) { day in
|
||
VStack {
|
||
Text(day.date.format("dd"))
|
||
.font(.system(size: 15, weight: .bold))
|
||
.foregroundStyle(isDateInCurrentMonth(day.date) ? isSameDate(day.date, vm.selectedDay) ? Color.white : Color.black: isSameDate(day.date, vm.selectedDay) ? Color.white : Color("greyForDaysInMonthTabView"))
|
||
}
|
||
.frame(width: 30, height: 30, alignment: .center)
|
||
.background( content: {
|
||
Group {
|
||
if isSameDate(day.date, vm.selectedDay) {
|
||
Color("blueColor")
|
||
}
|
||
else {
|
||
Color("background")
|
||
}
|
||
if isSameDate(day.date, vm.selectedDay) {
|
||
Color("blueColor")
|
||
}
|
||
}
|
||
}
|
||
)
|
||
.overlay (
|
||
Group {
|
||
if day.date.isToday && !isSameDate(day.date, vm.selectedDay) {
|
||
RoundedRectangle(cornerRadius: 100)
|
||
.stroke(Color("blueColor"), lineWidth: 2)
|
||
}
|
||
}
|
||
)
|
||
.cornerRadius(15)
|
||
.onTapGesture {
|
||
if isSameWeek(day.date, vm.selectedDay) {
|
||
print("На одной неделе")
|
||
}
|
||
else {
|
||
var difBetweenWeeks = weeksBetween(startDate: vm.selectedDay, endDate: day.date)
|
||
if day.date < vm.selectedDay {
|
||
difBetweenWeeks = difBetweenWeeks * -1
|
||
}
|
||
print(difBetweenWeeks)
|
||
vm.fetchWeekSchedule("", difBetweenWeeks)
|
||
}
|
||
vm.selectedDay = day.date
|
||
vm.updateSelectedDayIndex()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func paginateMonth(_ indexOfWeek: Int = 0) {
|
||
let calendar = Calendar.current
|
||
if monthSlider.indices.contains(currentMonthIndex) {
|
||
if let firstDate = monthSlider[currentMonthIndex].first?.week[0].date,
|
||
currentMonthIndex == 0 {
|
||
// switch (vm.numOfGroup) {
|
||
// case "":
|
||
// vm.week -= 1
|
||
// default:
|
||
// vm.fetchWeekSchedule("new week", -1)
|
||
// }
|
||
monthSlider.insert(firstDate.createPreviousMonth(), at: 0)
|
||
monthSlider.removeLast()
|
||
currentMonthIndex = 1
|
||
vm.selectedDay = calendar.date(byAdding: .weekOfYear, value: -5, to: vm.selectedDay) ?? Date.init()
|
||
vm.updateSelectedDayIndex()
|
||
vm.fetchWeekSchedule("", -5)
|
||
}
|
||
|
||
if let lastDate = monthSlider[currentMonthIndex].last?.week[6].date,
|
||
currentMonthIndex == (monthSlider.count - 1) {
|
||
// switch (vm.numOfGroup) {
|
||
// case "":
|
||
// vm.week += 1
|
||
// default:
|
||
// vm.fetchWeekSchedule("new week", 1)
|
||
// }
|
||
monthSlider.append(lastDate.createNextMonth())
|
||
monthSlider.removeFirst()
|
||
currentMonthIndex = monthSlider.count - 2
|
||
vm.selectedDay = calendar.date(byAdding: .weekOfYear, value: 5, to: vm.selectedDay) ?? Date.init()
|
||
vm.updateSelectedDayIndex()
|
||
vm.fetchWeekSchedule("", 5)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#Preview {
|
||
ContentView()
|
||
}
|