TeachMate/TeachMate/Views/CourseFormView.swift

222 lines
6.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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())
}