Files
Verde-Web/routes/api.php
admin c8404564fe feat(backend): complete Modules 2 + 3 (geo + user management)
Module 2 — Geographic Data: PSGC tables (regions/provinces/cities/
barangays) with native geometry(polygon|point, 4326) columns; cascading
dropdown endpoints; ST_Contains-based GPS resolution; service-area CRUD
with barangay attach/detach; SamplePsgcSeeder + psgc:import command.

Module 3 — User Management: 5 role-specific profile tables (driver/
helper/scanner/store_partner with verification_status + rejection
reason); profile auto-created on register; admin user CRUD with
filters/pagination, suspend/activate, profile approve/reject;
self-service /me + /me/profile with role-aware validation that blocks
self-approval and resets rejected profiles to pending on resubmit.

69 feature tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:59:56 +08:00

94 lines
5.1 KiB
PHP

<?php
use App\Http\Controllers\Api\V1\Admin\AdminUserController;
use App\Http\Controllers\Api\V1\Auth\ForgotPasswordController;
use App\Http\Controllers\Api\V1\Auth\LoginController;
use App\Http\Controllers\Api\V1\Auth\LogoutController;
use App\Http\Controllers\Api\V1\Auth\MeController;
use App\Http\Controllers\Api\V1\Auth\RefreshTokenController;
use App\Http\Controllers\Api\V1\Auth\RegisterController;
use App\Http\Controllers\Api\V1\Auth\ResendOtpController;
use App\Http\Controllers\Api\V1\Auth\ResetPasswordController;
use App\Http\Controllers\Api\V1\Auth\SelfProfileController;
use App\Http\Controllers\Api\V1\Auth\UpdateSelfController;
use App\Http\Controllers\Api\V1\Auth\VerifyOtpController;
use App\Http\Controllers\Api\V1\Geo\BarangayController;
use App\Http\Controllers\Api\V1\Geo\CityMunicipalityController;
use App\Http\Controllers\Api\V1\Geo\ProvinceController;
use App\Http\Controllers\Api\V1\Geo\RegionController;
use App\Http\Controllers\Api\V1\Geo\ResolveLocationController;
use App\Http\Controllers\Api\V1\Geo\ServiceAreaController;
use App\Http\Controllers\Api\V1\HealthController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes (v1)
|--------------------------------------------------------------------------
| All routes here are prefixed with /api/v1 (configured in bootstrap/app.php).
*/
Route::get('/health', HealthController::class)->name('api.v1.health');
Route::prefix('auth')->name('api.v1.auth.')->group(function () {
Route::middleware('throttle:10,1')->group(function () {
Route::post('/register', RegisterController::class)->name('register');
Route::post('/login', LoginController::class)->name('login');
Route::post('/forgot-password', ForgotPasswordController::class)->name('forgot-password');
Route::post('/reset-password', ResetPasswordController::class)->name('reset-password');
Route::post('/otp/verify', VerifyOtpController::class)->name('otp.verify');
Route::post('/otp/resend', ResendOtpController::class)->name('otp.resend');
});
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', LogoutController::class)->name('logout');
Route::post('/refresh', RefreshTokenController::class)->name('refresh');
Route::get('/me', MeController::class)->name('me');
});
});
Route::middleware('auth:sanctum')->prefix('me')->name('api.v1.me.')->group(function () {
Route::patch('/', UpdateSelfController::class)->name('update');
Route::get('/profile', [SelfProfileController::class, 'show'])->name('profile.show');
Route::patch('/profile', [SelfProfileController::class, 'update'])->name('profile.update');
});
Route::prefix('admin/users')
->name('api.v1.admin.users.')
->middleware(['auth:sanctum', 'role:admin'])
->group(function () {
Route::get('/', [AdminUserController::class, 'index'])->name('index');
Route::get('/{user:uuid}', [AdminUserController::class, 'show'])->name('show');
Route::patch('/{user:uuid}', [AdminUserController::class, 'update'])->name('update');
Route::delete('/{user:uuid}', [AdminUserController::class, 'destroy'])->name('destroy');
Route::post('/{user:uuid}/suspend', [AdminUserController::class, 'suspend'])->name('suspend');
Route::post('/{user:uuid}/activate', [AdminUserController::class, 'activate'])->name('activate');
Route::post('/{user:uuid}/approve-profile', [AdminUserController::class, 'approveProfile'])->name('approve-profile');
Route::post('/{user:uuid}/reject-profile', [AdminUserController::class, 'rejectProfile'])->name('reject-profile');
});
Route::middleware('auth:sanctum')->group(function () {
Route::get('/me', MeController::class)->name('api.v1.me');
});
Route::prefix('geo')->name('api.v1.geo.')->group(function () {
Route::get('/regions', RegionController::class)->name('regions.index');
Route::get('/provinces', ProvinceController::class)->name('provinces.index');
Route::get('/cities', CityMunicipalityController::class)->name('cities.index');
Route::get('/barangays', BarangayController::class)->name('barangays.index');
Route::post('/resolve', ResolveLocationController::class)->name('resolve');
});
Route::prefix('service-areas')
->name('api.v1.service-areas.')
->middleware(['auth:sanctum', 'role:admin'])
->group(function () {
Route::get('/', [ServiceAreaController::class, 'index'])->name('index');
Route::post('/', [ServiceAreaController::class, 'store'])->name('store');
Route::get('/{service_area}', [ServiceAreaController::class, 'show'])->name('show');
Route::patch('/{service_area}', [ServiceAreaController::class, 'update'])->name('update');
Route::delete('/{service_area}', [ServiceAreaController::class, 'destroy'])->name('destroy');
Route::post('/{service_area}/barangays', [ServiceAreaController::class, 'attachBarangays'])->name('barangays.attach');
Route::delete('/{service_area}/barangays/{barangay}', [ServiceAreaController::class, 'detachBarangay'])->name('barangays.detach');
});