Skip to content

amberleyvs/offside-outlet-mobile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tugas 7: Elemen Dasar Flutter

I need your help with the following content:


1. Jelaskan apa itu widget tree pada Flutter dan bagaimana hubungan parent-child (induk-anak) bekerja antar widget.

Widget tree adalah struktur hierarki yang menggambarkan bagaimana widget disusun dalam aplikasi Flutter.
Setiap elemen di layar (teks, tombol, kolom, dll) adalah widget, dan semua widget saling bersarang (nested).

  • Parent (induk): Widget yang membungkus atau berisi widget lain.
  • Child (anak): Widget yang berada di dalam parent.

Pada proyek ini contohnya Scaffold adalah parent yang memiliki child AppBar dan body.
Lalu body berisi Column → Row → InfoCard → Text.


2. Sebutkan semua widget yang kamu gunakan dalam proyek ini dan jelaskan fungsinya.

  • MaterialApp: Widget root aplikasi. Mengatur tema, judul, dan halaman awal (home).
  • Scaffold: Menyediakan struktur dasar halaman (AppBar, Body, FloatingActionButton, dsb).
  • AppBar: Menampilkan header di bagian atas aplikasi dengan judul (“Offside Outlet”).
  • Padding: Memberikan jarak di sekeliling konten (EdgeInsets.all(16.0)).
  • Column: Menyusun widget secara vertikal (atas ke bawah).
  • Row: Menyusun widget secara horizontal (samping).
  • InfoCard: Widget kustom buatanmu untuk menampilkan info nama, NPM, kelas.
  • Card: Memberi efek seperti kartu (elevasi/bayangan, border melengkung).
  • GridView.count: Menyusun daftar tombol (ItemCard) menjadi grid 3 kolom.
  • ItemCard / ProductCard: Widget kustom tombol berwarna untuk menampilkan aksi produk.
  • Icon: Menampilkan ikon seperti inventory, person, add.
  • Text: Menampilkan teks seperti “All Products” atau “Pilih aksi produk”.
  • InkWell: Memberikan efek sentuhan dan menangani event onTap().
  • SnackBar: Muncul sementara di bawah layar untuk memberi notifikasi (“Kamu telah menekan tombol …”).
  • ScaffoldMessenger: Menampilkan atau menyembunyikan SnackBar di layar.

3. Apa fungsi dari widget MaterialApp? Jelaskan mengapa widget ini sering digunakan sebagai widget root.

MaterialApp adalah widget utama yang membungkus seluruh aplikasi Flutter berbasis Material Design.

Fungsinya:

  • Mengatur tema warna aplikasi.
  • Menyediakan navigasi antar halaman (Navigator).
  • Menentukan halaman awal aplikasi melalui home.
  • Menangani localization, routes, dan debug banner.

Widget MaterialApp sering jadi root karena menyediakan semua konfigurasi dasar yang dibutuhkan hampir setiap aplikasi Flutter modern. Tanpa MaterialApp, kita tidak bisa memakai widget seperti Scaffold, AppBar, atau SnackBar yang merupakan bagian dari Material Design system.


4. Jelaskan perbedaan antara StatelessWidget dan StatefulWidget. Kapan kamu memilih salah satunya?

  • StatelessWidget: Bersifat tidak berubah (immutable) dan datanya tidak bisa berubah setelah dibuat.
    Hanya mengimplementasikan metode build() untuk menampilkan UI yang statis (misalnya Text atau Icon).
  • StatefulWidget: Dirancang untuk data yang bisa berubah (mutable) seiring berjalannya aplikasi.
    Menggunakan metode createState() dan mengandalkan setState() untuk memicu pembangunan kembali widget secara selektif dan memperbarui tampilan menjadi dinamis dan interaktif (misalnya Form atau Checkbox).

Dalam proyek ini saya memakai StatelessWidget karena tampilannya tidak berubah secara real-time.


5. Apa itu BuildContext dan mengapa penting di Flutter? Bagaimana penggunaannya di metode build?

