Catatan Programmer

refactor lengkap kode login Supabase di Flutter agar lebih modular, bersih, dan siap untuk skala produksi

 

Berikut adalah refactor lengkap kode login Supabase di Flutter agar lebih modular, bersih, dan siap untuk skala produksi.


 

 🧱 Struktur File Baru

lib/
├── main.dart
├── pages/
│   ├── login_page.dart
│   └── home_page.dart
├── services/
│   └── auth_service.dart

 

✅ 1. auth_service.dart – Logika Supabase Dipisah

lib/services/auth_service.dart

import 'package:supabase_flutter/supabase_flutter.dart';

class AuthService {
  final supabase = Supabase.instance.client;

  Future<AuthResponse?> login(String email, String password) async {
    try {
      final response = await supabase.auth.signInWithPassword(
        email: email,
        password: password,
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  Future<void> logout() async {
    await supabase.auth.signOut();
  }
}

 

✅ 2. login_page.dart – Lebih Rapi & Aman

lib/pages/login_page.dart

import 'package:flutter/material.dart';
import 'package:your_project/services/auth_service.dart';
import 'package:your_project/pages/home_page.dart';

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

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final _authService = AuthService();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  String? errorMessage;

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  Future<void> _login() async {
    final email = _emailController.text.trim();
    final password = _passwordController.text;

    try {
      final response = await _authService.login(email, password);

      if (!mounted) return;

      if (response?.user != null) {
        Navigator.pushReplacement(
          context,
          MaterialPageRoute(builder: (context) => const HomePage()),
        );
      } else {
        setState(() {
          errorMessage = "Login gagal. Email atau password salah.";
        });
      }
    } catch (e) {
      if (!mounted) return;
      setState(() {
        errorMessage = "Terjadi kesalahan saat login.";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Login")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _emailController,
              decoration: const InputDecoration(labelText: "Email"),
              keyboardType: TextInputType.emailAddress,
            ),
            TextField(
              controller: _passwordController,
              decoration: const InputDecoration(labelText: "Password"),
              obscureText: true,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _login,
              child: const Text("Login"),
            ),
            if (errorMessage != null)
              Padding(
                padding: const EdgeInsets.only(top: 16.0),
                child: Text(errorMessage!,
                    style: const TextStyle(color: Colors.red)),
              ),
          ],
        ),
      ),
    );
  }
}

 

✅ 3. home_page.dart

lib/pages/home_page.dart

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Home")),
      body: const Center(child: Text("Selamat datang di halaman Home!")),
    );
  }
}

 

✅ 4. main.dart – Inisialisasi Supabase & Routing

lib/main.dart

import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:your_project/pages/login_page.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Supabase.initialize(
    url: 'https://YOUR_PROJECT_ID.supabase.co',
    anonKey: 'YOUR_SUPABASE_ANON_KEY',
  );

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Supabase Auth Demo',
      theme: ThemeData(primarySwatch: Colors.teal),
      home: const LoginPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

 

🧪 Bonus: Tes Login Gagal & Berhasil

  • Gunakan email/pw valid dari Supabase Auth Console.

  • Jika login gagal, pesan akan muncul di bawah tombol.

  • Jika berhasil, langsung diarahkan ke HomePage.


 

✅ Kelebihan Refactor Ini

  • 🔄 Modular: Pemisahan logika auth dan UI

  • 🛡️ Aman: Cek mounted sebelum akses context

  • ♻️ Reusable: AuthService bisa digunakan di halaman lain

  • 🎯 Scalable: Cocok untuk project skala menengah-besar



No comments:

Post a Comment

About