MIF_E31230069/spk_mobile/GETTING_STARTED.md

541 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🚀 Getting Started - API Integration Ready!
**Backend API server sudah berjalan di `http://127.0.0.1:8000`**
Semua API services sudah siap. Inilah cara memulai menggunakan API di Flutter app Anda.
---
## ⚡ Quick Start (3 Langkah)
### Step 1: Update Base URL (PENTING!)
**File**: `lib/config/app_config.dart`
Cari line ini:
```dart
static const String baseUrl = 'http://192.168.18.16:8000/api';
```
**Ganti IP `192.168.18.16` dengan IP komputer Anda:**
Cek IP komputer:
- **Windows**: Buka Command Prompt, ketik `ipconfig`, cari "IPv4 Address"
- **MacOS/Linux**: Terminal, ketik `ifconfig`
Contoh hasil:
```
IPv4 Address : 192.168.1.10
```
Jadi ubah menjadi:
```dart
static const String baseUrl = 'http://192.168.1.10:8000/api';
```
### Step 2: Load Token di Main
**File**: `lib/main.dart`
Tambahkan ini di `main()`:
```dart
import 'package:spk_mobile/services/auth_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Load saved token jika ada
final authService = AuthService();
await authService.loadToken();
runApp(const MyApp());
}
```
### Step 3: Test API Connection
Ada 2 cara:
**Cara 1: Otomatis (Add to main.dart)**
```dart
import 'package:spk_mobile/test/api_test_helper.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final authService = AuthService();
await authService.loadToken();
// Test API
await APITestHelper.testGetKontrakan();
runApp(const MyApp());
}
```
**Cara 2: Manual (Call method when needed)**
```dart
// Di button atau dialog
final helper = APITestHelper();
await helper.testGetKontrakan();
```
---
## 📚 Documentation Files
Setelah selesai dengan 3 langkah di atas, baca dokumentasi sesuai kebutuhan:
| File | Untuk Apa | Baca Kapan |
|------|-----------|-----------|
| [README_API_INTEGRATION.md](README_API_INTEGRATION.md) | Overview lengkap | Pertama kali |
| [API_QUICKSTART.md](API_QUICKSTART.md) | Contoh kode | Saat implementasi |
| [API_INTEGRATION_GUIDE.md](API_INTEGRATION_GUIDE.md) | Referensi length | Saat butuh detail |
| [SCREEN_IMPLEMENTATION_CHECKLIST.md](SCREEN_IMPLEMENTATION_CHECKLIST.md) | Guide per screen | Saat build screen |
| [API_STATUS.md](API_STATUS.md) | Status & checklist | QA & submission |
---
## 🎯 Langkah Berikutnya
### 1. Verify Setup Bekerja
```dart
// Run di app Anda
await APITestHelper.testGetKontrakan();
// Seharusnya melihat: "✓ Found X kontrakan"
```
### 2. Mulai Build Screens
Pilih salah satu screen dan follow guide:
**Option A: Start with Login (Recommended)**
- Buka `SCREEN_IMPLEMENTATION_CHECKLIST.md`
- Scroll ke "1⃣ Login Screen"
- Copy dan implement code
**Option B: Start with Kontrakan List**
- Buka `SCREEN_IMPLEMENTATION_CHECKLIST.md`
- Scroll ke "3⃣ Kontrakan List Screen"
- Copy dan implement code
**Option C: Quick Example**
- Buka `API_QUICKSTART.md`
- Lihat "Common API Usage Examples"
- Copy contoh kode
### 3. Implement Services
Setiap screen butuh service(s):
```dart
import 'package:spk_mobile/services/xxx_service.dart';
class MyScreen extends StatefulWidget {
@override
State<MyScreen> createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
// Initialize service
final _service = XxxService();
// Data, loading, error states
List<Data> _data = [];
bool _isLoading = true;
String? _error;
@override
void initState() {
super.initState();
_loadData();
}
void _loadData() async {
try {
setState(() {
_isLoading = true;
_error = null;
});
// Call API
_data = await _service.getData();
setState(() => _isLoading = false);
} catch (e) {
setState(() {
_error = 'Error: $e';
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
// Build UI dengan 3 states: loading, error, data
if (_isLoading) return CircularProgressIndicator();
if (_error != null) return Text(_error!);
if (_data.isEmpty) return Text('No data');
return ListView.builder(
itemCount: _data.length,
itemBuilder: (context, index) {
return ListTile(title: Text(_data[index].toString()));
},
);
}
}
```
---
## 💡 Available Services
### 1. AuthService
```dart
import 'package:spk_mobile/services/auth_service.dart';
final auth = AuthService();
// Login
final result = await auth.login('email@example.com', 'password');
// Register
await auth.register(
name: 'John',
email: 'john@example.com',
password: 'password',
passwordConfirmation: 'password',
role: 'mahasiswa',
);
// Update profile
await auth.updateProfile(
name: 'John Doe',
phone: '081234567890',
);
// Logout
await auth.logout();
// Check auth status
print(auth.isAuthenticated);
print(auth.currentUser?.name);
```
### 2. KontrakanService
```dart
import 'package:spk_mobile/services/kontrakan_service.dart';
final service = KontrakanService();
// Get list
final list = await service.getKontrakan(
search: 'nyaman',
hargaMax: 1000000,
jumlahKamar: 2,
);
// Get detail
final detail = await service.getKontrakanById(1);
// Get recommendations
final recommendations = await service.getRecommendations(
hargaMax: 1500000,
);
```
### 3. BookingService
```dart
import 'package:spk_mobile/services/booking_service.dart';
final service = BookingService();
// Get history
final bookings = await service.getBookingHistory();
// Create booking
final result = await service.createBooking(
kontrakanId: 1,
tanggalMulai: DateTime.now(),
durasiBulan: 3,
paymentProof: File('/path/to/image.jpg'),
);
// Cancel
await service.cancelBooking(1);
```
### 4. ReviewService (NEW)
```dart
import 'package:spk_mobile/services/review_service.dart';
final service = ReviewService();
// Add review
await service.addKontrakanReview(
kontrakanId: 1,
rating: 4.5,
comment: 'Bagus dan nyaman!',
);
// Update
await service.updateReview(
reviewId: 1,
rating: 5.0,
comment: 'Updated comment',
);
// Delete
await service.deleteReview(1);
```
### 5. FavoriteService (NEW)
```dart
import 'package:spk_mobile/services/favorite_service.dart';
final service = FavoriteService();
// Toggle favorite
final result = await service.toggleKontrakanFavorite(1);
print('Is favorite: ${result['isFavorite']}');
// Check if favorite
final isFav = await service.isKontrakanFavorite(1);
// Get all favorites
final favs = await service.getFavorites();
print('Kontrakan favorites: ${favs['kontrakan']}');
```
### 6. LaundryService
```dart
import 'package:spk_mobile/services/laundry_service.dart';
final service = LaundryService();
// Get list
final list = await service.getLaundry(
search: 'express',
hargaMax: 10000,
);
// Get detail
final detail = await service.getLaundryById(1);
```
---
## ✅ Checklist Before Building
- [ ] Backend running? (`php artisan serve`)
- [ ] Base URL updated? (Check IP)
- [ ] Token loading added? (In main.dart)
- [ ] Test API working? (APITestHelper)
- [ ] Read docs? (Start with README_API_INTEGRATION.md)
- [ ] Ready to code? (Pick a screen, follow checklist)
---
## 🎯 Recommended Screen Implementation Order
1. **Login Screen** ← Start here (simplest)
2. **Kontrakan List** (use public API, no auth)
3. **Kontrakan Detail** (expand list functionality)
4. **Booking** (user interaction, file upload)
5. **Booking History** (auth required)
6. **Other Screens** (in any order)
---
## 🚨 Common Issues & Quick Fixes
### "Connection Refused"
```
Problem: API tidak bisa connect
Fix:
1. Check backend running: php artisan serve
2. Verify base URL is correct (check IP with ipconfig)
3. Firewall allow port 8000
```
### "Unauthorized 401"
```
Problem: Token invalid
Fix:
1. Login lagi
2. Check loadToken() called in main.dart
```
### "Method not found"
```
Problem: Service method tidak ada
Fix:
Check documentation di API_INTEGRATION_GUIDE.md
atau lihat list method di atas
```
### "Image upload fails"
```
Problem: File tidak upload
Fix:
1. Pastikan file path benar
2. Use image_picker package
3. Check file permissions
```
---
## 📊 Test Matrix
Sebelum push code, test:
| Feature | Test | Status |
|---------|------|--------|
| Login | Try login with correct credentials | [ ] |
| Register | Try register new user | [ ] |
| Browse Kontrakan | Load list, test filter, search | [ ] |
| View Detail | Open kontrakan detail | [ ] |
| Create Booking | Create booking dengan image | [ ] |
| Add Review | Add review dengan rating | [ ] |
| Favorite | Toggle favorite items | [ ] |
| Navigation | All buttons navigate correctly | [ ] |
| Error Handling | Test offline, invalid data | [ ] |
| Loading States | Show spinner while loading | [ ] |
---
## 🎓 Learning Resources in Project
### Code Examples
- `API_QUICKSTART.md` - Has 15+ code examples
- `SCREEN_IMPLEMENTATION_CHECKLIST.md` - Has template code for each screen
- `test/api_test_helper.dart` - Real usage examples
### API Reference
- `API_INTEGRATION_GUIDE.md` - Complete endpoint documentation
- `API_STATUS.md` - All endpoints listed
### Implementation Guides
- `SCREEN_IMPLEMENTATION_CHECKLIST.md` - Step by step per screen
- `README_API_INTEGRATION.md` - Overview and navigation
---
## 💻 Example: First Screen (Login)
```dart
import 'package:flutter/material.dart';
import 'package:spk_mobile/services/auth_service.dart';
class LoginScreen extends StatefulWidget {
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailCtrl = TextEditingController();
final _passCtrl = TextEditingController();
final _auth = AuthService();
bool _loading = false;
String? _error;
void _login() async {
setState(() {
_loading = true;
_error = null;
});
final result = await _auth.login(
_emailCtrl.text,
_passCtrl.text,
);
setState(() => _loading = false);
if (result['success']) {
// Success - navigate
Navigator.of(context).pushReplacementNamed('/home');
} else {
// Error
setState(() => _error = result['message']);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(result['message'])),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _emailCtrl,
decoration: InputDecoration(labelText: 'Email'),
),
SizedBox(height: 16),
TextField(
controller: _passCtrl,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 24),
_loading
? CircularProgressIndicator()
: ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
if (_error != null) ...[
SizedBox(height: 16),
Text(_error!, style: TextStyle(color: Colors.red)),
],
],
),
),
);
}
@override
void dispose() {
_emailCtrl.dispose();
_passCtrl.dispose();
super.dispose();
}
}
```
Copy code di atas, adjust sesuai UI design Anda!
---
## 🎉 You're Ready!
**Sekarang Anda siap untuk:**
1. Update base URL ✓
2. Load token ✓
3. Test API ✓
4. Build screens with services ✓
---
## 📞 Need Help?
Dokumentasi tersedia:
- `README_API_INTEGRATION.md` - Overview
- `API_QUICKSTART.md` - Contoh kode
- `SCREEN_IMPLEMENTATION_CHECKLIST.md` - Detail per screen
- `API_INTEGRATION_GUIDE.md` - Referensi lengkap
---
**Happy Coding! 🚀**
*Last Updated: February 23, 2026*
*Status: Ready for Development*