BuildContext adalah objek yang menyimpan informasi lokasi widget di dalam widget tree.
Dengan BuildContext, Flutter mengetahui posisi widget berada dalam hierarki, tema atau ThemeData apa yang berlaku, dan akses ke widget induk seperti Scaffold atau Navigator.


6. Jelaskan konsep "hot reload" di Flutter dan bagaimana bedanya dengan "hot restart".

Hot Reload dan Hot Restart adalah dua fitur utama Flutter yang mempercepat proses pengembangan aplikasi.

  • Hot Reload digunakan untuk menerapkan perubahan kecil secara cepat, seperti mengubah teks, warna, atau tata letak (layout), tanpa menghapus state atau data yang sedang aktif pada aplikasi. Artinya, jika sedang berada pada suatu halaman dengan data tertentu, data tersebut tetap dipertahankan setelah reload dilakukan. Prosesnya sangat cepat karena hanya memperbarui kode UI yang berubah.
  • Hot Restart digunakan untuk memulai ulang seluruh aplikasi dari awal. Semua state widget akan dihapus dan aplikasi dijalankan kembali seperti saat pertama kali dijalankan. Fitur ini biasanya digunakan ketika terjadi perubahan besar pada struktur kode atau variabel global, karena memastikan aplikasi memuat ulang seluruh logika dan data dari awal.

Tugas 8: Flutter Navigation, Layouts, Forms, and Input Elements

1. Jelaskan perbedaan antara Navigator.push() dan Navigator.pushReplacement() pada Flutter. Dalam kasus apa sebaiknya masing-masing digunakan pada aplikasi Football Shop kamu?

Perbedaan utama:

  • Navigator.push() menambahkan halaman baru di atas navigation stack. Pengguna masih bisa kembali ke halaman sebelumnya dengan tombol Back.
  • Navigator.pushReplacement() mengganti halaman yang aktif dengan halaman baru. Halaman lama dikeluarkan dari stack, jadi tidak bisa kembali ke sana.

Contoh:

  • Pakai Navigator.push() saat aksi yang memang perlu “jalan pulang”. Misalnya, dari drawer pilih Add Product → masuk ke form → setelah submit, pengguna bisa menekan Back untuk kembali ke halaman utama.
  • Pakai Navigator.pushReplacement() untuk perpindahan antarmenu utama supaya stack tidak menumpuk. Misalnya, dari drawer pilih Home → halaman utama langsung menggantikan halaman sekarang, jadi tidak ada banyak “Home” berlapis di stack.

2. Bagaimana kamu memanfaatkan hierarchy widget seperti Scaffold, AppBar, dan Drawer untuk membangun struktur halaman yang konsisten di seluruh aplikasi?

  • Scaffold jadi “tulang punggung” tiap halaman. tempat standar untuk AppBar, body, Drawer, dan komponen lain. Hasilnya, struktur UI konsisten di seluruh aplikasi.
  • AppBar di bagian atas Scaffold yang menampilkan judul/branding dan aksi (icon search, add, dsb.).
  • Drawer sebagai navigasi utama yang berisi tautan antar‐halaman
  • pushReplacement untuk pindah antar halaman utama supaya stack tetap bersih.

Contoh:

Scaffold(
  appBar: AppBar(
    title: Text('Football Shop'),
    backgroundColor: Theme.of(context).colorScheme.primary,
  ),
  drawer: LeftDrawer(), 
  body: ... 
)

3. Dalam konteks desain antarmuka, apa kelebihan menggunakan layout widget seperti Padding, SingleChildScrollView, dan ListView saat menampilkan elemen-elemen form? Berikan contoh penggunaannya dari aplikasi kamu.

  • Padding memberikan jarak di sekitar widget, membuat tampilan lebih rapi dan nyaman untuk disentuh.
  • SingleChildScrollView membuat form bisa di-scroll, sehingga semua field tetap bisa diakses meski layar kecil.
  • ListView cocok untuk menampilkan daftar widget yang dinamis, misal banyak field atau daftar produk.

Contoh:

SingleChildScrollView(
  child: Padding(
    padding: EdgeInsets.all(8.0),
    child: Column(
      children: [
        TextFormField(...), 
        SizedBox(height: 8),
        TextFormField(...), 
      ],
    ),
  ),
)

