Aufgaben-JSON testweise von Web-URL laden, Ankunft-Task als Button, RadioGroup-Umstellung
- TEMP-Loader: Aufgaben beim Oeffnen der Task-Seite von https://appcreation.de/download/task.json laden (Fallback: Tour-Daten) - Task-Typ 1 (Ankunft melden) als Bestaetigungs-Button statt Checkbox - Statusauswahl (Typ 11) auf RadioGroup umgestellt (Deprecation behoben) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1d0d23c1a9
commit
d864b9c72a
2 files changed
+92
-12
No files matched your search
@@ -2,6 +2,8 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:dart_mq/dart_mq.dart';
|
import 'package:dart_mq/dart_mq.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
// TEMP (nur zum Testen, s. _tempTaskJsonUrl): wieder entfernen.
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:image/image.dart' as image_lib;
|
import 'package:image/image.dart' as image_lib;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -25,6 +27,44 @@ import '../model/tour_task.dart';
|
|||||||
import '../tools/app_localizations.dart';
|
import '../tools/app_localizations.dart';
|
||||||
import '../tools/util.dart';
|
import '../tools/util.dart';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// TEMPORÄR — NUR ZUM TESTEN, WIEDER ENTFERNEN
|
||||||
|
//
|
||||||
|
// Lädt das Aufgaben-JSON beim Öffnen der Seite von einer Webseite statt die
|
||||||
|
// Aufgaben der übergebenen Tour zu verwenden. Die URL muss entweder eine
|
||||||
|
// JSON-Liste von Aufgaben liefern oder ein Objekt mit einer "tasks"-Liste.
|
||||||
|
//
|
||||||
|
// Zum Entfernen: diesen Block, den http-Import oben und die mit
|
||||||
|
// "TEMP" markierte Zeile in _fetchTaskList() löschen. Alternativ die URL auf
|
||||||
|
// null setzen, dann greift wieder das normale Verhalten (auch bei Ladefehler).
|
||||||
|
// =============================================================================
|
||||||
|
// ignore: unnecessary_nullable_for_final_variable_declarations
|
||||||
|
const String? _tempTaskJsonUrl = "https://appcreation.de/download/task.json";
|
||||||
|
|
||||||
|
Future<List<TourTask>?> _tempLoadTasksFromWeb() async {
|
||||||
|
final url = _tempTaskJsonUrl;
|
||||||
|
if (url == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.get(Uri.parse(url));
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
debugPrint("TEMP: Aufgaben-JSON laden fehlgeschlagen, HTTP ${response.statusCode}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final decoded = jsonDecode(utf8.decode(response.bodyBytes));
|
||||||
|
final list = decoded is List ? decoded : (decoded as Map<String, dynamic>)['tasks'] as List<dynamic>;
|
||||||
|
|
||||||
|
return list.map((e) => TourTask.fromJson(e as Map<String, dynamic>)).toList();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("TEMP: Aufgaben-JSON laden fehlgeschlagen: $e");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ========================================================== ENDE TEMPORÄR ====
|
||||||
|
|
||||||
/// Seiten-Wizard zur Bearbeitung der Aufgaben einer Tour. Pro Aufgabe wird
|
/// Seiten-Wizard zur Bearbeitung der Aufgaben einer Tour. Pro Aufgabe wird
|
||||||
/// genau eine Seite angezeigt; mit „Zurück"/„Weiter" navigiert der Bearbeiter
|
/// genau eine Seite angezeigt; mit „Zurück"/„Weiter" navigiert der Bearbeiter
|
||||||
/// zwischen den Aufgaben, die letzte Seite schließt die Tour ab.
|
/// zwischen den Aufgaben, die letzte Seite schließt die Tour ab.
|
||||||
@@ -98,7 +138,10 @@ class _TaskListPageState extends State<TaskListPage> with ProducerMixin {
|
|||||||
Future<List<TaskInfo>> _fetchTaskList() async {
|
Future<List<TaskInfo>> _fetchTaskList() async {
|
||||||
List<TaskInfo> taskList = [];
|
List<TaskInfo> taskList = [];
|
||||||
|
|
||||||
for (var task in widget.tour.tasks!) {
|
// TEMP (nur zum Testen): Aufgaben von Webseite statt aus der Tour laden.
|
||||||
|
final tasks = await _tempLoadTasksFromWeb() ?? widget.tour.tasks!;
|
||||||
|
|
||||||
|
for (var task in tasks) {
|
||||||
final box = MyApp.objectBoxStore.box<TaskInfo>();
|
final box = MyApp.objectBoxStore.box<TaskInfo>();
|
||||||
final query = box.query(TaskInfo_.sId.equals(task.sId)).build();
|
final query = box.query(TaskInfo_.sId.equals(task.sId)).build();
|
||||||
var taskInfo = query.findFirst();
|
var taskInfo = query.findFirst();
|
||||||
@@ -274,7 +317,7 @@ class _TaskListPageState extends State<TaskListPage> with ProducerMixin {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1:
|
case 1:
|
||||||
return _buildConfirmBody(draft, 'confirm_arrival'.tr);
|
return _buildConfirmButtonBody(draft, 'confirm_arrival'.tr);
|
||||||
case 2:
|
case 2:
|
||||||
return _buildSignatureBody(taskInfo, draft);
|
return _buildSignatureBody(taskInfo, draft);
|
||||||
case 3:
|
case 3:
|
||||||
@@ -300,7 +343,39 @@ class _TaskListPageState extends State<TaskListPage> with ProducerMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bestätigungs-Aufgabe (Ankunft melden = 1, Checkbox = 6).
|
/// Bestätigung per Button (Ankunft melden = 1). Antippen bestätigt bzw.
|
||||||
|
/// nimmt die Bestätigung wieder zurück; der Zustand wird über ein
|
||||||
|
/// Häkchen-Symbol im Button angezeigt.
|
||||||
|
Widget _buildConfirmButtonBody(_TaskDraft draft, String label) {
|
||||||
|
final confirmed = draft.confirmed;
|
||||||
|
return SizedBox(
|
||||||
|
height: 52,
|
||||||
|
child: MaterialButton(
|
||||||
|
color: Constants.colorPrimary,
|
||||||
|
elevation: 3,
|
||||||
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))),
|
||||||
|
onPressed: () => setState(() => draft.confirmed = !confirmed),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (confirmed) ...[
|
||||||
|
const Icon(Icons.check_circle, color: Colors.white),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontSize: 16, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bestätigungs-Aufgabe als Checkbox (Typ 6).
|
||||||
Widget _buildConfirmBody(_TaskDraft draft, String label) {
|
Widget _buildConfirmBody(_TaskDraft draft, String label) {
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
value: draft.confirmed,
|
value: draft.confirmed,
|
||||||
@@ -339,14 +414,20 @@ class _TaskListPageState extends State<TaskListPage> with ProducerMixin {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
...options.map((o) => RadioListTile<int>(
|
RadioGroup<int>(
|
||||||
value: o.code,
|
groupValue: draft.selectedCode,
|
||||||
groupValue: draft.selectedCode,
|
onChanged: (value) => setState(() => draft.selectedCode = value),
|
||||||
contentPadding: EdgeInsets.zero,
|
child: Column(
|
||||||
activeColor: Constants.colorPrimary,
|
children: options
|
||||||
title: Text(o.label),
|
.map((o) => RadioListTile<int>(
|
||||||
onChanged: (value) => setState(() => draft.selectedCode = value),
|
value: o.code,
|
||||||
)),
|
contentPadding: EdgeInsets.zero,
|
||||||
|
activeColor: Constants.colorPrimary,
|
||||||
|
title: Text(o.label),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
if (requiresRemark) ...[
|
if (requiresRemark) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Util.getDefaultTextField(
|
Util.getDefaultTextField(
|
||||||
|
|||||||
@@ -16,4 +16,3 @@ class MessageHeader {
|
|||||||
|
|
||||||
Map<String, dynamic> toJson() => _$MessageHeaderToJson(this);
|
Map<String, dynamic> toJson() => _$MessageHeaderToJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user