feat: add dynamic hospital branches, update contact page hero and navigation, and implement branch management template.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
BIN
Binary file not shown.
Binary file not shown.
+12
@@ -127,6 +127,18 @@ public class GlobalControllerAdvice {
|
||||
return settingService.getValue("theme_mod_customCss", "");
|
||||
}
|
||||
|
||||
@ModelAttribute("hospitalBranches")
|
||||
public java.util.List<java.util.Map<String, Object>> getHospitalBranches() {
|
||||
String defaultJson = "[{\"id\":\"sis-can-tho\",\"name\":\"Bệnh viện Đa khoa Quốc Tế S.I.S Cần Thơ\",\"address\":\"397 Nguyễn Văn Cừ, P. An Bình, TP. Cần Thơ\",\"phone\":\"18001115\",\"email\":\"cskh@dotquy.vn\",\"website\":\"https://sisvietnam.vn/\",\"mapUrl\":\"https://maps.google.com/maps?q=Bệnh%20viện%20Đa%20khoa%20Quốc%20Tế%20S.I.S%20Cần%20Thơ&t=&z=16&ie=UTF8&iwloc=&output=embed\"},{\"id\":\"sis-da-nang\",\"name\":\"Bệnh viện Đa khoa Quốc Tế S.I.S Đà Nẵng\",\"address\":\"201 Nguyễn Chí Thanh, Phường 12, Quận 5, TP. Hồ Chí Minh\",\"phone\":\"(84.28) 3955 5548\",\"email\":\"bvdaihoccoso2@umc.edu.vn\",\"website\":\"#\",\"mapUrl\":\"#\"},{\"id\":\"sis-nha-trang\",\"name\":\"Bệnh viện Đa khoa Quốc Tế S.I.S Nha Trang\",\"address\":\"221B Hoàng Văn Thụ, Phường 8, Q. Phú Nhuận, TP. Hồ Chí Minh\",\"phone\":\"(84.28) 3842 0070\",\"email\":\"bvdaihoccoso3@umc.edu.vn\",\"website\":\"#\",\"mapUrl\":\"#\"}]";
|
||||
String json = settingService.getValue("hospital_branches", defaultJson);
|
||||
if (json.trim().isEmpty()) json = defaultJson;
|
||||
try {
|
||||
return new com.fasterxml.jackson.databind.ObjectMapper().readValue(json, new com.fasterxml.jackson.core.type.TypeReference<java.util.List<java.util.Map<String, Object>>>() {});
|
||||
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private java.util.List<com.sisvietnamvn.web.service.dto.WidgetDto> getWidgets(String area) {
|
||||
String json = settingService.getValue("theme_widgets_" + area, "[]");
|
||||
try {
|
||||
|
||||
+13
@@ -139,4 +139,17 @@ public class ManageSettingController {
|
||||
public String savePrivacySettings(@RequestParam Map<String, String> allParams, RedirectAttributes redirectAttributes) {
|
||||
return saveSettings(allParams, redirectAttributes, "privacy");
|
||||
}
|
||||
|
||||
// --- Branches Settings ---
|
||||
|
||||
@GetMapping("/branches")
|
||||
public String showBranchesSettings(Model model) {
|
||||
addSettingsToModel(model);
|
||||
return "manage/settings/branches";
|
||||
}
|
||||
|
||||
@PostMapping("/branches/save")
|
||||
public String saveBranchesSettings(@RequestParam Map<String, String> allParams, RedirectAttributes redirectAttributes) {
|
||||
return saveSettings(allParams, redirectAttributes, "branches");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -13,9 +13,11 @@ import java.util.Map;
|
||||
public class CoreSettingsRegistrar {
|
||||
|
||||
private final AdminSettingsManager settingsManager;
|
||||
private final AdminMenuManager adminMenuManager;
|
||||
|
||||
public CoreSettingsRegistrar(AdminSettingsManager settingsManager) {
|
||||
public CoreSettingsRegistrar(AdminSettingsManager settingsManager, AdminMenuManager adminMenuManager) {
|
||||
this.settingsManager = settingsManager;
|
||||
this.adminMenuManager = adminMenuManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@@ -56,6 +58,9 @@ public class CoreSettingsRegistrar {
|
||||
settingsManager.registerSetting(page, "date_format", "F j, Y");
|
||||
|
||||
// --- Menu Registration for Modules ---
|
||||
// Register the "Branches" management page under Settings
|
||||
adminMenuManager.addOptionsPage("Quản lý Chi nhánh", "Chi nhánh", "manage_options", "branches");
|
||||
|
||||
// (Snippets menu is now statically defined under Components)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,4 +562,28 @@ body, h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
.widget-sidebar-area {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#map-section .branch-text {
|
||||
color: #111827; /* text-gray-900 */
|
||||
}
|
||||
|
||||
#map-section .branch-card {
|
||||
background-color: var(--color-white, #ffffff);
|
||||
}
|
||||
|
||||
/* Active State */
|
||||
#map-section .branch-card.active {
|
||||
background-color: var(--color-old-brick); /* bg-primary-600 */
|
||||
}
|
||||
#map-section .branch-card.active .branch-title,
|
||||
#map-section .branch-card.active .branch-text,
|
||||
#map-section .branch-card.active .branch-icon {
|
||||
color: #ffffff; /* text-white */
|
||||
}
|
||||
|
||||
/* Hero Background Override */
|
||||
.bg-linear-hero {
|
||||
background: linear-gradient(180deg, transparent, #000) !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/manage-layout}">
|
||||
<head>
|
||||
<title>Quản lý Chi nhánh</title>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<h1 class="h3 mb-4 text-gray-800">Quản lý Chi nhánh</h1>
|
||||
|
||||
<div th:if="${successMessage}" class="alert alert-success alert-dismissible fade show">
|
||||
<span th:text="${successMessage}"></span>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div th:if="${errorMessage}" class="alert alert-danger alert-dismissible fade show">
|
||||
<span th:text="${errorMessage}"></span>
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body">
|
||||
<form th:action="@{/manage/settings/branches/save}" method="post" id="branchesForm">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
<input type="hidden" name="hospital_branches" id="hospital_branches_input" />
|
||||
|
||||
<!-- Raw JSON from backend to initialize JS -->
|
||||
<script th:inline="javascript">
|
||||
var initialBranches = /*[[${settings['hospital_branches']}]]*/ '[]';
|
||||
if (!initialBranches || initialBranches === 'null') initialBranches = '[]';
|
||||
var branchesData = [];
|
||||
try {
|
||||
branchesData = JSON.parse(initialBranches);
|
||||
} catch(e) {
|
||||
branchesData = [];
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="branches-container">
|
||||
<!-- JS will render branches here -->
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-success mb-4" onclick="addBranch()">+ Thêm chi nhánh</button>
|
||||
|
||||
<hr>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary">Lưu thay đổi</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function escapeHtml(unsafe) {
|
||||
return (unsafe || '').toString()
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function renderBranches() {
|
||||
const container = document.getElementById('branches-container');
|
||||
container.innerHTML = '';
|
||||
branchesData.forEach((branch, index) => {
|
||||
const html = `
|
||||
<div class="card mb-3 border-left-primary">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="m-0 font-weight-bold text-primary">Chi nhánh ${index + 1}</h5>
|
||||
<div>
|
||||
<button type="button" class="btn btn-secondary btn-sm mr-2" onclick="moveUp(${index})" ${index === 0 ? 'disabled' : ''}>Lên</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm mr-2" onclick="moveDown(${index})" ${index === branchesData.length - 1 ? 'disabled' : ''}>Xuống</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" onclick="removeBranch(${index})">Xóa</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 form-group">
|
||||
<label>Tên chi nhánh</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.name)}" onchange="updateBranch(${index}, 'name', this.value)" required>
|
||||
</div>
|
||||
<div class="col-md-6 form-group">
|
||||
<label>ID (Mã chi nhánh)</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.id)}" onchange="updateBranch(${index}, 'id', this.value)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 form-group">
|
||||
<label>Địa chỉ</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.address)}" onchange="updateBranch(${index}, 'address', this.value)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 form-group">
|
||||
<label>Điện thoại</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.phone)}" onchange="updateBranch(${index}, 'phone', this.value)">
|
||||
</div>
|
||||
<div class="col-md-4 form-group">
|
||||
<label>Email</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.email)}" onchange="updateBranch(${index}, 'email', this.value)">
|
||||
</div>
|
||||
<div class="col-md-4 form-group">
|
||||
<label>Website</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.website)}" onchange="updateBranch(${index}, 'website', this.value)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 form-group">
|
||||
<label>Google Maps Embed URL</label>
|
||||
<input type="text" class="form-control" value="${escapeHtml(branch.mapUrl)}" onchange="updateBranch(${index}, 'mapUrl', this.value)">
|
||||
<small class="text-muted">Lấy URL trong thuộc tính src của mã nhúng Google Maps iframe.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.insertAdjacentHTML('beforeend', html);
|
||||
});
|
||||
}
|
||||
|
||||
function addBranch() {
|
||||
branchesData.push({
|
||||
id: '', name: '', address: '', phone: '', email: '', website: '', mapUrl: ''
|
||||
});
|
||||
renderBranches();
|
||||
}
|
||||
|
||||
function removeBranch(index) {
|
||||
if(confirm('Bạn có chắc muốn xóa chi nhánh này?')) {
|
||||
branchesData.splice(index, 1);
|
||||
renderBranches();
|
||||
}
|
||||
}
|
||||
|
||||
function updateBranch(index, field, value) {
|
||||
branchesData[index][field] = value;
|
||||
}
|
||||
|
||||
function moveUp(index) {
|
||||
if (index > 0) {
|
||||
const temp = branchesData[index - 1];
|
||||
branchesData[index - 1] = branchesData[index];
|
||||
branchesData[index] = temp;
|
||||
renderBranches();
|
||||
}
|
||||
}
|
||||
|
||||
function moveDown(index) {
|
||||
if (index < branchesData.length - 1) {
|
||||
const temp = branchesData[index + 1];
|
||||
branchesData[index + 1] = branchesData[index];
|
||||
branchesData[index] = temp;
|
||||
renderBranches();
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('branchesForm').addEventListener('submit', function(e) {
|
||||
document.getElementById('hospital_branches_input').value = JSON.stringify(branchesData);
|
||||
});
|
||||
|
||||
// Initial render
|
||||
renderBranches();
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -9,16 +9,73 @@
|
||||
|
||||
<body>
|
||||
<div layout:fragment="content" id="bvdhyd-contact">
|
||||
<!-- Hero Section -->
|
||||
<section class="overflow-hidden relative w-full bg-white xl:h-[580px] md:h-[550px] h-[calc(100svh-122px-56px)]">
|
||||
<div class="bg-linear-hero absolute inset-x-0 bottom-0 top-[20%] z-10"></div>
|
||||
<img alt="Bệnh viện" fetchpriority="high" loading="eager" class="absolute inset-0 w-full h-full object-cover max-md:hidden" src="https://bvdaihoc.com.vn/uploads/Demo/to%CC%80a%20nha%CC%80%20tru%CC%9Bo%CC%9B%CC%80ng%20vie%CC%A3%CC%82n%20la%CC%80m%20mo%CC%9B%CC%80.jpg" />
|
||||
</section>
|
||||
<!-- Content Top (Banner 3 lớp kết hợp Title bài Post) -->
|
||||
<div class="content-top">
|
||||
<div class="lc--layout-container lc--full">
|
||||
<div class="l--layout l--full">
|
||||
<div class="lr--layout-region lr--main">
|
||||
<div class="cc--component-container cc--homepage-hero">
|
||||
<div class="c--component c--homepage-hero"
|
||||
style="position: relative; overflow: hidden; height: 100vh; max-height: 38.125rem;">
|
||||
|
||||
<!-- ====== ẢNH NỀN ====== -->
|
||||
<img class="static-fallback-image" src="http://localhost:8080/uploads/2026/07/198e5233-0e9f-4618-8111-32c4df8ae318.jpg" th:alt="${page.title}" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1;" />
|
||||
|
||||
<!-- ====== TEXT OVERLAY ====== -->
|
||||
<div class="text-container centered"
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 4; pointer-events: none; display: flex; align-items: center; justify-content: center; background-color: rgba(0, 0, 0, 0.4);">
|
||||
<div class="slide-text-container-inner" style="pointer-events: auto; text-align: center; padding: 20px;">
|
||||
<div class="f--field f--page-title">
|
||||
<h1 class="hero-post-title" th:text="${page.title}">Liên hệ</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.hero-post-title {
|
||||
color: white;
|
||||
text-shadow: 0 2px 5px rgba(0,0,0,0.7);
|
||||
line-height: 1.2;
|
||||
margin: 0 auto;
|
||||
max-width: 1000px;
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.hero-post-title { font-size: 2.8rem; max-width: 800px; }
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.hero-post-title { font-size: 2.2rem; max-width: 600px; }
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.hero-post-title { font-size: 1.8rem; }
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sticky Navigation Bar -->
|
||||
<div class="bg-white shadow-md">
|
||||
<div class="container relative max-md:px-2 mx-auto">
|
||||
<div class="flex overflow-x-auto scrollbar-hide xl:justify-center" style="scroll-behavior: smooth;">
|
||||
<div class="flex space-x-8 py-4 px-4 md:px-0">
|
||||
<a data-tab-index="0" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/gioi-thieu-tong-quan">Giới thiệu tổng quan</a>
|
||||
<a data-tab-index="1" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/lich-su-benh-vien">Lịch sử hình thành</a>
|
||||
<a data-tab-index="2" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/tam-nhin-su-menh-gia-tri-cot-loi">Tầm nhìn - Sứ mệnh - Giá trị cốt lõi</a>
|
||||
<a data-tab-index="3" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/doi-ngu-lanh-dao">Ban lãnh đạo</a>
|
||||
<a data-tab-index="4" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/cac-don-vi">Các đơn vị</a>
|
||||
<a data-tab-index="5" class="whitespace-nowrap title-2 transition-colors duration-200 border-transparent text-gray-600 hover:text-primary-600" href="https://bvdaihoc.com.vn/thanh-tuu-va-giai-thuong">Thành tựu và giải thưởng</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<section class="xl:py-16 md:py-12 py-8 md:scroll-mt-[186px] relative z-20" id="map-section">
|
||||
<div class="container mx-auto px-4 lg:px-10 space-y-4 md:space-y-6 xl:space-y-8 max-w-7xl">
|
||||
<h1 th:text="${page.title}" class="text-primary-600 display-7 text-center uppercase">Liên hệ</h1>
|
||||
|
||||
<div class="grid grid-cols-12 gap-6">
|
||||
<!-- Left Sidebar (Branches) -->
|
||||
@@ -38,53 +95,16 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Hidden data -->
|
||||
<div id="postContentRaw" style="display:none;" th:text="${page.content}"></div>
|
||||
|
||||
<script>
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const rawData = document.getElementById("postContentRaw").textContent;
|
||||
const branchListContainer = document.getElementById("branch-list");
|
||||
const mapIframe = document.getElementById("map-iframe");
|
||||
|
||||
try {
|
||||
const data = JSON.parse(rawData);
|
||||
let branches = [];
|
||||
let currentBranch = null;
|
||||
// Inject branches from global settings via Thymeleaf
|
||||
const branches = /*[[${hospitalBranches}]]*/ [];
|
||||
|
||||
if (data.blocks) {
|
||||
data.blocks.forEach(block => {
|
||||
if (block.type === "header" && block.data.level === 2) {
|
||||
if (currentBranch) {
|
||||
branches.push(currentBranch);
|
||||
}
|
||||
currentBranch = {
|
||||
name: block.data.text,
|
||||
address: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
website: '',
|
||||
mapUrl: ''
|
||||
};
|
||||
} else if (block.type === "list" && currentBranch) {
|
||||
block.data.items.forEach(item => {
|
||||
// Remove html tags if any are embedded in string
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = item;
|
||||
const text = tempDiv.textContent || tempDiv.innerText || "";
|
||||
|
||||
if (text.toLowerCase().startsWith('địa chỉ')) currentBranch.address = text.split(':').slice(1).join(':').trim();
|
||||
else if (text.toLowerCase().startsWith('điện thoại')) currentBranch.phone = text.split(':').slice(1).join(':').trim();
|
||||
else if (text.toLowerCase().startsWith('email')) currentBranch.email = text.split(':').slice(1).join(':').trim();
|
||||
else if (text.toLowerCase().startsWith('website')) currentBranch.website = text.split(':').slice(1).join(':').trim();
|
||||
else if (text.toLowerCase().startsWith('map')) currentBranch.mapUrl = text.split(':').slice(1).join(':').trim();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (currentBranch) branches.push(currentBranch);
|
||||
}
|
||||
|
||||
if (branches.length > 0) {
|
||||
if (branches && branches.length > 0) {
|
||||
let html = '';
|
||||
branches.forEach((branch, index) => {
|
||||
const isFirst = index === 0;
|
||||
@@ -93,34 +113,31 @@
|
||||
mapIframe.src = branch.mapUrl;
|
||||
}
|
||||
|
||||
const bgClass = isFirst ? 'bg-primary-600' : 'bg-white';
|
||||
const titleClass = isFirst ? 'text-white' : 'text-primary-600';
|
||||
const iconClass = isFirst ? 'text-white' : 'text-primary-600';
|
||||
const textClass = isFirst ? 'text-white' : 'text-gray-900';
|
||||
const activeClass = isFirst ? 'active' : '';
|
||||
|
||||
html += `
|
||||
<div class="branch-card rounded-lg overflow-hidden cursor-pointer ${bgClass}" data-map-url="${branch.mapUrl}" onclick="selectBranch(this)">
|
||||
<div class="branch-card rounded-lg overflow-hidden cursor-pointer ${activeClass}" data-map-url="${branch.mapUrl}" onclick="selectBranch(this)">
|
||||
<div class="xl:p-4 p-3 space-y-2">
|
||||
<div class="title-1 ${titleClass} branch-title">${branch.name}</div>
|
||||
<div class="title-1 branch-title">${branch.name}</div>
|
||||
${branch.address ? `
|
||||
<div class="flex items-start gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-map-pin size-4 flex-shrink-0 mt-1 branch-icon ${iconClass}"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
<a href="${branch.mapUrl}" target="_blank" rel="noopener noreferrer nofollow" class="flex-1 body-2 lg:duration-150 lg:hover:underline underline-offset-4 branch-text ${textClass}">${branch.address}</a>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-map-pin size-4 flex-shrink-0 mt-1 branch-icon"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
<a href="${branch.mapUrl}" target="_blank" rel="noopener noreferrer nofollow" class="flex-1 body-2 lg:duration-150 lg:hover:underline underline-offset-4 branch-text">${branch.address}</a>
|
||||
</div>` : ''}
|
||||
${branch.phone ? `
|
||||
<div class="flex items-start gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-phone size-4 flex-shrink-0 mt-1 branch-icon ${iconClass}"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
|
||||
<a href="tel:${branch.phone.replace(/[^0-9]/g, '')}" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text ${textClass}">${branch.phone}</a>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-phone size-4 flex-shrink-0 mt-1 branch-icon"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
|
||||
<a href="tel:${branch.phone.replace(/[^0-9]/g, '')}" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text">${branch.phone}</a>
|
||||
</div>` : ''}
|
||||
${branch.email ? `
|
||||
<div class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail size-4 flex-shrink-0 branch-icon ${iconClass}"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg>
|
||||
<a href="mailto:${branch.email}" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text ${textClass}">${branch.email}</a>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mail size-4 flex-shrink-0 branch-icon"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg>
|
||||
<a href="mailto:${branch.email}" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text">${branch.email}</a>
|
||||
</div>` : ''}
|
||||
${branch.website ? `
|
||||
<div class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe size-4 flex-shrink-0 branch-icon ${iconClass}"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
|
||||
<a href="${branch.website}" target="_blank" rel="noopener noreferrer nofollow" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text ${textClass}">${branch.website}</a>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe size-4 flex-shrink-0 branch-icon"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
|
||||
<a href="${branch.website}" target="_blank" rel="noopener noreferrer nofollow" class="flex-1 body-2 lg:hover:underline underline-offset-4 lg:duration-150 branch-text">${branch.website}</a>
|
||||
</div>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
@@ -135,46 +152,13 @@
|
||||
|
||||
// Global function to handle branch selection
|
||||
function selectBranch(element) {
|
||||
// Update active state of all cards
|
||||
const cards = document.querySelectorAll('.branch-card');
|
||||
cards.forEach(card => {
|
||||
// Reset to inactive state
|
||||
card.className = 'branch-card rounded-lg overflow-hidden cursor-pointer bg-white';
|
||||
|
||||
// Update text colors
|
||||
const title = card.querySelector('.branch-title');
|
||||
if (title) title.className = 'title-1 text-primary-600 branch-title';
|
||||
|
||||
const icons = card.querySelectorAll('.branch-icon');
|
||||
icons.forEach(icon => {
|
||||
icon.classList.remove('text-white');
|
||||
icon.classList.add('text-primary-600');
|
||||
});
|
||||
|
||||
const texts = card.querySelectorAll('.branch-text');
|
||||
texts.forEach(text => {
|
||||
text.classList.remove('text-white');
|
||||
text.classList.add('text-gray-900');
|
||||
});
|
||||
// Remove active class from all cards
|
||||
document.querySelectorAll('.branch-card').forEach(card => {
|
||||
card.classList.remove('active');
|
||||
});
|
||||
|
||||
// Set active state on clicked card
|
||||
element.className = 'branch-card rounded-lg overflow-hidden cursor-pointer bg-primary-600';
|
||||
|
||||
const title = element.querySelector('.branch-title');
|
||||
if (title) title.className = 'title-1 text-white branch-title';
|
||||
|
||||
const icons = element.querySelectorAll('.branch-icon');
|
||||
icons.forEach(icon => {
|
||||
icon.classList.remove('text-primary-600');
|
||||
icon.classList.add('text-white');
|
||||
});
|
||||
|
||||
const texts = element.querySelectorAll('.branch-text');
|
||||
texts.forEach(text => {
|
||||
text.classList.remove('text-gray-900');
|
||||
text.classList.add('text-white');
|
||||
});
|
||||
// Add active class to clicked card
|
||||
element.classList.add('active');
|
||||
|
||||
// Update Map URL
|
||||
const mapUrl = element.getAttribute('data-map-url');
|
||||
@@ -204,4 +188,4 @@
|
||||
</style>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -153,36 +153,18 @@
|
||||
</div>
|
||||
|
||||
<div class="sis-footer-right">
|
||||
<div class="sis-hospital-box">
|
||||
<h3>Bệnh viện Đa khoa Quốc Tế S.I.S Cần Thơ</h3>
|
||||
<p>397 Nguyễn Văn Cừ, P. An Bình, <br>TP. Cần Thơ</p>
|
||||
<p><strong>Hotline:</strong> 18001115</p>
|
||||
<p><strong>Email:</strong> cskh@dotquy.vn</p>
|
||||
<div class="sis-hospital-box" th:each="branch : ${hospitalBranches}">
|
||||
<h3 th:text="${branch.name}">Tên Bệnh viện</h3>
|
||||
<p th:text="${branch.address}">Địa chỉ</p>
|
||||
<p th:if="${branch.phone != null and branch.phone != ''}"><strong>Hotline:</strong> <span th:text="${branch.phone}"></span></p>
|
||||
<p th:if="${branch.email != null and branch.email != ''}"><strong>Email:</strong> <span th:text="${branch.email}"></span></p>
|
||||
<div class="sis-hospital-icons">
|
||||
<svg viewBox="0 0 24 24" aria-label="Website"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
||||
<a href="https://www.google.com/maps?cid=6717580334500129934&g_mp=CiVnb29nbGUubWFwcy5wbGFjZXMudjEuUGxhY2VzLkdldFBsYWNlEAMYASAF&hl=vi&gl=GB&source=embed" target="_blank"><svg viewBox="0 0 24 24" aria-label="Bản đồ"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sis-hospital-box">
|
||||
<h3>Bệnh viện Đa khoa Quốc Tế S.I.S Đà Nẵng</h3>
|
||||
<p>201 Nguyễn Chí Thanh, Phường 12, Quận 5,<br>TP. Hồ Chí Minh</p>
|
||||
<p><strong>Hotline:</strong> (84.28) 3955 5548</p>
|
||||
<p><strong>Email:</strong> bvdaihoccoso2@umc.edu.vn</p>
|
||||
<div class="sis-hospital-icons">
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sis-hospital-box">
|
||||
<h3>Bệnh viện Đa khoa Quốc Tế S.I.S Nha Trang</h3>
|
||||
<p>221B Hoàng Văn Thụ, Phường 8, Q. Phú Nhuận,<br>TP. Hồ Chí Minh</p>
|
||||
<p><strong>Hotline:</strong> (84.28) 3842 0070</p>
|
||||
<p><strong>Email:</strong> bvdaihoccoso3@umc.edu.vn</p>
|
||||
<div class="sis-hospital-icons">
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
|
||||
<a th:if="${branch.website != null and branch.website != ''}" th:href="${branch.website}" target="_blank" aria-label="Website">
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
|
||||
</a>
|
||||
<a th:if="${branch.mapUrl != null and branch.mapUrl != ''}" th:href="${branch.mapUrl}" target="_blank" aria-label="Bản đồ">
|
||||
<svg viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
Reference in New Issue
Block a user