196 lines
4.1 KiB
Markdown
196 lines
4.1 KiB
Markdown
# Explore Lumajang Admin Panel
|
|
|
|
## Struktur Utama
|
|
|
|
- `app/Models/Kategori.php` dan `app/Models/Wisata.php`: model relasi kategori dan destinasi.
|
|
- `app/Http/Controllers/Admin`: controller dashboard, login, CRUD wisata, CRUD kategori, dan user aplikasi.
|
|
- `app/Http/Controllers/API`: API auth, destinations, dan kategori untuk Flutter.
|
|
- `app/Http/Resources`: format JSON `success`, `message`, dan `data`.
|
|
- `resources/views/admin`: Blade admin panel Bootstrap 5.
|
|
- `storage/app/public/images`: penyimpanan gambar wisata.
|
|
- `storage/app/public/videos`: penyimpanan video wisata.
|
|
- `storage/app/public/models`: penyimpanan model GLB/GLTF wisata AR.
|
|
- `routes/web.php`: route admin berbasis session dan middleware `auth` + `admin`.
|
|
- `routes/api.php`: endpoint JSON untuk aplikasi Flutter.
|
|
|
|
## Instalasi
|
|
|
|
```bash
|
|
cd website/wisata_web
|
|
composer install
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
```
|
|
|
|
Atur database MySQL di `.env`:
|
|
|
|
```env
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=3306
|
|
DB_DATABASE=explore_lumajang_ar
|
|
DB_USERNAME=root
|
|
DB_PASSWORD=
|
|
```
|
|
|
|
Jalankan migrasi, seeder admin awal, dan storage link:
|
|
|
|
```bash
|
|
php artisan migrate --seed
|
|
php artisan storage:link
|
|
php artisan serve
|
|
```
|
|
|
|
Admin panel tersedia di:
|
|
|
|
```text
|
|
http://127.0.0.1:8000/admin/login
|
|
```
|
|
|
|
Akun admin awal:
|
|
|
|
```text
|
|
Email: admin@explorelumajang.test
|
|
Password: password
|
|
```
|
|
|
|
Ganti password ini sebelum digunakan untuk produksi.
|
|
|
|
Seeder juga membuat contoh data demo:
|
|
|
|
- `Ranu Pani`: wisata normal.
|
|
- `Puncak B29`: wisata AR, tombol AR aktif jika `model_path` tersedia.
|
|
- `Air Terjun Tumpak Sewu`: wisata video, video player aktif jika `is_video = true`.
|
|
|
|
## Endpoint API Flutter
|
|
|
|
Base URL lokal Android emulator:
|
|
|
|
```text
|
|
http://10.0.2.2:8000/api
|
|
```
|
|
|
|
Base URL perangkat fisik:
|
|
|
|
```text
|
|
http://IP_LAPTOP_KAMU:8000/api
|
|
```
|
|
|
|
Endpoint publik:
|
|
|
|
```text
|
|
GET /health
|
|
POST /register
|
|
POST /login
|
|
POST /forgot-password
|
|
GET /kategori
|
|
GET /destinations
|
|
GET /destinations/{id}
|
|
```
|
|
|
|
Endpoint dengan token Bearer:
|
|
|
|
```text
|
|
GET /profile
|
|
POST /logout
|
|
POST /wisata/{id}/gambar
|
|
```
|
|
|
|
Contoh response login:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Success",
|
|
"data": {
|
|
"token_type": "Bearer",
|
|
"token": "plain-token",
|
|
"user": {
|
|
"id": 1,
|
|
"name": "User",
|
|
"email": "user@example.com",
|
|
"role": "user",
|
|
"created_at": "2026-05-20T10:00:00.000000Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Contoh response wisata:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Success",
|
|
"data": {
|
|
"id": 1,
|
|
"title": "Ranu Pani",
|
|
"category": {
|
|
"id": 1,
|
|
"name": "Wisata Alam",
|
|
"slug": "wisata-alam"
|
|
},
|
|
"location": "Senduro, Lumajang",
|
|
"image": "http://IP_LAPTOP:8000/storage/images/file.jpg",
|
|
"rating": 4.8,
|
|
"distance": "48 km dari pusat kota",
|
|
"elevation": "2.100 mdpl",
|
|
"model_path": "http://IP_LAPTOP:8000/storage/models/file.glb",
|
|
"video_path": "http://IP_LAPTOP:8000/storage/videos/file.mp4",
|
|
"is_video": false,
|
|
"type": "normal",
|
|
"show_ar_button": false,
|
|
"show_video_player": false,
|
|
"latitude": -8.0092,
|
|
"longitude": 112.9446,
|
|
"google_maps_url": "https://www.google.com/maps?q=-8.0092000,112.9446000"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Integrasi Flutter
|
|
|
|
Simpan base URL di `auth_service.dart` atau konfigurasi environment Flutter. Untuk perangkat fisik gunakan IP laptop, bukan localhost:
|
|
|
|
```dart
|
|
const String baseUrl = 'http://IP_LAPTOP:8000/api';
|
|
```
|
|
|
|
Untuk Android emulator boleh memakai:
|
|
|
|
```dart
|
|
const String baseUrl = 'http://10.0.2.2:8000/api';
|
|
```
|
|
|
|
Untuk request login/register gunakan `POST`. Setelah login, simpan token dari `data.token`, lalu kirim pada endpoint protected:
|
|
|
|
```dart
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Bearer $token',
|
|
}
|
|
```
|
|
|
|
Untuk memuat destinasi:
|
|
|
|
```text
|
|
GET $baseUrl/wisata
|
|
GET $baseUrl/destinations
|
|
GET $baseUrl/destinations/{id}
|
|
GET $baseUrl/kategori
|
|
```
|
|
|
|
Field URL `image`, `model_path`, dan `video_path` sudah dikirim sebagai URL publik dari Laravel storage sehingga bisa langsung digunakan di Flutter.
|
|
|
|
Logic Flutter:
|
|
|
|
```dart
|
|
if (destination['show_ar_button'] == true) {
|
|
// tampilkan tombol AR dan buka model_path
|
|
}
|
|
|
|
if (destination['show_video_player'] == true) {
|
|
// tampilkan video player dari video_path
|
|
}
|
|
```
|