Autosave: 20260306-100128
This commit is contained in:
parent
230a62f266
commit
523db02f6f
36
api/cities.php
Normal file
36
api/cities.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../helpers.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$db = db();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method === 'POST') {
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
|
||||
$action = $input['action'] ?? '';
|
||||
|
||||
if ($action === 'add_city') {
|
||||
$name_en = $input['name_en'] ?? '';
|
||||
$name_ar = $input['name_ar'] ?? '';
|
||||
|
||||
if ($name_en && $name_ar) {
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO cities (name_en, name_ar) VALUES (?, ?)");
|
||||
$stmt->execute([$name_en, $name_ar]);
|
||||
$id = $db->lastInsertId();
|
||||
echo json_encode(['success' => true, 'id' => $id, 'name_en' => $name_en, 'name_ar' => $name_ar]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Missing fields']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid action']);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid request method']);
|
||||
11
db/migrations/20260306_create_services_module.sql
Normal file
11
db/migrations/20260306_create_services_module.sql
Normal file
@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS services (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name_en VARCHAR(255) NOT NULL,
|
||||
name_ar VARCHAR(255) NOT NULL,
|
||||
department_id INT NOT NULL,
|
||||
price DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
|
||||
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@ -58,15 +58,21 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><?php echo __('city'); ?></label>
|
||||
|
||||
<select name="city" class="form-select select2-modal">
|
||||
<option value=""><?php echo __('select'); ?>...</option>
|
||||
<?php foreach ($all_cities as $city):
|
||||
?><option value="<?php echo htmlspecialchars($city['name']); ?>"><?php echo htmlspecialchars($city['name']); ?></option>
|
||||
<?php endforeach;
|
||||
?></select>
|
||||
</div>
|
||||
<label class="form-label"><?php echo __('city'); ?></label>
|
||||
<div class="d-flex gap-2">
|
||||
<div class="flex-grow-1">
|
||||
<select name="city" id="add_patient_city" class="form-select select2-modal">
|
||||
<option value=""><?php echo __('select'); ?>...</option>
|
||||
<?php foreach ($all_cities as $city): ?>
|
||||
<option value="<?php echo htmlspecialchars($city['name']); ?>"><?php echo htmlspecialchars($city['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary" onclick="openQuickAddCityModal('add_patient_city')" title="<?php echo __('add_city'); ?>">
|
||||
<i class="bi bi-plus-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><?php echo __('blood_group'); ?></label>
|
||||
<input type="text" name="blood_group" class="form-control" placeholder="O+, A-, etc.">
|
||||
@ -156,15 +162,21 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><?php echo __('city'); ?></label>
|
||||
|
||||
<select name="city" id="edit_patient_city" class="form-select select2-modal">
|
||||
<option value=""><?php echo __('select'); ?>...</option>
|
||||
<?php foreach ($all_cities as $city):
|
||||
?><option value="<?php echo htmlspecialchars($city['name']); ?>"><?php echo htmlspecialchars($city['name']); ?></option>
|
||||
<?php endforeach;
|
||||
?></select>
|
||||
</div>
|
||||
<label class="form-label"><?php echo __('city'); ?></label>
|
||||
<div class="d-flex gap-2">
|
||||
<div class="flex-grow-1">
|
||||
<select name="city" id="edit_patient_city" class="form-select select2-modal">
|
||||
<option value=""><?php echo __('select'); ?>...</option>
|
||||
<?php foreach ($all_cities as $city): ?>
|
||||
<option value="<?php echo htmlspecialchars($city['name']); ?>"><?php echo htmlspecialchars($city['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary" onclick="openQuickAddCityModal('edit_patient_city')" title="<?php echo __('add_city'); ?>">
|
||||
<i class="bi bi-plus-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><?php echo __('blood_group'); ?></label>
|
||||
<input type="text" name="blood_group" id="edit_patient_blood_group" class="form-control" placeholder="O+, A-, etc.">
|
||||
@ -3282,6 +3294,109 @@ $drug_groups_js = $db->query("SELECT * FROM drugs_groups ORDER BY name_$lang")->
|
||||
setupAgeCalculation('add_patient_age', 'add_patient_dob');
|
||||
setupAgeCalculation('edit_patient_age', 'edit_patient_dob');
|
||||
</script>
|
||||
|
||||
<!-- Quick Add City Modal -->
|
||||
<div class="modal fade" id="quickAddCityModal" tabindex="-1" aria-hidden="true" style="z-index: 1060;"> <!-- Higher z-index to sit above patient modal -->
|
||||
<div class="modal-dialog modal-sm modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-light py-2">
|
||||
<h5 class="modal-title fs-6 fw-bold"><?php echo __('add_city'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="quickAddCityForm">
|
||||
<input type="hidden" id="quick_add_city_target_select_id">
|
||||
<div class="mb-2">
|
||||
<label class="form-label small"><?php echo __('name_en'); ?></label>
|
||||
<input type="text" id="quick_city_name_en" class="form-control form-control-sm" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small"><?php echo __('name_ar'); ?></label>
|
||||
<input type="text" id="quick_city_name_ar" class="form-control form-control-sm" dir="rtl" required>
|
||||
</div>
|
||||
<div id="quickCityError" class="text-danger small mb-2 d-none"></div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-sm"><?php echo __('save'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function openQuickAddCityModal(targetSelectId) {
|
||||
document.getElementById('quick_add_city_target_select_id').value = targetSelectId;
|
||||
document.getElementById('quick_city_name_en').value = '';
|
||||
document.getElementById('quick_city_name_ar').value = '';
|
||||
document.getElementById('quickCityError').classList.add('d-none');
|
||||
var modal = new bootstrap.Modal(document.getElementById('quickAddCityModal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
document.getElementById('quickAddCityForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var nameEn = document.getElementById('quick_city_name_en').value;
|
||||
var nameAr = document.getElementById('quick_city_name_ar').value;
|
||||
var targetId = document.getElementById('quick_add_city_target_select_id').value;
|
||||
|
||||
// Disable button to prevent double submit
|
||||
var btn = this.querySelector('button[type="submit"]');
|
||||
var originalText = btn.innerHTML;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<?php echo __('saving'); ?>...';
|
||||
|
||||
fetch('api/cities.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'add_city', name_en: nameEn, name_ar: nameAr })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
|
||||
if (data.success) {
|
||||
// Add to all city selects on the page with class select2-modal or matching name="city"
|
||||
var selects = document.querySelectorAll('select[name="city"]');
|
||||
selects.forEach(function(select) {
|
||||
var option = new Option(data.name_en, data.name_en);
|
||||
select.add(option, undefined);
|
||||
});
|
||||
|
||||
// Select in the target dropdown
|
||||
if (targetId) {
|
||||
var targetSelect = document.getElementById(targetId);
|
||||
if (targetSelect) {
|
||||
targetSelect.value = data.name_en;
|
||||
// Trigger change for Select2
|
||||
var event = new Event('change');
|
||||
targetSelect.dispatchEvent(event);
|
||||
if (window.jQuery) { $(targetSelect).trigger('change'); }
|
||||
}
|
||||
}
|
||||
|
||||
var modalEl = document.getElementById('quickAddCityModal');
|
||||
var modal = bootstrap.Modal.getInstance(modalEl);
|
||||
modal.hide();
|
||||
} else {
|
||||
var errDiv = document.getElementById('quickCityError');
|
||||
errDiv.textContent = data.error || 'Error adding city';
|
||||
errDiv.classList.remove('d-none');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = originalText;
|
||||
var errDiv = document.getElementById('quickCityError');
|
||||
errDiv.textContent = 'Network error';
|
||||
errDiv.classList.remove('d-none');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -146,6 +146,7 @@ $site_favicon = !empty($site_settings['company_favicon']) ? $site_settings['comp
|
||||
<a href="doctors.php" class="sidebar-link <?php echo $section === 'doctors' ? 'active' : ''; ?>"><i class="bi bi-person-badge me-2"></i> <?php echo __('doctors'); ?></a>
|
||||
<a href="nurses.php" class="sidebar-link <?php echo $section === 'nurses' ? 'active' : ''; ?>"><i class="bi bi-person-heart me-2"></i> <?php echo __('nurses'); ?></a>
|
||||
<a href="departments.php" class="sidebar-link <?php echo $section === 'departments' ? 'active' : ''; ?>"><i class="bi bi-diagram-3 me-2"></i> <?php echo __('departments'); ?></a>
|
||||
<a href="services.php" class="sidebar-link <?php echo $section === 'services' ? 'active' : ''; ?>"><i class="bi bi-activity me-2"></i> <?php echo __('services'); ?></a>
|
||||
<a href="cities.php" class="sidebar-link <?php echo $section === 'cities' ? 'active' : ''; ?>"><i class="bi bi-building me-2"></i> <?php echo __('cities'); ?></a>
|
||||
|
||||
<a href="#settingsSubmenu" data-bs-toggle="collapse" class="sidebar-link <?php echo in_array($section, ['employees', 'poisons', 'company_profile']) ? 'active' : ''; ?> d-flex justify-content-between align-items-center">
|
||||
|
||||
@ -48,7 +48,10 @@ if (isset($_GET['ajax_search'])) {
|
||||
<?php else: ?>
|
||||
<?php foreach ($patients as $p): ?>
|
||||
<tr>
|
||||
<td class="px-4">
|
||||
<td class="px-4 text-secondary">
|
||||
<?php echo str_pad($p['id'], 6, '0', STR_PAD_LEFT); ?>
|
||||
</td>
|
||||
<td class="px-4">
|
||||
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($p['name']); ?></div>
|
||||
<small class="text-muted"><?php echo $p['dob']; ?></small>
|
||||
</td>
|
||||
@ -62,7 +65,11 @@ if (isset($_GET['ajax_search'])) {
|
||||
<td class="text-secondary"><?php echo htmlspecialchars($p['policy_number'] ?: '-'); ?></td>
|
||||
<td class="text-end px-4">
|
||||
<div class="btn-group shadow-sm border rounded bg-white">
|
||||
<button class="btn btn-link text-primary py-1 px-2 border-end"
|
||||
<a href="print_patient_label.php?id=<?php echo $p['id']; ?>" target="_blank" class="btn btn-link text-dark py-1 px-2 border-end"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('print'); ?>">
|
||||
<i class="bi bi-upc-scan"></i>
|
||||
</a>
|
||||
<button class="btn btn-link text-primary py-1 px-2 border-end"
|
||||
onclick="showEditPatientModal(<?php echo htmlspecialchars(json_encode($p, JSON_UNESCAPED_UNICODE)); ?>)"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('edit'); ?>">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
@ -174,6 +181,7 @@ if (isset($_GET['ajax_search'])) {
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light text-secondary">
|
||||
<tr>
|
||||
<th class="px-4 py-3"><?php echo __('patient_number'); ?></th>
|
||||
<th class="px-4 py-3"><?php echo __('name'); ?></th>
|
||||
<th class="py-3"><?php echo __('age'); ?></th>
|
||||
<th class="py-3"><?php echo __('phone'); ?></th>
|
||||
@ -193,6 +201,9 @@ if (isset($_GET['ajax_search'])) {
|
||||
<?php else: ?>
|
||||
<?php foreach ($patients as $p): ?>
|
||||
<tr>
|
||||
<td class="px-4 text-secondary">
|
||||
<?php echo str_pad($p['id'], 6, '0', STR_PAD_LEFT); ?>
|
||||
</td>
|
||||
<td class="px-4">
|
||||
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($p['name']); ?></div>
|
||||
<small class="text-muted"><?php echo $p['dob']; ?></small>
|
||||
@ -207,6 +218,10 @@ if (isset($_GET['ajax_search'])) {
|
||||
<td class="text-secondary"><?php echo htmlspecialchars($p['policy_number'] ?: '-'); ?></td>
|
||||
<td class="text-end px-4">
|
||||
<div class="btn-group shadow-sm border rounded bg-white">
|
||||
<a href="print_patient_label.php?id=<?php echo $p['id']; ?>" target="_blank" class="btn btn-link text-dark py-1 px-2 border-end"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('print'); ?>">
|
||||
<i class="bi bi-upc-scan"></i>
|
||||
</a>
|
||||
<button class="btn btn-link text-primary py-1 px-2 border-end"
|
||||
onclick="showEditPatientModal(<?php echo htmlspecialchars(json_encode($p, JSON_UNESCAPED_UNICODE)); ?>)"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('edit'); ?>">
|
||||
|
||||
352
includes/pages/services.php
Normal file
352
includes/pages/services.php
Normal file
@ -0,0 +1,352 @@
|
||||
<?php
|
||||
// Handle Form Submissions
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['action'])) {
|
||||
try {
|
||||
if ($_POST['action'] === 'add_service') {
|
||||
$stmt = $db->prepare("INSERT INTO services (name_en, name_ar, department_id, price, is_active) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$_POST['name_en'],
|
||||
$_POST['name_ar'],
|
||||
$_POST['department_id'],
|
||||
$_POST['price'],
|
||||
isset($_POST['is_active']) ? 1 : 0
|
||||
]);
|
||||
$_SESSION['flash_message'] = '<div class="alert alert-success">' . __('service_added_successfully') . '</div>';
|
||||
} elseif ($_POST['action'] === 'edit_service') {
|
||||
$stmt = $db->prepare("UPDATE services SET name_en = ?, name_ar = ?, department_id = ?, price = ?, is_active = ? WHERE id = ?");
|
||||
$stmt->execute([
|
||||
$_POST['name_en'],
|
||||
$_POST['name_ar'],
|
||||
$_POST['department_id'],
|
||||
$_POST['price'],
|
||||
isset($_POST['is_active']) ? 1 : 0,
|
||||
$_POST['id']
|
||||
]);
|
||||
$_SESSION['flash_message'] = '<div class="alert alert-success">' . __('service_updated_successfully') . '</div>';
|
||||
} elseif ($_POST['action'] === 'delete_service') {
|
||||
$stmt = $db->prepare("DELETE FROM services WHERE id = ?");
|
||||
$stmt->execute([$_POST['id']]);
|
||||
$_SESSION['flash_message'] = '<div class="alert alert-success">' . __('service_deleted_successfully') . '</div>';
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['flash_message'] = '<div class="alert alert-danger">' . __('error') . ': ' . $e->getMessage() . '</div>';
|
||||
}
|
||||
header("Location: services.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch Departments for Dropdown
|
||||
$deptQuery = "SELECT * FROM departments ORDER BY name_$lang";
|
||||
$deptStmt = $db->query($deptQuery);
|
||||
$all_departments = $deptStmt->fetchAll();
|
||||
|
||||
// Pagination and Search
|
||||
$search_name = $_GET['name'] ?? '';
|
||||
$search_dept = $_GET['department_id'] ?? '';
|
||||
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
$limit = 10;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$where = "WHERE 1=1";
|
||||
$params = [];
|
||||
|
||||
if ($search_name) {
|
||||
$where .= " AND (s.name_en LIKE ? OR s.name_ar LIKE ?)";
|
||||
$params[] = "%$search_name%";
|
||||
$params[] = "%$search_name%";
|
||||
}
|
||||
if ($search_dept) {
|
||||
$where .= " AND s.department_id = ?";
|
||||
$params[] = $search_dept;
|
||||
}
|
||||
|
||||
// Count Total
|
||||
$countQuery = "SELECT COUNT(*) FROM services s $where";
|
||||
$stmt = $db->prepare($countQuery);
|
||||
$stmt->execute($params);
|
||||
$totalServices = $stmt->fetchColumn();
|
||||
$totalPages = ceil($totalServices / $limit);
|
||||
|
||||
// Fetch Data
|
||||
$query = "
|
||||
SELECT s.*, d.name_$lang as department_name
|
||||
FROM services s
|
||||
LEFT JOIN departments d ON s.department_id = d.id
|
||||
$where
|
||||
ORDER BY s.id DESC
|
||||
LIMIT $limit OFFSET $offset";
|
||||
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute($params);
|
||||
$services = $stmt->fetchAll();
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h3 class="fw-bold text-secondary"><?php echo __('services'); ?></h3>
|
||||
<button class="btn btn-primary shadow-sm" data-bs-toggle="modal" data-bs-target="#addServiceModal">
|
||||
<i class="bi bi-plus-lg me-1"></i> <?php echo __('add_service'); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Search Bar -->
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<form method="GET" action="services.php" class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0 text-muted"><i class="bi bi-search"></i></span>
|
||||
<input type="text" name="name" class="form-control bg-light border-start-0" placeholder="<?php echo __('search_by_name'); ?>" value="<?php echo htmlspecialchars($search_name); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select name="department_id" class="form-select bg-light">
|
||||
<option value=""><?php echo __('department'); ?> (<?php echo __('all'); ?>)</option>
|
||||
<?php foreach ($all_departments as $dept): ?>
|
||||
<option value="<?php echo $dept['id']; ?>" <?php echo $search_dept == $dept['id'] ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($dept['name_'.$lang]); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="submit" class="btn btn-secondary w-100"><?php echo __('search'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light text-secondary">
|
||||
<tr>
|
||||
<th class="px-4 py-3"><?php echo __('name'); ?></th>
|
||||
<th class="py-3"><?php echo __('department'); ?></th>
|
||||
<th class="py-3"><?php echo __('price'); ?></th>
|
||||
<th class="py-3"><?php echo __('status'); ?></th>
|
||||
<th class="py-3 text-end px-4"><?php echo __('actions'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($services)): ?>
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-5 text-muted">
|
||||
<i class="bi bi-gear-wide-connected display-4 d-block mb-3"></i>
|
||||
<?php echo __('no_services_found'); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($services as $s): ?>
|
||||
<tr>
|
||||
<td class="px-4">
|
||||
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($s['name_'.$lang]); ?></div>
|
||||
<small class="text-muted"><?php echo htmlspecialchars($s['name_'.($lang == 'en' ? 'ar' : 'en')]); ?></small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-primary bg-opacity-10 text-primary border border-primary border-opacity-25 px-2 py-1">
|
||||
<?php echo htmlspecialchars($s['department_name'] ?: '-'); ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="fw-bold text-success">
|
||||
<?php echo number_format($s['price'], 2); ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($s['is_active']): ?>
|
||||
<span class="badge bg-success bg-opacity-10 text-success border border-success border-opacity-25 px-2 py-1">
|
||||
<i class="bi bi-check-circle me-1"></i> <?php echo __('active'); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-secondary bg-opacity-10 text-secondary border border-secondary border-opacity-25 px-2 py-1">
|
||||
<i class="bi bi-slash-circle me-1"></i> <?php echo __('inactive'); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-end px-4">
|
||||
<div class="btn-group shadow-sm border rounded bg-white">
|
||||
<button class="btn btn-link text-primary py-1 px-2 border-end"
|
||||
onclick="showEditServiceModal(<?php echo htmlspecialchars(json_encode($s, JSON_UNESCAPED_UNICODE)); ?>)"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('edit'); ?>">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
<button class="btn btn-link text-danger py-1 px-2"
|
||||
onclick="showDeleteServiceModal(<?php echo $s['id']; ?>)"
|
||||
data-bs-toggle="tooltip" title="<?php echo __('delete'); ?>">
|
||||
<i class="bi bi-trash3"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<?php if ($totalPages > 1): ?>
|
||||
<div class="d-flex justify-content-between align-items-center p-3 border-top">
|
||||
<div class="text-muted small">
|
||||
<?php echo __('showing'); ?> <?php echo $offset + 1; ?> - <?php echo min($offset + $limit, $totalServices); ?> <?php echo __('of'); ?> <?php echo $totalServices; ?>
|
||||
</div>
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination pagination-sm mb-0">
|
||||
<li class="page-item <?php echo $page <= 1 ? 'disabled' : ''; ?>">
|
||||
<a class="page-link" href="?page=<?php echo $page - 1; ?>&name=<?php echo urlencode($search_name); ?>&department_id=<?php echo urlencode($search_dept); ?>" aria-label="Previous">
|
||||
<span aria-hidden="true">«</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
|
||||
<li class="page-item <?php echo $page == $i ? 'active' : ''; ?>">
|
||||
<a class="page-link" href="?page=<?php echo $i; ?>&name=<?php echo urlencode($search_name); ?>&department_id=<?php echo urlencode($search_dept); ?>">
|
||||
<?php echo $i; ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endfor; ?>
|
||||
<li class="page-item <?php echo $page >= $totalPages ? 'disabled' : ''; ?>">
|
||||
<a class="page-link" href="?page=<?php echo $page + 1; ?>&name=<?php echo urlencode($search_name); ?>&department_id=<?php echo urlencode($search_dept); ?>" aria-label="Next">
|
||||
<span aria-hidden="true">»</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Service Modal -->
|
||||
<div class="modal fade" id="addServiceModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" action="services.php" class="modal-content">
|
||||
<input type="hidden" name="action" value="add_service">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?php echo __('add_service'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('name_en'); ?></label>
|
||||
<input type="text" name="name_en" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('name_ar'); ?></label>
|
||||
<input type="text" name="name_ar" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('department'); ?></label>
|
||||
<select name="department_id" class="form-select" required>
|
||||
<option value=""><?php echo __('select_department'); ?></option>
|
||||
<?php foreach ($all_departments as $dept): ?>
|
||||
<option value="<?php echo $dept['id']; ?>">
|
||||
<?php echo htmlspecialchars($dept['name_'.$lang]); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('price'); ?></label>
|
||||
<input type="number" name="price" step="0.01" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="addServiceActive" checked>
|
||||
<label class="form-check-label" for="addServiceActive"><?php echo __('active'); ?></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('cancel'); ?></button>
|
||||
<button type="submit" class="btn btn-primary"><?php echo __('save'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Service Modal -->
|
||||
<div class="modal fade" id="editServiceModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" action="services.php" class="modal-content">
|
||||
<input type="hidden" name="action" value="edit_service">
|
||||
<input type="hidden" name="id" id="editServiceId">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?php echo __('edit_service'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('name_en'); ?></label>
|
||||
<input type="text" name="name_en" id="editServiceNameEn" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('name_ar'); ?></label>
|
||||
<input type="text" name="name_ar" id="editServiceNameAr" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('department'); ?></label>
|
||||
<select name="department_id" id="editServiceDeptId" class="form-select" required>
|
||||
<option value=""><?php echo __('select_department'); ?></option>
|
||||
<?php foreach ($all_departments as $dept): ?>
|
||||
<option value="<?php echo $dept['id']; ?>">
|
||||
<?php echo htmlspecialchars($dept['name_'.$lang]); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"><?php echo __('price'); ?></label>
|
||||
<input type="number" name="price" id="editServicePrice" step="0.01" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="editServiceActive">
|
||||
<label class="form-check-label" for="editServiceActive"><?php echo __('active'); ?></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('cancel'); ?></button>
|
||||
<button type="submit" class="btn btn-primary"><?php echo __('save_changes'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Service Modal -->
|
||||
<div class="modal fade" id="deleteServiceModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST" action="services.php" class="modal-content">
|
||||
<input type="hidden" name="action" value="delete_service">
|
||||
<input type="hidden" name="id" id="deleteServiceId">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><?php echo __('delete_service'); ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p><?php echo __('are_you_sure_delete_service'); ?></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('cancel'); ?></button>
|
||||
<button type="submit" class="btn btn-danger"><?php echo __('delete'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showEditServiceModal(service) {
|
||||
document.getElementById('editServiceId').value = service.id;
|
||||
document.getElementById('editServiceNameEn').value = service.name_en;
|
||||
document.getElementById('editServiceNameAr').value = service.name_ar;
|
||||
document.getElementById('editServiceDeptId').value = service.department_id;
|
||||
document.getElementById('editServicePrice').value = service.price;
|
||||
document.getElementById('editServiceActive').checked = service.is_active == 1;
|
||||
|
||||
var modal = new bootstrap.Modal(document.getElementById('editServiceModal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
function showDeleteServiceModal(id) {
|
||||
document.getElementById('deleteServiceId').value = id;
|
||||
var modal = new bootstrap.Modal(document.getElementById('deleteServiceModal'));
|
||||
modal.show();
|
||||
}
|
||||
</script>
|
||||
30
lang.php
30
lang.php
@ -2,6 +2,7 @@
|
||||
$translations = [
|
||||
'en' => [
|
||||
'dashboard' => 'Dashboard',
|
||||
'patient_number' => 'Patient Number',
|
||||
'patients' => 'Patients',
|
||||
'doctors' => 'Doctors',
|
||||
'appointments' => 'Appointments',
|
||||
@ -253,6 +254,19 @@ $translations = [
|
||||
'civil_id' => 'Civil ID',
|
||||
'nationality' => 'Nationality',
|
||||
'city' => 'City',
|
||||
'services' => 'Services',
|
||||
'add_service' => 'Add Service',
|
||||
'edit_service' => 'Edit Service',
|
||||
'delete_service' => 'Delete Service',
|
||||
'service_added_successfully' => 'Service added successfully',
|
||||
'service_updated_successfully' => 'Service updated successfully',
|
||||
'service_deleted_successfully' => 'Service deleted successfully',
|
||||
'search_by_name' => 'Search by Name',
|
||||
'no_services_found' => 'No services found',
|
||||
'select_department' => 'Select Department',
|
||||
'active' => 'Active',
|
||||
'inactive' => 'Inactive',
|
||||
'are_you_sure_delete_service' => 'Are you sure you want to delete this service?',
|
||||
],
|
||||
'ar' => [
|
||||
'attachment' => 'المرفق',
|
||||
@ -268,6 +282,7 @@ $translations = [
|
||||
'laboratory_inquiries' => 'استفسارات المختبر',
|
||||
'xray_inquiries' => 'استفسارات الأشعة',
|
||||
'dashboard' => 'لوحة القيادة',
|
||||
'patient_number' => 'رقم المريض',
|
||||
'patients' => 'المرضى',
|
||||
'doctors' => 'الأطباء',
|
||||
'appointments' => 'المواعيد',
|
||||
@ -509,5 +524,18 @@ $translations = [
|
||||
'civil_id' => 'الرقم المدني',
|
||||
'nationality' => 'الجنسية',
|
||||
'city' => 'المدينة',
|
||||
'services' => 'الخدمات',
|
||||
'add_service' => 'إضافة خدمة',
|
||||
'edit_service' => 'تعديل خدمة',
|
||||
'delete_service' => 'حذف خدمة',
|
||||
'service_added_successfully' => 'تم إضافة الخدمة بنجاح',
|
||||
'service_updated_successfully' => 'تم تحديث الخدمة بنجاح',
|
||||
'service_deleted_successfully' => 'تم حذف الخدمة بنجاح',
|
||||
'search_by_name' => 'البحث بالاسم',
|
||||
'no_services_found' => 'لم يتم العثور على خدمات',
|
||||
'select_department' => 'اختر القسم',
|
||||
'active' => 'نشط',
|
||||
'inactive' => 'غير نشط',
|
||||
'are_you_sure_delete_service' => 'هل أنت متأكد أنك تريد حذف هذه الخدمة؟',
|
||||
]
|
||||
];
|
||||
];
|
||||
|
||||
151
print_patient_label.php
Normal file
151
print_patient_label.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$db = db();
|
||||
$lang = $_SESSION['lang'] ?? 'en';
|
||||
|
||||
$patient_id = $_GET['id'] ?? 0;
|
||||
|
||||
if (!$patient_id) {
|
||||
die("Invalid Patient ID");
|
||||
}
|
||||
|
||||
// Fetch Patient
|
||||
$stmt = $db->prepare("SELECT * FROM patients WHERE id = ?");
|
||||
$stmt->execute([$patient_id]);
|
||||
$patient = $stmt->fetch();
|
||||
|
||||
if (!$patient) {
|
||||
die("Patient not found");
|
||||
}
|
||||
|
||||
// Fetch Settings
|
||||
$stmt = $db->query("SELECT setting_key, setting_value FROM settings");
|
||||
$settings = [];
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$settings[$row['setting_key']] = $row['setting_value'];
|
||||
}
|
||||
|
||||
$hospital_name = $settings['company_name'] ?? 'Hospital Management System';
|
||||
$patient_no = str_pad($patient['id'], 6, '0', STR_PAD_LEFT);
|
||||
$age = calculate_age($patient['dob']);
|
||||
$gender_raw = strtolower($patient['gender'] ?? '');
|
||||
$gender = $gender_raw == 'male' ? __('male') : ($gender_raw == 'female' ? __('female') : __('other'));
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="<?php echo $lang; ?>" dir="<?php echo $lang == 'ar' ? 'rtl' : 'ltr'; ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Patient Label - <?php echo $patient_no; ?></title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.label-container {
|
||||
width: 40mm;
|
||||
height: 25mm;
|
||||
margin: 20px auto;
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
padding: 1mm;
|
||||
}
|
||||
.hospital-name {
|
||||
font-weight: bold;
|
||||
font-size: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.patient-name {
|
||||
font-weight: bold;
|
||||
font-size: 9px;
|
||||
margin: 1px 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
.meta-info {
|
||||
font-size: 7px;
|
||||
color: #000;
|
||||
line-height: 1.1;
|
||||
}
|
||||
#barcode {
|
||||
max-width: 95%;
|
||||
height: 8mm; /* Reduced height for barcode */
|
||||
}
|
||||
|
||||
@media print {
|
||||
@page {
|
||||
size: 40mm 25mm;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
margin: 0;
|
||||
}
|
||||
.label-container {
|
||||
margin: 0;
|
||||
border: none;
|
||||
width: 40mm;
|
||||
height: 25mm;
|
||||
page-break-inside: avoid;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.no-print {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="window.print()">
|
||||
|
||||
<div class="no-print" style="text-align: center; margin-top: 10px;">
|
||||
<button onclick="window.print()" style="padding: 10px 20px; cursor: pointer;">Print Label</button>
|
||||
<button onclick="window.close()" style="padding: 10px 20px; cursor: pointer;">Close</button>
|
||||
</div>
|
||||
|
||||
<div class="label-container">
|
||||
<div class="hospital-name"><?php echo htmlspecialchars($hospital_name); ?></div>
|
||||
|
||||
<svg id="barcode"></svg>
|
||||
|
||||
<div class="patient-name"><?php echo htmlspecialchars($patient['name']); ?></div>
|
||||
<div class="meta-info">
|
||||
Age: <?php echo $age; ?> | DOB: <?php echo $patient['dob']; ?> <br>
|
||||
<?php echo $gender; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
JsBarcode("#barcode", "<?php echo $patient_no; ?>", {
|
||||
format: "CODE128",
|
||||
width: 1, /* Thinner bars */
|
||||
height: 25, /* Shorter bars */
|
||||
displayValue: true,
|
||||
fontSize: 8,
|
||||
marginTop: 1,
|
||||
marginBottom: 1,
|
||||
margin: 0
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
17
services.php
Normal file
17
services.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
// Session check
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$section = 'services';
|
||||
$title = __('services');
|
||||
|
||||
require_once __DIR__ . '/includes/layout/header.php';
|
||||
require_once __DIR__ . '/includes/pages/services.php';
|
||||
require_once __DIR__ . '/includes/layout/footer.php';
|
||||
Loading…
x
Reference in New Issue
Block a user