Main Menu

Membuat Aplikasi To-Do List dengan Flutter dan Supabase #6: Menampilkan Data Todo List


👍 0 ❤️ 0 💡 0 🔥 0 🙌 0 🥳 0
Membuat Aplikasi To-Do List dengan Flutter dan Supabase #6: Menampilkan Data Todo List

Halo teman-teman pada artikel sebelumnya kita sudah membuat StateManagement menggunakan BLoC yang nanti digunakan untuk mengelola dan memisahkan antara Logika Bisnis dengan UI. Langkah selanjutnya kita akan membuat tampilan yang nanti digunakan untuk menampilkan data todo list dari database Supabase.

Membuat UI Todo List

Sekarang teman-teman membuat folder dengan nama screen di dalam folder /lib/, lalu di dalam folder /lib/screen buat file dengan nama todo_screen.dart lalu kita ketik kode berikut:

import 'package:flutter/material.dart';

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State<TodoScreen> createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  @override
  void initState() {
    // TODO: Load Data Todo List
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Todo List')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    decoration: const InputDecoration(
                      hintText: 'Tambahkan tugas baru',
                      border: OutlineInputBorder(),
                    ),
                    onSubmitted: (value) {},
                  ),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {
                    // TODO: Tambah Data Todo List
                  },
                  child: const Text('Tambah'),
                ),
              ],
            ),
          ),
          Expanded(
            child: RefreshIndicator(
              onRefresh: () async {
                // TODO: Refresh Data Todo List
              },
              child: ListView.builder(
                itemCount: 0, // TODO: Ganti dengan jumlah todo
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(
                      'Todo Item $index',
                    ), // TODO: Ganti dengan data todo
                    trailing: Checkbox(
                      value: false, // TODO: Ganti dengan status isDone
                      onChanged: (value) {
                        // TODO: Update Data Todo List
                      },
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

setelah itu kita rubah file pada main.dart menjadi berikut:

import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/screen/todo_screen.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: ".env");

  final String supabaseUrl = dotenv.env['SUPABASE_URL'] ?? '';
  final String supabaseAnonKey = dotenv.env['ANON_KEY'] ?? '';

  await Supabase.initialize(url: supabaseUrl, anonKey: supabaseAnonKey);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const TodoScreen(),
    );
  }
}

Sekarang kita coba jalankan maka tampilannya kurang lebih seperti berikut:

Menampilkan Data dari Supabase

Setelah membuat Ui sekarang kita menampilkan data dari database, pertama kita impelementasikan BLoC Provider. Kita buka file main.dart lalu ketik kode berikut:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:todo_list_supabase/cubit/todo_cubit.dart';
import 'package:todo_list_supabase/screen/todo_screen.dart';
import 'package:todo_list_supabase/service/todo_service.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: ".env");

  final String supabaseUrl = dotenv.env['SUPABASE_URL'] ?? '';
  final String supabaseAnonKey = dotenv.env['ANON_KEY'] ?? '';

  await Supabase.initialize(url: supabaseUrl, anonKey: supabaseAnonKey);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final TodoService service = TodoService();
  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => TodoCubit([], service),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        ),
        home: const TodoScreen(),
      ),
    );
  }
}

Perubahan kode di atas terletak pada kelas MyApp(), kita initialisasi TodoService yang nanti kita masukkan pada TodoCubit.

class MyApp extends StatelessWidget {
  final TodoService service = TodoService();
  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => TodoCubit([], service),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        ),
        home: const TodoScreen(),
      ),
    );
  }
}

