remove bats, add snow. base code for an email modal and store code for cookies.
Some checks failed
Build / build (push) Has been cancelled

This commit is contained in:
Trenton Zimmer
2024-11-22 15:33:11 -05:00
parent 0d2159c25b
commit 74094e3ed9
10 changed files with 397 additions and 183 deletions

View File

@@ -1,2 +1,2 @@
VITE_API_URL="http://10.5.7.231:8000/"
VITE_API_URL="http://10.5.7.5:8000/"
VITE_API_KEY="your_api_key_should_be_here"

View File

@@ -46,16 +46,24 @@
<noscript>
<strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!-- Snow -->
<div id="particles-js"></div>
<script src="/assets/particles.js"></script>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script src="/assets/snow.js"></script>
<!-- Bats! -->
<script src="https://code.jquery.com/jquery.js"></script>
<!-- <script src="https://code.jquery.com/jquery.js"></script>
<script src="/assets/halloween-bats.js"></script>
<script type="text/javascript">
window.halloweenBats = $.halloweenBats({
image: "/assets/bats.png",
});
</script>
</script> -->
<audio id="audio" src="/assets/sounds/konami.mp3" class="hidden">
</body>
</html>

View File

@@ -1,212 +1,205 @@
(function ($) {
"use strict";
var innerWidth, innerHeight;
'use strict';
var innerWidth,
innerHeight;
function Bat($body, options) {
this._options = options;
function Bat($body, options) {
this._options = options;
this._initialize($body);
}
this._initialize($body);
}
Bat.prototype._initialize = function ($body) {
this._$bat = $('<div class="halloween-bat"/>');
Bat.prototype._initialize = function ($body) {
this._$bat = $('<div class="halloween-bat"/>');
this._x = this.randomPosition("horizontal");
this._y = this.randomPosition("vertical");
this._tx = this.randomPosition("horizontal");
this._ty = this.randomPosition("vertical");
this._dx = -5 + Math.random() * 10;
this._dy = -5 + Math.random() * 10;
this._positionUpdateTimer = this._getPositionUpdateTime();
this._x = this.randomPosition('horizontal');
this._y = this.randomPosition('vertical');
this._tx = this.randomPosition('horizontal');
this._ty = this.randomPosition('vertical');
this._dx = -5 + Math.random() * 10;
this._dy = -5 + Math.random() * 10;
this._positionUpdateTimer = this._getPositionUpdateTime();
this._frame = Math.random() * this._options.frames;
this._frame = Math.round(this._frame);
this._$bat.css({
position: "absolute",
left: this._x + "px",
top: this._y + "px",
zIndex: this._options.zIndex,
width: this._options.width + "px",
height: this._options.height + "px",
backgroundImage: "url(" + this._options.image + ")",
backgroundRepeat: "no-repeat",
});
this._frame = Math.random() * this._options.frames;
this._frame = Math.round(this._frame);
this._$bat.css({
position: 'absolute',
left: this._x + 'px',
top: this._y + 'px',
zIndex: this._options.zIndex,
width: this._options.width + 'px',
height: this._options.height + 'px',
backgroundImage: 'url(' + this._options.image + ')',
backgroundRepeat: 'no-repeat'
});
$body.append(this._$bat);
};
$body.append(this._$bat);
};
/**
* @returns {number}
* @private
*/
Bat.prototype._getPositionUpdateTime = function () {
return 0.5 + Math.random();
};
/**
* @returns {number}
* @private
*/
Bat.prototype._getPositionUpdateTime = function () {
return 0.5 + Math.random();
};
/**
* @param {string} direction
* @returns {number}
*/
Bat.prototype.randomPosition = function (direction) {
var screenLength, imageLength;
/**
* @param {string} direction
* @returns {number}
*/
Bat.prototype.randomPosition = function (direction) {
var screenLength,
imageLength;
if (direction === "horizontal") {
screenLength = innerWidth;
imageLength = this._options.width;
} else {
screenLength = innerHeight;
imageLength = this._options.height;
}
if (direction === 'horizontal') {
screenLength = innerWidth;
imageLength = this._options.width;
}
else {
screenLength = innerHeight;
imageLength = this._options.height;
}
return Math.random() * (screenLength - imageLength);
};
return Math.random() * (screenLength - imageLength);
};
Bat.prototype.move = function (deltaTime) {
var left, top, length, dLeft, dTop, ddLeft, ddTop;
Bat.prototype.move = function (deltaTime) {
var left,
top,
length,
dLeft,
dTop,
ddLeft,
ddTop;
left = this._tx - this._x;
top = this._ty - this._y;
left = this._tx - this._x;
top = this._ty - this._y;
length = Math.sqrt(left * left + top * top);
length = Math.max(1, length);
length = Math.sqrt(left * left + top * top);
length = Math.max(1, length);
dLeft = this._options.speed * (left / length);
dTop = this._options.speed * (top / length);
dLeft = this._options.speed * (left / length);
dTop = this._options.speed * (top / length);
ddLeft = (dLeft - this._dx) / this._options.flickering;
ddTop = (dTop - this._dy) / this._options.flickering;
ddLeft = (dLeft - this._dx) / this._options.flickering;
ddTop = (dTop - this._dy) / this._options.flickering;
this._dx += ddLeft * deltaTime * 25;
this._dy += ddTop * deltaTime * 25;
this._dx += ddLeft * deltaTime * 25;
this._dy += ddTop * deltaTime * 25;
this._x += this._dx * deltaTime * 25;
this._y += this._dy * deltaTime * 25;
this._x += this._dx * deltaTime * 25;
this._y += this._dy * deltaTime * 25;
this._x = Math.max(0, Math.min(this._x, innerWidth - this._options.width));
this._y = Math.max(
0,
Math.min(this._y, innerHeight - this._options.height)
);
this._x = Math.max(0, Math.min(this._x, innerWidth - this._options.width));
this._y = Math.max(0, Math.min(this._y, innerHeight - this._options.height));
this.applyPosition();
this.applyPosition();
this._positionUpdateTimer -= deltaTime;
if (this._positionUpdateTimer < 0) {
this._tx = this.randomPosition("horizontal");
this._ty = this.randomPosition("vertical");
this._positionUpdateTimer -= deltaTime;
if (this._positionUpdateTimer < 0) {
this._tx = this.randomPosition('horizontal');
this._ty = this.randomPosition('vertical');
this._positionUpdateTimer = this._getPositionUpdateTime();
}
};
this._positionUpdateTimer = this._getPositionUpdateTime();
}
};
Bat.prototype.applyPosition = function () {
this._$bat.css({
left: this._x + "px",
top: this._y + "px",
});
};
Bat.prototype.applyPosition = function () {
this._$bat.css({
left: this._x + 'px',
top: this._y + 'px'
});
};
Bat.prototype.animate = function (deltaTime) {
var frame;
Bat.prototype.animate = function (deltaTime) {
var frame;
this._frame += 5 * deltaTime;
this._frame += 5 * deltaTime;
if (this._frame >= this._options.frames) {
this._frame -= this._options.frames;
}
if (this._frame >= this._options.frames) {
this._frame -= this._options.frames;
}
frame = Math.floor(this._frame);
frame = Math.floor(this._frame);
this._$bat.css(
"backgroundPosition",
"0 " + frame * -this._options.height + "px"
);
};
this._$bat.css(
'backgroundPosition',
'0 ' + (frame * -this._options.height) + 'px'
);
};
$.halloweenBats = function (options) {
var $window = $(window),
$target,
plugin,
isRunning = false,
isActiveWindow = true,
bats = [],
defaults = {
image: "bats.png", // Path to the image.
zIndex: 10000, // The z-index you need.
amount: 3, // Bat amount.
width: 35, // Image width.
height: 20, // Animation frame height.
frames: 4, // Amount of animation frames.
speed: 20, // Higher value = faster.
flickering: 15, // Higher value = slower.
target: "body", // Target element
};
$.halloweenBats = function (options) {
var $window = $(window),
$target,
plugin,
isRunning = false,
isActiveWindow = true,
bats = [],
defaults = {
image: 'bats.png', // Path to the image.
zIndex: 10000, // The z-index you need.
amount: 3, // Bat amount.
width: 35, // Image width.
height: 20, // Animation frame height.
frames: 4, // Amount of animation frames.
speed: 20, // Higher value = faster.
flickering: 15, // Higher value = slower.
target: 'body' // Target element
};
options = $.extend({}, defaults, options);
options = $.extend({}, defaults, options);
$target = $(options.target);
$target = $(options.target);
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
plugin = {
isRunning: false,
start: function () {
var lastTime = Date.now();
plugin = {
isRunning: false,
start: function() {
var lastTime = Date.now();
isRunning = true;
isRunning = true;
function animate() {
var time = Date.now(),
deltaTime = (time - lastTime) / 1000;
function animate() {
var time = Date.now(),
deltaTime = (time - lastTime) / 1000;
lastTime = time;
lastTime = time;
if (isActiveWindow) {
$.each(bats, function (index, bat) {
bat.move(deltaTime);
bat.animate(deltaTime);
});
}
if (isActiveWindow) {
$.each(bats, function (index, bat) {
bat.move(deltaTime);
bat.animate(deltaTime);
});
}
if (isRunning) {
requestAnimationFrame(animate);
}
}
if (isRunning) {
requestAnimationFrame(animate);
}
}
animate();
},
stop: function () {
isRunning = false;
},
};
animate();
},
stop: function() {
isRunning = false;
}
};
while (bats.length < options.amount) {
bats.push(new Bat($target, options));
}
while (bats.length < options.amount) {
bats.push(new Bat($target, options));
}
plugin.start();
plugin.start();
$window.resize(function () {
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
});
$window.resize(function () {
innerWidth = $target.innerWidth();
innerHeight = $target.innerHeight();
});
$window.focus(function () {
isActiveWindow = true;
});
$window.focus(function() {
isActiveWindow = true;
});
$window.blur(function () {
isActiveWindow = false;
});
$window.blur(function() {
isActiveWindow = false;
});
return plugin;
};
}(jQuery));
return plugin;
};
})(jQuery);

