testing 101

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-06-30 19:32:00 +08:00
parent fe47bdea3c
commit 17326b2c2e
78 changed files with 4804 additions and 1054 deletions
@@ -0,0 +1,174 @@
const BADGE_GRADIENTS = {
// ── Original 12 ──────────────────────────────────────────────────────────────
purple: "linear-gradient(145deg, #a855f7cc 0%, #7e22cebf 55%, #3b0764b3 100%)",
green: "linear-gradient(145deg, #4ade80cc 0%, #15803dbf 55%, #14532db3 100%)",
rose: "linear-gradient(145deg, #fb7185cc 0%, #be123cbf 55%, #4c0519b3 100%)",
amber: "linear-gradient(145deg, #fbbf24cc 0%, #d97706bf 55%, #78350fb3 100%)",
sky: "linear-gradient(145deg, #38bdf8cc 0%, #0369a1bf 55%, #0c4a6eb3 100%)",
indigo: "linear-gradient(145deg, #818cf8cc 0%, #4338cabf 55%, #1e1b4bb3 100%)",
teal: "linear-gradient(145deg, #2dd4bfcc 0%, #0f766ebf 55%, #042f2eb3 100%)",
orange: "linear-gradient(145deg, #fb923ccc 0%, #c2410cbf 55%, #431407b3 100%)",
pink: "linear-gradient(145deg, #f472b6cc 0%, #be185dbf 55%, #500724b3 100%)",
cyan: "linear-gradient(145deg, #22d3eecc 0%, #0e7490bf 55%, #083344b3 100%)",
lime: "linear-gradient(145deg, #a3e635cc 0%, #4d7c0fbf 55%, #1a2e05b3 100%)",
slate: "linear-gradient(145deg, #94a3b8cc 0%, #475569bf 55%, #0f172ab3 100%)",
// ── Extended 18 ──────────────────────────────────────────────────────────────
red: "linear-gradient(145deg, #f87171cc 0%, #b91c1cbf 55%, #450a0ab3 100%)",
yellow: "linear-gradient(145deg, #fde047cc 0%, #a16207bf 55%, #3d1f00b3 100%)",
violet: "linear-gradient(145deg, #a78bfacc 0%, #6d28d9bf 55%, #2e1065b3 100%)",
fuchsia: "linear-gradient(145deg, #e879f9cc 0%, #a21cafbf 55%, #4a044eb3 100%)",
emerald: "linear-gradient(145deg, #34d399cc 0%, #047857bf 55%, #064e3bb3 100%)",
blue: "linear-gradient(145deg, #60a5facc 0%, #1d4ed8bf 55%, #1e3a8ab3 100%)",
zinc: "linear-gradient(145deg, #a1a1aacc 0%, #3f3f46bf 55%, #18181bb3 100%)",
stone: "linear-gradient(145deg, #d6d3d1cc 0%, #57534ebf 55%, #1c1917b3 100%)",
brown: "linear-gradient(145deg, #d97706cc 0%, #7c2d12bf 55%, #1c0902b3 100%)",
gold: "linear-gradient(145deg, #fcd34dcc 0%, #b45309bf 55%, #451a03b3 100%)",
navy: "linear-gradient(145deg, #93c5fdcc 0%, #1e40afbf 55%, #0f172ab3 100%)",
forest: "linear-gradient(145deg, #86efaccc 0%, #166534bf 55%, #052e16b3 100%)",
wine: "linear-gradient(145deg, #fda4afcc 0%, #9f1239bf 55%, #3b0014b3 100%)",
charcoal: "linear-gradient(145deg, #9ca3afcc 0%, #374151bf 55%, #111827b3 100%)",
midnight: "linear-gradient(145deg, #818cf8cc 0%, #312e81bf 55%, #0d0c1db3 100%)",
lavender: "linear-gradient(145deg, #ddd6fecc 0%, #7c3aedbf 55%, #2e1065b3 100%)",
salmon: "linear-gradient(145deg, #fca5a5cc 0%, #e11d48bf 55%, #4c0519b3 100%)",
mint: "linear-gradient(145deg, #a7f3d0cc 0%, #059669bf 55%, #022c22b3 100%)",
};
const SOLID_GRADIENTS = {
// ── Original 12 ──────────────────────────────────────────────────────────────
purple: "linear-gradient(145deg, #a855f7 0%, #7e22ce 55%, #3b0764 100%)",
green: "linear-gradient(145deg, #4ade80 0%, #15803d 55%, #14532d 100%)",
rose: "linear-gradient(145deg, #fb7185 0%, #be123c 55%, #4c0519 100%)",
amber: "linear-gradient(145deg, #fbbf24 0%, #d97706 55%, #78350f 100%)",
sky: "linear-gradient(145deg, #38bdf8 0%, #0369a1 55%, #0c4a6e 100%)",
indigo: "linear-gradient(145deg, #818cf8 0%, #4338ca 55%, #1e1b4b 100%)",
teal: "linear-gradient(145deg, #2dd4bf 0%, #0f766e 55%, #042f2e 100%)",
orange: "linear-gradient(145deg, #fb923c 0%, #c2410c 55%, #431407 100%)",
pink: "linear-gradient(145deg, #f472b6 0%, #be185d 55%, #500724 100%)",
cyan: "linear-gradient(145deg, #22d3ee 0%, #0e7490 55%, #083344 100%)",
lime: "linear-gradient(145deg, #a3e635 0%, #4d7c0f 55%, #1a2e05 100%)",
slate: "linear-gradient(145deg, #94a3b8 0%, #475569 55%, #0f172a 100%)",
// ── Extended 18 ──────────────────────────────────────────────────────────────
red: "linear-gradient(145deg, #f87171 0%, #b91c1c 55%, #450a0a 100%)",
yellow: "linear-gradient(145deg, #fde047 0%, #a16207 55%, #3d1f00 100%)",
violet: "linear-gradient(145deg, #a78bfa 0%, #6d28d9 55%, #2e1065 100%)",
fuchsia: "linear-gradient(145deg, #e879f9 0%, #a21caf 55%, #4a044e 100%)",
emerald: "linear-gradient(145deg, #34d399 0%, #047857 55%, #064e3b 100%)",
blue: "linear-gradient(145deg, #60a5fa 0%, #1d4ed8 55%, #1e3a8a 100%)",
zinc: "linear-gradient(145deg, #a1a1aa 0%, #3f3f46 55%, #18181b 100%)",
stone: "linear-gradient(145deg, #d6d3d1 0%, #57534e 55%, #1c1917 100%)",
brown: "linear-gradient(145deg, #d97706 0%, #7c2d12 55%, #1c0902 100%)",
gold: "linear-gradient(145deg, #fcd34d 0%, #b45309 55%, #451a03 100%)",
navy: "linear-gradient(145deg, #93c5fd 0%, #1e40af 55%, #0f172a 100%)",
forest: "linear-gradient(145deg, #86efac 0%, #166534 55%, #052e16 100%)",
wine: "linear-gradient(145deg, #fda4af 0%, #9f1239 55%, #3b0014 100%)",
charcoal: "linear-gradient(145deg, #9ca3af 0%, #374151 55%, #111827 100%)",
midnight: "linear-gradient(145deg, #818cf8 0%, #312e81 55%, #0d0c1d 100%)",
lavender: "linear-gradient(145deg, #ddd6fe 0%, #7c3aed 55%, #2e1065 100%)",
salmon: "linear-gradient(145deg, #fca5a5 0%, #e11d48 55%, #4c0519 100%)",
mint: "linear-gradient(145deg, #a7f3d0 0%, #059669 55%, #022c22 100%)",
};
export default function CourseBadge({ title = "Course Title", level, color = "purple", imageUrl, mini = false }) {
const levelLabel = level
? `${level.charAt(0).toUpperCase()}${level.slice(1)} Level`
: null;
// ── Mini variant: just the gradient + logo mark, no text/line ──────────────
if (mini) {
return (
<div className="relative w-12 h-12 rounded-xl overflow-hidden flex-shrink-0 select-none shadow-md">
{imageUrl ? (
<>
<div
className="absolute inset-0"
style={{
backgroundImage: `url(${imageUrl})`,
backgroundSize: "cover",
backgroundPosition: "center",
}}
/>
<div
className="absolute inset-0"
style={{ background: BADGE_GRADIENTS[color] ?? BADGE_GRADIENTS.purple }}
/>
</>
) : (
<div
className="absolute inset-0"
style={{ background: SOLID_GRADIENTS[color] ?? SOLID_GRADIENTS.purple }}
/>
)}
{/* HIDE OUR LOGO */}
{/* <div className="relative h-full flex items-center justify-center">
<img src="/philpro-white-single.png" alt="Philpro" className="h-5 w-5 object-contain drop-shadow" />
</div> */}
</div>
);
}
return (
<div className="relative w-44 h-48 rounded-2xl overflow-hidden flex-shrink-0 select-none shadow-lg">
{/* ── Layer 1: Background — image when set, solid gradient otherwise ── */}
{imageUrl ? (
<div
className="absolute inset-0"
style={{
backgroundImage: `url(${imageUrl})`,
backgroundSize: "cover",
backgroundPosition: "center",
}}
/>
) : (
<div
className="absolute inset-0"
style={{ background: SOLID_GRADIENTS[color] ?? SOLID_GRADIENTS.purple }}
/>
)}
{/* ── Layer 2: Gradient colour overlay on top of the image ── */}
{imageUrl && (
<div
className="absolute inset-0"
style={{ background: BADGE_GRADIENTS[color] ?? BADGE_GRADIENTS.purple }}
/>
)}
{/* ── Layer 3: Soft glow in the upper-right corner (always present) ── */}
<div
className="absolute -top-6 -right-6 w-28 h-28 rounded-full pointer-events-none"
style={{
background: "radial-gradient(circle, rgba(255,255,255,0.15), transparent 70%)",
}}
/>
{/* ── Layer 4: Content ── */}
<div className="relative flex flex-col justify-between h-full p-3.5">
<div className="flex-1 flex flex-col justify-center gap-1.5 pr-2">
<p className="text-white font-bold text-sm leading-snug line-clamp-4 drop-shadow">
{title}
</p>
{levelLabel && (
<p className="text-white/60 text-[9.5px] font-semibold uppercase tracking-widest drop-shadow">
{levelLabel}
</p>
)}
</div>
<div>
<div className="border-t border-white/20 mb-2" />
<div className="flex items-center justify-between gap-2">
<img
src="/philpro-white-single.png"
alt="Philpro"
className="h-5 object-contain drop-shadow"
/>
<span className="text-white/75 text-[8.5px] font-bold uppercase tracking-[0.12em] text-right leading-tight drop-shadow">
Course<br />Completion
</span>
</div>
</div>
</div>
</div>
);
}
@@ -78,7 +78,7 @@ function UserDetailDialog({ open, onOpenChange, entry, courseId }) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-lg flex flex-col max-h-[80vh]">
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<div className="flex items-center gap-3">
{entry && <UserAvatar name={entry.user.full_name} email={entry.user.email} avatarUrl={entry.user.avatar_url} />}
@@ -110,7 +110,7 @@ function UserDetailDialog({ open, onOpenChange, entry, courseId }) {
<Separator />
{/* ── Unit / lesson breakdown — fills remaining height and scrolls ── */}
<ScrollArea className="flex-1 min-h-0 pr-2">
<ScrollArea className="max-h-[50vh] pr-2">
{detailLoading && !breakdown ? (
<div className="space-y-3 py-1">
{[...Array(4)].map((_, i) => (