新增活動申請

This commit is contained in:
jasonchenwork 2025-06-03 13:01:49 +08:00
parent a6123b506f
commit 8d9f204a44
2 changed files with 243 additions and 5 deletions

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'activity_submit.dart';
class ActivityListPage extends StatefulWidget {
const ActivityListPage({Key? key}) : super(key: key);
@ -93,7 +94,7 @@ class _ActivityListPageState extends State<ActivityListPage> {
children: [
TextButton(
onPressed: () {
// TODO:
// TODO :
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
@ -110,20 +111,27 @@ class _ActivityListPageState extends State<ActivityListPage> {
),
child: const Text('查看詳情'),
),
const SizedBox(width: 8),
if (canRegister && id != null)
if (canRegister && id != null) ...[
const SizedBox(width: 8),
ElevatedButton(
onPressed: () => openRegisterModal(id),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 12,
),
),
child: const Text('我要報名'),
child: const Text(
'我要報名',
style: TextStyle(color: Colors.white),
),
),
],
],
),
],
@ -188,7 +196,13 @@ class _ActivityListPageState extends State<ActivityListPage> {
alignment: Alignment.centerRight,
child: ElevatedButton.icon(
onPressed: () {
// TODO:
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) => const ActivitySubmitPage(),
),
);
},
icon: const Icon(Icons.add),
label: const Text('提交活動申請'),

224
lib/activity_submit.dart Normal file
View File

@ -0,0 +1,224 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:io';
class ActivitySubmitPage extends StatefulWidget {
const ActivitySubmitPage({super.key});
@override
State<ActivitySubmitPage> createState() => _ActivitySubmitPageState();
}
class _ActivitySubmitPageState extends State<ActivitySubmitPage> {
final _formKey = GlobalKey<FormState>();
final _titleController = TextEditingController();
final _locationController = TextEditingController();
final _descriptionController = TextEditingController();
DateTime? _startDate;
DateTime? _endDate;
String _needRegister = '';
String _repeatOption = 'none';
int _repeatCount = 1;
File? _poster;
Future<void> _selectDateTime(bool isStart) async {
final now = DateTime.now();
final date = await showDatePicker(
context: context,
initialDate: now,
firstDate: now,
lastDate: DateTime(now.year + 2),
);
if (date == null) return;
final time = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(now),
);
if (time == null) return;
final selected = DateTime(
date.year,
date.month,
date.day,
time.hour,
time.minute,
);
setState(() {
if (isStart) {
_startDate = selected;
} else {
_endDate = selected;
}
});
}
void _submitForm() {
if (!_formKey.currentState!.validate()) return;
if (_startDate == null || _endDate == null) {
_showAlert('請選擇開始與結束時間');
return;
}
if (_endDate!.isBefore(_startDate!)) {
_showAlert('結束時間必須晚於開始時間!');
return;
}
final formatter = DateFormat('yyyy-MM-dd HH:mm');
final message =
StringBuffer()
..writeln('活動申請已送出')
..writeln('名稱:${_titleController.text}')
..writeln('開始時間:${formatter.format(_startDate!)}')
..writeln('結束時間:${formatter.format(_endDate!)}')
..writeln('地點:${_locationController.text}')
..writeln('描述:${_descriptionController.text}')
..writeln('需報名統計:$_needRegister');
if (_repeatOption != 'none') {
final map = {'weekly': '每週', 'biweekly': '每兩週', 'monthly': '每月'};
message.writeln('重複設定:${map[_repeatOption]},共重複 $_repeatCount');
}
if (_poster != null) {
message.writeln('檔案名稱:${_poster!.path.split('/').last}');
}
_showAlert(message.toString());
}
void _showAlert(String text) {
// print('Submit button pressed'); // Debug
showDialog(
context: context,
builder:
(_) => AlertDialog(
title: const Text('訊息'),
content: Text(text),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('確定'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('提交活動申請'),
backgroundColor: const Color(0xFF9eaf9f),
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _titleController,
decoration: const InputDecoration(labelText: '活動名稱'),
validator: (value) => value!.isEmpty ? '必填' : null,
),
const SizedBox(height: 12),
_buildDateField('開始時間', _startDate, () => _selectDateTime(true)),
const SizedBox(height: 12),
_buildDateField('結束時間', _endDate, () => _selectDateTime(false)),
const SizedBox(height: 12),
TextFormField(
controller: _locationController,
decoration: const InputDecoration(labelText: '地點'),
validator: (value) => value!.isEmpty ? '必填' : null,
),
const SizedBox(height: 12),
TextFormField(
controller: _descriptionController,
decoration: const InputDecoration(labelText: '活動描述'),
maxLines: 4,
validator: (value) => value!.isEmpty ? '必填' : null,
),
const SizedBox(height: 12),
DropdownButtonFormField<String>(
value: _needRegister,
decoration: const InputDecoration(labelText: '是否需統計報名人數?'),
items:
['', '']
.map((v) => DropdownMenuItem(value: v, child: Text(v)))
.toList(),
onChanged: (v) => setState(() => _needRegister = v!),
),
const SizedBox(height: 12),
DropdownButtonFormField<String>(
value: _repeatOption,
decoration: const InputDecoration(labelText: '是否重複舉辦'),
items: const [
DropdownMenuItem(value: 'none', child: Text('')),
DropdownMenuItem(value: 'weekly', child: Text('每週一次')),
DropdownMenuItem(value: 'biweekly', child: Text('每兩週一次')),
DropdownMenuItem(value: 'monthly', child: Text('每月一次')),
],
onChanged: (v) => setState(() => _repeatOption = v!),
),
if (_repeatOption != 'none') ...[
const SizedBox(height: 12),
TextFormField(
decoration: const InputDecoration(labelText: '重複次數(不含首次)'),
keyboardType: TextInputType.number,
initialValue: '1',
onChanged:
(v) =>
_repeatCount =
int.tryParse(v) != null ? int.parse(v) : 1,
),
],
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: () {
// `file_picker`
_showAlert('尚未實作檔案選擇功能,請整合 file_picker 或 image_picker');
},
icon: const Icon(Icons.upload_file),
label: const Text('上傳活動海報'),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _submitForm,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
padding: const EdgeInsets.symmetric(
vertical: 12,
horizontal: 32,
),
),
child: const Text(
'送出申請',
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
);
}
Widget _buildDateField(String label, DateTime? value, VoidCallback onTap) {
final formatter = DateFormat('yyyy-MM-dd HH:mm');
return Row(
children: [
Expanded(
child: Text(
'$label${value != null ? formatter.format(value) : '未選擇'}',
),
),
TextButton(onPressed: onTap, child: const Text('選擇')),
],
);
}
}