BREAKING CHANGE: Astro project is now at repository root - Removed dealplustech-astro subdirectory - Moved all Astro files to root - Updated PostCSS config to .cjs - Removed old Next.js files ✅ 11 pages built successfully ✅ Cookie consent banner included ✅ Privacy/Terms links in footer ✅ Ready for Easypanel deployment (no root dir needed) Migration path: - Old structure: /dealplustech-astro/ - New structure: / (root)
189 lines
8.2 KiB
Plaintext
189 lines
8.2 KiB
Plaintext
---
|
|
---
|
|
|
|
<div id="consent-preferences-modal" class="fixed inset-0 z-50 hidden">
|
|
<div class="fixed inset-0 bg-black/50 transition-opacity" id="consent-modal-backdrop"></div>
|
|
<div class="fixed inset-0 flex items-center justify-center p-4">
|
|
<div class="relative bg-white rounded-xl shadow-2xl w-full max-w-lg max-h-[90vh] overflow-y-auto">
|
|
<div class="p-6">
|
|
<h2 class="text-xl font-semibold text-gray-900 mb-2">ตั้งค่าคุกกี้</h2>
|
|
<p class="text-sm text-gray-600 mb-6">
|
|
คุณสามารถปรับแต่งการตั้งค่าคุกกี้ได้ตามต้องการ
|
|
</p>
|
|
|
|
<div class="space-y-5">
|
|
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
|
|
<div>
|
|
<span class="font-medium text-gray-900">จำเป็น (เปิดเสมอ)</span>
|
|
<p class="text-xs text-gray-500 mt-0.5">คุกกี้ที่จำเป็นสำหรับการทำงานของเว็บไซต์</p>
|
|
</div>
|
|
<label class="relative inline-flex items-center cursor-not-allowed">
|
|
<input type="checkbox" checked disabled class="sr-only peer" />
|
|
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
|
|
<div>
|
|
<span class="font-medium text-gray-900">วิเคราะห์การใช้งาน</span>
|
|
<p class="text-xs text-gray-500 mt-0.5">ช่วยให้เราเข้าใจว่าผู้ใช้งานใช้เว็บไซต์อย่างไร</p>
|
|
</div>
|
|
<label class="relative inline-flex items-center cursor-pointer">
|
|
<input type="checkbox" id="consent-analytics" class="sr-only peer" />
|
|
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
|
|
<div>
|
|
<span class="font-medium text-gray-900">การตลาด</span>
|
|
<p class="text-xs text-gray-500 mt-0.5">ใช้สำหรับการตลาดและโฆษณา</p>
|
|
</div>
|
|
<label class="relative inline-flex items-center cursor-pointer">
|
|
<input type="checkbox" id="consent-marketing" class="sr-only peer" />
|
|
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-green-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 flex flex-col sm:flex-row gap-3">
|
|
<button
|
|
id="consent-save"
|
|
class="flex-1 px-5 py-2.5 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500"
|
|
>
|
|
บันทึกการตั้งค่า
|
|
</button>
|
|
<button
|
|
id="consent-close"
|
|
class="px-5 py-2.5 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400"
|
|
>
|
|
ยกเลิก
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const POLICY_VERSION = '1.0';
|
|
const STORAGE_KEY = 'dealplustech_consent';
|
|
|
|
function generateSessionId(): string {
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
const r = Math.random() * 16 | 0;
|
|
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
return v.toString(16);
|
|
});
|
|
}
|
|
|
|
function getSessionId(): string {
|
|
let sessionId = localStorage.getItem('dealplustech_session');
|
|
if (!sessionId) {
|
|
sessionId = generateSessionId();
|
|
localStorage.setItem('dealplustech_session', sessionId);
|
|
}
|
|
return sessionId;
|
|
}
|
|
|
|
function getConsent(): { essential: boolean; analytics: boolean; marketing: boolean } | null {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (stored) {
|
|
try {
|
|
return JSON.parse(stored);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function saveConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(consent));
|
|
}
|
|
|
|
function applyConsent(consent: { analytics: boolean; marketing: boolean }) {
|
|
if (consent.analytics) {
|
|
document.body.classList.add('analytics-enabled');
|
|
} else {
|
|
document.body.classList.remove('analytics-enabled');
|
|
}
|
|
if (consent.marketing) {
|
|
document.body.classList.add('marketing-enabled');
|
|
} else {
|
|
document.body.classList.remove('marketing-enabled');
|
|
}
|
|
|
|
window.dispatchEvent(new CustomEvent('consent-updated', { detail: consent }));
|
|
}
|
|
|
|
async function logConsent(consent: { essential: boolean; analytics: boolean; marketing: boolean }) {
|
|
try {
|
|
await fetch('/api/consent', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
sessionId: getSessionId(),
|
|
essential: consent.essential,
|
|
analytics: consent.analytics,
|
|
marketing: consent.marketing,
|
|
policyVersion: POLICY_VERSION,
|
|
}),
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to log consent:', error);
|
|
}
|
|
}
|
|
|
|
function openModal() {
|
|
const modal = document.getElementById('consent-preferences-modal');
|
|
const analyticsCheckbox = document.getElementById('consent-analytics') as HTMLInputElement;
|
|
const marketingCheckbox = document.getElementById('consent-marketing') as HTMLInputElement;
|
|
|
|
const existingConsent = getConsent();
|
|
if (existingConsent) {
|
|
analyticsCheckbox.checked = existingConsent.analytics;
|
|
marketingCheckbox.checked = existingConsent.marketing;
|
|
} else {
|
|
analyticsCheckbox.checked = false;
|
|
marketingCheckbox.checked = false;
|
|
}
|
|
|
|
modal?.classList.remove('hidden');
|
|
}
|
|
|
|
function closeModal() {
|
|
const modal = document.getElementById('consent-preferences-modal');
|
|
modal?.classList.add('hidden');
|
|
}
|
|
|
|
async function handleSave() {
|
|
const analyticsCheckbox = document.getElementById('consent-analytics') as HTMLInputElement;
|
|
const marketingCheckbox = document.getElementById('consent-marketing') as HTMLInputElement;
|
|
|
|
const consent = {
|
|
essential: true,
|
|
analytics: analyticsCheckbox.checked,
|
|
marketing: marketingCheckbox.checked,
|
|
};
|
|
|
|
saveConsent(consent);
|
|
await logConsent(consent);
|
|
applyConsent(consent);
|
|
closeModal();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const modal = document.getElementById('consent-preferences-modal');
|
|
const backdrop = document.getElementById('consent-modal-backdrop');
|
|
const saveBtn = document.getElementById('consent-save');
|
|
const closeBtn = document.getElementById('consent-close');
|
|
|
|
window.addEventListener('open-consent-preferences', openModal);
|
|
|
|
backdrop?.addEventListener('click', closeModal);
|
|
closeBtn?.addEventListener('click', closeModal);
|
|
saveBtn?.addEventListener('click', handleSave);
|
|
});
|
|
</script>
|