first commit structure of app
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AnwendungController extends GetxController {
|
||||
final count = 0.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {}
|
||||
|
||||
@override
|
||||
void onClose() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../models/kauf_filament_model.dart';
|
||||
import '../services/get_storage_services.dart';
|
||||
|
||||
class HomeController extends GetxController {
|
||||
static const storageKey = 'kauf_filamente';
|
||||
|
||||
final storage = Get.find<GetStorageService>();
|
||||
final uuid = const Uuid();
|
||||
|
||||
final filamente = <KaufFilamentModel>[].obs;
|
||||
|
||||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
final haendlerController = TextEditingController();
|
||||
final farbeController = TextEditingController();
|
||||
final preisController = TextEditingController();
|
||||
final markeController = TextEditingController();
|
||||
final gewichtController = TextEditingController();
|
||||
|
||||
final kaufdatum = DateTime.now().obs;
|
||||
final material = 'PLA'.obs;
|
||||
final editingId = RxnString();
|
||||
|
||||
final materialien = [
|
||||
'PLA',
|
||||
'PLA+',
|
||||
'PLA light',
|
||||
'PLA-CF',
|
||||
'PLA+',
|
||||
'PETG',
|
||||
'PETG-CF',
|
||||
'ABS',
|
||||
'ASA',
|
||||
'TPU',
|
||||
'Sonstiges',
|
||||
];
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
loadFilamente();
|
||||
}
|
||||
|
||||
void loadFilamente() {
|
||||
final data = storage.getModelList(storageKey);
|
||||
|
||||
filamente.assignAll(
|
||||
data.map(KaufFilamentModel.fromJson),
|
||||
);
|
||||
|
||||
sortFilamente();
|
||||
}
|
||||
|
||||
void sortFilamente() {
|
||||
filamente.sort(
|
||||
(a, b) => b.kaufdatum.compareTo(a.kaufdatum),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> persist() async {
|
||||
await storage.saveModelList(
|
||||
storageKey,
|
||||
filamente.map((f) => f.toJson()).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> saveFilament() async {
|
||||
if (!formKey.currentState!.validate()) return;
|
||||
|
||||
final preis = double.tryParse(
|
||||
preisController.text.trim().replaceAll(',', '.'),
|
||||
);
|
||||
|
||||
if (preis == null || !preis.isFinite || preis < 0) {
|
||||
Get.snackbar('Ungültiger Preis', 'Bitte Preis überprüfen.');
|
||||
return;
|
||||
}
|
||||
|
||||
final filament = KaufFilamentModel(
|
||||
filamentId: editingId.value ?? uuid.v4(),
|
||||
marke: markeController.text.trim(),
|
||||
kaufdatum: kaufdatum.value,
|
||||
haendler: haendlerController.text.trim(),
|
||||
material: material.value,
|
||||
preis: preis,
|
||||
farbe: farbeController.text.trim(),
|
||||
gewicht: gewichtController.text.trim().isEmpty
|
||||
? '1kg'
|
||||
: gewichtController.text.trim(),
|
||||
);
|
||||
|
||||
if (editingId.value == null) {
|
||||
filamente.add(filament);
|
||||
} else {
|
||||
final index = filamente.indexWhere(
|
||||
(f) => f.filamentId == editingId.value,
|
||||
);
|
||||
|
||||
if (index < 0) {
|
||||
Get.snackbar('Fehler', 'Datensatz nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
filamente[index] = filament;
|
||||
}
|
||||
|
||||
sortFilamente();
|
||||
await persist();
|
||||
resetForm();
|
||||
}
|
||||
|
||||
void editFilament(KaufFilamentModel filament) {
|
||||
editingId.value = filament.filamentId;
|
||||
kaufdatum.value = filament.kaufdatum;
|
||||
markeController.text = filament.marke;
|
||||
haendlerController.text = filament.haendler;
|
||||
material.value = filament.material;
|
||||
preisController.text = filament.preis.toStringAsFixed(2);
|
||||
farbeController.text = filament.farbe;
|
||||
gewichtController.text = filament.gewicht;
|
||||
}
|
||||
|
||||
Future<void> duplicateFilament(
|
||||
KaufFilamentModel filament,
|
||||
) async {
|
||||
filamente.add(
|
||||
filament.copyWith(filamentId: uuid.v4()),
|
||||
);
|
||||
|
||||
sortFilamente();
|
||||
await persist();
|
||||
}
|
||||
|
||||
Future<void> deleteFilament(String filamentId) async {
|
||||
filamente.removeWhere((f) => f.filamentId == filamentId);
|
||||
if (editingId.value == filamentId) resetForm();
|
||||
await persist();
|
||||
}
|
||||
|
||||
void resetForm() {
|
||||
editingId.value = null;
|
||||
haendlerController.clear();
|
||||
markeController.clear();
|
||||
farbeController.clear();
|
||||
preisController.clear();
|
||||
kaufdatum.value = DateTime.now();
|
||||
material.value = 'PLA';
|
||||
gewichtController.clear();
|
||||
formKey.currentState?.reset();
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
haendlerController.dispose();
|
||||
markeController.dispose();
|
||||
farbeController.dispose();
|
||||
preisController.dispose();
|
||||
gewichtController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
import '../../controller/home_controller.dart';
|
||||
import '../controller/anwendung_controller.dart';
|
||||
|
||||
class SampleBindings extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<HomeController>(() => HomeController());
|
||||
Get.lazyPut<AnwendungController>(() => AnwendungController());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../pages/home_view.dart';
|
||||
import 'sample_bindings.dart';
|
||||
|
||||
class SampleRouts {
|
||||
static final sampleBindings = SampleBindings();
|
||||
static List<GetPage<dynamic>> samplePages = [
|
||||
GetPage(
|
||||
name: HomeView.routeName,
|
||||
page: () => const HomeView(),
|
||||
binding: sampleBindings,
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'helper/sample_bindings.dart';
|
||||
import 'helper/sample_routes.dart';
|
||||
import 'pages/home_view.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'services/get_storage_services.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await GetStorage.init();
|
||||
Get.put<GetStorageService>(
|
||||
GetStorageService(),
|
||||
permanent: true,
|
||||
);
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetMaterialApp(
|
||||
title: 'Flutter Filament Verwaltung',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: const Color.fromARGB(255, 38, 135, 184)), useMaterial3: true),
|
||||
initialBinding: SampleBindings(),
|
||||
initialRoute: HomeView.routeName,
|
||||
getPages: SampleRouts.samplePages,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
class KaufFilamentModel {
|
||||
final String filamentId;
|
||||
final DateTime kaufdatum;
|
||||
final String haendler;
|
||||
final String marke;
|
||||
final String material;
|
||||
final double preis;
|
||||
final String farbe;
|
||||
final String gewicht;
|
||||
|
||||
const KaufFilamentModel({
|
||||
required this.filamentId,
|
||||
required this.kaufdatum,
|
||||
required this.haendler,
|
||||
required this.marke,
|
||||
required this.material,
|
||||
required this.preis,
|
||||
required this.farbe,
|
||||
required this.gewicht,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'filamentId': filamentId,
|
||||
'kaufdatum': kaufdatum.toIso8601String(),
|
||||
'haendler': haendler,
|
||||
'marke': marke,
|
||||
'material': material,
|
||||
'preis': preis,
|
||||
'farbe': farbe,
|
||||
'gewicht': gewicht,
|
||||
};
|
||||
|
||||
factory KaufFilamentModel.fromJson(Map<String, dynamic> json) {
|
||||
return KaufFilamentModel(
|
||||
filamentId: json['filamentId'] as String,
|
||||
kaufdatum: DateTime.parse(json['kaufdatum'] as String),
|
||||
haendler: json['haendler'] as String,
|
||||
marke: json['marke'] ?? '',
|
||||
material: json['material'] as String,
|
||||
preis: (json['preis'] as num).toDouble(),
|
||||
farbe: json['farbe'] as String,
|
||||
gewicht: json['gewicht'] ?? '1000'
|
||||
);
|
||||
}
|
||||
|
||||
KaufFilamentModel copyWith({
|
||||
String? filamentId,
|
||||
DateTime? kaufdatum,
|
||||
String? haendler,
|
||||
String? marke,
|
||||
String? material,
|
||||
double? preis,
|
||||
String? farbe,
|
||||
String? gewicht,
|
||||
}) {
|
||||
return KaufFilamentModel(
|
||||
filamentId: filamentId ?? this.filamentId,
|
||||
kaufdatum: kaufdatum ?? this.kaufdatum,
|
||||
haendler: haendler ?? this.haendler,
|
||||
marke: marke ?? this.marke,
|
||||
material: material ?? this.material,
|
||||
preis: preis ?? this.preis,
|
||||
farbe: farbe ?? this.farbe,
|
||||
gewicht: gewicht ?? this.gewicht
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../controller/anwendung_controller.dart';
|
||||
|
||||
class AnwendungView extends GetView<AnwendungController> {
|
||||
static const routeName = '/anwendung-view';
|
||||
const AnwendungView({super.key, required String filamentId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Anwendung'),
|
||||
centerTitle: true,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
)
|
||||
),
|
||||
body: Container(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../controller/home_controller.dart';
|
||||
import '../models/kauf_filament_model.dart';
|
||||
import 'anwendung_view.dart';
|
||||
|
||||
class HomeView extends GetView<HomeController> {
|
||||
static const routeName = '/home-view';
|
||||
const HomeView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dateFormat = DateFormat('dd.MM.yyyy');
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Filament Einkaufsverwaltung'),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.blue.shade300,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// EINGABEBEREICH
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Form(
|
||||
key: controller.formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Obx(() => ListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
side: const BorderSide(
|
||||
color: Colors.grey,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||
title: const Text('Kaufdatum'),
|
||||
subtitle: Text(
|
||||
dateFormat.format(controller.kaufdatum.value),
|
||||
),
|
||||
trailing: const Icon(Icons.calendar_month),
|
||||
onTap: () async {
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: controller.kaufdatum.value,
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
|
||||
if (date != null) {
|
||||
controller.kaufdatum.value = date;
|
||||
}
|
||||
},
|
||||
)),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
TextFormField(
|
||||
controller: controller.haendlerController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Wo gekauft / Händler',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value == null || value.trim().isEmpty
|
||||
? 'Händler eingeben'
|
||||
: null,
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
TextFormField(
|
||||
controller: controller.markeController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Marke',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value == null || value.trim().isEmpty
|
||||
? 'Marke eingeben'
|
||||
: null,
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Obx(() => DropdownButtonFormField<String>(
|
||||
key: ValueKey(
|
||||
'${controller.editingId.value ?? "new"}'
|
||||
'_${controller.material.value}',
|
||||
),
|
||||
initialValue: controller.material.value,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Material',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
items: controller.materialien.map((item) {
|
||||
return DropdownMenuItem(
|
||||
value: item,
|
||||
child: Text(item),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
controller.material.value = value;
|
||||
}
|
||||
},
|
||||
)),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: controller.farbeController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Farbe',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value == null || value.trim().isEmpty
|
||||
? 'Farbe eingeben'
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: controller.preisController,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Preis (€)',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
final price = double.tryParse(
|
||||
(value ?? '').replaceAll(',', '.'),
|
||||
);
|
||||
if (price == null ||
|
||||
!price.isFinite ||
|
||||
price < 0) {
|
||||
return 'Preis ungültig';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
TextFormField(
|
||||
controller: controller.gewichtController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Gewicht in Gramm (g)',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value == null || value.trim().isEmpty
|
||||
? 'Gewicht eingeben g'
|
||||
: null,
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
Obx(() => Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: controller.saveFilament,
|
||||
icon: Icon(
|
||||
controller.editingId.value == null
|
||||
? Icons.add
|
||||
: Icons.save,
|
||||
),
|
||||
label: Text(
|
||||
controller.editingId.value == null
|
||||
? 'Filament speichern'
|
||||
: 'Änderungen speichern',
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller.editingId.value != null)
|
||||
IconButton(
|
||||
tooltip: 'Bearbeitung abbrechen',
|
||||
onPressed: controller.resetForm,
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
|
||||
// LISTENBEREICH
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final filamente = controller.filamente;
|
||||
|
||||
if (filamente.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('Noch keine Filamente gespeichert'),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: filamente.length,
|
||||
itemBuilder: (context, index) {
|
||||
final filament = filamente[index];
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 4,
|
||||
),
|
||||
child: ListTile(
|
||||
leading: const CircleAvatar(
|
||||
child: Icon(Icons.inventory_2_outlined),
|
||||
),
|
||||
title: Text(
|
||||
'${filament.material} – ${filament.farbe}',
|
||||
),
|
||||
subtitle: Text(
|
||||
'${filament.haendler}\n'
|
||||
'${dateFormat.format(filament.kaufdatum)}'
|
||||
' | ${filament.preis.toStringAsFixed(2)} €',
|
||||
),
|
||||
isThreeLine: true,
|
||||
onTap: () => Get.to(
|
||||
() => AnwendungView(
|
||||
filamentId: filament.filamentId,
|
||||
),
|
||||
),
|
||||
trailing: PopupMenuButton<String>(
|
||||
onSelected: (action) =>
|
||||
_handleAction(context, action, filament),
|
||||
itemBuilder: (context) => const [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.edit),
|
||||
title: Text('Bearbeiten'),
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'duplicate',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.copy),
|
||||
title: Text('Duplizieren'),
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.delete_outline),
|
||||
title: Text('Löschen'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleAction(
|
||||
BuildContext context,
|
||||
String action,
|
||||
KaufFilamentModel filament,
|
||||
) async {
|
||||
switch (action) {
|
||||
case 'edit':
|
||||
controller.editFilament(filament);
|
||||
break;
|
||||
|
||||
case 'duplicate':
|
||||
await controller.duplicateFilament(filament);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (dialogContext) => AlertDialog(
|
||||
title: const Text('Filament löschen?'),
|
||||
content: Text(
|
||||
'${filament.material} – ${filament.farbe} löschen?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogContext, false),
|
||||
child: const Text('Abbrechen'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(dialogContext, true),
|
||||
child: const Text('Löschen'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
await controller.deleteFilament(filament.filamentId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
class GetStorageService extends GetxService {
|
||||
final GetStorage _box = GetStorage();
|
||||
|
||||
// CREATE / UPDATE
|
||||
Future<void> save<T>(String key, T value) async {
|
||||
await _box.write(key, value);
|
||||
}
|
||||
|
||||
// READ
|
||||
T? get<T>(String key) {
|
||||
return _box.read<T>(key);
|
||||
}
|
||||
|
||||
// READ mit Defaultwert
|
||||
T getOrDefault<T>(String key, T defaultValue) {
|
||||
return get<T>(key) ?? defaultValue;
|
||||
}
|
||||
|
||||
// DELETE
|
||||
Future<void> delete(String key) async {
|
||||
await _box.remove(key);
|
||||
}
|
||||
|
||||
// EXISTS
|
||||
bool exists(String key) {
|
||||
return _box.hasData(key);
|
||||
}
|
||||
|
||||
// CLEAR ALL
|
||||
Future<void> clear() async {
|
||||
await _box.erase();
|
||||
}
|
||||
|
||||
// READ LIST
|
||||
List<T> getList<T>(String key) {
|
||||
final data = _box.read<List<dynamic>>(key);
|
||||
return data?.cast<T>() ?? <T>[];
|
||||
}
|
||||
|
||||
// SAVE LIST
|
||||
Future<void> saveList<T>(String key, List<T> items) async {
|
||||
await _box.write(key, items);
|
||||
}
|
||||
|
||||
// ADD ITEM
|
||||
Future<void> addItem<T>(String key, T item) async {
|
||||
final items = getList<T>(key);
|
||||
items.add(item);
|
||||
await saveList<T>(key, items);
|
||||
}
|
||||
|
||||
// UPDATE ITEM
|
||||
Future<void> updateItem<T>(String key, int index, T item) async {
|
||||
final items = getList<T>(key);
|
||||
|
||||
if (index < 0 || index >= items.length) {
|
||||
throw RangeError.index(index, items);
|
||||
}
|
||||
|
||||
items[index] = item;
|
||||
await saveList<T>(key, items);
|
||||
}
|
||||
|
||||
// DELETE ITEM
|
||||
Future<void> deleteItem<T>(String key, int index) async {
|
||||
final items = getList<T>(key);
|
||||
|
||||
if (index < 0 || index >= items.length) {
|
||||
throw RangeError.index(index, items);
|
||||
}
|
||||
|
||||
items.removeAt(index);
|
||||
await saveList<T>(key, items);
|
||||
}
|
||||
|
||||
Future<void> saveModelList(
|
||||
String key,
|
||||
List<Map<String, dynamic>> items,
|
||||
) async {
|
||||
await _box.write(key, items);
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> getModelList(String key) {
|
||||
final data = _box.read<List<dynamic>>(key) ?? [];
|
||||
|
||||
return data.map((item) => Map<String, dynamic>.from(item as Map)).toList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user