# **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.