222 lines
6.6 KiB
Swift
222 lines
6.6 KiB
Swift
//
|
||
// CourseFormView.swift
|
||
// TeachMate
|
||
//
|
||
// Created by Hongli on 2025/3/18.
|
||
//
|
||
|
||
import SwiftUI
|
||
import SwiftData
|
||
|
||
// 课程表单视图
|
||
struct CourseFormView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@Environment(\.modelContext) private var modelContext
|
||
@Environment(\.colorScheme) private var colorScheme
|
||
@Query private var semesters: [Semester]
|
||
|
||
enum FormMode {
|
||
case add
|
||
case edit(CourseModel)
|
||
}
|
||
|
||
let mode: FormMode
|
||
let onSave: (CourseModel) -> Void
|
||
|
||
@State private var name: String = ""
|
||
@State private var selectedColor: String = "#FCF3CF" // 默认黄色
|
||
@State private var selectedSemester: Semester?
|
||
|
||
// 可选颜色
|
||
private let colorOptions = [
|
||
"#FCF3CF", // 黄色
|
||
"#D6EAF8", // 蓝色
|
||
"#FADBD8", // 红色
|
||
"#D5F5E3", // 绿色
|
||
"#E8DAEF" // 紫色
|
||
]
|
||
|
||
private var isFormValid: Bool {
|
||
!name.isEmpty && selectedSemester != nil
|
||
}
|
||
|
||
var body: some View {
|
||
NavigationStack {
|
||
courseFormContent
|
||
.navigationTitle(navigationTitle)
|
||
.toolbarRole(.editor)
|
||
.toolbar {
|
||
ToolbarItem(placement: .cancellationAction) {
|
||
Button("取消") {
|
||
dismiss()
|
||
}
|
||
}
|
||
|
||
ToolbarItem(placement: .confirmationAction) {
|
||
Button("保存") {
|
||
saveCourse()
|
||
dismiss()
|
||
}
|
||
.disabled(!isFormValid)
|
||
}
|
||
}
|
||
.onAppear {
|
||
setupInitialValues()
|
||
}
|
||
}
|
||
}
|
||
|
||
// Main content view
|
||
private var courseFormContent: some View {
|
||
ZStack {
|
||
// Background
|
||
(colorScheme == .dark ? Color.black : Color.gray.opacity(0.1))
|
||
.ignoresSafeArea()
|
||
|
||
// Main content with horizontal layout
|
||
HStack(spacing: 0) {
|
||
// Left side - Form content
|
||
formFieldsSection
|
||
}
|
||
.frame(minWidth: 600, idealWidth: 700, maxHeight: .infinity)
|
||
}
|
||
}
|
||
|
||
// Form fields section
|
||
private var formFieldsSection: some View {
|
||
ScrollView(.vertical) {
|
||
VStack(spacing: 24) {
|
||
// 课程信息
|
||
FormSection(title: "课程信息") {
|
||
courseInfoSection
|
||
}
|
||
|
||
// 颜色选择
|
||
FormSection(title: "课程颜色") {
|
||
colorSelectionSection
|
||
}
|
||
}
|
||
.padding()
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
.frame(minWidth: 300, idealWidth: 350, maxWidth: .infinity)
|
||
}
|
||
|
||
// Course information section
|
||
private var courseInfoSection: some View {
|
||
VStack(alignment: .leading, spacing: 16) {
|
||
// Course name input
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
TextField("课程名称", text: $name)
|
||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||
.autocorrectionDisabled()
|
||
.frame(maxWidth: .infinity)
|
||
|
||
Text("请输入课程的完整名称")
|
||
.font(.caption)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
|
||
Divider()
|
||
|
||
// 学期选择
|
||
HStack {
|
||
Text("学期:")
|
||
.foregroundStyle(.secondary)
|
||
|
||
Spacer()
|
||
|
||
Picker("学期", selection: $selectedSemester) {
|
||
if semesters.isEmpty {
|
||
Text("请先创建学期").tag(nil as Semester?)
|
||
} else {
|
||
ForEach(semesters) { semester in
|
||
Text(semester.title).tag(semester as Semester?)
|
||
}
|
||
}
|
||
}
|
||
.pickerStyle(.menu)
|
||
}
|
||
|
||
Divider()
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
|
||
// Color selection section
|
||
private var colorSelectionSection: some View {
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
HStack {
|
||
ForEach(colorOptions, id: \.self) { colorHex in
|
||
Circle()
|
||
.fill(Color(hex: colorHex) ?? .gray)
|
||
.frame(width: 30, height: 30)
|
||
.overlay(
|
||
Circle()
|
||
.stroke(selectedColor == colorHex ? Color.black : Color.clear, lineWidth: 2)
|
||
)
|
||
.onTapGesture {
|
||
selectedColor = colorHex
|
||
}
|
||
.padding(5)
|
||
}
|
||
}
|
||
|
||
Text("选择一个颜色来标识课程")
|
||
.font(.caption)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
|
||
private var navigationTitle: String {
|
||
switch mode {
|
||
case .add:
|
||
return "添加课程"
|
||
case .edit:
|
||
return "编辑课程"
|
||
}
|
||
}
|
||
|
||
private func setupInitialValues() {
|
||
switch mode {
|
||
case .add:
|
||
// 如果有当前学期,默认选择它
|
||
selectedSemester = semesters.first(where: { $0.isCurrent }) ?? semesters.first
|
||
case .edit(let course):
|
||
name = course.name
|
||
selectedColor = course.colorHex
|
||
selectedSemester = course.semester
|
||
}
|
||
}
|
||
|
||
private func saveCourse() {
|
||
switch mode {
|
||
case .add:
|
||
guard let semester = selectedSemester else { return }
|
||
|
||
let newCourse = CourseModel(
|
||
name: name,
|
||
colorHex: selectedColor
|
||
)
|
||
newCourse.semester = semester
|
||
onSave(newCourse)
|
||
|
||
case .edit(let course):
|
||
course.name = name
|
||
course.colorHex = selectedColor
|
||
course.semester = selectedSemester
|
||
onSave(course)
|
||
}
|
||
}
|
||
}
|
||
#Preview("添加课程") {
|
||
CourseFormView(mode: .add, onSave: { _ in })
|
||
.modelContainer(PreviewData.createContainer())
|
||
}
|
||
|
||
#Preview("编辑课程") {
|
||
CourseFormView(mode: .edit(PreviewData.createSampleCourse()), onSave: { _ in })
|
||
.modelContainer(PreviewData.createContainer())
|
||
}
|