161 lines
4.7 KiB
Swift
161 lines
4.7 KiB
Swift
//
|
||
// DateNavView.swift
|
||
// dimensionhub
|
||
//
|
||
// Created by 安礼成 on 2025/2/20.
|
||
//
|
||
|
||
import Foundation
|
||
import SwiftUI
|
||
import Observation
|
||
|
||
@Observable
|
||
final class DateNavModel {
|
||
|
||
struct DateModel: Codable, Identifiable {
|
||
struct Month: Codable {
|
||
let id: String
|
||
let name: String
|
||
let disabled: Bool
|
||
}
|
||
|
||
let id = UUID().uuidString
|
||
let year: String
|
||
let months: [Month]
|
||
|
||
enum CodingKeys: String, CodingKey {
|
||
case year
|
||
case months
|
||
}
|
||
}
|
||
|
||
var dateModels: [DateModel]
|
||
|
||
init() {
|
||
self.dateModels = []
|
||
}
|
||
|
||
@MainActor
|
||
func loadDateCells(userId: String) async {
|
||
self.dateModels = await getDateModelData(userId: userId)
|
||
}
|
||
|
||
// 增加了一个缓存的逻辑
|
||
private func getDateModelData(userId: String) async -> [DateModel] {
|
||
let models = await DataCache.shared.getDateModelCache()
|
||
if models.count > 0 {
|
||
return models
|
||
} else {
|
||
let response = await API.getDateIndex(userId: userId, as: [DateModel].self)
|
||
switch response {
|
||
case .error(let code, let message):
|
||
return []
|
||
case .result(let models):
|
||
await DataCache.shared.setDateModelCache(models)
|
||
return models
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
struct DateNavView: View {
|
||
@AppStorage("userId") private var userId: String = Utils.defaultUserId()
|
||
@State var navModel = DateNavModel()
|
||
|
||
@Binding var selectGroupId: String
|
||
@Binding var showDateNavPopover: Bool
|
||
|
||
var onSelected: (String) -> Void
|
||
|
||
var body: some View {
|
||
ScrollView(.vertical, showsIndicators: false) {
|
||
VStack(alignment: .center) {
|
||
ForEach(navModel.dateModels) { model in
|
||
VStack(alignment: .leading, spacing: 10) {
|
||
Text(model.year)
|
||
HStack {
|
||
ForEach(model.months, id: \.id) { month in
|
||
if month.disabled {
|
||
DateDisabledItemView(datetime: month.name)
|
||
} else {
|
||
DateItemView(id: month.id,
|
||
datetime: month.name,
|
||
selected: month.id == selectGroupId,
|
||
showDateNavPopover: $showDateNavPopover,
|
||
onSelected: onSelected)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.task {
|
||
await self.navModel.loadDateCells(userId: self.userId)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
extension DateNavView {
|
||
|
||
struct DateItemView: View {
|
||
let id: String
|
||
let datetime: String
|
||
@State var selected: Bool
|
||
@Binding var showDateNavPopover: Bool
|
||
|
||
var onSelected: (String) -> Void
|
||
|
||
var body: some View {
|
||
Rectangle()
|
||
.frame(width: 80, height: 50)
|
||
.foregroundColor(selected ? Color.black : Color.white)
|
||
.cornerRadius(10)
|
||
.overlay {
|
||
RoundedRectangle(cornerRadius: 10)
|
||
.stroke(Color.black, lineWidth: 1)
|
||
Text(datetime)
|
||
.foregroundColor(selected ? Color.white : Color.black)
|
||
.font(.system(size: 20, weight: .regular))
|
||
|
||
}
|
||
.onTapGesture {
|
||
// 如果之前的状态就是选中状态,则不触发回调函数
|
||
if !self.selected {
|
||
onSelected(id)
|
||
}
|
||
|
||
self.selected = true
|
||
self.showDateNavPopover = false
|
||
}
|
||
}
|
||
}
|
||
|
||
struct DateDisabledItemView: View {
|
||
let datetime: String
|
||
|
||
var body: some View {
|
||
Rectangle()
|
||
.frame(width: 80, height: 50)
|
||
.foregroundColor(Color.white)
|
||
.cornerRadius(10)
|
||
.overlay {
|
||
RoundedRectangle(cornerRadius: 10)
|
||
.stroke(style: StrokeStyle(lineWidth: 1, dash: [4]))
|
||
Text(datetime)
|
||
.foregroundColor(Color.yellow)
|
||
.font(.system(size: 20, weight: .regular))
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//#Preview {
|
||
// DateNavView()
|
||
//}
|