4. Bagaimana kamu menyesuaikan warna tema agar aplikasi Football Shop memiliki identitas visual yang konsisten dengan brand toko?

  • Warna utama dan properti tema diatur di ThemeData pada MaterialApp.
  • Menggunakan warna utama brand untuk primarySwatch dan background AppBar.
  • Terapkan skema warna ke tombol, ikon, dan highlight agar konsisten.

Contoh:

MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.blue),
    appBarTheme: AppBarTheme(
      backgroundColor: Color(0xFF2563EB), 
      foregroundColor: Colors.white,
    ),
  ),
  home: MyHomePage(...),
)

Tugas 9: Integrasi Layanan Web Django dengan Aplikasi Flutter

1. Jelaskan mengapa kita perlu membuat model Dart saat mengambil/mengirim data JSON? Apa konsekuensinya jika langsung memetakan Map<String, dynamic> tanpa model (terkait validasi tipe, null-safety, maintainability)?

Saat berkomunikasi dengan Django, data yang dikirim/diterima biasanya dalam bentuk JSON. Di Flutter, lebih aman dan rapi kalau JSON itu di-mapping dulu ke model Dart (class) daripada dibiarkan sebagai Map<String, dynamic>.

Alasannya:

  • Validasi tipe & type-safety
    Dengan model, setiap field punya tipe jelas: String, int, bool, DateTime, dll. Kalau backend mengirim tipe yang salah atau kita salah pakai, error bisa cepat ketahuan saat compile / parse, bukan diam-diam di runtime.

  • Null-safety
    Dengan model, kita bisa menentukan mana field yang required dan mana yang boleh null. Ini mengurangi risiko error seperti Null check operator used on a null value.

  • Maintainability & readability
    Akses item.name, item.price jauh lebih jelas daripada map['name'], map['price']. Kalau nama field di backend berubah, cukup perbaiki di satu file model, bukan di semua tempat yang pakai map['...'].

Konsekuensi kalau langsung memakai Map<String, dynamic> tanpa model:

  • Lebih rawan typo key ('naem' bukannya 'name') dan tetap lolos compile.
  • Tidak ada jaminan tipe data, sehingga gampang muncul error aneh di runtime.
  • Null-safety susah diawasi karena semua dianggap dynamic.
  • Kode cepat berantakan dan susah di-maintain kalau aplikasi makin besar.

2. Apa fungsi package http dan CookieRequest dalam tugas ini? Jelaskan perbedaan peran http vs CookieRequest.

  • Package http

    • Library umum untuk melakukan HTTP request (GET, POST, dll).
    • Tidak otomatis mengatur cookie atau session.
    • Cocok untuk: Mengakses endpoint publik dan kasus di mana kita sendiri yang urus header/token.
  • CookieRequest (dari pbp_django_auth)

    • Wrapper khusus yang didesain untuk integrasi dengan Django.
    • Menyimpan dan mengirim cookie session Django secara otomatis.
    • Menyediakan method:
      • login(url, body) login ke Django dan simpan cookie.
      • logout(url) logout dan hapus session.
      • get(url) dan postJson(url, body) request dengan cookie yang sama.

Perbedaannya: http itu general, low-level, tidak tahu apa-apa soal session Django. Sedangkan CookieRequest lebih spesifik untuk autentikasi + session Django, mengelola cookie otomatis, dan sudah terintegrasi dengan pola tugas PBP.


3. Jelaskan mengapa instance CookieRequest perlu untuk dibagikan ke semua komponen di aplikasi Flutter.

Karena session user itu satu, bukan per-halaman. Aplikasi Flutter harus pakai satu instance CookieRequest yang sama di semua widget.

Untuk itu, MaterialApp di main.dart dibungkus dengan Provider:

  • Di main.dart:

    Provider(
      create: (_) => CookieRequest(),
      child: MaterialApp(...),
    );
  • Di setiap widget yang butuh request:

    final request = context.watch<CookieRequest>();

