feat: implement doctor API synchronization and add contact page support with media assets

This commit is contained in:
2026-07-23 07:37:31 +07:00
parent abdf9467e6
commit 107e191e93
537 changed files with 2690 additions and 267 deletions
@@ -2,7 +2,7 @@
<div class="c--component c--tabbed-media-content">
<div class="tabbed-media-content-text-col">
<div data-component-id="umass_base:section-title" class="f--section-title">
<h2 style="color: var(--color-brand);">LiveStream</h2>
<h2 style="color: var(--color-old-brick);">LiveStream</h2>
</div>
<div data-component-id="umass_base:tabbed-container" data-once="tabbed-container">
<div class="tab-labels-container" role="tablist">
@@ -1,66 +1,205 @@
<div class="submenu-wrapper" style="left: -671.344px;width: 1920px;">
<button class="button-back">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5 10" width="5" height="10">
<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#881c1c" points="0,5 5,0 5,10 "></polygon>
</svg> Back </button>
<span class="navigation-title">VỀ BỆNH VIỆN</span>
<!-- Mobile Submenu Layout (Simple List) -->
<ul class="submenu mobile-only">
<li class="menu-item">
<a href="#">GIỚI THIỆU TỔNG QUAN</a>
</li>
<li class="menu-item">
<a href="#">LỊCH SỬ BỆNH VIỆN</a>
</li>
<li class="menu-item">
<a href="#">TẦM NHÌN - SỨ MỆNH - GIÁ TRỊ CỐT LÕI</a>
</li>
<li class="menu-item">
<a href="#">BAN LÃNH ĐẠO</a>
</li>
<li class="menu-item">
<a href="#">CÁC ĐƠN VỊ</a>
</li>
</ul>
<!-- Mega Menu Content Layout -->
<div class="mega-menu-content desktop-only">
<!-- Column 1: Info (Title and Text) -->
<div class="mega-col-info">
<h3>VỀ BỆNH VIỆN</h3>
<p style="text-transform: math-auto;">Bệnh viện Đột quỵ Quốc tế tự hào là đơn vị tiên phong trong việc cung cấp dịch vụ khám chữa bệnh chất lượng cao, mang lại sự tin cậy và an tâm cho bệnh nhân.</p>
</div>
<!-- Column 2: The actual Submenu Links -->
<div class="mega-col-links">
<ul class="submenu">
<li class="menu-item">
<a href="#">GIỚI THIỆU TỔNG QUAN</a>
</li>
<li class="menu-item">
<a href="#">LỊCH SỬ BỆNH VIỆN</a>
</li>
<li class="menu-item">
<a href="#">TẦM NHÌN - SỨ MỆNH - GIÁ TRỊ CỐT LÕI</a>
</li>
<li class="menu-item">
<a href="#">BAN LÃNH ĐẠO</a>
</li>
<li class="menu-item">
<a href="#">CÁC ĐƠN VỊ</a>
</li>
</ul>
</div>
<!-- Column 3: Featured Image -->
<div class="mega-col-image">
<!-- Try to use a hospital-like image if we can, or fallback to logo -->
<img src="/theme-assets/umass/images/logo.png" alt="Featured Image" style="object-fit: contain; background: white; padding: 20px;">
</div>
</div>
<!-- End Mega Menu Layout -->
<style>
.education-slider-wrapper {
position: relative;
padding: 0px;
/* Space for buttons */
}
</div>
.education-slider-container {
overflow: hidden;
width: 100%;
}
.education-slider-wrapper .news-grid,
.education-slider-wrapper .row,
.education-slider-track {
display: flex !important;
flex-wrap: nowrap !important;
gap: 20px;
margin: 0 !important;
transition: transform 0.4s ease;
}
/* Force children to be fixed width cards */
.education-slider-wrapper .news-grid>*,
.education-slider-wrapper .row>*,
.education-slider-track>* {
flex: 0 0 calc(33.333% - 14px) !important;
/* show 3 cards at a time */
max-width: none !important;
}
@media (max-width: 992px) {
.education-slider-wrapper .news-grid>*,
.education-slider-wrapper .row>*,
.education-slider-track>* {
flex: 0 0 calc(50% - 10px) !important;
}
}
@media (max-width: 576px) {
.education-slider-wrapper .news-grid>*,
.education-slider-wrapper .row>*,
.education-slider-track>* {
flex: 0 0 100% !important;
}
}
.edu-slider-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background-color: rgba(200, 200, 200, 0.5);
/* mờ / transparent */
color: #333;
border: none;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 10;
transition: background-color 0.2s, color 0.2s;
line-height: 1;
}
.edu-slider-btn:hover {
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
}
.edu-slider-btn.prev-btn {
left: -10px;
}
.edu-slider-btn.next-btn {
right: -10px;
}
.edu-slider-btn:disabled {
opacity: 0.2;
cursor: not-allowed;
}
/* --- Hiệu ứng crop (zoom) ảnh khi hover --- */
.education-slider-wrapper .featured-grid__item .news-card__image {
overflow: hidden !important;
display: block;
}
.education-slider-wrapper .featured-grid__item .news-card__image img {
transition: transform 0.4s ease-in-out !important;
}
.education-slider-wrapper .featured-grid__item:hover .news-card__image img {
transform: scale(1.1) !important;
}
</style>
<body>
<div class="cc--component-container cc--news-events">
<div class="c--component c--news-events">
<!-- Header -->
<div class="news-events-row">
<div class="education-column news-column" style="width: 100%;">
<div
style="display: flex; justify-content: space-between; align-items: baseline; border-bottom: 2px solid var(--color-brand); margin-bottom: 16px;">
<!-- Thêm flex-grow: 1 vào style của h2 -->
<h2 class="section-title--news"
style="font-size: 2rem; margin: 0; padding-bottom: 4px; border-bottom: unset;">ĐÀO TẠO</h2>
<a href="/news/education" class="news-events-section__cta news-events-section__cta--desktop"
style="color: var(--color-brand); font-weight: 800; font-size: 16px; text-transform: uppercase; text-decoration: none; border-bottom: unset;">XEM
THÊM</a>
</div>
<div class="education-slider-wrapper" style="padding-right: 0;">
<button class="edu-slider-btn prev-btn" aria-label="Previous">&lsaquo;</button>
<div class="education-slider-container">
<div class="education-slider-track">
[component:news-grid data-source="posts:tag=education,limit=5,collection=news_posts"]
</div>
</div>
<button class="edu-slider-btn next-btn" aria-label="Next">&rsaquo;</button>
</div>
</div>
</div><!-- Mobile Footer CTA -->
<div class="news-events-section__footer"><a href="/news/education"
class="news-events-section__cta news-events-section__cta--mobile">Xem Thêm</a></div>
</div>
</div>
</body>
<script>
document.addEventListener("DOMContentLoaded", function() {
const wrappers = document.querySelectorAll('.education-slider-wrapper');
wrappers.forEach(wrapper => {
const prevBtn = wrapper.querySelector('.prev-btn');
const nextBtn = wrapper.querySelector('.next-btn');
let track = wrapper.querySelector('.education-slider-track');
if (track && track.children.length === 1 && (track.children[0].classList.contains('news-grid') || track.children[0].classList.contains('row'))) {
track = track.children[0];
track.classList.add('education-slider-track');
}
if (!track) return;
let currentIndex = 0;
function updateSlider() {
const items = track.children;
if(items.length === 0) return;
const itemWidth = items[0].getBoundingClientRect().width;
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
track.style.transform = `translateX(-${currentIndex * (itemWidth + gap)}px)`;
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
prevBtn.disabled = currentIndex === 0;
nextBtn.disabled = currentIndex >= items.length - visibleCount;
}
prevBtn.addEventListener('click', () => {
if (currentIndex > 0) {
currentIndex--;
updateSlider();
}
});
nextBtn.addEventListener('click', () => {
const items = track.children;
const itemWidth = items[0].getBoundingClientRect().width;
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
if (currentIndex < items.length - visibleCount) {
currentIndex++;
updateSlider();
}
});
window.addEventListener('resize', () => {
const items = track.children;
if(items.length === 0) return;
const itemWidth = items[0].getBoundingClientRect().width;
const gap = parseFloat(window.getComputedStyle(track).gap) || 20;
const containerWidth = wrapper.querySelector('.education-slider-container').getBoundingClientRect().width;
const visibleCount = Math.max(1, Math.floor((containerWidth + gap) / (itemWidth + gap)));
if (currentIndex > items.length - visibleCount) {
currentIndex = Math.max(0, items.length - visibleCount);
}
updateSlider();
});
setTimeout(updateSlider, 200);
});
});
</script>