Aplikasi restoran yang menampilkan daftar restoran, detail, pencarian, fitur ulasan, favorit, pengaturan tema, dan notifikasi harian menggunakan REST API dari Dicoding Restaurant API.
| Kategori | Library | Versi |
|---|---|---|
| Framework | Flutter (Dart SDK) | ^3.11.1 |
| State Management | provider | ^6.1.2 |
| HTTP Client | http | ^1.2.1 |
| Database | sqflite | ^2.4.2 |
| Key-Value Storage | shared_preferences | ^2.5.3 |
| Notifikasi | flutter_local_notifications | ^21.0.0 |
| Background Task | workmanager | ^0.9.0+3 |
| Timezone | timezone | ^0.11.0 |
| Font | google_fonts | ^6.2.1 |
| Testing | mockito | ^5.4.6 |
| UI | Material 3 | built-in |
- Daftar restoran dengan gambar, rating, dan kota
- Detail restoran (deskripsi, menu makanan & minuman, kategori)
- Deskripsi panjang dengan tombol "Lihat selengkapnya / Sembunyikan"
- Pencarian restoran
- Tulis & kirim ulasan
- Favorit restoran (simpan/hapus ke database SQLite)
- Dark mode / Light mode toggle (persisten via SharedPreferences)
- Pilih warna tema (10 pilihan warna)
- Pilih font (8 pilihan Google Fonts)
- Daily reminder notifikasi pukul 11.00 (restoran acak dari API)
- Bottom Navigation Bar (Home, Favorit, Pengaturan)
- Hero animation untuk transisi gambar (dengan prefix unik per tab)
lib/
├── main.dart # Entry point + init SharedPrefs, Workmanager, Notifications
├── app.dart # MultiProvider & MaterialApp setup
├── core/
│ ├── constants/
│ │ ├── app_constants.dart # Base URL & image endpoints
│ │ └── error_messages.dart # Pesan error terpusat
│ ├── exceptions/
│ │ └── app_exception.dart # Custom exception class
│ ├── models/
│ │ ├── app_color.dart # Model preset warna tema
│ │ └── app_font.dart # Model preset font
│ └── theme/
│ └── app_theme.dart # Light & dark ThemeData factory
├── data/
│ ├── local/
│ │ └── database_helper.dart # SQLite singleton (DatabaseHelper)
│ ├── models/
│ │ ├── restaurant.dart # Model list restoran + toMap/fromMap
│ │ ├── restaurant_detail.dart # Model detail restoran
│ │ ├── menu_item.dart # Model item menu
│ │ └── customer_review.dart # Model ulasan
│ └── repositories/
│ ├── restaurant_repository.dart # Abstract interface (API)
│ ├── restaurant_repository_impl.dart # Implementasi HTTP client
│ ├── favorite_repository.dart # Abstract interface (SQLite)
│ └── favorite_repository_impl.dart # Implementasi SQLite
├── providers/
│ ├── states/
│ │ ├── restaurant_list_state.dart # Sealed state: list restoran
│ │ ├── restaurant_detail_state.dart # Sealed state: detail restoran
│ │ ├── search_state.dart # Sealed state: pencarian
│ │ └── favorite_state.dart # Sealed state: favorit
│ ├── restaurant_list_provider.dart # State management list restoran
│ ├── restaurant_detail_provider.dart # State management detail & review
│ ├── search_provider.dart # State management pencarian
│ ├── theme_provider.dart # State management tema (SharedPreferences)
│ ├── favorite_provider.dart # State management favorit (SQLite)
│ └── reminder_provider.dart # State management daily reminder
├── services/
│ ├── notification_service.dart # FlutterLocalNotificationsPlugin init & show
│ └── workmanager_service.dart # Workmanager callback dispatcher + fetch random restoran
└── ui/
├── screens/
│ ├── main/
│ │ └── main_screen.dart # BottomNavigationBar + IndexedStack shell
│ ├── restaurant_list/
│ │ └── restaurant_list_screen.dart # Halaman daftar restoran (tab Home)
│ ├── restaurant_detail/
│ │ └── restaurant_detail_screen.dart # Halaman detail + tombol favorit
│ ├── search/
│ │ └── search_screen.dart # Halaman pencarian
│ ├── favorite/
│ │ └── favorite_screen.dart # Halaman daftar favorit (tab Favorit)
│ ├── settings/
│ │ └── settings_screen.dart # Halaman pengaturan (tab Settings)
│ ├── color_picker/
│ │ └── color_picker_screen.dart # Halaman pilih warna tema
│ └── font_picker/
│ └── font_picker_screen.dart # Halaman pilih font
└── widgets/
├── restaurant_card.dart # Card restoran (reusable, heroTagPrefix)
├── error_view.dart # Widget error dengan tombol retry
└── loading_indicator.dart # Loading spinner
test/
├── match_test.dart # 1 unit test (Result equality)
├── providers/
│ ├── restaurant_list_provider_test.dart # 3 unit tests (initial, success, error)
│ └── restaurant_list_provider_test.mocks.dart
└── widgets/
└── restaurant_card_test.dart # 2 widget tests (render, onTap)
integration_test/
├── app_test.dart # 1 integration test (launch -> list -> detail)
└── notification_test.dart # 2 integration tests (notifikasi hardcoded & API)
UI (StatelessWidget + Builder)
↕ context.watch / context.read
Provider (ChangeNotifier + sealed class State)
↕
Repository (abstract interface)
↕
HTTP Client / SQLite / SharedPreferences
- Sealed class untuk state management (
Loading,Loaded,Error,Initial) context.watch<T>()di dalamBuilderuntuk scoped rebuildcontext.read<T>()di callback untuk one-time access tanpa subscribe- Repository pattern dengan abstract interface untuk dependency injection
- DatabaseHelper singleton untuk akses SQLite
- SharedPreferences diinject melalui
main.dartke provider - Workmanager dengan top-level
callbackDispatcheruntuk background task - Hero animation menggunakan
heroTagPrefixunik per tab (home_,fav_,search_) untuk menghindari konflik diIndexedStack AppExceptionsebagai custom exceptionErrorMessagesuntuk memusatkan semua string error
flutter pub get
flutter runminSdk: 26- Core library desugaring enabled
- Permissions:
INTERNET,POST_NOTIFICATIONS,RECEIVE_BOOT_COMPLETED
Total: 9 test cases (4 unit + 2 widget + 3 integration)
# Unit + Widget tests (6 test cases)
flutter test
# Integration test - app flow
flutter test integration_test/app_test.dart
# Integration test - notifikasi (harus di device/emulator)
flutter test integration_test/notification_test.dart
# Semua integration tests
flutter test integration_test/| Jenis | File | Jumlah | Deskripsi |
|---|---|---|---|
| Unit | test/match_test.dart |
1 | Result equality |
| Unit | test/providers/restaurant_list_provider_test.dart |
3 | State awal, fetch sukses, fetch gagal |
| Widget | test/widgets/restaurant_card_test.dart |
2 | Render data, onTap callback |
| Integration | integration_test/app_test.dart |
1 | Launch → list → tap card → detail |
| Integration | integration_test/notification_test.dart |
2 | Notifikasi hardcoded & dari API |
Dokumentasi teori dan penjelasan detail tersedia di folder .docs/:
| # | Dokumen | Isi |
|---|---|---|
| 01 | Arsitektur | 3-layer architecture, dependency injection, alur data |
| 02 | State Management | Provider, sealed class, context.watch vs read |
| 03 | Database SQLite | Singleton pattern, CRUD, favorit |
| 04 | SharedPreferences | Persistensi tema dan pengingat |
| 05 | Notifikasi & Background | flutter_local_notifications, Workmanager |
| 06 | Testing | Unit, widget, integration test |
| 07 | Tema & Material 3 | ColorScheme, dark mode, font |
| 08 | Navigasi | Bottom nav, IndexedStack, Hero animation |
| 09 | API & Networking | REST API, error handling, models |
cd /opt/homebrew/var/www/learn-dart/2026/learning-path-flutter/flutter-fundamental
zip -r restaurant_app.zip restaurant_app_flutter/ \
-x "restaurant_app_flutter/.docs/*" \
-x "restaurant_app_flutter/.dart_tool/*" \
-x "restaurant_app_flutter/build/*" \
-x "restaurant_app_flutter/.flutter-plugins*" \
-x "restaurant_app_flutter/android/.gradle/*"Base URL: https://restaurant-api.dicoding.dev
| Endpoint | Method | Keterangan |
|---|---|---|
/list |
GET | Daftar semua restoran |
/detail/{id} |
GET | Detail restoran berdasarkan ID |
/search?q={query} |
GET | Pencarian restoran |
/review |
POST | Kirim ulasan baru |