275 lines
11 KiB
PHP
275 lines
11 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', __('app.patients'))
|
|
@section('page_title', __('app.patients'))
|
|
|
|
@section('content')
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">{{ __('app.patients') }}</h3>
|
|
<div class="card-tools">
|
|
<div class="input-group input-group-sm" style="width: 250px;">
|
|
<input type="text" id="search-patients" class="form-control float-right" placeholder="{{ __('app.search') }}...">
|
|
<div class="input-group-append">
|
|
<button type="button" class="btn btn-default" onclick="loadPatients()">
|
|
<i class="fas fa-search"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-primary btn-sm ml-2" onclick="showCreateModal()">
|
|
<i class="fas fa-plus"></i> {{ __('app.create') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body table-responsive p-0">
|
|
<table class="table table-hover text-nowrap" id="patients-table">
|
|
<thead>
|
|
<tr>
|
|
<th>{{ __('app.code') ?? 'Code' }}</th>
|
|
<th>{{ __('app.name') }}</th>
|
|
<th>{{ __('app.phone') ?? 'Phone' }}</th>
|
|
<th>{{ __('app.email') }}</th>
|
|
<th>{{ __('app.status') }}</th>
|
|
<th>{{ __('app.actions') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="patients-tbody">
|
|
<tr>
|
|
<td colspan="6" class="text-center">{{ __('app.loading') ?? 'Loading...' }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="card-footer clearfix" id="pagination-container">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create/Edit Modal -->
|
|
<div class="modal fade" id="patientModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="modalTitle">{{ __('app.create') }}</h5>
|
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
</div>
|
|
<form id="patientForm" onsubmit="savePatient(event)">
|
|
<div class="modal-body">
|
|
<div id="form-errors" class="alert alert-danger d-none"></div>
|
|
<input type="hidden" id="patient_id">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label>{{ __('app.first_name') ?? 'First Name' }} *</label>
|
|
<input type="text" class="form-control" name="first_name" required>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label>{{ __('app.last_name') ?? 'Last Name' }} *</label>
|
|
<input type="text" class="form-control" name="last_name" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label>{{ __('app.phone') ?? 'Phone' }}</label>
|
|
<input type="tel" class="form-control" name="phone">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label>{{ __('app.whatsapp') ?? 'WhatsApp' }}</label>
|
|
<input type="tel" class="form-control" name="whatsapp">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>{{ __('app.email') }}</label>
|
|
<input type="email" class="form-control" name="email">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ __('app.cancel') }}</button>
|
|
<button type="submit" class="btn btn-primary">{{ __('app.save') }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script src="{{ asset('js/api.js') }}"></script>
|
|
<script>
|
|
let currentPage = 1;
|
|
|
|
// Load patients on page load
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadPatients();
|
|
});
|
|
|
|
// Search on Enter key
|
|
document.getElementById('search-patients').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
loadPatients();
|
|
}
|
|
});
|
|
|
|
async function loadPatients(page = 1) {
|
|
currentPage = page;
|
|
const search = document.getElementById('search-patients').value;
|
|
|
|
try {
|
|
const response = await api.getPatients({
|
|
search: search,
|
|
page: page,
|
|
per_page: 20
|
|
});
|
|
|
|
renderPatients(response.data);
|
|
renderPagination(response.meta, response.links);
|
|
} catch (error) {
|
|
console.error('Failed to load patients:', error);
|
|
}
|
|
}
|
|
|
|
function renderPatients(patients) {
|
|
const tbody = document.getElementById('patients-tbody');
|
|
|
|
if (patients.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" class="text-center">{{ __("app.no_results") ?? "No patients found" }}</td></tr>';
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = patients.map(patient => `
|
|
<tr>
|
|
<td>${patient.patient_code}</td>
|
|
<td>${patient.full_name}</td>
|
|
<td>${patient.phone || '-'}</td>
|
|
<td>${patient.email || '-'}</td>
|
|
<td>
|
|
<span class="badge badge-${patient.status === 'active' ? 'success' : 'secondary'}">
|
|
${patient.status}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-info" onclick="editPatient(${patient.id})">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-danger" onclick="deletePatient(${patient.id})">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
function renderPagination(meta, links) {
|
|
const container = document.getElementById('pagination-container');
|
|
|
|
let html = '<ul class="pagination pagination-sm m-0 float-right">';
|
|
|
|
// Previous
|
|
if (meta.current_page > 1) {
|
|
html += `<li class="page-item"><a class="page-link" href="#" onclick="loadPatients(${meta.current_page - 1})">«</a></li>`;
|
|
}
|
|
|
|
// Page numbers
|
|
for (let i = 1; i <= meta.last_page; i++) {
|
|
if (i === meta.current_page) {
|
|
html += `<li class="page-item active"><span class="page-link">${i}</span></li>`;
|
|
} else if (i === 1 || i === meta.last_page || (i >= meta.current_page - 1 && i <= meta.current_page + 1)) {
|
|
html += `<li class="page-item"><a class="page-link" href="#" onclick="loadPatients(${i})">${i}</a></li>`;
|
|
} else if (i === meta.current_page - 2 || i === meta.current_page + 2) {
|
|
html += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
|
|
}
|
|
}
|
|
|
|
// Next
|
|
if (meta.current_page < meta.last_page) {
|
|
html += `<li class="page-item"><a class="page-link" href="#" onclick="loadPatients(${meta.current_page + 1})">»</a></li>`;
|
|
}
|
|
|
|
html += '</ul>';
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
function showCreateModal() {
|
|
document.getElementById('patientForm').reset();
|
|
document.getElementById('patient_id').value = '';
|
|
document.getElementById('modalTitle').textContent = '{{ __("app.create") }} {{ __("app.patient") }}';
|
|
document.getElementById('form-errors').classList.add('d-none');
|
|
$('#patientModal').modal('show');
|
|
}
|
|
|
|
async function editPatient(id) {
|
|
try {
|
|
const patient = await api.getPatient(id);
|
|
document.getElementById('patient_id').value = patient.data.id;
|
|
document.querySelector('[name="first_name"]').value = patient.data.first_name;
|
|
document.querySelector('[name="last_name"]').value = patient.data.last_name;
|
|
document.querySelector('[name="phone"]').value = patient.data.phone || '';
|
|
document.querySelector('[name="whatsapp"]').value = patient.data.whatsapp || '';
|
|
document.querySelector('[name="email"]').value = patient.data.email || '';
|
|
|
|
document.getElementById('modalTitle').textContent = '{{ __("app.edit") }} {{ __("app.patient") }}';
|
|
document.getElementById('form-errors').classList.add('d-none');
|
|
$('#patientModal').modal('show');
|
|
} catch (error) {
|
|
console.error('Failed to load patient:', error);
|
|
}
|
|
}
|
|
|
|
async function savePatient(event) {
|
|
event.preventDefault();
|
|
|
|
const form = event.target;
|
|
const data = {
|
|
first_name: form.first_name.value,
|
|
last_name: form.last_name.value,
|
|
phone: form.phone.value,
|
|
whatsapp: form.whatsapp.value,
|
|
email: form.email.value || null,
|
|
};
|
|
|
|
const id = document.getElementById('patient_id').value;
|
|
const errorDiv = document.getElementById('form-errors');
|
|
|
|
try {
|
|
if (id) {
|
|
await api.updatePatient(id, data);
|
|
api.showSuccess('Patient updated successfully');
|
|
} else {
|
|
await api.createPatient(data);
|
|
api.showSuccess('Patient created successfully');
|
|
}
|
|
|
|
$('#patientModal').modal('hide');
|
|
loadPatients(currentPage);
|
|
} catch (error) {
|
|
errorDiv.textContent = error.message;
|
|
errorDiv.classList.remove('d-none');
|
|
}
|
|
}
|
|
|
|
async function deletePatient(id) {
|
|
if (!confirm('{{ __("app.confirm_delete") ?? "Are you sure?" }}')) return;
|
|
|
|
try {
|
|
await api.deletePatient(id);
|
|
api.showSuccess('Patient deleted successfully');
|
|
loadPatients(currentPage);
|
|
} catch (error) {
|
|
console.error('Failed to delete patient:', error);
|
|
}
|
|
}
|
|
</script>
|
|
@endpush
|