# **Technical Test – Flutter Developer Intern at Horus Technology** ## **Project: "Simple Blog Reader + Cloud Favorites"** ----- ### 🎯 **1. Tujuan Singkat** Membuat aplikasi Flutter (iOS & Android) yang memiliki fungsi sebagai berikut: 1. Menampilkan daftar artikel dari API publik tanpa autentikasi. 2. Menampilkan detail artikel. 3. Menyimpan dan menghapus artikel favorit **secara cloud** (Firebase atau Supabase). 4. Menangani kondisi *loading* & *error* dengan baik (misalnya, menggunakan *shimmer/skeleton*). 5. **BONUS**: Implementasi *dark-mode*, *pull-to-refresh*, dan *infinite scroll*. > **Catatan:** Fitur login/register tidak wajib. Jika pengguna **anonim**, favorit tetap bisa disimpan menggunakan *device-ID*. Poin tambahan akan diberikan jika ada fitur login. ----- ### 💻 **2. Persyaratan Teknis** * **Framework**: Flutter `≥ 3.10` (stable). * **State Management**: Bebas memilih (Provider, Riverpod, BLoC, GetX). * **HTTP Client**: Bebas memilih (http, dio, dsb.). * **Cloud Backend**: Pilih salah satu: * **Firebase**: Firestore + Firebase Authentication (Anonim / Email). * **Supabase**: Postgres + Supabase Auth (Anonim / Email). * **Testing**: Unit/widget test tidak diwajibkan, namun akan menjadi nilai tambah. ----- ### 🌐 **3. Pilihan API Publik (Pilih Satu)** | API | Base-URL | Dokumentasi | Catatan | | --------------- | ------------------------------------ | ----------------------------------------- | ----------------------------------- | | JSONPlaceholder | `https://jsonplaceholder.typicode.com` | [Link](https://jsonplaceholder.typicode.com/) | Data *dummy* untuk post & user, tanpa API key. | | NewsAPI.org | `https://newsapi.org/v2` | [Link](https://newsapi.org/) | Berita aktual, membutuhkan API key gratis. | | Dev.to | `https://dev.to/api/articles` | [Link](https://developers.forem.com/api) | Blog teknologi, tanpa API key. | ----- ### 🚀 **4. Contoh Setup Cepat (Firebase)** ```bash # 1. Buat project baru di Firebase Console # 2. Aktifkan Authentication (Anonymous & Email/Password) # 3. Buat database Firestore # Jalankan di terminal Anda flutter create simple_blog_reader cd simple_blog_reader flutterfire configure flutter pub add firebase_core firebase_auth cloud_firestore flutter pub add http flutter_riverpod shimmer ``` > Jika menggunakan Supabase, ganti langkah di atas dengan dependensi `supabase_flutter`. ----- ### 📝 **5. Alur Kerja & Fitur Minimal** #### **5.1. Persiapan Awal** * **Model**: Buat model data untuk `Post`, `User`, dan `FavoritePost`. * **Service**: Siapkan kelas servis untuk `PostApiService` dan `FavoriteCloudService`. #### **5.2. Layer Repository** Strukturkan logika pengambilan data dan favorit. ``` lib/repositories/ ├─ post_repository.dart // Mengambil data post & user dari API └─ favorite_repository.dart // Fungsi CRUD favorit ke cloud ``` #### **5.3. State Management** Gunakan Provider/Notifier untuk mengelola state: * `postsProvider`: Mengelola daftar artikel. * `postDetailProvider`: Mengelola detail artikel. * `favoritesProvider`: Mengelola daftar favorit (sinkronisasi *real-time*). #### **5.4. Tampilan (UI) – 4 Halaman Utama** | Halaman | Fitur Minimal | | ---------------------------- | --------------------------------------------------------------------------------------------------------- | | **A. Splash / Login** (Opsional) | • Opsi login anonim atau email. \<br\> • Tombol untuk melanjutkan sebagai tamu. | | **B. Post List** | • GET data `/posts` atau `/top-headlines`.\<br\> • Tampilkan *shimmer loading*.\<br\> • Indikator favorit (⭐) pada setiap item. | | **C. Post Detail** | • Tampilkan judul, isi, dan penulis artikel.\<br\> • Tombol "Tambah / Hapus Favorit" yang tersinkronisasi ke cloud. | | **D. Favorites** | • Tampilkan daftar artikel favorit pengguna.\<br\> • Tap untuk melihat detail.\<br\> • Opsional: *Swipe-to-delete*. | #### **5.5. Penanganan Error & Loading** * Buat widget `ShimmerPostCard` untuk efek *loading*. * Buat `ErrorRetryWidget` yang berisi tombol untuk mencoba lagi jika terjadi kegagalan. #### **5.6. Implementasi Cloud Favorites** * **Firebase**: Gunakan struktur koleksi `favorites/{userId}/items`. `userId` bisa berupa `uid` dari Auth. * **Supabase**: Gunakan tabel `favorites` dengan kolom `(id, user_id, post_id)`. * Gunakan *listener* (Stream) dari Firestore atau Supabase untuk sinkronisasi data secara *real-time*. ----- ### 📁 **6. Rekomendasi Struktur Folder** ``` lib/ ├─ main.dart ├─ models/ │ ├─ post.dart │ └─ favorite.dart ├─ repositories/ │ ├─ post_repository.dart │ └─ favorite_repository.dart ├─ providers/ │ └─ ... ├─ services/ │ ├─ auth_service.dart │ └─ cloud_service.dart ├─ screens/ │ ├─ post_list_screen.dart │ ├─ post_detail_screen.dart │ └─ favorites_screen.dart └─ widgets/ ├─ post_card.dart ├─ shimmer_card.dart └─ error_retry.dart ``` ----- ### ✅ **7. Deliverables** 1. **Source Code**: Repository publik di **GitHub**. 2. **Dokumentasi**: File `README.md` yang berisi: * Cara menjalankan proyek (`flutter run`). * Penjelasan backend yang digunakan (Firebase atau Supabase). * *Screenshot* atau GIF aplikasi (mode terang & gelap). * Catatan singkat mengenai arsitektur dan *state management* yang dipilih. ----- ### 🏆 **8. Kriteria Penilaian (Total 100 + 20 Poin Bonus)** | Kriteria | Bobot | | ------------------------------------------- | ----- | | Fungsionalitas Inti (List, Detail, Favorit) | 40 | | Kualitas Kode & Struktur Proyek | 25 | | Penanganan Loading & Error (UI/UX) | 15 | | Implementasi Backend Cloud | 20 | | **Fitur Bonus** (Dark Mode, dsb.) | +20 | ----- **Selamat Mengerjakan\!** Hasil akan didiskusikan saat sesi wawancara.