Remove unused Asnaf detail and list pages to streamline the application structure and improve maintainability.
This commit is contained in:
parent
53aa85985f
commit
46737de097
@ -1,674 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ref, computed, onMounted } from 'vue';
|
|
||||||
import { useAsnafMockData } from '~/composables/useAsnafMockData';
|
|
||||||
import { useToast } from 'vue-toastification';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const toast = useToast();
|
|
||||||
|
|
||||||
const { getProfileById } = useAsnafMockData();
|
|
||||||
const profile = ref(null);
|
|
||||||
const loading = ref(true);
|
|
||||||
const isLoadingAnalysis = ref(false);
|
|
||||||
const confirmDelete = ref(false);
|
|
||||||
const activeTab = ref('personal');
|
|
||||||
|
|
||||||
// Load profile data
|
|
||||||
onMounted(async () => {
|
|
||||||
const id = route.params.id;
|
|
||||||
loading.value = true;
|
|
||||||
const fetchedProfile = getProfileById(id);
|
|
||||||
|
|
||||||
if (fetchedProfile) {
|
|
||||||
profile.value = { ...fetchedProfile, analysis: null };
|
|
||||||
loading.value = false;
|
|
||||||
} else {
|
|
||||||
toast.error('Profil tidak dijumpai');
|
|
||||||
navigateTo('/BF-PRF/AS/LIST');
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// New function to be called by a button
|
|
||||||
async function fetchAIAnalysis() {
|
|
||||||
if (!profile.value) {
|
|
||||||
toast.error('Profil data tidak tersedia untuk analisis.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isLoadingAnalysis.value = true;
|
|
||||||
try {
|
|
||||||
const requestBody = {
|
|
||||||
monthlyIncome: profile.value.monthlyIncome,
|
|
||||||
otherIncome: profile.value.otherIncome,
|
|
||||||
totalIncome: profile.value.totalIncome,
|
|
||||||
occupation: profile.value.occupation,
|
|
||||||
maritalStatus: profile.value.maritalStatus,
|
|
||||||
dependents: profile.value.dependents,
|
|
||||||
// Add other fields you want to send for analysis here
|
|
||||||
};
|
|
||||||
|
|
||||||
const analysisResponse = await $fetch('/api/analyze-asnaf', {
|
|
||||||
method: 'POST',
|
|
||||||
body: requestBody,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (profile.value) {
|
|
||||||
profile.value.analysis = analysisResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching AI Analysis from /api/analyze-asnaf:", error);
|
|
||||||
toast.error('Gagal memuat analisis AI dari server.');
|
|
||||||
if (profile.value) {
|
|
||||||
profile.value.analysis = {
|
|
||||||
hadKifayahPercentage: 'Ralat',
|
|
||||||
kategoriAsnaf: 'Ralat Server',
|
|
||||||
kategoriKeluarga: 'Ralat Server',
|
|
||||||
cadanganKategori: 'Ralat Server',
|
|
||||||
statusKelayakan: 'Ralat Server',
|
|
||||||
cadanganBantuan: [{ nama: 'Tidak dapat memuat cadangan bantuan', peratusan: 'Ralat' }],
|
|
||||||
ramalanJangkaMasaPulih: 'Ralat Server',
|
|
||||||
rumusan: 'Ralat Server'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
isLoadingAnalysis.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Computed status color
|
|
||||||
const statusColor = computed(() => {
|
|
||||||
if (!profile.value) return '';
|
|
||||||
|
|
||||||
switch (profile.value.status) {
|
|
||||||
case 'Aktif': return 'success';
|
|
||||||
case 'Tidak Aktif': return 'danger';
|
|
||||||
case 'Dalam Semakan': return 'warning';
|
|
||||||
default: return 'secondary';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Computed category color
|
|
||||||
const categoryColor = computed(() => {
|
|
||||||
if (!profile.value) return '';
|
|
||||||
|
|
||||||
switch (profile.value.kategori) {
|
|
||||||
case 'Fakir': return 'danger';
|
|
||||||
case 'Miskin': return 'warning';
|
|
||||||
case 'Mualaf': return 'info';
|
|
||||||
case 'Fi-sabilillah': return 'primary';
|
|
||||||
case 'Gharimin': return 'secondary';
|
|
||||||
case 'Ibnu Sabil': return 'success';
|
|
||||||
default: return 'primary';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Page metadata
|
|
||||||
definePageMeta({
|
|
||||||
title: "Maklumat Asnaf",
|
|
||||||
middleware: ["auth"],
|
|
||||||
requiresAuth: true,
|
|
||||||
breadcrumb: [
|
|
||||||
{
|
|
||||||
name: "Dashboard",
|
|
||||||
path: "/",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "BF-PRF",
|
|
||||||
path: "/BF-PRF",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Asnaf",
|
|
||||||
path: "/BF-PRF/AS",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Senarai",
|
|
||||||
path: "/BF-PRF/AS/LIST",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Maklumat",
|
|
||||||
path: "/BF-PRF/AS/DETAIL",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Navigation functions
|
|
||||||
function navigateToList() {
|
|
||||||
navigateTo('/BF-PRF/AS/LIST');
|
|
||||||
}
|
|
||||||
|
|
||||||
function navigateToEdit() {
|
|
||||||
navigateTo(`/BF-PRF/AS/UP/01?id=${profile.value.id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDelete() {
|
|
||||||
confirmDelete.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function confirmDeleteProfile() {
|
|
||||||
toast.success('Profil telah dipadamkan');
|
|
||||||
navigateTo('/BF-PRF/AS/LIST');
|
|
||||||
confirmDelete.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelDelete() {
|
|
||||||
confirmDelete.value = false;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="space-y-6">
|
|
||||||
<LayoutsBreadcrumb />
|
|
||||||
|
|
||||||
<!-- Loading state -->
|
|
||||||
<div v-if="loading" class="flex justify-center items-center py-20">
|
|
||||||
<div class="text-center">
|
|
||||||
<Loading />
|
|
||||||
<p class="mt-4 text-gray-600">Memuat maklumat asnaf...</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<!-- Header with actions -->
|
|
||||||
<div class="flex flex-col md:flex-row md:justify-between md:items-center gap-4 mb-6">
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<h1 class="text-2xl font-bold text-primary">{{ profile.nama }}</h1>
|
|
||||||
<rs-badge :variant="statusColor">{{ profile.status }}</rs-badge>
|
|
||||||
<rs-badge :variant="categoryColor">{{ profile.kategori }}</rs-badge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<rs-button variant="secondary-outline" @click="navigateToList">
|
|
||||||
<Icon name="mdi:arrow-left" size="18" class="mr-1" />
|
|
||||||
Kembali
|
|
||||||
</rs-button>
|
|
||||||
|
|
||||||
<rs-button variant="primary" @click="navigateToEdit">
|
|
||||||
<Icon name="mdi:pencil" size="18" class="mr-1" />
|
|
||||||
Kemaskini
|
|
||||||
</rs-button>
|
|
||||||
|
|
||||||
<rs-button variant="danger" @click="handleDelete">
|
|
||||||
<Icon name="mdi:delete" size="18" class="mr-1" />
|
|
||||||
Padam
|
|
||||||
</rs-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Profile Overview -->
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
|
|
||||||
<!-- Profile Photo and Basic Info -->
|
|
||||||
<rs-card class="lg:col-span-1">
|
|
||||||
<div class="p-6 flex flex-col items-center">
|
|
||||||
<div class="w-32 h-32 rounded-full bg-gray-200 flex items-center justify-center mb-4 overflow-hidden">
|
|
||||||
<Icon name="mdi:account" size="64" class="text-gray-400" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="text-xl font-semibold text-center">{{ profile.nama }}</h2>
|
|
||||||
<p class="text-gray-500 text-center mb-4">{{ profile.id }}</p>
|
|
||||||
|
|
||||||
<div class="w-full text-center">
|
|
||||||
<rs-badge :variant="categoryColor" class="mb-2">{{ profile.kategori }}</rs-badge>
|
|
||||||
<p class="text-sm text-gray-600">Didaftarkan pada {{ new Date(profile.tarikhDaftar).toLocaleDateString('ms-MY') }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<!-- Personal Information -->
|
|
||||||
<rs-card class="lg:col-span-2">
|
|
||||||
<template #header>
|
|
||||||
<div class="px-4 py-3">
|
|
||||||
<h3 class="text-lg font-semibold text-primary flex items-center">
|
|
||||||
<Icon name="mdi:account-details" size="20" class="mr-2" />
|
|
||||||
Maklumat Peribadi
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #body>
|
|
||||||
<div class="p-4">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">No. Kad Pengenalan</h4>
|
|
||||||
<p>{{ profile.idNumber }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Jantina</h4>
|
|
||||||
<p>{{ profile.gender }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Tarikh Lahir</h4>
|
|
||||||
<p>{{ new Date(profile.birthDate).toLocaleDateString('ms-MY') }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Status Perkahwinan</h4>
|
|
||||||
<p>{{ profile.maritalStatus }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Pekerjaan</h4>
|
|
||||||
<p>{{ profile.occupation }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Pendapatan Bulanan</h4>
|
|
||||||
<p>RM {{ profile.monthlyIncome }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<!-- Contact Information -->
|
|
||||||
<rs-card class="lg:col-span-3">
|
|
||||||
<template #header>
|
|
||||||
<div class="px-4 py-3">
|
|
||||||
<h3 class="text-lg font-semibold text-primary flex items-center">
|
|
||||||
<Icon name="mdi:contacts" size="20" class="mr-2" />
|
|
||||||
Maklumat Perhubungan
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #body>
|
|
||||||
<div class="p-4">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-x-6 gap-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Alamat</h4>
|
|
||||||
<p>{{ profile.alamat || 'Tiada' }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">No. Telefon</h4>
|
|
||||||
<p>{{ profile.telefon }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Emel</h4>
|
|
||||||
<p>{{ profile.email }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tabbed Details -->
|
|
||||||
<rs-card>
|
|
||||||
<template #header>
|
|
||||||
<div class="px-4 py-3 border-b">
|
|
||||||
<div class="flex overflow-x-auto space-x-4">
|
|
||||||
<button
|
|
||||||
@click="activeTab = 'personal'"
|
|
||||||
class="py-2 px-1 border-b-2 font-medium text-sm whitespace-nowrap transition-colors"
|
|
||||||
:class="activeTab === 'personal' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:account-group" size="18" class="mr-1" />
|
|
||||||
Maklumat Keluarga
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="activeTab = 'income'"
|
|
||||||
class="py-2 px-1 border-b-2 font-medium text-sm whitespace-nowrap transition-colors"
|
|
||||||
:class="activeTab === 'income' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:cash" size="18" class="mr-1" />
|
|
||||||
Maklumat Pendapatan
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="activeTab = 'aid'"
|
|
||||||
class="py-2 px-1 border-b-2 font-medium text-sm whitespace-nowrap transition-colors"
|
|
||||||
:class="activeTab === 'aid' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:gift" size="18" class="mr-1" />
|
|
||||||
Maklumat Bantuan
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="activeTab = 'documents'"
|
|
||||||
class="py-2 px-1 border-b-2 font-medium text-sm whitespace-nowrap transition-colors"
|
|
||||||
:class="activeTab === 'documents' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:file-document" size="18" class="mr-1" />
|
|
||||||
Dokumen
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="activeTab = 'analysis'"
|
|
||||||
class="py-2 px-1 border-b-2 font-medium text-sm whitespace-nowrap transition-colors"
|
|
||||||
:class="activeTab === 'analysis' ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:chart-bar" size="18" class="mr-1" />
|
|
||||||
Analisis Data
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #body>
|
|
||||||
<!-- Family Information Tab -->
|
|
||||||
<div v-if="activeTab === 'personal'" class="p-6">
|
|
||||||
<div v-if="profile.spouse" class="mb-8">
|
|
||||||
<h3 class="text-lg font-semibold text-primary mb-4">Maklumat Pasangan</h3>
|
|
||||||
<div class="bg-gray-50 p-4 rounded-lg">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Nama</h4>
|
|
||||||
<p>{{ profile.spouse.name }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">No. Kad Pengenalan</h4>
|
|
||||||
<p>{{ profile.spouse.idNumber }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 class="text-lg font-semibold text-primary mb-4">Tanggungan</h3>
|
|
||||||
|
|
||||||
<div v-if="profile.dependents && profile.dependents.length > 0">
|
|
||||||
<div class="overflow-x-auto">
|
|
||||||
<table class="min-w-full divide-y divide-gray-200">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Bil.</th>
|
|
||||||
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nama</th>
|
|
||||||
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Umur</th>
|
|
||||||
<th class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Hubungan</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="bg-white divide-y divide-gray-200">
|
|
||||||
<tr v-for="(dependent, index) in profile.dependents" :key="index" class="hover:bg-gray-50">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">{{ index + 1 }}</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">{{ dependent.name }}</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">{{ dependent.age }}</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">{{ dependent.relationship }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="bg-gray-50 p-6 rounded-lg text-center">
|
|
||||||
<Icon name="mdi:account-off" size="48" class="text-gray-400 mb-2" />
|
|
||||||
<p class="text-gray-500">Tiada tanggungan</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Income Information Tab -->
|
|
||||||
<div v-if="activeTab === 'income'" class="p-6">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
||||||
<rs-card>
|
|
||||||
<div class="p-4 text-center">
|
|
||||||
<div class="mb-2">
|
|
||||||
<Icon name="mdi:cash-multiple" size="36" class="text-primary" />
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-gray-500">Pendapatan Bulanan</p>
|
|
||||||
<p class="text-xl font-bold text-primary">RM {{ profile.monthlyIncome }}</p>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<rs-card>
|
|
||||||
<div class="p-4 text-center">
|
|
||||||
<div class="mb-2">
|
|
||||||
<Icon name="mdi:cash-plus" size="36" class="text-primary" />
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-gray-500">Pendapatan Lain</p>
|
|
||||||
<p class="text-xl font-bold text-primary">RM {{ profile.otherIncome }}</p>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<rs-card>
|
|
||||||
<div class="p-4 text-center">
|
|
||||||
<div class="mb-2">
|
|
||||||
<Icon name="mdi:cash-register" size="36" class="text-primary" />
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-gray-500">Jumlah Pendapatan</p>
|
|
||||||
<p class="text-xl font-bold text-primary">RM {{ profile.totalIncome }}</p>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<h3 class="text-lg font-semibold text-primary mb-4">Butiran Pendapatan</h3>
|
|
||||||
<div class="bg-gray-50 p-4 rounded-lg">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Pekerjaan</h4>
|
|
||||||
<p>{{ profile.occupation }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Pendapatan Bulanan</h4>
|
|
||||||
<p>RM {{ profile.monthlyIncome }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Pendapatan Lain</h4>
|
|
||||||
<p>RM {{ profile.otherIncome }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Jumlah Pendapatan</h4>
|
|
||||||
<p>RM {{ profile.totalIncome }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Aid Information Tab -->
|
|
||||||
<div v-if="activeTab === 'aid'" class="p-6">
|
|
||||||
<div class="bg-gray-50 p-6 rounded-lg text-center">
|
|
||||||
<Icon name="mdi:gift-off" size="48" class="text-gray-400 mb-2" />
|
|
||||||
<p class="text-gray-500">Tiada maklumat bantuan</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Documents Tab -->
|
|
||||||
<div v-if="activeTab === 'documents'" class="p-6">
|
|
||||||
<h3 class="text-lg font-semibold text-primary mb-4">Dokumen Sokongan</h3>
|
|
||||||
|
|
||||||
<div v-if="profile.documents && profile.documents.length > 0">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
||||||
<div v-for="(doc, index) in profile.documents" :key="index" class="border rounded-lg overflow-hidden">
|
|
||||||
<div class="bg-gray-50 p-4 flex items-center">
|
|
||||||
<Icon name="mdi:file-document" size="24" class="text-primary mr-3" />
|
|
||||||
<div>
|
|
||||||
<h4 class="font-medium">{{ doc.name }}</h4>
|
|
||||||
<p class="text-sm text-gray-500">{{ doc.size }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="p-3 flex justify-end">
|
|
||||||
<rs-button variant="primary-text" size="sm">
|
|
||||||
<Icon name="mdi:download" size="16" class="mr-1" />
|
|
||||||
Muat Turun
|
|
||||||
</rs-button>
|
|
||||||
<rs-button variant="secondary-text" size="sm">
|
|
||||||
<Icon name="mdi:eye" size="16" class="mr-1" />
|
|
||||||
Papar
|
|
||||||
</rs-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="bg-gray-50 p-6 rounded-lg text-center">
|
|
||||||
<Icon name="mdi:file-document-off" size="48" class="text-gray-400 mb-2" />
|
|
||||||
<p class="text-gray-500">Tiada dokumen</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Analysis Tab -->
|
|
||||||
<div v-if="activeTab === 'analysis'" class="p-6">
|
|
||||||
<!-- Button to trigger AI Analysis -->
|
|
||||||
<div v-if="!profile.analysis && !isLoadingAnalysis" class="text-center mb-6">
|
|
||||||
<rs-button variant="primary" @click="fetchAIAnalysis" size="lg">
|
|
||||||
<Icon name="mdi:brain" size="20" class="mr-2" />
|
|
||||||
Jalankan Analisis AI
|
|
||||||
</rs-button>
|
|
||||||
<p class="text-sm text-gray-500 mt-2">Klik untuk mendapatkan penilaian berdasarkan data profil.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Loading State for AI Analysis -->
|
|
||||||
<div v-if="isLoadingAnalysis" class="text-center py-10">
|
|
||||||
<Loading />
|
|
||||||
<p class="mt-4 text-gray-600">Analisis AI sedang dijalankan...</p>
|
|
||||||
<p class="text-sm text-gray-500">Sila tunggu sebentar.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Display Analysis Results -->
|
|
||||||
<div v-if="profile.analysis && !isLoadingAnalysis" class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
||||||
|
|
||||||
<!-- AI Analysis Main Column (takes 2/3 on lg screens) -->
|
|
||||||
<div class="lg:col-span-2 space-y-6">
|
|
||||||
<!-- Card 1: Analisis Had Kifayah & Kelayakan -->
|
|
||||||
<rs-card>
|
|
||||||
<template #header>
|
|
||||||
<h3 class="text-lg font-semibold text-primary p-4 border-b">Analisis Had Kifayah & Kelayakan (AI)</h3>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<div class="p-4 space-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500 mb-1">Peratusan Had Kifayah</h4>
|
|
||||||
<div v-if="profile.analysis.hadKifayahPercentage === 'N/A' || profile.analysis.hadKifayahPercentage === 'Ralat'" class="text-gray-500">
|
|
||||||
{{ profile.analysis.hadKifayahPercentage }}
|
|
||||||
</div>
|
|
||||||
<div v-else class="relative pt-1">
|
|
||||||
<div class="overflow-hidden h-4 text-xs flex rounded bg-gray-200">
|
|
||||||
<div
|
|
||||||
:style="{ width: profile.analysis.hadKifayahPercentage }"
|
|
||||||
:class="{
|
|
||||||
'bg-red-500': parseInt(profile.analysis.hadKifayahPercentage) < 60,
|
|
||||||
'bg-yellow-500': parseInt(profile.analysis.hadKifayahPercentage) >= 60 && parseInt(profile.analysis.hadKifayahPercentage) < 80,
|
|
||||||
'bg-green-500': parseInt(profile.analysis.hadKifayahPercentage) >= 80 && parseInt(profile.analysis.hadKifayahPercentage) <= 100,
|
|
||||||
'bg-blue-500': parseInt(profile.analysis.hadKifayahPercentage) > 100
|
|
||||||
}"
|
|
||||||
class="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center"
|
|
||||||
>
|
|
||||||
{{ profile.analysis.hadKifayahPercentage }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Kategori Asnaf (AI)</h4>
|
|
||||||
<p>{{ profile.analysis.kategoriAsnaf }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Kategori Keluarga (AI)</h4>
|
|
||||||
<p>{{ profile.analysis.kategoriKeluarga }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Cadangan Kategori (AI)</h4>
|
|
||||||
<p>{{ profile.analysis.cadanganKategori }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Status Kelayakan (AI)</h4>
|
|
||||||
<p>{{ profile.analysis.statusKelayakan }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<!-- Card 2: Cadangan & Rumusan AI -->
|
|
||||||
<rs-card>
|
|
||||||
<template #header>
|
|
||||||
<h3 class="text-lg font-semibold text-primary p-4 border-b">Cadangan & Rumusan (AI)</h3>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<div class="p-4 space-y-4">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Cadangan Bantuan (AI)</h4>
|
|
||||||
<ul v-if="profile.analysis.cadanganBantuan && profile.analysis.cadanganBantuan.length > 0" class="list-disc list-inside space-y-1 mt-1">
|
|
||||||
<li v-for="(bantuan, index) in profile.analysis.cadanganBantuan" :key="index" class="text-gray-700">
|
|
||||||
{{ bantuan.nama }}
|
|
||||||
<span v-if="bantuan.peratusan && bantuan.peratusan !== 'Ralat'" class="font-semibold text-blue-600">({{ bantuan.peratusan }})</span>
|
|
||||||
<span v-else-if="bantuan.peratusan === 'Ralat'" class="text-red-500 text-xs">({{ bantuan.peratusan }})</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p v-else class="text-gray-500 mt-1">Tiada cadangan bantuan spesifik.</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Ramalan Jangka Masa Taraf Hidup Pulih (AI)</h4>
|
|
||||||
<p>{{ profile.analysis.ramalanJangkaMasaPulih }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Rumusan Keseluruhan (AI)</h4>
|
|
||||||
<div class="mt-1 p-3 bg-blue-50 border-l-4 border-blue-500 rounded-r-md">
|
|
||||||
<p class="whitespace-pre-line text-gray-700 text-sm">{{ profile.analysis.rumusan }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Original Data Column (takes 1/3 on lg screens) -->
|
|
||||||
<div class="lg:col-span-1">
|
|
||||||
<rs-card>
|
|
||||||
<template #header>
|
|
||||||
<h3 class="text-lg font-semibold text-gray-700 p-4 border-b">Ringkasan Profil (Data Asal)</h3>
|
|
||||||
</template>
|
|
||||||
<template #body>
|
|
||||||
<div class="p-4 space-y-3">
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Jenis Kategori (Asal)</h4>
|
|
||||||
<rs-badge :variant="categoryColor" class="mt-1">{{ profile.kategori }}</rs-badge>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Status Semasa (Asal)</h4>
|
|
||||||
<rs-badge :variant="statusColor" class="mt-1">{{ profile.status }}</rs-badge>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Jumlah Pendapatan (Asal)</h4>
|
|
||||||
<p>RM {{ profile.totalIncome }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 class="text-sm font-medium text-gray-500">Jumlah Tanggungan (Asal)</h4>
|
|
||||||
<p>{{ profile.dependents.length }} orang</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Delete Confirmation Modal -->
|
|
||||||
<rs-modal v-model="confirmDelete">
|
|
||||||
<template #header>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<Icon name="mdi:alert-circle" size="24" class="text-red-500 mr-2" />
|
|
||||||
<h3 class="text-lg font-medium">Padam Profil</h3>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #default>
|
|
||||||
<div class="p-4">
|
|
||||||
<p class="mb-4">Adakah anda pasti ingin memadam profil ini?</p>
|
|
||||||
<p class="text-sm text-gray-500 mb-2">Nama: <span class="font-medium">{{ profile?.nama }}</span></p>
|
|
||||||
<p class="text-sm text-gray-500">ID: <span class="font-medium">{{ profile?.id }}</span></p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<div class="flex justify-end gap-2">
|
|
||||||
<rs-button variant="secondary-outline" @click="cancelDelete">
|
|
||||||
Batal
|
|
||||||
</rs-button>
|
|
||||||
<rs-button variant="danger" @click="confirmDeleteProfile">
|
|
||||||
Padam
|
|
||||||
</rs-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-modal>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -1,337 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ref, computed, onMounted } from 'vue';
|
|
||||||
import { useAsnafMockData } from '~/composables/useAsnafMockData';
|
|
||||||
|
|
||||||
definePageMeta({
|
|
||||||
title: "Senarai Asnaf",
|
|
||||||
middleware: ["auth"],
|
|
||||||
requiresAuth: true,
|
|
||||||
breadcrumb: [
|
|
||||||
{
|
|
||||||
name: "Dashboard",
|
|
||||||
path: "/",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "BF-PRF",
|
|
||||||
path: "/BF-PRF",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Asnaf",
|
|
||||||
path: "/BF-PRF/AS",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Senarai",
|
|
||||||
path: "/BF-PRF/AS/LIST",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get asnaf data from the composable
|
|
||||||
const { asnafProfiles, statistics, filterProfiles, categories, statuses } = useAsnafMockData();
|
|
||||||
|
|
||||||
// Table reactivity control
|
|
||||||
const tableKey = ref(0);
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const totalProfiles = ref(0);
|
|
||||||
const isLoading = ref(false);
|
|
||||||
|
|
||||||
// Search and filter variables
|
|
||||||
const searchQuery = ref('');
|
|
||||||
const selectedStatus = ref('All');
|
|
||||||
const selectedCategory = ref('All');
|
|
||||||
|
|
||||||
// Table data and fields
|
|
||||||
const tableData = computed(() => {
|
|
||||||
return filterProfiles(searchQuery.value, selectedStatus.value, selectedCategory.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
const tableFields = [
|
|
||||||
{ field: 'no', label: 'No.' },
|
|
||||||
{ field: 'id', label: 'ID' },
|
|
||||||
{ field: 'nama', label: 'Nama' },
|
|
||||||
{ field: 'idNumber', label: 'No. ID' },
|
|
||||||
{ field: 'kategori', label: 'Kategori' },
|
|
||||||
{ field: 'status', label: 'Status' },
|
|
||||||
{ field: 'tindakan', label: 'Tindakan' }
|
|
||||||
];
|
|
||||||
|
|
||||||
// Generate table field and data mapping
|
|
||||||
const formattedTableData = computed(() => {
|
|
||||||
return tableData.value.map((profile, index) => ({
|
|
||||||
no: index + 1,
|
|
||||||
id: profile.id,
|
|
||||||
nama: profile.nama,
|
|
||||||
idNumber: profile.idNumber,
|
|
||||||
kategori: profile.kategori,
|
|
||||||
status: profile.status,
|
|
||||||
tindakan: profile.id
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
function getBadgeVariantForCategory(category) {
|
|
||||||
switch (category) {
|
|
||||||
case 'Fakir': return 'danger';
|
|
||||||
case 'Miskin': return 'warning';
|
|
||||||
case 'Mualaf': return 'info';
|
|
||||||
case 'Fi-sabilillah': return 'primary';
|
|
||||||
case 'Gharimin': return 'secondary';
|
|
||||||
case 'Ibnu Sabil': return 'success';
|
|
||||||
default: return 'primary';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBadgeVariantForStatus(status) {
|
|
||||||
switch (status) {
|
|
||||||
case 'Aktif': return 'success';
|
|
||||||
case 'Tidak Aktif': return 'danger';
|
|
||||||
case 'Dalam Semakan': return 'warning';
|
|
||||||
default: return 'secondary';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function navigateToDetail(id) {
|
|
||||||
console.log("Attempting to navigate to detail for ID:", id);
|
|
||||||
if (id) {
|
|
||||||
navigateTo(`/BF-PRF/AS/DETAIL/${id}`);
|
|
||||||
} else {
|
|
||||||
console.error("Navigation failed: ID is undefined or null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function navigateToRegistration() {
|
|
||||||
navigateTo('/BF-PRF/AS/FR/01');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
const handlePageChange = (newPage) => {
|
|
||||||
currentPage.value = newPage;
|
|
||||||
fetchProfiles();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fetch data
|
|
||||||
async function fetchProfiles() {
|
|
||||||
isLoading.value = true;
|
|
||||||
// Simulate API delay
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
|
||||||
|
|
||||||
totalProfiles.value = tableData.value.length;
|
|
||||||
isLoading.value = false;
|
|
||||||
tableKey.value++; // Force table re-render
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lifecycle hooks
|
|
||||||
onMounted(() => {
|
|
||||||
fetchProfiles();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="space-y-6">
|
|
||||||
<LayoutsBreadcrumb />
|
|
||||||
|
|
||||||
<!-- Header -->
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<h1 class="text-2xl font-bold text-primary">Senarai Asnaf</h1>
|
|
||||||
<rs-button
|
|
||||||
variant="primary"
|
|
||||||
class="flex items-center gap-2"
|
|
||||||
@click="navigateToRegistration"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="18" />
|
|
||||||
<span>Tambah Asnaf</span>
|
|
||||||
</rs-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Statistics Cards -->
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
||||||
<rs-card class="transition-all duration-300 hover:shadow-lg">
|
|
||||||
<div class="p-4 flex items-center gap-4">
|
|
||||||
<div class="p-4 flex justify-center items-center bg-blue-100 rounded-xl">
|
|
||||||
<Icon name="mdi:account-group" size="24" class="text-primary" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="block text-2xl font-bold text-primary">{{ statistics.total }}</span>
|
|
||||||
<span class="text-sm text-gray-600">Jumlah Asnaf</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<rs-card class="transition-all duration-300 hover:shadow-lg">
|
|
||||||
<div class="p-4 flex items-center gap-4">
|
|
||||||
<div class="p-4 flex justify-center items-center bg-green-100 rounded-xl">
|
|
||||||
<Icon name="mdi:check-circle" size="24" class="text-green-600" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="block text-2xl font-bold text-green-600">{{ statistics.active }}</span>
|
|
||||||
<span class="text-sm text-gray-600">Aktif</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<rs-card class="transition-all duration-300 hover:shadow-lg">
|
|
||||||
<div class="p-4 flex items-center gap-4">
|
|
||||||
<div class="p-4 flex justify-center items-center bg-yellow-100 rounded-xl">
|
|
||||||
<Icon name="mdi:clock-time-four" size="24" class="text-yellow-600" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="block text-2xl font-bold text-yellow-600">{{ statistics.review }}</span>
|
|
||||||
<span class="text-sm text-gray-600">Dalam Semakan</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<rs-card class="transition-all duration-300 hover:shadow-lg">
|
|
||||||
<div class="p-4 flex items-center gap-4">
|
|
||||||
<div class="p-4 flex justify-center items-center bg-red-100 rounded-xl">
|
|
||||||
<Icon name="mdi:close-circle" size="24" class="text-red-600" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="block text-2xl font-bold text-red-600">{{ statistics.inactive }}</span>
|
|
||||||
<span class="text-sm text-gray-600">Tidak Aktif</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Search and Filters -->
|
|
||||||
<rs-card>
|
|
||||||
<div class="p-4">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1">Carian</label>
|
|
||||||
<div class="relative rounded-md shadow-sm">
|
|
||||||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
||||||
<Icon name="mdi:magnify" size="18" class="text-gray-400" />
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
v-model="searchQuery"
|
|
||||||
type="text"
|
|
||||||
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-primary focus:border-primary"
|
|
||||||
placeholder="Cari dengan nama atau ID..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1">Status</label>
|
|
||||||
<select
|
|
||||||
v-model="selectedStatus"
|
|
||||||
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-primary focus:border-primary"
|
|
||||||
>
|
|
||||||
<option value="All">Semua Status</option>
|
|
||||||
<option v-for="status in statuses" :key="status" :value="status">
|
|
||||||
{{ status }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-1">Kategori</label>
|
|
||||||
<select
|
|
||||||
v-model="selectedCategory"
|
|
||||||
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-primary focus:border-primary"
|
|
||||||
>
|
|
||||||
<option value="All">Semua Kategori</option>
|
|
||||||
<option v-for="category in categories" :key="category" :value="category">
|
|
||||||
{{ category }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
|
|
||||||
<!-- Data Table -->
|
|
||||||
<rs-card>
|
|
||||||
<template #header>
|
|
||||||
<div class="px-4 py-3 flex items-center justify-between">
|
|
||||||
<h2 class="text-lg font-semibold text-primary">Senarai Asnaf</h2>
|
|
||||||
<span class="text-sm text-gray-500">
|
|
||||||
{{ tableData.length }} asnaf dijumpai
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #body>
|
|
||||||
<div v-if="isLoading && tableData.length === 0" class="py-8 text-center">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<Icon name="mdi:loading" size="2rem" class="text-blue-500 animate-spin" />
|
|
||||||
</div>
|
|
||||||
<p class="mt-2 text-gray-600">Memuat data...</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<rs-table
|
|
||||||
v-else
|
|
||||||
class="mt-4"
|
|
||||||
:key="tableKey"
|
|
||||||
:data="formattedTableData"
|
|
||||||
:columns="tableFields"
|
|
||||||
:pageSize="pageSize"
|
|
||||||
:showNoColumn="true"
|
|
||||||
:options="{
|
|
||||||
variant: 'default',
|
|
||||||
hover: true,
|
|
||||||
striped: true,
|
|
||||||
bordered: true
|
|
||||||
}"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:total-items="totalProfiles"
|
|
||||||
@page-change="handlePageChange"
|
|
||||||
>
|
|
||||||
<template v-slot:no="data">
|
|
||||||
{{ data.text }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:id="data">
|
|
||||||
{{ data.text }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:nama="data">
|
|
||||||
<div class="font-medium">{{ data.text }}</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:idNumber="data">
|
|
||||||
{{ data.text }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:kategori="data">
|
|
||||||
<rs-badge :variant="getBadgeVariantForCategory(data.text)">{{ data.text }}</rs-badge>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:status="data">
|
|
||||||
<rs-badge :variant="getBadgeVariantForStatus(data.text)">
|
|
||||||
{{ data.text }}
|
|
||||||
</rs-badge>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:tindakan="data">
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<rs-button
|
|
||||||
variant="primary"
|
|
||||||
size="sm"
|
|
||||||
class="!px-2 !py-1"
|
|
||||||
@click="() => {
|
|
||||||
navigateToDetail(data.value.tindakan);
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:eye" size="1rem" class="mr-1" />
|
|
||||||
Lihat
|
|
||||||
</rs-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-table>
|
|
||||||
|
|
||||||
<!-- Empty State -->
|
|
||||||
<div v-if="!isLoading && tableData.length === 0" class="text-center py-8">
|
|
||||||
<div class="flex justify-center mb-4">
|
|
||||||
<Icon name="mdi:magnify" size="4rem" class="text-gray-400" />
|
|
||||||
</div>
|
|
||||||
<h3 class="text-lg font-medium text-gray-500">Tiada Profil Ditemui</h3>
|
|
||||||
<p class="text-gray-500 mt-2">Sila cuba carian lain atau reset penapis.</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
Loading…
x
Reference in New Issue
Block a user