Alasannya:

  • Satu sumber truth untuk session
    Login di halaman A harus otomatis membuat halaman B juga "tahu" bahwa user sudah login. Ini hanya bisa kalau semuanya pakai instance CookieRequest yang sama.

  • Cookie konsisten
    Cookie session disimpan di dalam CookieRequest. Kalau tiap halaman punya objek sendiri, maka session bisa beda-beda dan backend akan menganggap kita belum login.

  • Lebih rapi daripada global variable
    Provider memberi cara yang bersih untuk mengakses CookieRequest di mana saja tanpa oper-oper variabel lewat constructor.


4. Jelaskan konfigurasi konektivitas yang diperlukan agar Flutter dapat berkomunikasi dengan Django. Mengapa kita perlu menambahkan 10.0.2.2 pada ALLOWED_HOSTS, mengaktifkan CORS dan pengaturan SameSite/cookie, dan menambahkan izin akses internet di Android? Apa yang akan terjadi jika konfigurasi tersebut tidak dilakukan dengan benar?

Supaya Flutter bisa terhubung dengan Django, ada beberapa konfigurasi penting:

a. Menambahkan 10.0.2.2 pada ALLOWED_HOSTS

  • Di Android emulator, "localhost" = emulator itu sendiri, bukan laptop kita.
  • 10.0.2.2 adalah alamat khusus yang menunjuk ke localhost mesin host dari sudut pandang emulator.
  • Jadi di settings.py:
    ALLOWED_HOSTS = [..., "10.0.2.2"]

Jika ini tidak dilakukan:

  • Django akan memunculkan error DisallowedHost dan menolak request dari 10.0.2.2.

b. Mengaktifkan CORS (Cross-Origin Resource Sharing)

  • Flutter app dan Django biasanya beda origin (beda port/domain).
  • django-cors-headers digunakan untuk mengizinkan request dari Flutter.
  • Misalnya:
    CORS_ALLOW_ALL_ORIGINS = True  
    CORS_ALLOW_CREDENTIALS = True

Jika tidak diatur dengan benar:

  • Browser/client bisa blok request dengan error CORS.
  • Cookie (session) mungkin tidak akan dikirim jika CORS_ALLOW_CREDENTIALS atau header terkait tidak tepat.

c. Pengaturan SameSite dan cookie

  • Supaya cookie session Django bisa terkirim dalam konteks berbeda, diatur misalnya:
    CSRF_COOKIE_SECURE = True  
    SESSION_COOKIE_SECURE = True  
    CSRF_COOKIE_SAMESITE = 'None'  
    SESSION_COOKIE_SAMESITE = 'None'

Jika salah konfigurasi:

  • Cookie session bisa tidak ikut terkirim, sehingga Django selalu menganggap user belum login meskipun user sudah login dari Flutter.

d. Menambahkan izin akses internet di Android

  • Di AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />

Kalau izin ini tidak ada:

  • Aplikasi Android tidak bisa akses internet sama sekali, sehingga semua HTTP request ke Django akan gagal.

5. Jelaskan mekanisme pengiriman data mulai dari input hingga dapat ditampilkan pada Flutter.

Alur umumnya:

  1. User melakukan input / aksi di Flutter
    Contoh: membuka halaman daftar item atau submit form.

  2. Flutter mengirim request ke Django

    • Untuk GET list item:
      response = await request.get("http://[APP_URL]/json/");
    • Untuk POST data (misalnya create item):
      response = await request.postJson(
        "http://[APP_URL]/create-flutter/",
        jsonEncode({...}),
      );
  3. Django memproses request

    • Untuk GET:
      • Mengambil data dari database (misalnya Item.objects.filter(user=request.user)).
      • Meng-serialize ke JSON dan mengembalikannya ke Flutter.
    • Untuk POST:
      • Parse request.body menjadi JSON.
      • Validasi data dan membuat objek baru di database.
      • Mengembalikan JSON yang berisi status sukses/gagal.
  4. Flutter menerima JSON dan memetakan ke model Dart

    • Data (list map) di-loop dan dikonversi ke List<Model> dengan fromJson:
      List<Item> items = [];
      for (var d in response) {
        items.add(Item.fromJson(d));
      }
  5. UI menampilkan data

    • Menggunakan FutureBuilder:
      • Saat future masih jalan → tampil CircularProgressIndicator.
      • Saat future selesai → build ListView.builder dengan data model.
    • Tiap item di-render dalam Card atau ListTile yang menampilkan field seperti name, price, description, thumbnail, category, is_featured.

