262 lines
15 KiB
PHP
262 lines
15 KiB
PHP
<?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>
|