Selanjutnya kita buka file todo_screen.dart lalu ketik kode berikut:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:todo_list_supabase/cubit/todo_cubit.dart';
import 'package:todo_list_supabase/model/todo_model.dart';

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State<TodoScreen> createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  @override
  void initState() {
    context.read<TodoCubit>().fetchTodos(); // Fetch todos on init
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Todo List')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    decoration: const InputDecoration(
                      hintText: 'Tambahkan tugas baru',
                      border: OutlineInputBorder(),
                    ),
                    onSubmitted: (value) {},
                  ),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {
                    // TODO: Tambah Data Todo List
                  },
                  child: const Text('Tambah'),
                ),
              ],
            ),
          ),
          Expanded(
            child: RefreshIndicator(
              onRefresh: () async {
                // TODO: Refresh Data Todo List
              },
              child: BlocBuilder<TodoCubit, List<TodoModel>>(
                builder: (context, state) {
                  final todos = state;
                  if (todos.isEmpty) {
                    return const Center(
                      child: Text(
                        'Belum ada tugas',
                        style: TextStyle(fontSize: 18),
                      ),
                    );
                  }
                  return ListView.builder(
                    itemCount: todos.length, // TODO: Ganti dengan jumlah todo
                    itemBuilder: (context, index) {
                      final todo = todos[index];
                      return ListTile(
                        title: Text(
                          todo.title,
                          style: TextStyle(
                            decoration: todo.isDone
                                ? TextDecoration.lineThrough
                                : null,
                          ),
                        ), // TODO: Ganti dengan data todo
                        leading: Checkbox(
                          value: todo.isDone,
                          onChanged: (_) {
                            // TODO: Update status todo
                          },
                        ),
                        trailing: IconButton(
                          icon: const Icon(Icons.delete, color: Colors.red),
                          onPressed: () {
                            // TODO: Hapus data todo
                          },
                        ),
                      );
                    },
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Perubahan kode di atas yang pertama kita memanggil method fetchTodos() dari TodosCubit yang sudah kita buat di dalam method initState().

@override
void initState() {
	context.read<TodoCubit>().fetchTodos(); // Fetch todos on init
	super.initState();
}

Lalu kita bungkus ListView.builder() dengan BlockBuilder() untuk menampilkan data.

BlocBuilder<TodoCubit, List<TodoModel>>(
                builder: (context, state) {
                  final todos = state;
                  if (todos.isEmpty) {
                    return const Center(
                      child: Text(
                        'Belum ada tugas',
                        style: TextStyle(fontSize: 18),
                      ),
                    );
                  }
                  return ListView.builder(
                    itemCount: todos.length, // TODO: Ganti dengan jumlah todo
                    itemBuilder: (context, index) {
                      final todo = todos[index];
                      return ListTile(
                        title: Text(
                          todo.title,
                          style: TextStyle(
                            decoration: todo.isDone
                                ? TextDecoration.lineThrough
                                : null,
                          ),
                        ), // TODO: Ganti dengan data todo
                        leading: Checkbox(
                          value: todo.isDone,
                          onChanged: (_) {
                            // TODO: Update status todo
                          },
                        ),
                        trailing: IconButton(
                          icon: const Icon(Icons.delete, color: Colors.red),
                          onPressed: () {
                            // TODO: Hapus data todo
                          },
                        ),
                      );
                    },
                  );
                },
              ),

Kita juga melakukan pengecekan jika data tidak ada maka akan menampilkan sebuah widget Text dengan tulisan Belum ada tugas, jika ada maka akan menampilkan data berupa widget ListTile().

Sekarang kita jalankan maka tampilannya kurang lebih seperti berikut:

Untuk menampilkan data tugas coba kita isi data di dalam Supabase dengan cara kita buka menu Table Editor -> Pilih tabel -> Create Table

Setelah kita memasukkan data maka tampilan android kurang lebih seperti berikut:

Kesimpulan

Pada tutorial kali ini kita sudah membuat ui untuk menampilkan data dari database supabase, dan mencoba memasukkan data secara manual menggunakan supabase langsung, pada tutorial selanjutnya kita akan membuat fungsi untuk mencentang todo list kita.

Ebook Premium

Membangun Dashboard dan Aplikasi Android Food Store Dengan Laravel Filament, Flutter dan Payment Gateway

Membangun Aplikasi Donasi Online dengan Laravel, Flutter dan Payment Gateway


Faisal Mahadi
Mobile Apps Developer | Android Enthusiast | Keep Learning | Android Dev Serta Owner Hariankoding.com

Suka dengan tulisan di SantriKoding? Kamu bisa memberikan dukungan dengan berdonasi atau bagikan konten ini di sosial media. Terima kasih atas dukungan Anda!

KEBIJAKAN KOMENTAR

Saat memberikan komenatar silahkan memberikan informasi lengkap tentang error, seperti: screenshot, link kode, dll. Baca aturan komentar kami