add import export and items
This commit is contained in:
@@ -2,9 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../controller/anwendung_controller.dart';
|
||||
import '../helper/display_formats.dart';
|
||||
import '../widgets/anwendung_form.dart';
|
||||
import '../widgets/entry_panel.dart';
|
||||
|
||||
class AnwendungView extends GetView<AnwendungController> {
|
||||
static const routeName = '/anwendung-view';
|
||||
@@ -39,32 +37,6 @@ class AnwendungView extends GetView<AnwendungController> {
|
||||
child: AnwendungForm(controller: controller),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 24),
|
||||
sliver: Obx(() {
|
||||
final entries = controller.anwendungen.toList();
|
||||
return SavedEntries(
|
||||
title: 'Gespeicherte Profile',
|
||||
count: entries.length,
|
||||
emptyText: 'Noch keine Verarbeitungsprofile für dieses Filament gespeichert.',
|
||||
itemBuilder: (context, index) {
|
||||
final entry = entries[index];
|
||||
return SavedEntryCard(
|
||||
key: ValueKey(entry.anwendungId),
|
||||
title:
|
||||
'Druck ${DisplayFormats.number(entry.druckTemperatur)} °C · Bett ${DisplayFormats.number(entry.druckbettTemperatur)} °C',
|
||||
subtitle: DisplayFormats.date(entry.erstelltAm),
|
||||
details: [
|
||||
'Bauraum geschlossen: ${entry.bauraumGeschlossen ? "Ja" : "Nein"}',
|
||||
if (entry.bauraumTemperatur != null)
|
||||
'Bauraum ${DisplayFormats.number(entry.bauraumTemperatur!)} °C',
|
||||
],
|
||||
notes: entry.sonstiges,
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../controller/export_controller.dart';
|
||||
import '../helper/storage_keys.dart';
|
||||
import '../widgets/entry_panel.dart';
|
||||
|
||||
class ExportView extends GetView<ExportController> {
|
||||
static const routeName = '/export-view';
|
||||
const ExportView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Datensicherung')),
|
||||
body: SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 760),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Obx(() {
|
||||
final busy = controller.isBusy.value;
|
||||
final backup = controller.pendingBackup.value;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
EntryPanel(
|
||||
title: 'Daten exportieren',
|
||||
subtitle: 'Sichere Filamente, Verarbeitungsprofile, Bauteile inklusive Fotos und Verbrauch sowie deine Materialarten in einer JSON-Datei.\n\nSpeichere die Datei außerhalb der App, zum Beispiel in Dokumente oder in deiner Cloud. So kannst du sie nach einer Neuinstallation wieder importieren.',
|
||||
child: FilledButton.icon(
|
||||
onPressed: busy ? null : controller.exportData,
|
||||
icon: const Icon(Icons.file_download_outlined),
|
||||
label: const Text('Als JSON exportieren'),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
EntryPanel(
|
||||
title: 'Daten importieren',
|
||||
subtitle: 'Wähle eine JSON-Datensicherung dieser App. Beim Import werden alle aktuell gespeicherten Daten durch den Inhalt der Datei ersetzt. Exportiere bei Bedarf vorher deinen aktuellen Bestand.',
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
OutlinedButton.icon(
|
||||
onPressed: busy ? null : controller.selectImport,
|
||||
icon: const Icon(Icons.file_upload_outlined),
|
||||
label: const Text('JSON-Datei auswählen'),
|
||||
),
|
||||
if (backup != null) ...[
|
||||
const SizedBox(height: 16),
|
||||
const Text('Geprüfte Datensicherung:'),
|
||||
Text(
|
||||
'${backup.data[StorageKeys.filamente]!.length} Filamente',
|
||||
),
|
||||
Text(
|
||||
'${backup.data[StorageKeys.anwendungen]!.length} Profile',
|
||||
),
|
||||
Text(
|
||||
'${backup.data[StorageKeys.bauteile]!.length} Bauteile',
|
||||
),
|
||||
Text(
|
||||
backup.data[StorageKeys.materialien]!.isEmpty
|
||||
? 'Materialarten: Standardliste'
|
||||
: '${(backup.data[StorageKeys.materialien]!.single['werte'] as List).length} Materialarten',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton.icon(
|
||||
onPressed: busy
|
||||
? null
|
||||
: () => _confirmImport(context),
|
||||
icon: const Icon(Icons.restore),
|
||||
label: const Text('Daten ersetzen und importieren'),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
if (busy) ...[
|
||||
const SizedBox(height: 20),
|
||||
const LinearProgressIndicator(),
|
||||
],
|
||||
EntryMessage(
|
||||
message: controller.message.value,
|
||||
hasError: controller.hasError.value,
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> _confirmImport(BuildContext context) async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Alle Daten ersetzen?'),
|
||||
content: const Text(
|
||||
'Der aktuelle Bestand wird vollständig durch die ausgewählte Datensicherung ersetzt. Auch eine leere Sicherung ersetzt den Bestand.',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: const Text('Abbrechen'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: const Text('Daten ersetzen'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (confirmed == true) await controller.importData();
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import '../widgets/filament_form.dart';
|
||||
import '../widgets/filament_inventory.dart';
|
||||
import 'anwendung_view.dart';
|
||||
import 'bauteil_view.dart';
|
||||
import 'export_view.dart';
|
||||
|
||||
class HomeView extends GetView<HomeController> {
|
||||
static const routeName = '/home-view';
|
||||
@@ -39,6 +40,24 @@ class HomeView extends GetView<HomeController> {
|
||||
],
|
||||
),
|
||||
),
|
||||
drawer: Drawer(
|
||||
child: SafeArea(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
const ListTile(title: Text('Filamentverwaltung')),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.import_export),
|
||||
title: const Text('Daten exportieren / importieren'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
Get.toNamed(ExportView.routeName);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: Align(
|
||||
|
||||
Reference in New Issue
Block a user