cbbfb145dc
Applies a few Hook Model (trigger/action/reward/investment) patterns on top of the existing swipe/match loop: - Daily streak: a flame badge in the home header, backed by the new checkin endpoint — an external trigger to return daily. - Profile completeness meter + badge collection on the profile page (client-computed from existing data) — the investment loop nudging users to fill out bio/photos/answers. - Bio editor on the profile page, shown on swipe cards and candidate detail so profiles read richer. - Catch the Hearts: a small tap mini-game (falling hearts, bonus items, 20s timer, persisted high score) shown instead of a dead end when the discover feed runs out, so there's still a reason to stay in the app. - Micro-animations: heart-burst on like, confetti on match, tap feedback on all buttons (active:scale-95). Fixed a React "purity" lint violation along the way (Math.random() can't be called inside useMemo under this project's rules — moved to useState lazy initializers, which run once on mount as intended).
26 lines
1.0 KiB
TypeScript
26 lines
1.0 KiB
TypeScript
"use client";
|
|
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { Flame } from "lucide-react";
|
|
|
|
// نشان استریک روزانه؛ تریگر بیرونی کلاسیک برای برگشت روزانهی کاربر (Hook Model).
|
|
// وقتی عدد عوض میشه یه بار کوچیک pop میزنه تا حس جایزه گرفتن بده.
|
|
export function StreakBadge({ count }: { count: number }) {
|
|
if (count <= 0) return null;
|
|
|
|
return (
|
|
<AnimatePresence mode="popLayout">
|
|
<motion.div
|
|
key={count}
|
|
initial={{ scale: 0.6, opacity: 0 }}
|
|
animate={{ scale: 1, opacity: 1 }}
|
|
transition={{ type: "spring", stiffness: 400, damping: 15 }}
|
|
className="flex items-center gap-1 rounded-(--radius-full) bg-amber-50 border border-amber-200 px-2.5 py-1 text-amber-600"
|
|
>
|
|
<Flame size={13} fill="currentColor" className="text-amber-500" />
|
|
<span className="text-[12px] font-extrabold">{count.toLocaleString("fa-IR")}</span>
|
|
</motion.div>
|
|
</AnimatePresence>
|
|
);
|
|
}
|