feat: Wabenhain Honig-Shop Anwendung
Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei: Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich (Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung, PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma- Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
1 parent
5c76fcc266
commit
c7927f2883
240 files changed
+26096
-137
No files matched your search
@@ -0,0 +1,60 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Script from "next/script";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
turnstile?: {
|
||||
render: (container: HTMLElement, options: Record<string, unknown>) => string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface TurnstileWidgetProps {
|
||||
siteKey: string;
|
||||
onVerify: (token: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloudflare-Turnstile-CAPTCHA-Widget. Wird nur eingebunden, wenn eine
|
||||
* NEXT_PUBLIC_TURNSTILE_SITE_KEY konfiguriert ist (siehe README) — ohne
|
||||
* Konfiguration rendern die umgebenden Formulare gar nicht erst diese
|
||||
* Komponente und bleiben unveraendert nutzbar.
|
||||
*/
|
||||
export function TurnstileWidget({ siteKey, onVerify }: TurnstileWidgetProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [scriptLoaded, setScriptLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!scriptLoaded || !containerRef.current || !window.turnstile) return;
|
||||
window.turnstile.render(containerRef.current, {
|
||||
sitekey: siteKey,
|
||||
callback: onVerify,
|
||||
"expired-callback": () => onVerify(""),
|
||||
"error-callback": () => onVerify(""),
|
||||
});
|
||||
}, [scriptLoaded, siteKey, onVerify]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Script
|
||||
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
|
||||
strategy="afterInteractive"
|
||||
onLoad={() => setScriptLoaded(true)}
|
||||
/>
|
||||
<div ref={containerRef} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** Turnstile-Widget fuer klassische (nicht per fetch/JSON gesendete) Formulare: legt das Token als Hidden-Field ab. */
|
||||
export function TurnstileField({ siteKey, name = "turnstileToken" }: { siteKey: string; name?: string }) {
|
||||
const [token, setToken] = useState("");
|
||||
return (
|
||||
<>
|
||||
<TurnstileWidget siteKey={siteKey} onVerify={setToken} />
|
||||
<input type="hidden" name={name} value={token} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user