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
This commit is contained in:
@@ -1,196 +1,104 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { usePageTitle } from '../composables/Core/usePageTitle';
|
||||
import { useAuth } from '../composables/Core/useAuth.js';
|
||||
import { useUIStore } from '../stores/ui';
|
||||
import { useUserStore } from '../stores/user.js';
|
||||
import HomeUltimate from './Fragments/Home/HomeUltimate.vue';
|
||||
import HomePublic from './Fragments/Home/HomePublic.vue';
|
||||
import HomeSuperOperator from './Fragments/Home/HomeSuperOperator.vue';
|
||||
import HomeOperator from './Fragments/Home/HomeOperator.vue';
|
||||
import HomeStoreOwner from './Fragments/Home/HomeStoreOwner.vue';
|
||||
import HomeStoreManager from './Fragments/Home/HomeStoreManager.vue';
|
||||
import HomeShared from './Fragments/Home/HomeShared.vue';
|
||||
import HomeCooperative from './Fragments/Home/HomeCooperative.vue';
|
||||
import HomeCoopOfficer from './Fragments/Home/HomeCoopOfficer.vue';
|
||||
import HomeCoopMember from './Fragments/Home/HomeCoopMember.vue';
|
||||
import { executeRequest } from '../utils/executeRequest.js';
|
||||
import { navigate } from '../utils/navigate.js';
|
||||
|
||||
const uiStore = useUIStore();
|
||||
const userStore = useUserStore();
|
||||
usePageTitle(uiStore.appName);
|
||||
usePageTitle(uiStore.appName ?? 'Barangay System');
|
||||
|
||||
const {
|
||||
isUltimate, isPublic, isSuperOperator, isOperator,
|
||||
isCoordinator, isStoreOwner, isStoreManager,
|
||||
isSupplier, isSupplierOverseer, isRider,
|
||||
isUser, isPOSTerminal, role, user,
|
||||
isCoopOfficer, isCoopMember
|
||||
} = useAuth();
|
||||
const { isSuperAdmin, isPunongBarangay, isAdmin, isBarangayStaff, isResident, role } = useAuth();
|
||||
|
||||
const stats = ref({});
|
||||
const loading = ref(false);
|
||||
|
||||
const loadStats = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await executeRequest('/home-data');
|
||||
if (res?.props?.stats) stats.value = res.props.stats;
|
||||
} catch (e) { /* silent */ }
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const adminCards = [
|
||||
{ label: 'Residents', icon: '👥', route: '/Barangay/ManageResidents', color: 'bg-blue-500' },
|
||||
{ label: 'Households', icon: '🏠', route: '/Barangay/ManageHouseholds', color: 'bg-green-500' },
|
||||
{ label: 'Blotters', icon: '⚖️', route: '/Barangay/ManageBlotters', color: 'bg-orange-500' },
|
||||
{ label: 'Documents', icon: '📋', route: '/Barangay/ManageDocumentRequests', color: 'bg-purple-500' },
|
||||
{ label: 'Projects', icon: '🏗️', route: '/Barangay/ManageProjects', color: 'bg-indigo-500' },
|
||||
{ label: 'Budget', icon: '💰', route: '/Barangay/BudgetLedger', color: 'bg-emerald-500' },
|
||||
{ label: 'Announcements', icon: '📢', route: '/ManageAnnouncements', color: 'bg-yellow-500' },
|
||||
{ label: 'Settings', icon: '⚙️', route: '/SystemSettings', color: 'bg-gray-500' },
|
||||
];
|
||||
|
||||
const serviceCards = [
|
||||
{ label: 'Request Document', icon: '📄', route: '/Barangay/RequestDocument', color: 'bg-blue-500' },
|
||||
{ label: 'View Announcements', icon: '📢', route: '/ManageAnnouncements', color: 'bg-yellow-500' },
|
||||
];
|
||||
|
||||
onMounted(loadStats);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-page">
|
||||
<div
|
||||
class="home-bg-logo"
|
||||
:style="uiStore.appLogo ? { backgroundImage: `url('${uiStore.appLogo}')` } : null"
|
||||
aria-hidden="true"
|
||||
></div>
|
||||
|
||||
<div class="home-page-content">
|
||||
<div v-if="!isPublic" class="tf-container mt-3 mb-3">
|
||||
<h2 class="fw_6 text-center">{{ uiStore.appName }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Bible Verse of the Day -->
|
||||
<div v-if="!isPublic && uiStore.bibleVerseText" class="tf-container mt-2 mb-1">
|
||||
<div class="bible-verse-card px-4 py-3 rounded-4 text-center">
|
||||
<i class="fas fa-bible text-primary opacity-50 mb-2 d-block"></i>
|
||||
<p class="fst-italic mb-1 bible-verse-text">"{{ uiStore.bibleVerseText }}"</p>
|
||||
<small v-if="uiStore.bibleVerseReference" class="text-muted fw-semibold">— {{ uiStore.bibleVerseReference }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="userStore.loading" class="d-flex justify-content-center align-items-center py-5">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<!-- Case 1: Logged in as Ultimate -->
|
||||
<template v-if="isUltimate">
|
||||
<HomeUltimate />
|
||||
</template>
|
||||
|
||||
<!-- Case 2: Public / Guest User -->
|
||||
<template v-else-if="isPublic">
|
||||
<HomePublic />
|
||||
</template>
|
||||
|
||||
<!-- Case 3: Super Operator -->
|
||||
<template v-else-if="isSuperOperator">
|
||||
<HomeSuperOperator />
|
||||
</template>
|
||||
|
||||
<!-- Case 4: Operator -->
|
||||
<template v-else-if="isOperator">
|
||||
<HomeOperator />
|
||||
</template>
|
||||
|
||||
<!-- Case 5: Coordinator -->
|
||||
<template v-else-if="isCoordinator">
|
||||
<HomeCooperative />
|
||||
</template>
|
||||
|
||||
<!-- Case 6: Store Owner -->
|
||||
<template v-else-if="isStoreOwner">
|
||||
<HomeStoreOwner title="Store Owner" />
|
||||
</template>
|
||||
|
||||
<!-- Case 7: Store Manager -->
|
||||
<template v-else-if="isStoreManager">
|
||||
<HomeStoreManager />
|
||||
</template>
|
||||
|
||||
<!-- Case 8: Supplier -->
|
||||
<template v-else-if="isSupplier">
|
||||
<HomeShared title="Supplier" />
|
||||
</template>
|
||||
|
||||
<!-- Case 9: Supplier Overseer -->
|
||||
<template v-else-if="isSupplierOverseer">
|
||||
<HomeShared title="Supplier Overseer" />
|
||||
</template>
|
||||
|
||||
<!-- Case 10: Rider -->
|
||||
<template v-else-if="isRider">
|
||||
<HomeShared title="Rider" />
|
||||
</template>
|
||||
|
||||
<!-- Case 11: POS Terminal -->
|
||||
<template v-else-if="isPOSTerminal">
|
||||
<HomeShared title="POS Terminal" />
|
||||
</template>
|
||||
|
||||
<!-- Coop Officer -->
|
||||
<template v-else-if="isCoopOfficer">
|
||||
<HomeCoopOfficer />
|
||||
</template>
|
||||
|
||||
<!-- Coop Member -->
|
||||
<template v-else-if="isCoopMember">
|
||||
<HomeCoopMember />
|
||||
</template>
|
||||
|
||||
<!-- Case 11: Regular User -->
|
||||
<template v-else-if="isUser">
|
||||
<HomeShared title="User" />
|
||||
</template>
|
||||
|
||||
<!-- Fallback Dashboard -->
|
||||
<template v-else>
|
||||
<div class="tf-container mt-5 text-center">
|
||||
<h4>Welcome to {{ uiStore.appName }}</h4>
|
||||
<p>Your account type: <strong>{{ role }}</strong></p>
|
||||
<p>Please wait while we set up your personalized dashboard.</p>
|
||||
|
||||
<div class="mt-4">
|
||||
<img src="https://cdn.jsdelivr.net/gh/telemagnadon/obj-vault-3a@v2026.05.14-vendor-2/a/9908be28dd8a.bin" class="spinning" style="width: 50px;">
|
||||
<div class="p-4 max-w-5xl mx-auto">
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800">Barangay Management System</h1>
|
||||
<p class="text-gray-500 text-sm mt-1">Welcome. Here's today's overview.</p>
|
||||
</div>
|
||||
|
||||
<!-- Stats (admin/staff) -->
|
||||
<div v-if="isBarangayStaff" class="grid grid-cols-2 sm:grid-cols-4 gap-3 mb-5">
|
||||
<div class="bg-white rounded-xl shadow p-4 text-center">
|
||||
<div class="text-3xl font-bold text-blue-600">{{ stats.total_residents ?? 0 }}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">Residents</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow p-4 text-center">
|
||||
<div class="text-3xl font-bold text-green-600">{{ stats.total_households ?? 0 }}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">Households</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow p-4 text-center">
|
||||
<div class="text-3xl font-bold text-orange-600">{{ stats.open_blotters ?? 0 }}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">Open Blotters</div>
|
||||
</div>
|
||||
<div class="bg-white rounded-xl shadow p-4 text-center">
|
||||
<div class="text-3xl font-bold text-purple-600">{{ stats.pending_documents ?? 0 }}</div>
|
||||
<div class="text-xs text-gray-500 mt-1">Pending Docs</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Access (admin/staff) -->
|
||||
<div v-if="isBarangayStaff" class="mb-6">
|
||||
<h2 class="text-lg font-semibold text-gray-700 mb-3">Quick Access</h2>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
||||
<button
|
||||
v-for="card in adminCards"
|
||||
:key="card.label"
|
||||
@click="navigate(card.route)"
|
||||
:class="`${card.color} text-white rounded-xl p-4 flex flex-col items-center gap-2 hover:opacity-90 transition`"
|
||||
>
|
||||
<span class="text-3xl">{{ card.icon }}</span>
|
||||
<span class="text-sm font-medium">{{ card.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Services (resident) -->
|
||||
<div v-if="isResident" class="mb-6">
|
||||
<h2 class="text-lg font-semibold text-gray-700 mb-3">Services Available to You</h2>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
v-for="card in serviceCards"
|
||||
:key="card.label"
|
||||
@click="navigate(card.route)"
|
||||
:class="`${card.color} text-white rounded-xl p-5 flex flex-col items-center gap-2 hover:opacity-90 transition`"
|
||||
>
|
||||
<span class="text-4xl">{{ card.icon }}</span>
|
||||
<span class="text-sm font-medium">{{ card.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-page {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.home-bg-logo {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 35%;
|
||||
background-size: min(60vw, 520px) auto;
|
||||
opacity: 0.12;
|
||||
filter: saturate(0.9);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
:global(.dark-mode) .home-bg-logo {
|
||||
opacity: 0.15;
|
||||
filter: invert(1) saturate(0.8);
|
||||
}
|
||||
|
||||
.home-page-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.bible-verse-card {
|
||||
background: rgba(var(--bg-card-rgb, 255, 255, 255), 0.7);
|
||||
border: 1px solid rgba(var(--accent-color-rgb, 13, 110, 253), 0.15);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.bible-verse-text {
|
||||
color: var(--text-primary, #212529);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.spinning {
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user