Files
dealplustech/src/components/consent/ConsentPreferences.astro
Kunthawat Greethong 7a67f68d9f ♻️ Restructure: Move Astro to repository root
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)
2026-03-09 22:00:05 +07:00

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>