250 lines
7.8 KiB
Dart
250 lines
7.8 KiB
Dart
import 'package:fluent_ui/fluent_ui.dart';
|
|
import 'package:flutter/material.dart' show ButtonSegment, SegmentedButton;
|
|
import 'package:syncfusion_flutter_calendar/calendar.dart' as calendar;
|
|
import 'package:task_hub/models/schedule.dart';
|
|
import 'package:task_hub/widgets/schedule_dialog.dart';
|
|
|
|
class AppointmentDataSource extends calendar.CalendarDataSource {
|
|
AppointmentDataSource(List<calendar.Appointment> source) {
|
|
appointments = source;
|
|
}
|
|
}
|
|
|
|
class SchedulePage extends StatefulWidget {
|
|
const SchedulePage({super.key});
|
|
|
|
@override
|
|
State<SchedulePage> createState() => _SchedulePageState();
|
|
}
|
|
|
|
class _SchedulePageState extends State<SchedulePage> {
|
|
final calendar.CalendarController _calendarController =
|
|
calendar.CalendarController();
|
|
late List<calendar.Appointment> _appointments = [];
|
|
String _viewType = 'week';
|
|
|
|
void _addSchedule(Schedule? schedule) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => ScheduleDialog(
|
|
schedule: schedule,
|
|
onSave: (schedule) {
|
|
setState(() {
|
|
final appointment = calendar.Appointment(
|
|
id: schedule.id,
|
|
subject: schedule.title,
|
|
startTime: schedule.startTime,
|
|
endTime: schedule.endTime,
|
|
);
|
|
_appointments.add(appointment);
|
|
});
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
void _editSchedule(calendar.Appointment appointment) {
|
|
final schedule = Schedule(
|
|
id: appointment.id as int,
|
|
title: appointment.subject,
|
|
startTime: appointment.startTime,
|
|
endTime: appointment.endTime,
|
|
);
|
|
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => ScheduleDialog(
|
|
schedule: schedule,
|
|
onSave: (editedSchedule) {
|
|
setState(() {
|
|
final index = _appointments.indexWhere(
|
|
(t) => t.id == editedSchedule.id,
|
|
);
|
|
if (index != -1) {
|
|
final appointment = calendar.Appointment(
|
|
id: editedSchedule.id,
|
|
subject: editedSchedule.title,
|
|
startTime: editedSchedule.startTime,
|
|
endTime: editedSchedule.endTime,
|
|
);
|
|
_appointments[index] = appointment;
|
|
}
|
|
});
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
void _deleteSchedule(calendar.Appointment appointment) async {
|
|
await showDialog<String>(
|
|
context: context,
|
|
builder: (context) => ContentDialog(
|
|
title: const Text('确认删除该日程?'),
|
|
actions: [
|
|
Button(
|
|
child: const Text('取消'),
|
|
onPressed: () => Navigator.pop(context),
|
|
),
|
|
FilledButton(
|
|
child: const Text('确认'),
|
|
onPressed: () {
|
|
setState(() {
|
|
_appointments.removeWhere(
|
|
(schedule) => schedule.id == appointment.id,
|
|
);
|
|
});
|
|
Navigator.pop(context);
|
|
// Delete file here
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ScaffoldPage.withPadding(
|
|
header: PageHeader(
|
|
title: const Text('日程安排', style: TextStyle(color: Colors.white)),
|
|
commandBar: CommandBar(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
primaryItems: [
|
|
CommandBarButton(
|
|
icon: const Icon(FluentIcons.add, color: Colors.white),
|
|
label: const Text('添加日程', style: TextStyle(color: Colors.white)),
|
|
onPressed: () => _addSchedule(null),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
content: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
SegmentedButton<String>(
|
|
showSelectedIcon: false,
|
|
selected: <String>{_viewType},
|
|
onSelectionChanged: (Set<String> value) {
|
|
setState(() {
|
|
_viewType = value.first;
|
|
switch (_viewType) {
|
|
case 'week':
|
|
_calendarController.view = calendar.CalendarView.week;
|
|
break;
|
|
case 'month':
|
|
_calendarController.view = calendar.CalendarView.month;
|
|
break;
|
|
case 'schedule':
|
|
_calendarController.view = calendar.CalendarView.schedule;
|
|
break;
|
|
}
|
|
});
|
|
},
|
|
segments: const [
|
|
ButtonSegment(
|
|
value: 'week',
|
|
label: Text(
|
|
'周视图',
|
|
style: TextStyle(
|
|
fontFamily: 'CustomFont',
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
ButtonSegment(
|
|
value: 'month',
|
|
label: Text(
|
|
'月视图',
|
|
style: TextStyle(
|
|
fontFamily: 'CustomFont',
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
ButtonSegment(
|
|
value: 'schedule',
|
|
label: Text(
|
|
'日程视图',
|
|
style: TextStyle(
|
|
fontFamily: 'CustomFont',
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 20),
|
|
Expanded(child: Card(child: _buildSfCalendar())),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSfCalendar() {
|
|
return calendar.SfCalendar(
|
|
view: calendar.CalendarView.week,
|
|
controller: _calendarController,
|
|
backgroundColor: Colors.grey[20],
|
|
headerStyle: calendar.CalendarHeaderStyle(
|
|
backgroundColor: Colors.grey[20],
|
|
),
|
|
dataSource: AppointmentDataSource(_appointments),
|
|
firstDayOfWeek: 1,
|
|
showDatePickerButton: true,
|
|
showNavigationArrow: true,
|
|
showTodayButton: true,
|
|
allowViewNavigation: true,
|
|
// 月份视图设置
|
|
monthViewSettings: calendar.MonthViewSettings(
|
|
appointmentDisplayMode:
|
|
calendar.MonthAppointmentDisplayMode.appointment,
|
|
showAgenda: true,
|
|
),
|
|
scheduleViewSettings: calendar.ScheduleViewSettings(
|
|
monthHeaderSettings: calendar.MonthHeaderSettings(
|
|
backgroundColor: Colors.grey[20],
|
|
height: 85,
|
|
),
|
|
),
|
|
// 时间区域设置
|
|
timeSlotViewSettings: calendar.TimeSlotViewSettings(
|
|
startHour: 7,
|
|
endHour: 23,
|
|
timeFormat: 'HH:mm',
|
|
timeInterval: Duration(minutes: 30),
|
|
timeRulerSize: 60,
|
|
),
|
|
// 选择日期回调
|
|
onTap: (calendar.CalendarTapDetails details) {
|
|
if (_calendarController.view == calendar.CalendarView.week) {
|
|
if (details.targetElement == calendar.CalendarElement.calendarCell) {
|
|
if (!details.date!.isBefore(DateTime.now())) {
|
|
final schedule = Schedule(
|
|
title: '',
|
|
startTime: details.date!,
|
|
endTime: details.date!.add(Duration(minutes: 30)),
|
|
);
|
|
_addSchedule(schedule);
|
|
}
|
|
} else if (details.targetElement ==
|
|
calendar.CalendarElement.appointment) {
|
|
if (details.appointments?.length == 1) {
|
|
_editSchedule(details.appointments!.first);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
// 选择日程回调
|
|
onLongPress: (calendar.CalendarLongPressDetails details) async {
|
|
if (details.targetElement == calendar.CalendarElement.appointment) {
|
|
if (details.appointments?.length == 1) {
|
|
_deleteSchedule(details.appointments!.first);
|
|
}
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|