203 lines
8.2 KiB
TypeScript
203 lines
8.2 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Hand-designed sticker artwork as inline SVG — no external assets.
|
||
|
|
* Each sticker is keyed by id; packs (see gamification.ts) reference these ids.
|
||
|
|
*/
|
||
|
|
|
||
|
|
type SvgProps = { className?: string };
|
||
|
|
|
||
|
|
function Face({
|
||
|
|
bg1,
|
||
|
|
bg2,
|
||
|
|
children,
|
||
|
|
}: {
|
||
|
|
bg1: string;
|
||
|
|
bg2: string;
|
||
|
|
children: React.ReactNode;
|
||
|
|
}) {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<defs>
|
||
|
|
<radialGradient id="fg" cx="40%" cy="35%" r="75%">
|
||
|
|
<stop offset="0" stopColor={bg1} />
|
||
|
|
<stop offset="1" stopColor={bg2} />
|
||
|
|
</radialGradient>
|
||
|
|
</defs>
|
||
|
|
<circle cx="50" cy="50" r="44" fill="url(#fg)" stroke="rgba(0,0,0,0.18)" strokeWidth="2" />
|
||
|
|
{children}
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const STICKERS: Record<string, React.ReactNode> = {
|
||
|
|
/* ----------------------------- faces ----------------------------- */
|
||
|
|
happy: (
|
||
|
|
<Face bg1="#ffe680" bg2="#f5b301">
|
||
|
|
<circle cx="36" cy="44" r="5" fill="#3a2a00" />
|
||
|
|
<circle cx="64" cy="44" r="5" fill="#3a2a00" />
|
||
|
|
<path d="M32 62 Q50 80 68 62" fill="none" stroke="#3a2a00" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
sad: (
|
||
|
|
<Face bg1="#bfe3ff" bg2="#5aa6e0">
|
||
|
|
<circle cx="36" cy="44" r="5" fill="#13314d" />
|
||
|
|
<circle cx="64" cy="44" r="5" fill="#13314d" />
|
||
|
|
<path d="M32 70 Q50 56 68 70" fill="none" stroke="#13314d" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
<path d="M64 50 q4 10 0 16 q-4 -6 0 -16" fill="#2f8fd6" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
cool: (
|
||
|
|
<Face bg1="#ffe680" bg2="#f5b301">
|
||
|
|
<rect x="24" y="38" width="22" height="13" rx="5" fill="#1b1b1b" />
|
||
|
|
<rect x="54" y="38" width="22" height="13" rx="5" fill="#1b1b1b" />
|
||
|
|
<rect x="46" y="42" width="8" height="3" fill="#1b1b1b" />
|
||
|
|
<path d="M36 64 Q52 74 66 60" fill="none" stroke="#3a2a00" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
love: (
|
||
|
|
<Face bg1="#ffc1e3" bg2="#ff5fa2">
|
||
|
|
<path d="M30 40 l6 -6 6 6 -6 8 z" fill="#c1124e" />
|
||
|
|
<path d="M58 40 l6 -6 6 6 -6 8 z" fill="#c1124e" />
|
||
|
|
<path d="M34 62 Q50 78 66 62" fill="none" stroke="#7a0b30" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
angry: (
|
||
|
|
<Face bg1="#ff9d7a" bg2="#e23b1e">
|
||
|
|
<path d="M28 38 l16 6" stroke="#3a0a00" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
<path d="M72 38 l-16 6" stroke="#3a0a00" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
<circle cx="37" cy="50" r="4.5" fill="#3a0a00" />
|
||
|
|
<circle cx="63" cy="50" r="4.5" fill="#3a0a00" />
|
||
|
|
<path d="M34 72 Q50 60 66 72" fill="none" stroke="#3a0a00" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
|
||
|
|
/* ------------------------------ hokm ----------------------------- */
|
||
|
|
"hokm-badge": (
|
||
|
|
<>
|
||
|
|
<defs>
|
||
|
|
<linearGradient id="gold" x1="0" y1="0" x2="0" y2="1">
|
||
|
|
<stop offset="0" stopColor="#f1da8a" />
|
||
|
|
<stop offset="0.55" stopColor="#d4af37" />
|
||
|
|
<stop offset="1" stopColor="#b8860b" />
|
||
|
|
</linearGradient>
|
||
|
|
</defs>
|
||
|
|
<circle cx="50" cy="50" r="42" fill="url(#gold)" stroke="#7a5a00" strokeWidth="3" />
|
||
|
|
<circle cx="50" cy="50" r="34" fill="none" stroke="#7a5a00" strokeWidth="1.5" opacity="0.5" />
|
||
|
|
<text x="50" y="46" textAnchor="middle" fontFamily="Vazirmatn, sans-serif" fontWeight="900" fontSize="26" fill="#3a2a04">
|
||
|
|
حکم
|
||
|
|
</text>
|
||
|
|
<text x="50" y="72" textAnchor="middle" fontSize="20" fill="#3a2a04">
|
||
|
|
♠
|
||
|
|
</text>
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
"kot-stamp": (
|
||
|
|
<g transform="rotate(-14 50 50)">
|
||
|
|
<circle cx="50" cy="50" r="40" fill="none" stroke="#d11a2a" strokeWidth="5" />
|
||
|
|
<circle cx="50" cy="50" r="33" fill="none" stroke="#d11a2a" strokeWidth="2" />
|
||
|
|
<text x="50" y="60" textAnchor="middle" fontFamily="Vazirmatn, sans-serif" fontWeight="900" fontSize="34" fill="#d11a2a">
|
||
|
|
کُت!
|
||
|
|
</text>
|
||
|
|
</g>
|
||
|
|
),
|
||
|
|
crown: (
|
||
|
|
<>
|
||
|
|
<defs>
|
||
|
|
<linearGradient id="cg" x1="0" y1="0" x2="0" y2="1">
|
||
|
|
<stop offset="0" stopColor="#ffe89a" />
|
||
|
|
<stop offset="1" stopColor="#d4af37" />
|
||
|
|
</linearGradient>
|
||
|
|
</defs>
|
||
|
|
<path d="M18 70 L24 34 L40 54 L50 26 L60 54 L76 34 L82 70 Z" fill="url(#cg)" stroke="#7a5a00" strokeWidth="2.5" strokeLinejoin="round" />
|
||
|
|
<rect x="18" y="70" width="64" height="10" rx="3" fill="url(#cg)" stroke="#7a5a00" strokeWidth="2.5" />
|
||
|
|
<circle cx="50" cy="24" r="5" fill="#ff5d73" />
|
||
|
|
<circle cx="24" cy="32" r="4" fill="#6aa6ff" />
|
||
|
|
<circle cx="76" cy="32" r="4" fill="#6aa6ff" />
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
"ace-spade": (
|
||
|
|
<>
|
||
|
|
<rect x="24" y="14" width="52" height="72" rx="8" fill="#fffdf7" stroke="#caa84a" strokeWidth="2.5" />
|
||
|
|
<text x="34" y="32" textAnchor="middle" fontSize="14" fontWeight="800" fill="#1b1b1b">A</text>
|
||
|
|
<text x="50" y="62" textAnchor="middle" fontSize="34" fill="#1b1b1b">♠</text>
|
||
|
|
<text x="66" y="80" textAnchor="middle" fontSize="14" fontWeight="800" fill="#1b1b1b" transform="rotate(180 66 75)">A</text>
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
|
||
|
|
/* ----------------------------- persian --------------------------- */
|
||
|
|
chai: (
|
||
|
|
<>
|
||
|
|
<path d="M40 24 q4 -8 0 -14 M52 24 q5 -9 0 -16" fill="none" stroke="#cbd5e1" strokeWidth="3" strokeLinecap="round" opacity="0.8" />
|
||
|
|
<path d="M34 30 H66 L61 78 Q60 84 54 84 H46 Q40 84 39 78 Z" fill="#fff" stroke="#caa84a" strokeWidth="2.5" />
|
||
|
|
<path d="M37 40 H63 L59 72 Q58 76 53 76 H47 Q42 76 41 72 Z" fill="#a8431a" />
|
||
|
|
<ellipse cx="50" cy="88" rx="26" ry="6" fill="#e9d9a8" stroke="#caa84a" strokeWidth="2" />
|
||
|
|
<path d="M66 44 q14 2 12 16 q-2 10 -14 8" fill="none" stroke="#caa84a" strokeWidth="3" />
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
afarin: (
|
||
|
|
<>
|
||
|
|
<defs>
|
||
|
|
<linearGradient id="rib" x1="0" y1="0" x2="0" y2="1">
|
||
|
|
<stop offset="0" stopColor="#f1da8a" />
|
||
|
|
<stop offset="1" stopColor="#c9a227" />
|
||
|
|
</linearGradient>
|
||
|
|
</defs>
|
||
|
|
<path d="M14 36 H86 L74 50 L86 64 H14 L26 50 Z" fill="url(#rib)" stroke="#7a5a00" strokeWidth="2" />
|
||
|
|
<text x="50" y="56" textAnchor="middle" fontFamily="Vazirmatn, sans-serif" fontWeight="900" fontSize="20" fill="#3a2a04">
|
||
|
|
آفرین
|
||
|
|
</text>
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
rose: (
|
||
|
|
<>
|
||
|
|
<path d="M50 60 C40 80 30 84 26 92 M50 60 C60 80 70 84 74 92" stroke="#2f7d32" strokeWidth="4" fill="none" />
|
||
|
|
<path d="M30 74 q-12 -2 -14 -12 q12 0 16 8 M70 74 q12 -2 14 -12 q-12 0 -16 8" fill="#2f7d32" opacity="0.85" />
|
||
|
|
<circle cx="50" cy="42" r="22" fill="#d11a2a" />
|
||
|
|
<path d="M50 24 a18 18 0 0 1 0 36 a12 12 0 0 0 0 -24 a8 8 0 0 1 0 -12" fill="#a30f1f" opacity="0.7" />
|
||
|
|
<circle cx="50" cy="42" r="7" fill="#7a0b16" />
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
|
||
|
|
/* ------------------------------ taunt ---------------------------- */
|
||
|
|
clown: (
|
||
|
|
<Face bg1="#fff3d6" bg2="#ffd98a">
|
||
|
|
<circle cx="36" cy="44" r="4.5" fill="#1b1b1b" />
|
||
|
|
<circle cx="64" cy="44" r="4.5" fill="#1b1b1b" />
|
||
|
|
<circle cx="50" cy="56" r="7" fill="#e23b1e" />
|
||
|
|
<path d="M30 66 Q50 84 70 66" fill="none" stroke="#e23b1e" strokeWidth="5" strokeLinecap="round" />
|
||
|
|
<circle cx="22" cy="40" r="6" fill="#ff5fa2" opacity="0.8" />
|
||
|
|
<circle cx="78" cy="40" r="6" fill="#ff5fa2" opacity="0.8" />
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
sleep: (
|
||
|
|
<Face bg1="#ffe680" bg2="#f5b301">
|
||
|
|
<path d="M30 44 q6 -5 12 0 M58 44 q6 -5 12 0" fill="none" stroke="#3a2a00" strokeWidth="4" strokeLinecap="round" />
|
||
|
|
<circle cx="50" cy="64" r="5" fill="none" stroke="#3a2a00" strokeWidth="4" />
|
||
|
|
<text x="74" y="34" fontFamily="Vazirmatn, sans-serif" fontSize="16" fontWeight="900" fill="#13314d">z</text>
|
||
|
|
<text x="82" y="24" fontFamily="Vazirmatn, sans-serif" fontSize="11" fontWeight="900" fill="#13314d">z</text>
|
||
|
|
</Face>
|
||
|
|
),
|
||
|
|
weak: (
|
||
|
|
<>
|
||
|
|
<circle cx="50" cy="50" r="42" fill="#1f2b4d" stroke="#d11a2a" strokeWidth="3" />
|
||
|
|
<path d="M50 30 v26 M50 56 l-9 -9 M50 56 l9 -9" stroke="#ff6b81" strokeWidth="5" fill="none" strokeLinecap="round" />
|
||
|
|
<text x="50" y="80" textAnchor="middle" fontFamily="Vazirmatn, sans-serif" fontWeight="900" fontSize="16" fill="#ff6b81">
|
||
|
|
ضعیف!
|
||
|
|
</text>
|
||
|
|
</>
|
||
|
|
),
|
||
|
|
};
|
||
|
|
|
||
|
|
export const STICKER_IDS = Object.keys(STICKERS);
|
||
|
|
|
||
|
|
export function Sticker({ id, size = 64, className }: { id: string; size?: number } & SvgProps) {
|
||
|
|
const art = STICKERS[id];
|
||
|
|
if (!art) return null;
|
||
|
|
return (
|
||
|
|
<svg viewBox="0 0 100 100" width={size} height={size} className={className} role="img">
|
||
|
|
{art}
|
||
|
|
</svg>
|
||
|
|
);
|
||
|
|
}
|