CookieMonster.vue 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <template>
  2. <div id="cookie_monster" :class="`print:hidden z-50 ${isOpen ? 'mix-blend-normal' : 'mix-blend-difference'}`">
  3. <div v-if="isOpen" class="fixed bottom-2 right-2 left-2 sm:w-10/12 max-w-screen-md sm:mx-auto">
  4. <div class="border-2 bg-white border-sky-700 px-4 pt-3 pb-4 overflow-scroll">
  5. <client-only><fa-icon :icon="['fas', 'circle-xmark']" class="text-error text-4xl float-right" @click="isOpen = false" /></client-only>
  6. <div class="pb-4">
  7. <p>I use <strong>cookies</strong> for <a href="/cookies">reasons</a>. Please read the reasons before setting your preferences.</p>
  8. <div class="sm:pl-4 pt-2 grid sm:grid-cols-12 grid-cols-6">
  9. <p><input type="checkbox" class="form-control toggle toggle-primary" checked disabled /></p>
  10. <p class="col-span-5 sm:col-span-11"><strong>Consent</strong>: I must use a cookie to keep track of your choices, no way around it.</p>
  11. </div>
  12. <div class="sm:pl-4 pt-2 grid sm:grid-cols-12 grid-cols-6">
  13. <p><input type="checkbox" class="form-control toggle toggle-primary" v-model="consentStore.analytics" @change="(e: Event) => consentStore.analytics = (e.target as HTMLInputElement).checked " /></p>
  14. <p class="col-span-5 sm:col-span-11"><strong>Analytics</strong>: optional, but it'd be great if you agreed 😊</p>
  15. </div>
  16. <div class="sm:pl-4 pt-2 grid sm:grid-cols-12 grid-cols-6">
  17. <p><input type="checkbox" class="form-control toggle toggle-primary" v-model="consentStore.ads" @change="(e: Event) => consentStore.ads = (e.target as HTMLInputElement).checked" /></p>
  18. <p class="col-span-5 sm:col-span-11"><strong>Advertising</strong>: fully optional, feel free to skip this one.</p>
  19. </div>
  20. <p class="pt-2">You can read more on how I use cookies on <a href="/cookies">this page</a>.</p>
  21. </div>
  22. <div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
  23. <button class="btn btn-success" @click="acceptMyChoice">Accept my choice</button>
  24. <button class="btn btn-info btn-outline" @click="acceptAll">Accept all cookies</button>
  25. <button class="btn btn-error" @click="rejectAll">Reject all cookies</button>
  26. </div>
  27. </div>
  28. </div>
  29. <div v-else class="fixed max-w-0 bottom-2 sm:right-16 right-11 cursor-pointer" @click="isOpen = true">
  30. <ClientOnly><fa-icon icon="fa-solid fa-cookie-bite" class="sm:text-6xl text-4xl text-sky-500" /></ClientOnly>
  31. </div>
  32. </div>
  33. </template>
  34. <script lang="ts" setup>
  35. import { useConsent } from '~~/store/consent';
  36. const consentStore = useConsent();
  37. const error = useError();
  38. const isOpen = useState('isOpen', () => !consentStore.preferenceGiven && error.value === undefined);
  39. const rejectAll = (e: MouseEvent | undefined) => {
  40. window._paq.push(['forgetCookieConsentGiven']);
  41. consentStore.analytics = false;
  42. consentStore.ads = false;
  43. consentStore.preferenceGiven = true;
  44. isOpen.value = false;
  45. return e;
  46. }
  47. const acceptAll = (e: MouseEvent | undefined) => {
  48. window._paq.push(['rememberCookieConsentGiven']);
  49. consentStore.analytics = true;
  50. consentStore.ads = true;
  51. consentStore.preferenceGiven = true;
  52. isOpen.value = false;
  53. return e;
  54. }
  55. const acceptMyChoice = (e: MouseEvent | undefined) => {
  56. consentStore.preferenceGiven = true;
  57. isOpen.value = false;
  58. if (consentStore.analytics) {
  59. window._paq.push(['rememberCookieConsentGiven']);
  60. } else {
  61. window._paq.push(['forgetCookieConsentGiven']);
  62. }
  63. return e;
  64. }
  65. </script>
  66. <style lang="pcss">
  67. #cookie_monster {
  68. div {
  69. width: 100%;
  70. }
  71. a {
  72. color: theme(colors.sky.700);
  73. text-decoration: underline;
  74. }
  75. }
  76. </style>