List Belanja Bulanan risty
Penjelasan Kode Flutter List Belanja Gen Z
Kode berikut adalah contoh aplikasi Flutter untuk membuat shopping list atau daftar belanja yang sederhana tapi fungsional, dengan fitur penyimpanan localStorage browser agar data tidak hilang saat refresh halaman. Aplikasi ini menggunakan widget Stateful untuk mengelola daftar, dan fitur CRUD (Create, Read, Update, Delete) item belanja dengan tampilan yang menarik menggunakan warna pink cerah dan desain modern.
Penjelasan Struktur Kode
- Model ShoppingItem: Kelas ini menyimpan data item belanja dengan properti
id,name, danisDone(untuk menandai item sudah dibeli atau belum). Ada metodetoJson()danfromJson()untuk konversi data ke/dari format JSON. - Stateful Widget MyApp: Ini adalah widget utama aplikasi yang menyimpan daftar item dan mengatur UI. Menggunakan
TextEditingControlleruntuk input item baru. - Mekanisme Penyimpanan: Data disimpan dan dimuat dari
window.localStoragebrowser agar data bertahan meskipun halaman direfresh. - Fungsi CRUD: Ada fungsi untuk menambah, memperbarui, menghapus, dan menandai item sudah dibeli (toggle done) yang semua memanggil
setState()agar UI ter-update. - UI & Tema: Warna-warna pink lembut dan aksen digunakan untuk membuat aplikasi terasa modern dan ramah pengguna, dengan elemen seperti tombol, input teks, dan daftar yang mudah dioperasikan.
Kode Lengkap Aplikasi Flutter
import 'dart:convert';
import 'dart:html';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class ShoppingItem {
String id;
String name;
bool isDone; // tambah properti ini
ShoppingItem({required this.id, required this.name, this.isDone = false});
Map toJson() => {
'id': id,
'name': name,
'isDone': isDone,
};
factory ShoppingItem.fromJson(Map<String, dynamic> json) {
return ShoppingItem(
id: json['id'],
name: json['name'],
isDone: json['isDone'] ?? false,
);
}
}
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<ShoppingItem> items = [];
final TextEditingController _controller = TextEditingController();
@override
void initState() {
super.initState();
loadItemsFromStorage();
}
void loadItemsFromStorage() {
final storedData = window.localStorage['shopping_list'];
if (storedData != null) {
final List decoded = jsonDecode(storedData);
items = decoded.map((e) => ShoppingItem.fromJson(e)).toList();
setState(() {});
}
}
void saveItemsToStorage() {
final String encoded = jsonEncode(items.map((e) => e.toJson()).toList());
window.localStorage['shopping_list'] = encoded;
}
void addItem(String name) {
setState(() {
items.add(ShoppingItem(id: DateTime.now().toString(), name: name));
saveItemsToStorage();
});
_controller.clear();
}
void updateItem(String id, String newName) {
setState(() {
final index = items.indexWhere((item) => item.id == id);
if (index != -1) {
items[index].name = newName;
saveItemsToStorage();
}
});
}
void deleteItem(String id) {
setState(() {
items.removeWhere((item) => item.id == id);
saveItemsToStorage();
});
}
void toggleDone(String id) {
setState(() {
final index = items.indexWhere((item) => item.id == id);
if (index != -1) {
items[index].isDone = !items[index].isDone;
saveItemsToStorage();
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'List Belanja Gen Z',
theme: ThemeData(
primarySwatch: Colors.pink,
scaffoldBackgroundColor: Color(0xFFFFE4E6),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(),
filled: true,
fillColor: Colors.pink.shade50,
),
),
home: Scaffold(
appBar: AppBar(
title: Text('Belanja Bulanan risty๐'),
backgroundColor: Colors.pinkAccent.shade200,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Tambah item belanja...',
),
),
),
SizedBox(width: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.pinkAccent.shade100,
),
onPressed: () {
if (_controller.text.trim().isNotEmpty) {
addItem(_controller.text.trim());
}
},
child: Text('Tambah'),
),
],
),
SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
tileColor: Colors.pink.shade50,
leading: IconButton(
icon: Icon(
item.isDone
? Icons.check_circle
: Icons.radio_button_unchecked,
color: item.isDone
? Colors.pinkAccent.shade400
: Colors.grey,
),
onPressed: () => toggleDone(item.id),
),
title: Text(
item.name,
style: TextStyle(
decoration: item.isDone
? TextDecoration.lineThrough
: TextDecoration.none,
color: item.isDone ? Colors.grey : Colors.black,
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.edit, color: Colors.pinkAccent),
onPressed: () {
showDialog(
context: context,
builder: (context) {
final editController =
TextEditingController(text: item.name);
return AlertDialog(
title: Text('Edit Item'),
content: TextField(
controller: editController,
decoration: InputDecoration(
hintText: 'Nama item',
),
),
actions: [
TextButton(
onPressed: () =>
Navigator.pop(context),
child: Text('Batal'),
),
TextButton(
onPressed: () {
if (editController.text
.trim()
.isNotEmpty) {
updateItem(
item.id, editController.text.trim());
Navigator.pop(context);
}
},
child: Text('Simpan'),
),
],
);
},
);
},
),
IconButton(
icon: Icon(Icons.delete, color: Colors.pinkAccent),
onPressed: () {
deleteItem(item.id);
},
),
],
),
);
},
),
)
],
),
),
),
);
}
}
Untuk mencoba aplikasi ini secara langsung, kunjungi link berikut:
Komentar
Posting Komentar