Skip to content

Instantly share code, notes, and snippets.

@iandreyshev
Last active October 9, 2024 12:46
Show Gist options
  • Save iandreyshev/47b55d4c7cf3036dacb54b4ea41bd9af to your computer and use it in GitHub Desktop.
Save iandreyshev/47b55d4c7cf3036dacb54b4ea41bd9af to your computer and use it in GitHub Desktop.
Schedule list example
//
// ScrollToItem.swift
// SwiftUIArchitectureSample
//
// Created by Ivan Andreyshev on 04.10.2024.
//
import SwiftUI
struct ScheduleView: View {
@StateObject
private var viewModel = ScheduleViewModel()
@State
private var scrolledID: Int?
var body: some View {
VStack(spacing: 0) {
HStack(alignment: .top) {
ForEach(0..<viewModel.state.days.count, id: \.self) { index in
let day = viewModel.state.days[index]
Button(day.date.titleForDaysList()) {
withAnimation {
scrolledID = day.itemPosToScroll
}
}
.font(.title)
.frame(maxWidth: .infinity)
}
}
.padding(.vertical, 20)
.background(.red)
ScrollView {
LazyVStack(spacing: 20) {
ForEach(0..<viewModel.state.meetings.count, id: \.self) { index in
let item = viewModel.state.meetings[index]
VStack(spacing: 0) {
switch item {
case .emptyDay(let date):
Text(date.formatted(date: .complete, time: .omitted))
.padding(.vertical, 20)
.id(index)
Text("В этот день нет пар, радуйтесь")
case .meeting(let meeting):
if meeting.isFirst {
Text(meeting.startTime.formatted(date: .complete, time: .omitted))
.padding(.vertical, 20)
.id(index)
}
HStack {
VStack {
Text(meeting.title)
.font(.title)
Text(meeting.startTime.formatted(date: .long, time: .shortened))
}
.padding(.vertical, 80)
.frame(maxWidth: .infinity)
.background(.blue)
}
.clipShape(
RoundedRectangle(cornerRadius: 12)
)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(.red, lineWidth: 2)
)
.padding(.horizontal, 20)
}
}
}
}
}
.scrollPosition(id: $scrolledID)
}
.frame(maxWidth: .infinity)
}
}
struct ScheduleState {
var days: [Day] = []
var meetings: [MeetingItem] = []
}
struct Day {
var date: Date
var itemPosToScroll: Int
}
struct Meeting {
var title: String
var startTime: Date
var isFirst: Bool = false
}
enum MeetingItem {
case emptyDay(Date)
case meeting(Meeting)
}
class ScheduleViewModel: ObservableObject {
@Published
var state: ScheduleState = createState()
}
private func createState() -> ScheduleState {
let meetings: [MeetingItem] = [
// Position 0
.meeting(Meeting(title: "Русский язык", startTime: Date(timeIntervalSince1970: 1727769600), isFirst: true)),
.meeting(Meeting(title: "Литература", startTime: Date(timeIntervalSince1970: 1727773200))),
.meeting(Meeting(title: "Программирование", startTime: Date(timeIntervalSince1970: 1727776800))),
.meeting(Meeting(title: "Ужин", startTime: Date(timeIntervalSince1970: 1727780400))),
.meeting(Meeting(title: "Вечернее ООП", startTime: Date(timeIntervalSince1970: 1727784000))),
// Position 5
.emptyDay(Date(timeIntervalSince1970: 1727856000)),
// Position 6
.meeting(Meeting(title: "Поход в честер", startTime: Date(timeIntervalSince1970: 1727942400), isFirst: true)),
.meeting(Meeting(title: "Сангрита", startTime: Date(timeIntervalSince1970: 1727960400))),
.meeting(Meeting(title: "Шави", startTime: Date(timeIntervalSince1970: 1727967600))),
.meeting(Meeting(title: "Кальянная", startTime: Date(timeIntervalSince1970: 1727974800))),
.meeting(Meeting(title: "Вечерний Ассемблер", startTime: Date(timeIntervalSince1970: 1727982000))),
// Position 11
.meeting(Meeting(title: "Зарядка", startTime: Date(timeIntervalSince1970: 1728028800), isFirst: true)),
.meeting(Meeting(title: "Растяжка", startTime: Date(timeIntervalSince1970: 1728043200))),
.meeting(Meeting(title: "Велогонки", startTime: Date(timeIntervalSince1970: 1728050400))),
.meeting(Meeting(title: "Автогонки", startTime: Date(timeIntervalSince1970: 1728064800))),
.meeting(Meeting(title: "Полёт в космос", startTime: Date(timeIntervalSince1970: 1728075600)))
]
return .init(
days: [
Day(date: Date(timeIntervalSince1970: 1727769600), itemPosToScroll: 0),
Day(date: Date(timeIntervalSince1970: 1727856000), itemPosToScroll: 5),
Day(date: Date(timeIntervalSince1970: 1727942400), itemPosToScroll: 6),
Day(date: Date(timeIntervalSince1970: 1728028800), itemPosToScroll: 11)
],
meetings: meetings
)
}
extension Date {
func titleForDaysList() -> String {
let components = Calendar.current.dateComponents([.day, .weekday], from: self)
let weekDayStr = DateFormatter().shortWeekdaySymbols[components.weekday ?? 0]
return "\(components.day ?? 0)\n\(weekDayStr)"
}
}
#Preview {
ScheduleView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment