Initial commit

This commit is contained in:
Porawit Dongwang
2026-09-16 23:20:08 +07:00
commit 0041668dbb
32577 changed files with 3687927 additions and 0 deletions
@@ -0,0 +1,261 @@
<?php
require_once 'config.php';
checkLogin();
$topbar_text = getSystemSetting('topbar_text', 'ระบบตรวจสอบข้อมูล HOSxP');
$footer_text = getSystemSetting('footer_text', 'หน่วยงานสุขภาพดิจิทัล โรงพยาบาลเกาะสมุย');
// Fetch available profiles
$log_db = getDB(DB_LOG_HOST, DB_LOG_NAME, DB_LOG_USER, DB_LOG_PASS);
$stmt = $log_db->query("SELECT id, profile_name FROM export_profiles ORDER BY profile_name ASC");
$profiles = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>นำเข้าและตรวจสอบข้อมูล - <?php echo htmlspecialchars($topbar_text); ?></title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600&display=swap" rel="stylesheet">
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<link rel="icon" href="assets/img/logo.png" type="image/png">
<style>
body { font-family: 'Sarabun', sans-serif; }
/* Custom DataTables Styling */
.dataTables_wrapper { padding: 1rem 0; }
.dataTables_wrapper .dataTables_filter input {
border: 1px solid #d1d5db; border-radius: 0.5rem; padding: 0.35rem 0.75rem; margin-left: 0.5rem; outline: none; transition: all 0.2s;
}
.dataTables_wrapper .dataTables_filter input:focus {
border-color: #10b981; box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2);
}
.dataTables_wrapper .dataTables_length select {
border: 1px solid #d1d5db; border-radius: 0.5rem; padding: 0.25rem 1.5rem 0.25rem 0.75rem; margin: 0 0.5rem; outline: none;
}
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_length {
margin-bottom: 1rem;
}
table.dataTable.no-footer { border-bottom: 1px solid #e5e7eb; margin-top: 1rem !important; margin-bottom: 1rem !important; }
table.dataTable thead th {
border-bottom: 2px solid #e5e7eb; background-color: #f3f4f6; color: #374151; font-weight: 600; padding: 0.75rem 1rem; white-space: nowrap; text-align: center;
}
table.dataTable tbody td {
border-bottom: 1px solid #f3f4f6; padding: 1rem; color: #4b5563; vertical-align: top;
}
table.dataTable tbody tr:hover { background-color: #f9fafb; }
.dataTables_wrapper .dataTables_paginate .paginate_button {
padding: 0.35rem 0.85rem; margin-left: 0.25rem; border: 1px solid #d1d5db; border-radius: 0.5rem; background: white; color: #374151 !important; transition: all 0.2s; font-size: 0.875rem;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
background: #10b981 !important; color: white !important; border-color: #10b981; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.dataTables_wrapper .dataTables_paginate .paginate_button:not(.current):hover {
background: #f3f4f6 !important; border-color: #d1d5db; color: #111827 !important;
}
.dataTables_wrapper .dataTables_info { color: #6b7280; font-size: 0.875rem; padding-top: 0.85rem; }
</style>
</head>
<body class="bg-gray-100 flex flex-col min-h-screen">
<?php include 'topbar.php'; ?>
<div class="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
<!-- Upload Card -->
<div class="bg-white shadow rounded-lg mb-8">
<div class="px-6 py-5 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">นำเข้าไฟล์ Excel เพื่อตรวจสอบ</h3>
<p class="mt-1 text-sm text-gray-500">เลือกชุดข้อมูลและไฟล์ Excel ที่ต้องการตรวจสอบกับฐานข้อมูล HOSxP</p>
</div>
<div class="px-6 py-5">
<form id="uploadForm" enctype="multipart/form-data">
<div class="flex flex-col md:flex-row items-end gap-4">
<div class="w-full md:w-1/2">
<label class="block text-sm font-medium text-gray-700 mb-1">ชุดข้อมูล (Profile)</label>
<select name="profile_id" id="profile_id" required class="block w-full border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-green-500 focus:border-green-500 sm:text-sm bg-white h-[42px]">
<option value="">-- เลือกชุดข้อมูล --</option>
<?php foreach($profiles as $p): ?>
<option value="<?php echo htmlspecialchars($p['id']); ?>"><?php echo htmlspecialchars($p['profile_name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="w-full md:flex-grow">
<label class="block text-sm font-medium text-gray-700 mb-1">ไฟล์ Excel</label>
<input type="file" id="excel_file" name="excel_file" accept=".xlsx, .xls" required class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:border-0 file:text-sm file:font-semibold file:bg-green-50 file:text-green-700 hover:file:bg-green-100 border border-gray-300 rounded-md bg-white h-[42px]">
</div>
<div class="w-full md:w-auto flex-shrink-0">
<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition duration-150 h-[42px] whitespace-nowrap" id="btnUpload">
อัปโหลดและประมวลผล
</button>
</div>
</div>
</form>
<div id="loadingIndicator" class="hidden mt-4 text-center text-blue-600">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
กำลังประมวลผลข้อมูล...
</div>
<div id="uploadMessage" class="mt-4 text-sm hidden"></div>
</div>
</div>
<!-- Results Card -->
<div id="resultsCard" class="bg-white shadow rounded-lg hidden">
<div class="px-6 py-5 border-b border-gray-200 flex justify-between items-center">
<h3 class="text-lg font-medium text-gray-900">ผลการตรวจสอบ</h3>
<form action="export.php" method="POST" id="exportForm">
<input type="hidden" name="export_data" id="exportData">
<input type="hidden" name="original_filename" id="originalFilename">
<button type="submit" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline transition duration-150 flex items-center text-sm">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
ส่งออกเป็น Excel
</button>
</form>
</div>
<div class="px-6 py-5 overflow-x-auto">
<table id="resultsTable" class="display w-full text-sm">
<thead id="resultsHead">
<tr>
<!-- Headers will be generated dynamically -->
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<?php include 'footer.php'; ?>
<!-- jQuery, DataTables, and SweetAlert2 -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
let table;
$(document).ready(function() {
// DataTable will be initialized after upload is complete
$('#uploadForm').on('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
$('#btnUpload').prop('disabled', true).addClass('opacity-50');
$('#loadingIndicator').removeClass('hidden');
$('#uploadMessage').addClass('hidden');
$('#resultsCard').addClass('hidden');
$.ajax({
url: 'process.php',
type: 'POST',
data: formData,
success: function(response) {
$('#btnUpload').prop('disabled', false).removeClass('opacity-50');
$('#loadingIndicator').addClass('hidden');
try {
var res = typeof response === 'string' ? JSON.parse(response) : response;
if (res.status === 'success') {
Swal.fire({
icon: 'success',
title: 'ประมวลผลสำเร็จ',
text: res.message,
confirmButtonColor: '#10b981'
});
if(res.data && res.data.length > 0) {
// Destroy old table
if ($.fn.DataTable.isDataTable('#resultsTable')) {
table.destroy();
$('#resultsTable').empty();
}
// Generate Columns from data keys
let columns = [];
let firstRow = res.data[0];
for (let key in firstRow) {
columns.push({
title: key.toUpperCase(),
data: key,
className: 'whitespace-nowrap'
});
}
// Re-initialize DataTable with dynamic columns
table = $('#resultsTable').DataTable({
data: res.data,
columns: columns,
"language": {
"url": "//cdn.datatables.net/plug-ins/1.13.6/i18n/th.json"
},
destroy: true
});
$('#resultsCard').removeClass('hidden');
// Store data for export
$('#exportData').val(JSON.stringify(res.data));
// Store original filename for export
var originalName = $('#excel_file').prop('files')[0].name;
$('#originalFilename').val(originalName);
} else {
Swal.fire({
icon: 'warning',
title: 'ประมวลผลเสร็จสิ้น',
text: 'แต่ไม่พบข้อมูลที่ตรงกันในฐานข้อมูล HOSxP',
confirmButtonColor: '#f59e0b'
});
}
} else {
Swal.fire({
icon: 'error',
title: 'เกิดข้อผิดพลาด',
text: res.message,
confirmButtonColor: '#ef4444'
});
}
} catch (error) {
Swal.fire({
icon: 'error',
title: 'ระบบขัดข้อง',
text: 'เกิดข้อผิดพลาดในการประมวลผล (Invalid JSON)',
confirmButtonColor: '#ef4444'
});
console.error(error, response);
}
},
error: function(jqXHR, textStatus, errorThrown) {
$('#btnUpload').prop('disabled', false).removeClass('opacity-50');
$('#loadingIndicator').addClass('hidden');
var errorMsg = 'เกิดข้อผิดพลาดในการส่งข้อมูล (HTTP ' + jqXHR.status + ' ' + errorThrown + ')';
Swal.fire({
icon: 'error',
title: 'การเชื่อมต่อผิดพลาด',
html: errorMsg + (jqXHR.responseText ? `<br><span class="text-xs text-red-500">${jqXHR.responseText}</span>` : ''),
confirmButtonColor: '#ef4444'
});
},
cache: false,
contentType: false,
processData: false
});
});
});
</script>
</body>
</html>