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, dan isDone (untuk menandai item sudah dibeli atau belum). Ada metode toJson() dan fromJson() untuk konversi data ke/dari format JSON.
  • Stateful Widget MyApp: Ini adalah widget utama aplikasi yang menyimpan daftar item dan mengatur UI. Menggunakan TextEditingController untuk input item baru.
  • Mekanisme Penyimpanan: Data disimpan dan dimuat dari window.localStorage browser 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:

Buka Aplikasi List Belanja Gen Z

© 2025 by Risty ๐Ÿ’– - Flutter Shopping List App

Komentar

Postingan populer dari blog ini

jenis jenis sistem operasi mobile