Skip to content

Instantly share code, notes, and snippets.

@halimkun
Last active June 1, 2024 08:02
Show Gist options
  • Save halimkun/ad9120e3eb430dcd593d676745a985b0 to your computer and use it in GitHub Desktop.
Save halimkun/ad9120e3eb430dcd593d676745a985b0 to your computer and use it in GitHub Desktop.
RSIAP Mobile
// ..... Pemanggilan controller
final LoginController controller = Get.put(LoginController());

// .... Other Code ....

// ..... Login Button
  Obx(() => ElevatedButton(
    style: ElevatedButton.styleFrom(
      minimumSize: const Size(double.infinity, 40),
      padding: const EdgeInsets.symmetric(vertical: 15),
    ),
    onPressed: controller.isLoading.value
        ? null
        : () => controller.login(),
    child: controller.isLoading.value
        ? const CircularProgressIndicator()
        : const Text('Masuk'),
  ),
),
  
// .... Other Code ....

Penjelasan

  1. Obx(() => ...) adalah sebuah widget yang disediakan oleh GetX. Fungsinya adalah untuk membangun ulang UI setiap kali ada perubahan state yang diobservasi.

  2. ElevatedButton adalah widget tombol dengan elevasi (bayangan) yang disediakan oleh Flutter.

  3. style: ElevatedButton.styleFrom(...) digunakan untuk mengatur gaya tombol. Dalam kode ini, diatur agar tombol memiliki lebar maksimum (double.infinity), tinggi 40, dan padding vertikal 15.

  4. onPressed: controller.isLoading.value ? null : () => controller.login(), adalah callback yang dipanggil saat tombol ditekan. Jika controller.isLoading.value bernilai true (artinya sedang dalam proses loading), maka tombol tidak akan merespons apapun (null). Jika tidak, maka akan memanggil fungsi controller.login().

  5. child: controller.isLoading.value ? const CircularProgressIndicator() : const Text('Masuk'), adalah isi dari tombol. Jika controller.isLoading.value bernilai true, maka tombol akan menampilkan indikator loading (CircularProgressIndicator). Jika tidak, maka tombol akan menampilkan teks "Masuk".

Dalam konteks kode ini, controller kemungkinan adalah sebuah instance dari sebuah kelas yang mengimplementasikan logika bisnis untuk proses login. Variabel isLoading digunakan untuk mengontrol tampilan tombol saat proses login sedang berlangsung atau tidak.

class LoginController extends GetxController {
 // ..... Other Code .....
 
 Future<void> login() async {
    isLoading(true);
    // ambil text dari input
    final nomorRekamMedis = nomorRekamMedisController.text;
    final password = passwordController.text;

    // cek apakah no rm dan password kosong
    if (nomorRekamMedis.isEmpty || password.isEmpty) {
      // menampilkan get snackbar
      Get.snackbar(
        'Login Gagal',
        'Nomor rekam medis dan password tidak boleh kosong.',
        snackPosition: SnackPosition.BOTTOM,
        margin: const EdgeInsets.symmetric(vertical: 15, horizontal: 10),
      );
      isLoading(false);
      return;
    }

    // fake loading
    await Future.delayed(const Duration(milliseconds: 1200));

    // post data ke api login dengan body params no_rkm_medis dan password
    final response = await http.post(
      Uri.parse('${APIConfig.BASE_API_URL}/pasien/auth/login'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'no_rkm_medis': nomorRekamMedis,
        'password': password,
      }),
    );

