diff --git a/lib/activity.dart b/lib/activity.dart index 258a5ac..20aafa7 100644 --- a/lib/activity.dart +++ b/lib/activity.dart @@ -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 { children: [ TextButton( onPressed: () { - // TODO: 導向詳情頁 + // TODO : 查看詳情 }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, @@ -110,20 +111,27 @@ class _ActivityListPageState extends State { ), 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 { alignment: Alignment.centerRight, child: ElevatedButton.icon( onPressed: () { - // TODO: 導向提交活動頁 + Navigator.push( + context, + MaterialPageRoute( + builder: + (context) => const ActivitySubmitPage(), + ), + ); }, icon: const Icon(Icons.add), label: const Text('提交活動申請'), diff --git a/lib/activity_submit.dart b/lib/activity_submit.dart new file mode 100644 index 0000000..f1943a7 --- /dev/null +++ b/lib/activity_submit.dart @@ -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 createState() => _ActivitySubmitPageState(); +} + +class _ActivitySubmitPageState extends State { + final _formKey = GlobalKey(); + final _titleController = TextEditingController(); + final _locationController = TextEditingController(); + final _descriptionController = TextEditingController(); + DateTime? _startDate; + DateTime? _endDate; + String _needRegister = '否'; + String _repeatOption = 'none'; + int _repeatCount = 1; + File? _poster; + + Future _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( + 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( + 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('選擇')), + ], + ); + } +}