Files
gitlab-instance-0a899031_no…/app/components/CommunityButton.tsx
2026-03-10 01:35:37 -05:00

135 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"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>
)}
</>
);
}