    // cek response status = 200 (sukses)
    if (response.statusCode == 200) {
      // decode response json (dari api)
      final data = jsonDecode(response.body);
      final token = data['access_token']; // <-- Ambil token dari response

      // Simpan token kedalam local storage menggunakan GetStorage
      await box.write('token', token);
      
      // validate token + ambil detail pengguna, contoh response dibawah
      final pasien = await fetchPatientDetails(token);
      if (pasien['statusCode'] == 200) {
        // simpan kedalam local storage menggunakan GetStorage
        await box.write('user', pasien['pasien']);
      }

      // Navigasi ke layar utama
      Get.offNamed('/home');
    } else {
      // jika response status code tidak = 200
      // tampilkan get snackbar
      Get.snackbar(
        'Login Gagal',
        'Nomor rekam medis atau password salah.',
        snackPosition: SnackPosition.BOTTOM,
        margin: const EdgeInsets.symmetric(vertical: 15, horizontal: 10),
      );
    }
    // hentikan loading. 
    isLoading(false);
    
    // kondisi disi akan tetap berada pada halaman login
  }
 
 // ..... Other Code .....
}

Response Detail Pengguna

{
    "data": {
        "no_rkm_medis": "063490",
        "tgl_daftar": "2024-01-17",
        "nm_pasien": "M FAISAL HALIM",
        "jenis_kelamin": "L",
        "tgl_lahir": "2001-06-04",
        "alamat": "SAMPEL-LOLONG KARANGANYAR PEKALONGAN 51182",
        "no_tlp": "082329089580",
        "email": "int.halim@gmail.com"
    }
}

Penjelasan Fungsi Login di Dart (atau Flutter)

Berikut adalah penjelasan rinci tentang kode fungsi asynchronous yang menangani proses login pengguna:

Rincian Kode

  1. Deklarasi Fungsi:

    • Fungsi login() dideklarasikan sebagai Future<void>, yang berarti fungsi ini mengembalikan objek Future tanpa nilai kembalian.
  2. State Management:

    • Fungsi ini menggunakan state management dengan isLoading(true) untuk menampilkan indikator loading sebelum melakukan proses login.
  3. Mengambil Nilai Input:

    • Nilai dari input field untuk nomor rekam medis dan password diambil menggunakan nomorRekamMedisController.text dan passwordController.text.
  4. Pengecekan Input:

    • Pengecekan dilakukan untuk memastikan nomor rekam medis dan password tidak kosong. Jika salah satu atau keduanya kosong, maka akan menampilkan snackbar dengan pesan error.
  5. Simulasi Loading:

    • Setelah pengecekan selesai, terdapat penundaan semu (Future.delayed) selama 1,2 detik untuk mensimulasikan proses loading.
  6. Permintaan HTTP POST:

    • Kode melakukan permintaan HTTP POST ke endpoint API /pasien/auth/login dengan menggunakan package http. Request body berisi nomor rekam medis dan password dalam format JSON.
  7. Handling Respons Sukses:

    • Jika respons dari API memiliki status code 200 (sukses), kode akan mengambil token akses (access_token) dari respons JSON.
    • Token akses tersebut disimpan dalam penyimpanan lokal menggunakan package get_storage dengan kunci 'token'.
  8. Mendapatkan Detail Pengguna:

    • Fungsi fetchPatientDetails(token) dipanggil dengan meneruskan token akses untuk mendapatkan detail pengguna dari API.
    • Jika respons dari fetchPatientDetails memiliki status code 200, detail pengguna disimpan dalam penyimpanan lokal dengan kunci 'user'.
  9. Navigasi ke Layar Utama:

    • Setelah proses login berhasil, navigasi dilakukan ke layar utama (/home) menggunakan Get.offNamed().
  10. Handling Respons Gagal:

    • Jika respons dari API login memiliki status code selain 200, maka snackbar dengan pesan error "Nomor rekam medis atau password salah" akan ditampilkan.
  11. Mengubah State Loading:

    • Terakhir, state loading diubah menjadi false dengan isLoading(false).

Kesimpulan

Secara keseluruhan, kode ini menangani proses login pengguna dengan:

  • Melakukan validasi input
  • Mengirimkan permintaan ke API untuk autentikasi
  • Menyimpan token akses dan detail pengguna dalam penyimpanan lokal
  • Melakukan navigasi ke layar utama setelah login berhasil

Kode ini juga menampilkan indikator loading dan snackbar untuk memberikan umpan balik kepada pengguna.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment