feat: Add banner management functionality

- Implemented a new Banner model to represent banner data.
- Created a BannerRepository for database interactions related to banners.
- Developed a BannerService to handle business logic for banners.
- Added admin views for listing and adding banners.
- Integrated banner hooks for frontend rendering and click tracking.
- Created frontend styles and scripts for banner display and interaction.
- Updated database migrations to include a new banners table.
- Enhanced AdminController to manage banner actions and pages.
This commit is contained in:
2026-05-05 01:03:05 +03:30
parent 5930c1ad6f
commit 32c065e4b6
15 changed files with 1350 additions and 4 deletions

View File

@@ -0,0 +1,65 @@
(function () {
const closeButtons = document.querySelectorAll('.sodino-banner-close');
const clicked = new Set();
function getCookie(name) {
const value = '; ' + document.cookie;
const parts = value.split('; ' + name + '=');
if (parts.length === 2) {
return parts.pop().split(';').shift();
}
return null;
}
function sendClick(bannerId) {
if (!bannerId || clicked.has(bannerId) || !window.sodinoBannerFrontend) {
return;
}
clicked.add(bannerId);
fetch(window.sodinoBannerFrontend.ajaxUrl, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: 'action=sodino_banner_click&banner_id=' + encodeURIComponent(bannerId) + '&security=' + encodeURIComponent(window.sodinoBannerFrontend.nonce),
});
}
document.addEventListener('click', function (event) {
const target = event.target.closest('.sodino-banner-link');
if (target) {
const bannerId = target.dataset.bannerId;
sendClick(bannerId);
}
});
closeButtons.forEach(function (button) {
button.addEventListener('click', function () {
const wrapper = this.closest('.sodino-banner-wrap');
if (!wrapper) {
return;
}
wrapper.style.display = 'none';
const bannerId = wrapper.dataset.bannerId;
if (bannerId) {
document.cookie = 'sodino_banner_' + bannerId + '=hidden; path=/; max-age=' + 60 * 60 * 24;
}
});
});
document.querySelectorAll('.sodino-banner-wrap').forEach(function (banner) {
const bannerId = banner.dataset.bannerId;
if (getCookie('sodino_banner_' + bannerId) === 'hidden') {
banner.style.display = 'none';
}
if (banner.classList.contains('sodino-banner-popup')) {
setTimeout(function () {
if (getCookie('sodino_banner_' + bannerId) !== 'hidden') {
banner.style.display = 'block';
}
}, 2000);
}
});
})();