105
public/assets/snow.js Normal file
View File

@@ -0,0 +1,105 @@
particlesJS("particles-js", {
particles: {
number: {
value: 52,
density: {
enable: true,
value_area: 631.3280775270874,
},
},
color: {
value: "#fff",
},
shape: {
type: "circle",
stroke: {
width: 0,
color: "#000000",
},
polygon: {
nb_sides: 5,
},
},
opacity: {
value: 0.5,
random: true,
anim: {
enable: false,
speed: 1,
opacity_min: 0.1,
sync: false,
},
},
size: {
value: 5,
random: true,
anim: {
enable: false,
speed: 40,
size_min: 0.1,
sync: false,
},
},
line_linked: {
enable: false,
distance: 500,
color: "#ffffff",
opacity: 0.4,
width: 2,
},
move: {
enable: true,
speed: 1.5,
direction: "bottom",
random: false,
straight: false,
out_mode: "out",
bounce: false,
attract: {
enable: false,
rotateX: 600,
rotateY: 1200,
},
},
},
interactivity: {
detect_on: "canvas",
events: {
onhover: {
enable: false,
mode: "bubble",
},
onclick: {
enable: true,
mode: "repulse",
},
resize: true,
},
modes: {
grab: {
distance: 400,
line_linked: {
opacity: 0.5,
},
},
bubble: {
distance: 400,
size: 4,
duration: 0.3,
opacity: 1,
speed: 3,
},
repulse: {
distance: 200,
duration: 0.4,
},
push: {
particles_nb: 4,
},
remove: {
particles_nb: 2,
},
},
},
retina_detect: true,
});

View File

@@ -0,0 +1,74 @@
<script setup>
import { computed, ref } from "vue";
import CardBox from "@/components/CardBox.vue";
import OverlayLayer from "@/components/OverlayLayer.vue";
import BaseButton from "@/components/BaseButton.vue";
import BaseIcon from "./BaseIcon.vue";
import { mdiEmailAlertOutline } from "@mdi/js";
import { useMainStore } from "@/stores/main.js";
import { loadCookie, saveCookie, deleteCookie } from "@/stores/cookies";
const mainStore = useMainStore();
const killBox = ref(false);
const isActive = computed(() => {
if (mainStore.userData?.never_verify_email ?? false) {
return false;
}
if (
!(mainStore.userData?.email_verified ?? false) &&
!loadCookie("email_reminder")
) {
return true;
}
return false;
});
function verifyLater() {
if (saveCookie("email_reminder", true)) {
killBox.value = true;
return true;
} else {
return false;
}
}
</script>
<template>
<template v-if="isActive && !killBox">
<OverlayLayer :transparent="true">
<CardBox
class="shadow-lg max-h-modal w-11/12 md:w-3/5 lg:w-2/5 xl:w-4/12 z-50 text-white/90"
>
<div class="grid text-center justify-center grid-cols-1 gap-3">
<div class="place-self-center">
<BaseIcon
:path="mdiEmailAlertOutline"
class="text-yellow-600"
w="w-20"
:size="45"
/>
</div>
<h1 class="text-lg md:text-xl">
Please verify your email address to ensure that your password can be
reset in the future.
</h1>
<hr class="border-t border-1 mt-3 w-full" />
<div class="flex gap-2">
<BaseButton label="Verify" color="success" />
<BaseButton
label="Verify Later"
color="warning"
@click="verifyLater()"
/>
<BaseButton label="Never Verify" color="danger" />
</div>
</div>
</CardBox>
</OverlayLayer>
</template>
</template>

View File

@@ -42,4 +42,9 @@
img {
pointer-events: none;
}
#particles-js {
height: full;
position: absolute;
}

View File

@@ -14,6 +14,7 @@ import menuNavBar from "@/menuNavBar.js";
import { useMainStore } from "@/stores/main.js";
import { useStyleStore } from "@/stores/style.js";
import LoadingModal from "@/components/LoadingModal.vue";
// import EmailModal from "@/components/EmailModal.vue";
import BaseIcon from "@/components/BaseIcon.vue";
import NavBar from "@/components/NavBar.vue";
import NavBarItemPlain from "@/components/NavBarItemPlain.vue";
@@ -222,6 +223,7 @@ const menuAside = computed(() => {
'opacity-0': !loading && !saving,
}"
/>
<!-- <EmailModal class="transition-opacity duration-300 ease-out" /> -->
<div
v-if="userLoaded"
:class="[layoutAsidePadding, { 'ml-60 lg:ml-0': isAsideMobileExpanded }]"

View File

@@ -91,10 +91,13 @@ export async function APIPutCard(cardId) {
export async function APIDeleteCard(cardId) {
try {
const data = await mainStore.callApi(`/user/card`, "DELETE", {
cardId: cardId,
});
return data;
const confirmed = window.confirm("Are you really?");
if (confirmed) {
const data = await mainStore.callApi(`/user/card`, "DELETE", {
cardId: cardId,
});
return data;
}
} catch (error) {
console.log("Error deleting card:", error);
throw error;

33
src/stores/cookies.js Normal file
View File

@@ -0,0 +1,33 @@
import Cookies from "js-cookie";
export function loadCookie(key) {
try {
const data = Cookies.get(key);
return data;
} catch (error) {
this.errorCode = error.message;
throw error;
}
}
export function saveCookie(key, data, expires = 7) {
try {
Cookies.set(key, data, {
expires: expires,
});
return true;
} catch (error) {
this.errorCode = error.message;
throw error;
}
}
export function deleteCookie(key) {
try {
Cookies.remove(key);
return true;
} catch (error) {
this.errorCode = error.message;
throw error;
}
}

View File

@@ -75,15 +75,6 @@ export const useMainStore = defineStore("main", {
},
async callApi(endpoint, method = "GET", data = null, extraHeaders = {}) {
if (method === "DELETE") {
const confirmed = window.confirm("Are you really?");
if (!confirmed) {
this.isSaving = false;
this.isLoading = false;
return null; // Exit if user does not confirm
}
}
const apiServer = import.meta.env.VITE_API_URL;
const apiKey = import.meta.env.VITE_API_KEY;
let loadingTimeout;