6. Jelaskan mekanisme autentikasi dari login, register, hingga logout. Mulai dari input data akun pada Flutter ke Django hingga selesainya proses autentikasi oleh Django dan tampilnya menu pada Flutter.

a. Register

  1. User mengisi form register di Flutter (username, password, confirm password).
  2. Flutter mengirim request ke Django:
    response = await request.postJson(
      "http://[APP_URL]/auth/register/",
      jsonEncode({
        "username": username,
        "password1": password1,
        "password2": password2,
      }),
    );
  3. Django:
    • Parse JSON dari request.body.
    • Cek apakah password1 == password2.
    • Cek apakah username sudah ada di database.
    • Jika valid, membuat user baru dengan User.objects.create_user.
    • Mengembalikan JSON dengan status success atau error.
  4. Flutter:
    • Jika status == "success" tampilkan pesan "Successfully registered!" lalu redirect ke halaman login.
    • Jika gagal menampilkan pesan error via SnackBar/AlertDialog.

b. Login

  1. User mengisi username dan password di form login Flutter.

  2. Flutter memanggil:

    response = await request.login(
      "http://[APP_URL]/auth/login/",
      {
        "username": username,
        "password": password,
      },
    );
  3. Django:

    • Mengambil username dan password dari request.POST.
    • Memanggil authenticate(username=..., password=...).
    • Jika user valid dan aktif:
      • auth_login(request, user) → membuat session di server.
      • Mengembalikan JSON:
        {
          "username": user.username,
          "status": True,
          "message": "Login successful!"
        }
    • Jika gagal, mengembalikan status False dengan pesan error.
  4. CookieRequest:

    • Menyimpan cookie session dari Django.
    • Menandai request.loggedIn = true.
  5. Flutter:

    • Jika request.loggedIn == true, melakukan Navigator.pushReplacement ke halaman utama (misalnya MyHomePage()).
    • Menampilkan pesan sambutan misalnya "Login successful! Welcome, ".

c. Logout

  1. User menekan tombol Logout di Flutter.
  2. Flutter memanggil:
    response = await request.logout("http://[APP_URL]/auth/logout/");
  3. Django:
    • Mengambil username dari request.user.username.
    • Memanggil auth_logout(request) untuk menghapus session.
    • Mengembalikan JSON dengan status True/False dan message.
  4. CookieRequest:
    • Menghapus cookie/session yang tersimpan.
  5. Flutter:
    • Jika logout sukses ada SnackBar "Logged out successfully! See you again, ." dan melakukan Navigator.pushReplacement ke LoginPage().
    • Jika gagal akan menampilkan pesan error.

7. Cara mengimplementasikan checklist secara step-by-step (bukan hanya mengikuti tutorial) 1. Menyiapkan backend Django tugas

  • Memastikan proyek Django dari tugas sebelumnya berjalan (runserver atau deployment).
  • Menambahkan django-cors-headers, mengatur CORS_ALLOW_ALL_ORIGINS, CORS_ALLOW_CREDENTIALS, dan pengaturan cookie (CSRF_COOKIE_SAMESITE, SESSION_COOKIE_SAMESITE).
  • Menambahkan 10.0.2.2 dan domain deployment ke ALLOWED_HOSTS.

2. Membuat dan mengonfigurasi app authentication di Django

  • Menjalankan python manage.py startapp authentication.
  • Menambahkan "authentication" ke INSTALLED_APPS.
  • Membuat view login, register, dan logout di authentication/views.py.
  • Menambahkan urls authentication (login, register, logout) dan meng-include-nya di urls.py utama dengan prefix /auth/.

3. Menyiapkan endpoint JSON untuk item

  • Membuat view yang meng-serialize daftar item ke JSON.
  • Memastikan queryset difilter berdasarkan user yang login (filter(user=request.user)) sehingga hanya item milik user yang tampil.
  • Menambahkan path /json/ (atau nama lain) di urls.py.

