Files
BarangaySystem/resources/js/Pages/UserInfoEdit.vue
2026-06-06 18:43:00 +08:00

422 lines
19 KiB
Vue

<script setup>
import { ref, onMounted, watch, getCurrentInstance } from 'vue';
import axios from 'axios';
import { usePageTitle } from '../composables/Core/usePageTitle';
import { useNavigate } from '../composables/Core/useNavigate';
import { useModal } from '../composables/Core/useModal';
import CardSimple from '../Components/Core/CardSimple.vue';
import InputGroup from '../Components/Core/Forms/InputGroup.vue';
import InputGroupSelect from '../Components/Core/Forms/InputGroupSelect.vue';
import InputGroupButton from '../Components/Core/Forms/InputGroupButton.vue';
import InputGroupTextarea from '../Components/Core/Forms/InputGroupTextarea.vue';
import { useUserStore } from '../stores/user';
const userStore = useUserStore();
const props = defineProps({
target: String
});
usePageTitle('Member Profile');
const { navigate } = useNavigate();
const modal = useModal();
const form = ref({
firstname: '',
middlename: '',
lastname: '',
suffix: '',
gender: '',
dob: '',
fullname: '',
landline: '',
mobile: '',
email: '',
alt_email: '',
alt_landline: '',
alt_mobile: '',
facebook_url: '',
messenger_id: '',
viber_number: '',
tiktok_username: '',
region: '',
province: '',
city: '',
barangay: '',
civil_status: '',
children_count: 0,
education_level: '',
course: '',
school: '',
year_last_attended: '',
livelihood_source: '',
last_company: '',
last_position: '',
last_employment_year: '',
tin: '',
philhealth_id: '',
gov_id: '',
emergency_contact_name: '',
emergency_contact_address: '',
emergency_contact_phone: '',
emergency_contact_relation: '',
emergency_contact_user_id: null,
bank_details: { bank: '', account_number: '', account_name: '' },
addresses: [],
other_details: {}
});
const loading = ref(true);
const saving = ref(false);
const emergencyResults = ref([]);
const searchingEmergency = ref(false);
const linkedUser = ref(null);
const fetchUserInfo = async () => {
loading.value = true;
let targetHashkey = props.target;
// If no target provided, try to use the current user's hashkey from the store
if (!targetHashkey) {
if (!userStore.user) {
await userStore.fetchCurrentUser();
}
targetHashkey = userStore.user?.hashkey;
}
if (!targetHashkey) {
console.warn('[UserInfoEdit] No target hashkey found for profile fetch');
loading.value = false;
return;
}
try {
const response = await axios.post('/UserInfo/Get', { hashkey: targetHashkey });
if (response.data.success) {
const data = response.data.data;
form.value = { ...form.value, ...data };
if (!form.value.bank_details) form.value.bank_details = { bank: '', account_number: '', account_name: '' };
if (!form.value.addresses) form.value.addresses = [];
} else {
console.error('[UserInfoEdit] Backend returned success=false:', response.data.message);
}
} catch (error) {
console.error('[UserInfoEdit] Failed to fetch user info:', error);
} finally {
loading.value = false;
}
};
const handleSave = async () => {
saving.value = true;
try {
const response = await axios.post('/UserInfo/Update', {
hashkey: props.target,
...form.value
});
if (response.data.success) {
modal.open({ title: 'Success', body: 'Member profile updated successfully!' });
} else {
modal.open({ title: 'Error', body: response.data.message || 'Failed to update user information' });
}
} catch (error) {
modal.open({ title: 'Error', body: 'An error occurred while saving.' });
} finally {
saving.value = false;
}
};
const searchEmergency = async (val) => {
if (val.length < 3) {
emergencyResults.value = [];
return;
}
searchingEmergency.value = true;
try {
const response = await axios.post('/UserInfo/SearchEmergencyContact', { q: val });
if (response.data.success) {
emergencyResults.value = response.data.data;
}
} catch (error) {
console.error('Search failed');
} finally {
searchingEmergency.value = false;
}
};
const selectEmergencyUser = (user) => {
form.value.emergency_contact_name = user.fullname || user.name;
form.value.emergency_contact_phone = user.mobile_number;
form.value.emergency_contact_user_id = user.id;
emergencyResults.value = [];
};
onMounted(fetchUserInfo);
</script>
<template>
<div class="user-info-edit pb-5">
<div class="tf-container mt-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3 class="fw_6 mb-0">Detailed Member Profile</h3>
<InputGroupButton
:loading="saving"
:disabled="saving"
text="Save Changes"
variant="primary"
@click="handleSave"
/>
</div>
<div v-if="loading" class="text-center py-5">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="text-muted mt-3">Loading profile...</p>
</div>
<div v-else>
<CardSimple title="Personal Information" class="mb-4">
<template #headerAction>
<i class="fas fa-user-circle text-primary"></i>
</template>
<div class="row">
<div class="col-md-3">
<InputGroup v-model="form.firstname" label="First Name" id="firstname" placeholder="First Name" />
</div>
<div class="col-md-3">
<InputGroup v-model="form.middlename" label="Middle Name" id="middlename" placeholder="Middle Name" />
</div>
<div class="col-md-3">
<InputGroup v-model="form.lastname" label="Last Name" id="lastname" placeholder="Last Name" />
</div>
<div class="col-md-3">
<InputGroup v-model="form.suffix" label="Suffix" id="suffix" placeholder="e.g. Jr, III" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<InputGroupSelect
v-model="form.gender"
label="Gender"
id="gender"
:options="['Male', 'Female', 'Other']"
placeholder="Select Gender"
/>
</div>
<div class="col-md-6">
<InputGroup v-model="form.dob" type="date" label="Date of Birth" id="dob" />
</div>
</div>
<InputGroup v-model="form.fullname" label="Display/Full Name" id="fullname" placeholder="Juan Dela Cruz" />
</CardSimple>
<CardSimple title="Contact & Social" class="mb-4">
<template #headerAction>
<i class="fas fa-phone-alt text-primary"></i>
</template>
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.mobile" label="Primary Mobile" id="mobile" placeholder="09xxxxxxxxx" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.email" type="email" label="Primary Email" id="email" placeholder="email@example.com" />
</div>
</div>
<div class="row">
<div class="col-md-4">
<InputGroup v-model="form.facebook_url" label="Facebook Profile" id="facebook" placeholder="facebook.com/juan" icon="fas fa-facebook" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.messenger_id" label="Messenger ID" id="messenger" placeholder="Messenger username" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.viber_number" label="Viber Number" id="viber" placeholder="Viber number" />
</div>
</div>
<div class="row">
<div class="col-md-4">
<InputGroup v-model="form.tiktok_username" label="TikTok Username" id="tiktok" placeholder="@username" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.alt_mobile" label="Alt Mobile" id="alt_mobile" placeholder="Alternative number" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.landline" label="Landline" id="landline" placeholder="02-8xxx-xxxx" />
</div>
</div>
</CardSimple>
<CardSimple title="Address Information" class="mb-4">
<template #headerAction>
<i class="fas fa-map-marker-alt text-primary"></i>
</template>
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.region" label="Region" id="region" placeholder="e.g. Region III" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.province" label="Province" id="province" placeholder="e.g. Pampanga" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.city" label="City / Municipality" id="city" placeholder="e.g. San Fernando" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.barangay" label="Barangay" id="barangay" placeholder="e.g. Dolores" />
</div>
</div>
</CardSimple>
<CardSimple title="Family & Education" class="mb-4">
<template #headerAction>
<i class="fas fa-users-cog text-primary"></i>
</template>
<div class="row">
<div class="col-md-6">
<InputGroupSelect
v-model="form.civil_status"
label="Civil Status"
id="civil_status"
:options="['Single', 'Married', 'Widowed', 'Separated']"
placeholder="Select Status"
/>
</div>
<div class="col-md-6">
<InputGroup v-model.number="form.children_count" type="number" label="Number of Children" id="children" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.education_level" label="Education Level" id="education" placeholder="Highest attainment" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.course" label="Course / Major" id="course" placeholder="Course taken" />
</div>
</div>
<div class="row">
<div class="col-md-8">
<InputGroup v-model="form.school" label="School Attended" id="school" placeholder="Name of school" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.year_last_attended" label="Year Graduated" id="grad_year" placeholder="YYYY" />
</div>
</div>
</CardSimple>
<CardSimple title="Employment & Livelihood" class="mb-4">
<template #headerAction>
<i class="fas fa-briefcase text-primary"></i>
</template>
<InputGroup v-model="form.livelihood_source" label="Current Source of Livelihood" id="livelihood" placeholder="e.g. Farming, Business, Office Job" />
<InputGroup v-model="form.last_company" label="Company Last Employed" id="last_company" placeholder="Name of company" />
<div class="row">
<div class="col-md-8">
<InputGroup v-model="form.last_position" label="Position in the Company" id="last_position" placeholder="Job title" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.last_employment_year" label="Year Last Employed" id="last_employment_year" placeholder="YYYY" />
</div>
</div>
</CardSimple>
<CardSimple title="Government Information" class="mb-4">
<template #headerAction>
<i class="fas fa-id-card text-primary"></i>
</template>
<div class="row">
<div class="col-md-4">
<InputGroup v-model="form.tin" label="TIN Number" id="tin" placeholder="xxx-xxx-xxx" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.philhealth_id" label="PhilHealth ID" id="philhealth" placeholder="xxxx-xxxx-xxxx" />
</div>
<div class="col-md-4">
<InputGroup v-model="form.gov_id" label="Government ID" id="gov_id" placeholder="ID Number" />
</div>
</div>
</CardSimple>
<CardSimple title="Emergency Contact Information" class="mb-4">
<template #headerAction>
<i class="fas fa-exclamation-triangle text-danger"></i>
</template>
<div class="mb-4">
<InputGroup
id="emergency_search"
label="Search Existing Member to Link"
placeholder="Search by name or phone..."
icon="fas fa-search"
@input="searchEmergency($event.target.value)"
:hint="searchingEmergency ? 'Searching...' : ''"
/>
<div v-if="emergencyResults.length > 0" class="list-group mt-2 border-0 shadow-sm rounded-15 overflow-hidden">
<button v-for="user in emergencyResults" :key="user.id"
type="button"
class="list-group-item list-group-item-action border-0 py-3"
@click="selectEmergencyUser(user)">
<div class="fw-bold">{{ user.fullname || user.name }}</div>
<div class="small text-muted">{{ user.mobile_number }}</div>
</button>
</div>
</div>
<div class="row">
<div class="col-md-6">
<InputGroup
v-model="form.emergency_contact_name"
label="Contact Name"
id="emergency_name"
placeholder="Juan Dela Cruz"
:hint="form.emergency_contact_user_id ? 'Linked' : ''"
/>
</div>
<div class="col-md-6">
<InputGroup v-model="form.emergency_contact_relation" label="Relation" id="relation" placeholder="Spouse, Sibling, Friend" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.emergency_contact_phone" label="Contact Number" id="emergency_phone" placeholder="09xxxxxxxxx" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.emergency_contact_address" label="Address" id="emergency_address" placeholder="Full address" />
</div>
</div>
</CardSimple>
<CardSimple title="Bank Details" class="mb-4">
<template #headerAction>
<i class="fas fa-university text-primary"></i>
</template>
<InputGroup v-model="form.bank_details.bank" label="Bank Name / E-Wallet" id="bank" placeholder="e.g. GCash, Maya, BDO" />
<div class="row">
<div class="col-md-6">
<InputGroup v-model="form.bank_details.account_number" label="Account Number" id="account_number" placeholder="000123456789" />
</div>
<div class="col-md-6">
<InputGroup v-model="form.bank_details.account_name" label="Account Name" id="account_name" placeholder="Juan Dela Cruz" />
</div>
</div>
</CardSimple>
<div class="mt-4 mb-5">
<InputGroupButton
:loading="saving"
text="Update Entire Profile"
variant="primary"
size="lg"
buttonStyle="width: 100%; py-3 fw-bold shadow-lg"
@click="handleSave"
/>
<p class="text-center text-muted small mt-3">
<i class="fas fa-shield-alt me-1"></i> Data is stored securely in compliance with the Data Privacy Act.
</p>
</div>
</div>
</div>
</div>
</template>