137 lines
5.2 KiB
Dart
137 lines
5.2 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
import '../../app/app_controller.dart';
|
||
import '../../app/app_theme.dart';
|
||
import '../../data/json_schedule_import.dart';
|
||
import '../../domain/course.dart';
|
||
|
||
class ImportPreview extends StatefulWidget {
|
||
const ImportPreview({
|
||
super.key,
|
||
required this.draft,
|
||
required this.controller,
|
||
});
|
||
final ImportDraft draft;
|
||
final AppController controller;
|
||
@override
|
||
State<ImportPreview> createState() => _ImportPreviewState();
|
||
}
|
||
|
||
class _ImportPreviewState extends State<ImportPreview> {
|
||
bool _clearConfirmed = false, _busy = false;
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final draft = widget.draft, empty = draft.courses.isEmpty;
|
||
final allowed =
|
||
!_busy && (!empty || (draft.explicitlyEmpty && _clearConfirmed));
|
||
return SafeArea(
|
||
child: SingleChildScrollView(
|
||
padding: const EdgeInsets.fromLTRB(24, 8, 24, 28),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
const Text(
|
||
'确认你的课表',
|
||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'${draft.courses.length} 条课程安排 · ${draft.source == CourseSource.demo ? '示例体验' : '导入预览'}',
|
||
style: const TextStyle(color: river),
|
||
),
|
||
if (draft.semesterLabel != null) Text('学期:${draft.semesterLabel}'),
|
||
const SizedBox(height: 18),
|
||
if (empty)
|
||
Text(draft.explicitlyEmpty ? '此操作会清空当前课表。' : '没有识别到课程,当前课表保持不变。'),
|
||
if (empty && draft.explicitlyEmpty)
|
||
CheckboxListTile(
|
||
value: _clearConfirmed,
|
||
onChanged: (v) => setState(() => _clearConfirmed = v ?? false),
|
||
title: const Text('确认清空当前课表'),
|
||
contentPadding: EdgeInsets.zero,
|
||
),
|
||
for (final c in draft.courses)
|
||
Padding(
|
||
padding: const EdgeInsets.only(bottom: 10),
|
||
child: SurfaceCard(
|
||
padding: const EdgeInsets.all(14),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
c.name,
|
||
style: const TextStyle(fontWeight: FontWeight.w700),
|
||
),
|
||
const SizedBox(height: 5),
|
||
Text(
|
||
'${c.teacher} · ${c.room}',
|
||
style: const TextStyle(fontSize: 12),
|
||
),
|
||
const SizedBox(height: 4),
|
||
Text(
|
||
'周${const ['一', '二', '三', '四', '五', '六', '日'][c.weekday - 1]} · 第 ${c.startPeriod}–${c.endPeriod} 节',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: ink.withValues(alpha: 0.5),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
if (widget.controller.snapshot.settings.semester == null &&
|
||
draft.source != CourseSource.demo)
|
||
const Padding(
|
||
padding: EdgeInsets.only(bottom: 16),
|
||
child: Text(
|
||
'导入后请在设置中选择真实学期开始日,课表与提醒才会显示。',
|
||
style: TextStyle(fontSize: 12, height: 1.6),
|
||
),
|
||
),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: FilledButton(
|
||
onPressed: allowed
|
||
? () async {
|
||
setState(() => _busy = true);
|
||
await widget.controller.applyImport(
|
||
draft,
|
||
confirmedEmpty: _clearConfirmed,
|
||
);
|
||
if (!context.mounted) return;
|
||
if (widget.controller.lastError == null) {
|
||
Navigator.pop(context, true);
|
||
} else {
|
||
setState(() => _busy = false);
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text(widget.controller.lastError!),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
: null,
|
||
child: Text(
|
||
_busy
|
||
? '正在保存…'
|
||
: draft.source == CourseSource.demo
|
||
? '开始体验'
|
||
: '确认导入',
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Center(
|
||
child: TextButton(
|
||
onPressed: _busy ? null : () => Navigator.pop(context, false),
|
||
child: const Text('取消'),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|