4. Menyiapkan endpoint untuk create item dari Flutter

  • Membuat view create_<model>_flutter dengan @csrf_exempt.
  • Mem-parse request.body, memvalidasi data, menghapus tag HTML jika perlu (strip_tags), dan membuat objek baru di database dengan user=request.user.
  • Mengembalikan JsonResponse({"status": "success"}) jika berhasil.
  • Menambahkan path /create-flutter/ di urls.py.

5. Konfigurasi aplikasi Flutter

  • Menambahkan dependency provider, pbp_django_auth, dan http di pubspec.yaml.
  • Menambahkan izin internet di AndroidManifest.xml.
  • Mengubah main.dart supaya membungkus MaterialApp dengan Provider yang menyediakan satu instance CookieRequest.
  • Mengganti home: MyHomePage() menjadi home: const LoginPage().

6. Membuat halaman Login di Flutter

  • Membuat screens/login.dart dengan LoginPage (StatefulWidget).
  • Menambahkan TextEditingController untuk username dan password.
  • Mengambil CookieRequest via context.watch<CookieRequest>().
  • Di tombol login, memanggil request.login("http://[APP_URL]/auth/login/", {...}).
  • Jika berhasil, menampilkan SnackBar dan melakukan Navigator.pushReplacement ke halaman utama.

7. Membuat halaman Register di Flutter

  • Membuat screens/register.dart dengan form username, password, dan confirm password.
  • Mengirim data ke Django menggunakan request.postJson("http://[APP_URL]/auth/register/", jsonEncode({...})).
  • Menambahkan GestureDetector / tombol di LoginPage yang menavigasi ke RegisterPage.
  • Menangani response: jika status == 'success', tampilkan pesan dan kembali ke LoginPage.

8. Membuat model Dart custom dari endpoint JSON

  • Membuka endpoint JSON Django di browser (misal /json/).
  • Menyalin data JSON ke Quicktype dan meng-generate model Dart.
  • Menyalin model tersebut ke lib/models/<model>.dart dan menyesuaikan nama field / tipe sesuai kebutuhan.

9. Membuat halaman daftar item di Flutter

  • Membuat screens/item_list.dart.
  • Menulis fungsi Future<List<Item>> fetchItems(CookieRequest request) yang melakukan request.get("http://[APP_URL]/json/") dan mapping ke List<Item>.
  • Menggunakan FutureBuilder untuk memanggil fetchItems dan menampilkan:
    • CircularProgressIndicator saat loading.
    • ListView.builder yang berisi card item saat data sudah ada.
  • Di card item, menampilkan name, price, description, thumbnail, category, dan is_featured.

10. Membuat card item dan halaman detail item

  • Membuat widget ItemCard di lib/widgets/item_card.dart.
  • Memberikan onTap yang memanggil Navigator.push ke ItemDetailPage(item: item).
  • Membuat ItemDetailPage di screens/item_detail.dart yang menampilkan seluruh atribut model item.
  • Menambahkan tombol kembali (Navigator.pop) di AppBar atau di dalam body.

11. Memastikan filter item hanya milik user yang login

  • Di Django, memastikan view JSON hanya mengembalikan item dengan filter(user=request.user).
  • Menguji dengan login dua user berbeda dan memastikan item yang tampil di Flutter sesuai pemiliknya.

12. Menambahkan fitur logout di Flutter

  • Menambahkan opsi Logout di menu / drawer / card pada halaman utama.
  • Mengambil CookieRequest via context.watch<CookieRequest>() di widget tersebut.
  • Di onTap, memanggil request.logout("http://[APP_URL]/auth/logout/").
  • Menangani response: jika status True, tampilkan pesan "Logged out successfully!" dan Navigator.pushReplacement ke LoginPage.

13. Testing end-to-end

  • Register akun baru → login → tambah item dari Django/Flutter → cek apakah muncul di daftar item di Flutter → buka detail item → kembali → logout.
  • Memastikan URL [APP_URL] di Flutter sudah diganti ke URL backend yang benar (10.0.2.2:8000, localhost:8000, atau URL deployment).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors