add payday anim
This commit is contained in:
@@ -248,6 +248,15 @@
|
||||
// ─── Payday countdown (child view) ───
|
||||
let nowMs = $state(Date.now());
|
||||
let eowFired = $state(false);
|
||||
// Nyan-style payday party: rainbow banner + confetti when payday unlocks.
|
||||
let paydayParty = $state(false);
|
||||
let partyTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
function startPaydayParty() {
|
||||
paydayParty = true;
|
||||
fire();
|
||||
if (partyTimer) clearTimeout(partyTimer);
|
||||
partyTimer = setTimeout(() => (paydayParty = false), 15000);
|
||||
}
|
||||
$effect(() => {
|
||||
const id = setInterval(() => (nowMs = Date.now()), 1000);
|
||||
return () => clearInterval(id);
|
||||
@@ -269,6 +278,7 @@
|
||||
if (!pbToken || !famId) return;
|
||||
eowFired = true;
|
||||
memberApi.payday(famId).catch(() => {});
|
||||
startPaydayParty();
|
||||
});
|
||||
|
||||
function paydayWeekStart(): string {
|
||||
@@ -1273,6 +1283,16 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if paydayParty}
|
||||
<div class="payday-party" role="status" onclick={() => (paydayParty = false)}>
|
||||
<span class="party-cat">🐖</span>
|
||||
<div class="party-body">
|
||||
<p class="party-title">PAYDAY!!</p>
|
||||
<p class="party-sub">Your cash is ready — go collect it! 🎉</p>
|
||||
</div>
|
||||
<span class="party-stars">🌈⭐🌈</span>
|
||||
</div>
|
||||
{/if}
|
||||
<!-- HERO -->
|
||||
<header class="hero">
|
||||
<svg
|
||||
@@ -3107,6 +3127,91 @@
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* ── Payday party: nyan-style colour-cycling celebration ── */
|
||||
.payday-party {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: 1rem 1.2rem;
|
||||
border-radius: 14px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
#ef4444,
|
||||
#f97316,
|
||||
#eab308,
|
||||
#22c55e,
|
||||
#3b82f6,
|
||||
#a855f7,
|
||||
#ec4899,
|
||||
#ef4444
|
||||
);
|
||||
background-size: 300% 100%;
|
||||
animation:
|
||||
nyan-slide 3s linear infinite,
|
||||
party-pop 0.45s ease-out;
|
||||
box-shadow: 0 8px 24px rgba(168, 85, 247, 0.45);
|
||||
}
|
||||
@keyframes nyan-slide {
|
||||
to {
|
||||
background-position: 300% 0;
|
||||
}
|
||||
}
|
||||
@keyframes party-pop {
|
||||
from {
|
||||
transform: scale(0.85);
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
.party-cat {
|
||||
font-size: 2.6rem;
|
||||
animation: party-bounce 0.55s ease-in-out infinite alternate;
|
||||
}
|
||||
@keyframes party-bounce {
|
||||
from {
|
||||
transform: translateY(-4px) rotate(-10deg);
|
||||
}
|
||||
to {
|
||||
transform: translateY(4px) rotate(10deg);
|
||||
}
|
||||
}
|
||||
.party-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
.party-title {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.1em;
|
||||
animation: party-wiggle 1s ease-in-out infinite;
|
||||
}
|
||||
@keyframes party-wiggle {
|
||||
0%,
|
||||
100% {
|
||||
transform: rotate(-2deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
}
|
||||
.party-sub {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
opacity: 0.95;
|
||||
}
|
||||
.party-stars {
|
||||
margin-left: auto;
|
||||
font-size: 1.4rem;
|
||||
animation: party-bounce 0.55s ease-in-out infinite alternate-reverse;
|
||||
}
|
||||
/* Mobile: declared last so it wins over the base .goal-mini (.kanban)
|
||||
rules (same specificity, source order decides). */
|
||||
@media (max-width: 639px) {
|
||||
|
||||
Reference in New Issue
Block a user