You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.3 KiB
150 lines
5.3 KiB
import SwiftUI
|
|
|
|
// MARK: - Calendar Event Input Component
|
|
struct CalendarInputView: View {
|
|
@Binding var eventTitle: String
|
|
@Binding var eventDescription: String
|
|
@Binding var startDate: Date
|
|
@Binding var endDate: Date
|
|
@Binding var location: String
|
|
@FocusState var focusedField: CalendarField?
|
|
|
|
// Calendar field enum
|
|
enum CalendarField: Hashable {
|
|
case title, description, location
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(spacing: 16) {
|
|
// Event title
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text("event_title".localized)
|
|
.font(.subheadline)
|
|
.foregroundColor(.primary)
|
|
Text("*")
|
|
.foregroundColor(.red)
|
|
Spacer()
|
|
}
|
|
|
|
TextField("event_title_placeholder".localized, text: $eventTitle)
|
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
.focused($focusedField, equals: .title)
|
|
}
|
|
|
|
// Event description
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text("event_description".localized)
|
|
.font(.subheadline)
|
|
.foregroundColor(.primary)
|
|
Spacer()
|
|
}
|
|
|
|
TextField("event_description_placeholder".localized, text: $eventDescription)
|
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
.focused($focusedField, equals: .description)
|
|
}
|
|
|
|
// Start time
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text("start_time".localized)
|
|
.font(.subheadline)
|
|
.foregroundColor(.primary)
|
|
Text("*")
|
|
.foregroundColor(.red)
|
|
Spacer()
|
|
}
|
|
|
|
DatePicker("start_time".localized, selection: $startDate, displayedComponents: [.date, .hourAndMinute])
|
|
.datePickerStyle(CompactDatePickerStyle())
|
|
.labelsHidden()
|
|
}
|
|
|
|
// End time
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text("end_time".localized)
|
|
.font(.subheadline)
|
|
.foregroundColor(.primary)
|
|
Text("*")
|
|
.foregroundColor(.red)
|
|
Spacer()
|
|
}
|
|
|
|
DatePicker("end_time".localized, selection: $endDate, displayedComponents: [.date, .hourAndMinute])
|
|
.datePickerStyle(CompactDatePickerStyle())
|
|
.labelsHidden()
|
|
}
|
|
|
|
// Location
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text("event_location".localized)
|
|
.font(.subheadline)
|
|
.foregroundColor(.primary)
|
|
Spacer()
|
|
}
|
|
|
|
TextField("event_location_placeholder".localized, text: $location)
|
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
.focused($focusedField, equals: .location)
|
|
}
|
|
|
|
// Time validation hint
|
|
if endDate <= startDate {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Image(systemName: "exclamationmark.triangle")
|
|
.font(.caption)
|
|
.foregroundColor(.orange)
|
|
|
|
Text("time_setting_hint".localized)
|
|
.font(.caption)
|
|
.foregroundColor(.primary)
|
|
|
|
Spacer()
|
|
}
|
|
|
|
Text("end_time_must_be_after_start_time".localized)
|
|
.font(.caption)
|
|
.foregroundColor(.orange)
|
|
}
|
|
.padding(.horizontal, 12)
|
|
.padding(.vertical, 8)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 8)
|
|
.fill(Color.orange.opacity(0.1))
|
|
)
|
|
}
|
|
}
|
|
.toolbar {
|
|
ToolbarItemGroup(placement: .keyboard) {
|
|
Spacer()
|
|
Button("complete".localized) {
|
|
focusedField = nil
|
|
}
|
|
.foregroundColor(.blue)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
}
|
|
.onAppear {
|
|
// 设置默认时间
|
|
if startDate == Date() {
|
|
startDate = Date()
|
|
endDate = Calendar.current.date(byAdding: .hour, value: 1, to: startDate) ?? startDate
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
CalendarInputView(
|
|
eventTitle: .constant(""),
|
|
eventDescription: .constant(""),
|
|
startDate: .constant(Date()),
|
|
endDate: .constant(Calendar.current.date(byAdding: .hour, value: 1, to: Date()) ?? Date()),
|
|
location: .constant("")
|
|
)
|
|
} |