This commit is contained in:
eric
2026-03-10 01:35:37 -05:00
parent ff51622bb6
commit be7a298604
69 changed files with 11016 additions and 57 deletions

View File

@@ -0,0 +1,135 @@
"use client";
import { useState, useEffect } from "react";
import Link from "next/link";
import { COMMUNITY_CONFIG } from "@/config/course";
import { isPaid } from "@/app/lib/payment";
export function CommunityButton() {
const [open, setOpen] = useState(false);
const [paid, setPaid] = useState(false);
useEffect(() => {
setPaid(isPaid());
const onPay = () => setPaid(isPaid());
window.addEventListener("pay:updated", onPay);
return () => window.removeEventListener("pay:updated", onPay);
}, []);
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") setOpen(false);
};
if (open) {
window.addEventListener("keydown", onKeyDown);
document.body.style.overflow = "hidden";
}
return () => {
window.removeEventListener("keydown", onKeyDown);
document.body.style.overflow = "";
};
}, [open]);
if (!COMMUNITY_CONFIG.enabled || !COMMUNITY_CONFIG.wechat) return null;
return (
<>
<button
type="button"
onClick={() => setOpen(true)}
className="text-sm text-[var(--muted-foreground)] transition hover:text-[var(--foreground)]"
>
{COMMUNITY_CONFIG.wechat}
</button>
{open && (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm p-4"
onClick={() => setOpen(false)}
>
<div
className="relative w-full max-w-[420px] overflow-hidden rounded-2xl border border-[var(--border)] bg-[var(--background)] shadow-2xl"
onClick={(e) => e.stopPropagation()}
>
<div className="absolute inset-x-0 top-0 h-1 bg-gradient-to-r from-[var(--accent)] via-cyan-400 to-[var(--accent)]" />
<button
type="button"
onClick={() => setOpen(false)}
className="absolute right-3 top-3 rounded-full p-2 text-[var(--muted-foreground)] transition hover:bg-[var(--muted)] hover:text-[var(--foreground)]"
aria-label="关闭"
>
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
{paid ? (
<div className="p-8 pt-10">
<div className="mb-6 text-center">
<div className="mb-3 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-[var(--accent)]/30 to-cyan-500/20 text-3xl shadow-lg">
💬
</div>
<h3 className="text-xl font-semibold"></h3>
<p className="mt-2 text-sm text-[var(--muted-foreground)]">
</p>
</div>
<div className="flex justify-center">
<div className="relative flex h-56 w-56 items-center justify-center rounded-2xl bg-gradient-to-br from-[var(--card)] to-[var(--muted)]/30 p-5 shadow-inner ring-2 ring-[var(--accent)]/20">
<img
src={COMMUNITY_CONFIG.qrCodeUrl}
alt="社群二维码"
className="h-full w-full object-contain"
onError={(e) => {
const target = e.target as HTMLImageElement;
target.style.display = "none";
const fallback = target.parentElement?.querySelector(".qr-fallback");
if (fallback) (fallback as HTMLElement).classList.remove("hidden");
}}
/>
<div className="qr-fallback hidden absolute inset-0 flex flex-col items-center justify-center gap-2 rounded-2xl bg-[var(--muted)]/40 p-4 text-center text-sm text-[var(--muted-foreground)]">
<span className="text-4xl">📱</span>
<span></span>
<span className="text-xs">config/course.ts qrCodeUrl</span>
</div>
</div>
</div>
<p className="mt-5 text-center text-sm text-[var(--muted-foreground)]">
</p>
</div>
) : (
<div className="p-8 pt-10">
<div className="mb-6 text-center">
<div className="mb-3 inline-flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-amber-500/20 to-orange-500/10 text-4xl shadow-lg">
🔒
</div>
<h3 className="text-xl font-semibold"></h3>
<p className="mt-2 text-sm leading-relaxed text-[var(--muted-foreground)]">
</p>
</div>
<div className="flex flex-col gap-3">
<Link
href="/pay"
className="rounded-xl bg-[var(--accent)] px-6 py-4 text-center font-medium text-[var(--accent-foreground)] transition hover:opacity-90"
onClick={() => setOpen(false)}
>
</Link>
<button
type="button"
onClick={() => setOpen(false)}
className="rounded-xl border border-[var(--border)] px-6 py-3 text-sm transition hover:bg-[var(--muted)]"
>
</button>
</div>
</div>
)}
</div>
</div>
)}
</>
);
}