Files
BarangaySystem/resources/js/Pages/Barangay/RequestDocument.vue
Jonathan Sykes fbb7e3ff37
Some checks failed
tests / PHP 8.2 (swoole-5.1.6) (push) Has been cancelled
tests / PHP 8.3 (swoole-5.1.6) (push) Has been cancelled
tests / PHP 8.4 (swoole-6.0) (push) Has been cancelled
feat: implement barangay system phases 2-14
Complete adaptation from BukidBountyApp to Philippine barangay governance:

- Barangay models: Resident, Household, HouseholdMember, Blotter, BlotterHearing,
  DocumentRequest, RequestPayment, RequestType, BarangayProject, BarangayBudget
- Controllers: ResidentController, HouseholdController, BlotterController,
  BlotterHearingController, DocumentRequestController, RequestTypeController,
  ProjectController, BudgetController, QRPHController, AdminConsoleController,
  UserController, FileController, ChapterController, LoginController
- Vue pages: Home, ManageResidents, ResidentProfile, ManageHouseholds, ManageBlotters,
  BlotterDetail, RequestDocument, ManageDocumentRequests, DocumentRequestDetail,
  ManageRequestTypes, ManageProjects, BudgetLedger, AdminConsole
- Barangay roles: PunongBarangay, Kagawad, Secretary, Treasurer, SK, Tanod, BHW, Staff, Resident
- UserPermissions matrix rewritten with barangay-specific permission mappings
- VueRouteMap replaced with barangay SPA routes
- UserActions enum references corrected across all controllers
- Removed all market/cooperative/POS/subscription code and models
2026-06-07 03:09:09 +08:00

138 lines
5.9 KiB
Vue

<script setup>
import { ref, onMounted } from 'vue';
import { usePageTitle } from '../../composables/Core/usePageTitle';
import { executeRequest } from '../../utils/executeRequest.js';
import { navigate } from '../../utils/navigate.js';
usePageTitle('Request a Document');
const requestTypes = ref([]);
const myRequests = ref([]);
const loading = ref(false);
const submitting = ref(false);
const form = ref({ request_type_id: '', purpose: '' });
const selectedType = ref(null);
const submitted = ref(false);
const submittedDoc = ref(null);
const statusLabels = {
DRAFT: 'Draft', PENDING_PAYMENT: 'Pending Payment', PAID: 'Paid',
PROCESSING: 'Processing', READY: 'Ready for Pickup', CLAIMED: 'Claimed', CANCELLED: 'Cancelled',
};
const loadData = async () => {
loading.value = true;
const [typesRes, myRes] = await Promise.all([
executeRequest('/request-types'),
executeRequest('/documents/my'),
]);
if (typesRes.success) requestTypes.value = typesRes.data;
if (myRes.success) myRequests.value = myRes.data;
loading.value = false;
};
const onTypeSelect = () => {
selectedType.value = requestTypes.value.find(t => t.id == form.value.request_type_id);
};
const submit = async () => {
submitting.value = true;
const res = await executeRequest('/documents/submit', 'POST', form.value);
if (res.success) {
submittedDoc.value = res.data;
submitted.value = true;
loadData();
}
submitting.value = false;
};
const resetForm = () => {
submitted.value = false;
submittedDoc.value = null;
form.value = { request_type_id: '', purpose: '' };
selectedType.value = null;
};
const getStatus = (r) => r.status?.value ?? r.status;
onMounted(loadData);
</script>
<template>
<div class="p-4 max-w-3xl mx-auto">
<div class="mb-6">
<h1 class="text-2xl font-bold">Request a Document</h1>
<p class="text-gray-500 text-sm">Submit a request for a barangay certificate or clearance.</p>
</div>
<div v-if="loading" class="text-center py-8 text-gray-400">Loading...</div>
<div v-else-if="!submitted">
<div class="bg-white rounded-xl shadow p-5 mb-6">
<h2 class="font-semibold text-gray-700 mb-3">Select Document Type</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-4">
<div
v-for="t in requestTypes"
:key="t.id"
@click="form.request_type_id = t.id; onTypeSelect()"
:class="`border rounded-lg p-3 cursor-pointer transition ${form.request_type_id == t.id ? 'border-blue-500 bg-blue-50' : 'border-gray-200 hover:border-gray-300'}`"
>
<div class="font-medium text-sm">{{ t.name }}</div>
<div class="text-xs text-gray-500 mt-1">{{ t.description }}</div>
<div class="mt-2 flex justify-between text-xs">
<span class="font-semibold text-green-600">{{ t.base_fee > 0 ? `${t.base_fee}` : 'Free' }}</span>
<span class="text-gray-400">{{ t.processing_days }} day(s)</span>
</div>
</div>
</div>
<div v-if="selectedType" class="mt-2">
<label class="label">Purpose / Reason *</label>
<textarea v-model="form.purpose" class="input h-20" :placeholder="`State your purpose for requesting ${selectedType.name}...`"></textarea>
</div>
<div class="flex justify-end mt-4">
<button
@click="submit"
:disabled="!form.request_type_id || !form.purpose || submitting"
class="btn-primary disabled:opacity-50 disabled:cursor-not-allowed"
>
{{ submitting ? 'Submitting...' : 'Submit Request' }}
</button>
</div>
</div>
</div>
<div v-else class="bg-white rounded-xl shadow p-5 mb-6">
<div class="text-center">
<div class="text-4xl mb-2"></div>
<h2 class="text-xl font-bold text-green-600">Request Submitted!</h2>
<p class="text-gray-600 mt-1">Request No: <span class="font-mono font-bold">{{ submittedDoc?.request_no }}</span></p>
<p class="text-gray-500 text-sm mt-2">
{{ submittedDoc?.fee_amount > 0 ? `Please proceed to the barangay hall to pay ₱${submittedDoc.fee_amount}.` : 'Your request is free and will be processed shortly.' }}
</p>
<button @click="resetForm" class="btn-primary mt-4">Request Another</button>
</div>
</div>
<!-- My Requests -->
<div class="bg-white rounded-xl shadow p-5">
<h2 class="font-semibold text-gray-700 mb-3">My Requests</h2>
<div v-if="myRequests.length">
<div v-for="r in myRequests" :key="r.id" class="border-b py-3 flex justify-between items-center">
<div>
<div class="font-medium text-sm">{{ r.request_type?.name }}</div>
<div class="text-xs text-gray-400 font-mono">{{ r.request_no }}</div>
<div class="text-xs text-gray-500 mt-0.5">{{ r.created_at?.slice(0, 10) }}</div>
</div>
<span :class="`px-2 py-1 rounded-full text-xs font-medium ${getStatus(r) === 'CLAIMED' ? 'bg-green-100 text-green-700' : getStatus(r) === 'READY' ? 'bg-teal-100 text-teal-700' : 'bg-gray-100 text-gray-700'}`">
{{ statusLabels[getStatus(r)] ?? getStatus(r) }}
</span>
</div>
</div>
<p v-else class="text-gray-400 text-sm">No previous requests.</p>
</div>
</div>
</template>