修改幾個小 issue
This commit is contained in:
+27
-12
@@ -1,4 +1,4 @@
|
||||
// todo_api.dart (新增 Create 功能)
|
||||
// todo_api.dart
|
||||
|
||||
import './todo_model.dart';
|
||||
import '../services/generic_api_service.dart';
|
||||
@@ -10,16 +10,31 @@ class TodoApiService {
|
||||
|
||||
TodoApiService({this.currentUserId = 'admin'});
|
||||
|
||||
// 原始的查詢功能...
|
||||
/// 獲取指定日期的任務清單
|
||||
Future<List<Todo>> fetchTodos({DateTime? selectedDate}) async {
|
||||
Future<List<Todo>> fetchTodos({DateTime? selectedDate, String? statusFilter}) async {
|
||||
// 預設查詢今天的資料
|
||||
DateTime dateToQuery = selectedDate ?? DateTime.now();
|
||||
String formattedDate = DateFormat('yyyy-MM-dd').format(dateToQuery);
|
||||
|
||||
// 構建 queryFilter:過濾特定的 end_date 並根據 id 排序
|
||||
// 格式範例: 1^100^id^*^^end_date^2024-05-01
|
||||
String queryFilter = "1^100^id^*^^end_date^$formattedDate";
|
||||
// 1. 組合 wheresql_org (第 5 個參數)
|
||||
// 使用 LIKE 來比對 DATETIME 欄位,確保抓到該日期的所有時段
|
||||
String whereSql = "end_date LIKE '$formattedDate%'";
|
||||
|
||||
// 2. 如果有傳入狀態過濾條件,動態加上 AND 語法
|
||||
if (statusFilter != null && statusFilter != 'All') {
|
||||
String dbStatus = '';
|
||||
if (statusFilter == 'Done') dbStatus = 'DONE';
|
||||
else if (statusFilter == 'In Progress') dbStatus = 'WIP';
|
||||
else if (statusFilter == 'To do') dbStatus = 'TODO'; // 假設你的待辦狀態是 TODO
|
||||
|
||||
if (dbStatus.isNotEmpty) {
|
||||
whereSql += " AND pbi_status = '$dbStatus'";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 嚴格依照 API 規範組裝 10 個參數 (共 9 個 ^ 分隔符)
|
||||
// 格式:pageno^pagerec^orderby^udf_fields^wheresql_org^menuid^where_fields^where_value^where_field^where_idvalue
|
||||
String queryFilter = "1^100^id^*^$whereSql^^^^^";
|
||||
|
||||
return await _apiService.fetchList<Todo>(
|
||||
tableName: "eip_todolist",
|
||||
@@ -36,14 +51,14 @@ class TodoApiService {
|
||||
"task_name": todo.taskName,
|
||||
"task_desc": todo.description,
|
||||
"issue_priority": todo.priority,
|
||||
"pbi_status": todo.status ?? 'WIP', // 預設為進行中
|
||||
"pbi_status": todo.status ?? 'WIP',
|
||||
"end_date": todo.endDate != null ? DateFormat('yyyy-MM-dd HH:mm:ss').format(todo.endDate!) : null,
|
||||
"create_user": currentUserId,
|
||||
"create_date": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
|
||||
// 新增時先不寫入 update_user / update_date
|
||||
};
|
||||
|
||||
try {
|
||||
// 根據 Generic API 規範,使用 action: "C" 進行新增
|
||||
await _apiService.fetchList<dynamic>(
|
||||
tableName: "eip_todolist",
|
||||
pk: "id",
|
||||
@@ -63,13 +78,13 @@ class TodoApiService {
|
||||
Future<bool> updateTodoStatus(int id, String status) async {
|
||||
final Map<String, dynamic> data = {
|
||||
"id": id, // 必填 PK
|
||||
"pbi_status": status, // 更新狀態為 'DONE'
|
||||
"modify_user": currentUserId,
|
||||
"modify_date": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
|
||||
"pbi_status": status, // 更新狀態
|
||||
// 修正為 Schema 正確的欄位名稱 update_user / update_date
|
||||
"update_user": currentUserId,
|
||||
"update_date": DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
|
||||
};
|
||||
|
||||
try {
|
||||
// 使用 Action "U" 代表 Update
|
||||
await _apiService.fetchList<dynamic>(
|
||||
tableName: "eip_todolist",
|
||||
pk: "id",
|
||||
|
||||
+26
-13
@@ -1,4 +1,4 @@
|
||||
// todo_form.dart (適配 Todo Model)
|
||||
// todo_form.dart (適配 Todo Model - 中文化與選項調整)
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
@@ -21,8 +21,10 @@ class _TodoFormState extends State<TodoForm> {
|
||||
final TextEditingController _nameController = TextEditingController();
|
||||
final TextEditingController _descController = TextEditingController();
|
||||
|
||||
String _selectedClass = 'Work';
|
||||
String _selectedPriority = 'Medium';
|
||||
// 根據需求更新預設值與選項
|
||||
String _selectedClass = '工作';
|
||||
String _selectedPriority = 'Middle';
|
||||
String _selectedStatus = 'ToDo'; // 新增狀態變數
|
||||
DateTime _endDate = DateTime.now().add(const Duration(days: 7));
|
||||
|
||||
final Color primaryPurple = const Color(0xFF6542D0);
|
||||
@@ -53,7 +55,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
className: _selectedClass,
|
||||
description: _descController.text,
|
||||
priority: _selectedPriority,
|
||||
status: 'WIP',
|
||||
status: _selectedStatus, // 這裡改為帶入表單選擇的狀態
|
||||
endDate: _endDate,
|
||||
createdBy: widget.userId,
|
||||
);
|
||||
@@ -77,7 +79,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
appBar: AppBar(
|
||||
backgroundColor: bgLight, elevation: 0,
|
||||
leading: IconButton(icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black87), onPressed: () => Navigator.pop(context)),
|
||||
title: const Text('New Task', style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold)),
|
||||
title: const Text('新增任務', style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold)),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
@@ -87,15 +89,25 @@ class _TodoFormState extends State<TodoForm> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildDropdownField('Task Category', _selectedClass, ['Work', 'Personal', 'Urgent'], (val) => setState(() => _selectedClass = val!)),
|
||||
// 類別:改為 固定三個選項
|
||||
_buildDropdownField('任務類別', _selectedClass, ['工作', '個人行程', '其他'], (val) => setState(() => _selectedClass = val!)),
|
||||
const SizedBox(height: 20),
|
||||
_buildTextField('Task Name', _nameController, 'e.g. Design UI Mockup', Icons.edit_note),
|
||||
|
||||
// 名稱與說明:加上中文提示
|
||||
_buildTextField('任務名稱', _nameController, '例如:撰寫系統分析報告', Icons.edit_note),
|
||||
const SizedBox(height: 20),
|
||||
_buildTextField('Description', _descController, 'Enter details here...', Icons.description, isMultiline: true),
|
||||
_buildTextField('任務說明', _descController, '請輸入任務詳細說明...', Icons.description, isMultiline: true),
|
||||
const SizedBox(height: 20),
|
||||
_buildDropdownField('Priority', _selectedPriority, ['High', 'Medium', 'Low'], (val) => setState(() => _selectedPriority = val!)),
|
||||
|
||||
// 優先級:改為 High, Middle, Low
|
||||
_buildDropdownField('優先級', _selectedPriority, ['High', 'Middle', 'Low'], (val) => setState(() => _selectedPriority = val!)),
|
||||
const SizedBox(height: 20),
|
||||
_buildDatePicker('Due Date', _endDate),
|
||||
|
||||
// 新增狀態下拉選單
|
||||
_buildDropdownField('目前狀態', _selectedStatus, ['ToDo', 'WIP', 'Hold', 'Done'], (val) => setState(() => _selectedStatus = val!)),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
_buildDatePicker('截止日期', _endDate),
|
||||
const SizedBox(height: 40),
|
||||
_buildSubmitButton(),
|
||||
],
|
||||
@@ -119,7 +131,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
controller: controller,
|
||||
maxLines: isMultiline ? 3 : 1,
|
||||
decoration: InputDecoration(hintText: hint, border: InputBorder.none, isDense: true, contentPadding: const EdgeInsets.only(top: 8)),
|
||||
validator: (v) => v == null || v.isEmpty ? 'Cannot be empty' : null,
|
||||
validator: (v) => v == null || v.isEmpty ? '此欄位不能為空' : null, // 必填防呆中文化
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -155,7 +167,8 @@ class _TodoFormState extends State<TodoForm> {
|
||||
children: [
|
||||
Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
||||
const SizedBox(height: 4),
|
||||
Text(DateFormat('dd MMM, yyyy').format(date), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
// 日期格式也順便調整成台灣習慣的 YYYY/MM/DD
|
||||
Text(DateFormat('yyyy/MM/dd').format(date), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
Icon(Icons.calendar_today, color: primaryPurple, size: 20),
|
||||
@@ -172,7 +185,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(backgroundColor: primaryPurple, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), elevation: 5),
|
||||
onPressed: _handleSubmit,
|
||||
child: const Text('Create Task', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)),
|
||||
child: const Text('建立任務', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// todo_model.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
@@ -11,6 +12,8 @@ class Todo {
|
||||
final DateTime? endDate; // end_date (預計完成日期)
|
||||
final String? createdBy; // create_user (建立者)
|
||||
final DateTime? createDate; // create_date (建立日期)
|
||||
final String? updatedBy; // update_user (更新者) - 配合新 Schema 新增
|
||||
final DateTime? updateDate; // update_date (更新日期) - 配合新 Schema 新增
|
||||
|
||||
Todo({
|
||||
required this.id,
|
||||
@@ -22,6 +25,8 @@ class Todo {
|
||||
this.endDate,
|
||||
this.createdBy,
|
||||
this.createDate,
|
||||
this.updatedBy,
|
||||
this.updateDate,
|
||||
});
|
||||
|
||||
// Factory 構造函數:從 API 返回的 JSON (Map) 創建 Todo 物件
|
||||
@@ -29,7 +34,6 @@ class Todo {
|
||||
// 輔助函數:安全解析日期字串
|
||||
DateTime? parseDate(dynamic date) {
|
||||
if (date is String && date.isNotEmpty) {
|
||||
// 假設日期格式為 YYYY-MM-DD HH:mm:ss.sss 或 YYYY-MM-DD
|
||||
return DateTime.tryParse(date);
|
||||
}
|
||||
return null;
|
||||
@@ -45,6 +49,8 @@ class Todo {
|
||||
endDate: parseDate(json['end_date']),
|
||||
createdBy: json['create_user'] as String?,
|
||||
createDate: parseDate(json['create_date']),
|
||||
updatedBy: json['update_user'] as String?,
|
||||
updateDate: parseDate(json['update_date']),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user