Modul Praktikum RPL – Mobile Programming
Di era digital, pemesanan makanan tidak lagi harus datang langsung ke kantin. Dengan aplikasi mobile, siswa bisa memesan makanan dan minuman langsung dari kelas, lalu pesanan dikirim melalui WhatsApp ke kurir/jastip.
Pada praktikum ini, kita akan membuat Aplikasi Kantin SMKN 1 Banjar menggunakan Flutter (Dart) yang dapat:
Menampilkan daftar menu
Menambahkan item ke keranjang
Menghitung total harga otomatis
Checkout dan mengirim pesanan ke WhatsApp
Menyimpan nomor WhatsApp admin
🎯 Tujuan Pembelajaran
Setelah mengikuti praktikum ini, peserta didik mampu:
Memahami struktur dasar project Flutter.
Membuat tampilan UI menggunakan Widget.
Mengelola state sederhana (keranjang belanja).
Menggunakan package eksternal (
url_launcher).Menghubungkan aplikasi dengan WhatsApp.
Build APK aplikasi Android.
🧠 Konsep yang Dipelajari
| Konsep | Penjelasan |
|---|---|
| StatelessWidget | Widget yang tidak berubah |
| StatefulWidget | Widget yang bisa berubah (dynamic) |
| List & Object | Menyimpan data menu |
| setState() | Mengubah tampilan saat data berubah |
| url_launcher | Membuka WhatsApp dari aplikasi |
| Build APK | Mengubah project menjadi file install Android |
🛠 Persiapan Alat
Pastikan sudah terinstall:
Flutter SDK
Android Studio (Emulator)
VS Code + Extension Flutter
Cek dengan:
flutter doctor
🚀 Langkah Praktikum
1️⃣ Membuat Project Baru
flutter create kantin_smkn1banjar
cd kantin_smkn1banjar
code .
2️⃣ Tambahkan Dependency
Buka pubspec.yaml, tambahkan:
dependencies:
flutter:
sdk: flutter
url_launcher: ^6.2.5
Lalu jalankan:
flutter pub get
📦 Struktur Aplikasi
Aplikasi ini memiliki fitur:
Beranda (Daftar Menu)
Keranjang
Checkout
Kirim ke WhatsApp
💻 FULL SOURCE CODE (main.dart)
Salin seluruh kode berikut ke:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(KantinApp());
}
class KantinApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Kantin SMKN 1 Banjar',
theme: ThemeData(primarySwatch: Colors.green),
home: HomeScreen(),
);
}
}
class MenuItem {
final String nama;
final int harga;
int qty;
MenuItem({required this.nama, required this.harga, this.qty = 0});
}
List<MenuItem> daftarMenu = [
MenuItem(nama: "Nasi Goreng", harga: 12000),
MenuItem(nama: "Mie Ayam", harga: 10000),
MenuItem(nama: "Bakso", harga: 13000),
MenuItem(nama: "Es Teh", harga: 5000),
MenuItem(nama: "Pop Ice", harga: 5000),
];
List<MenuItem> keranjang = [];
String nomorWA = "6281234567890";
int ongkir = 2000;
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int get total =>
keranjang.fold(0, (sum, item) => sum + (item.harga * item.qty));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Kantin SMKN 1 Banjar"),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => CartScreen()));
},
)
],
),
body: ListView.builder(
itemCount: daftarMenu.length,
itemBuilder: (context, index) {
final item = daftarMenu[index];
return Card(
child: ListTile(
title: Text(item.nama),
subtitle: Text("Rp ${item.harga}"),
trailing: item.qty == 0
? ElevatedButton(
onPressed: () {
setState(() {
item.qty = 1;
keranjang.add(item);
});
},
child: Text("Tambah"),
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
item.qty--;
if (item.qty == 0) {
keranjang.remove(item);
}
});
},
),
Text(item.qty.toString()),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
item.qty++;
});
},
),
],
),
),
);
},
),
floatingActionButton: keranjang.isEmpty
? null
: FloatingActionButton.extended(
label: Text("Rp $total"),
icon: Icon(Icons.payment),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => CheckoutScreen()));
},
),
);
}
}
class CartScreen extends StatelessWidget {
int get subtotal =>
keranjang.fold(0, (sum, item) => sum + (item.harga * item.qty));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Keranjang")),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: keranjang.length,
itemBuilder: (context, index) {
final item = keranjang[index];
return ListTile(
title: Text("${item.nama} x${item.qty}"),
subtitle: Text("Rp ${item.harga * item.qty}"),
);
},
),
),
Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("Subtotal: Rp $subtotal"),
Text("Ongkir: Rp $ongkir"),
Text(
"Total: Rp ${subtotal + ongkir}",
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
)
],
),
);
}
}
class CheckoutScreen extends StatelessWidget {
void kirimWA() async {
String pesan = "Pesanan Kantin SMKN 1 Banjar\n\n";
for (var item in keranjang) {
pesan += "- ${item.nama} x${item.qty} = Rp ${item.harga * item.qty}\n";
}
int total =
keranjang.fold(0, (sum, item) => sum + (item.harga * item.qty));
pesan += "\nOngkir: Rp $ongkir";
pesan += "\nTotal: Rp ${total + ongkir}";
final url =
"https://wa.me/$nomorWA?text=${Uri.encodeComponent(pesan)}";
await launchUrl(Uri.parse(url),
mode: LaunchMode.externalApplication);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Checkout")),
body: Center(
child: ElevatedButton(
child: Text("Kirim ke WhatsApp"),
onPressed: kirimWA,
),
),
);
}
}
📦 Cara Build APK
flutter build apk --release
File APK ada di:
build/app/outputs/flutter-apk/app-release.apk
📝 Tugas Praktikum Siswa
Tambahkan 3 menu baru.
Ubah ongkir menjadi 3000.
Tambahkan input nama dan kelas saat checkout.
Tambahkan halaman pengaturan nomor WA.
Ubah tema warna aplikasi.
📊 Refleksi Pembelajaran
Diskusikan dengan siswa:
Apa fungsi
setState()?Mengapa kita menggunakan List?
Bagaimana cara kerja pengiriman ke WhatsApp?
Bagaimana jika ingin menyimpan data ke database?
🚀 Pengembangan Lanjutan
Untuk level lanjut, aplikasi bisa dikembangkan menjadi:
Login siswa
Firebase database
Dashboard admin
Export PDF laporan
QRIS pembayaran
Teaching Factory Kantin Digital
Salam Redaksi.







Tidak ada komentar:
Posting Komentar