Updated so that the rules and class text can be updated through the admin page
This commit is contained in:
@@ -8,8 +8,12 @@ import { IoIosMail } from "react-icons/io";
|
||||
import Footer from '../components/Footer';
|
||||
import Header from '../components/Header';
|
||||
import BeachRegistrationForm from './BeachRegistrationForm';
|
||||
import { SiteConfig } from '../lib/config';
|
||||
import Image from 'next/image';
|
||||
import matsommar from "../../public/images/hk-mosf.webp";
|
||||
|
||||
export default function BeachClientPage({ config, turnstileSiteKey }: { config: any, turnstileSiteKey: string }) {
|
||||
|
||||
export default function BeachClientPage({ config, turnstileSiteKey }: { config: SiteConfig, turnstileSiteKey: string }) {
|
||||
const [timeInfo, setTimeInfo] = useState({
|
||||
dateStr: 'Laddar...',
|
||||
matchStr: 'Laddar...',
|
||||
@@ -54,9 +58,9 @@ export default function BeachClientPage({ config, turnstileSiteKey }: { config:
|
||||
{/* Logotyp med subtil hover-effekt */}
|
||||
<div className="relative group cursor-default">
|
||||
<div className="absolute -inset-4 bg-white/20 blur-2xl rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-700" />
|
||||
<img
|
||||
<Image
|
||||
className="w-full max-w-62.5 md:max-w-75 relative drop-shadow-2xl transform hover:scale-105 transition-transform duration-500"
|
||||
src="/images/hk-mosf.webp"
|
||||
src={matsommar}
|
||||
alt="Mat- & Sommarfesten"
|
||||
/>
|
||||
</div>
|
||||
@@ -130,20 +134,19 @@ export default function BeachClientPage({ config, turnstileSiteKey }: { config:
|
||||
<FaClipboardList size={24} />
|
||||
<h4 className="font-beachday text-2xl uppercase tracking-[0.05em] text-black">Regler</h4>
|
||||
</div>
|
||||
<p className="text-gray-700 text-base leading-relaxed">
|
||||
Matcherna spelas 4v4 med <a target="_blank" rel="noreferrer" className="text-[#39979f] font-bold hover:underline" href="https://www.volleyboll.se/forbundet/valkommen-till-volleyboll/grenar-och-spelformer/volleyboll">inomhusregler</a>,
|
||||
förutom poängräkningen som följer reglerna för <a target="_blank" rel="noreferrer" className="text-[#39979f] font-bold hover:underline" href="https://www.volleyboll.se/forbundet/valkommen-till-volleyboll/grenar-och-spelformer/beachvolley">beachvolley</a>.
|
||||
Turneringsformen som kommer spelas är <span className='italic'>Double Elimination</span> vilket betyder att alla lag spelar minst två matcher under dagen.
|
||||
</p>
|
||||
<div
|
||||
className="text-gray-700 text-base leading-relaxed [&_a]:text-[#39979f] [&_a]:font-bold [&_a:hover]:underline [&_i]:italic [&_em]:italic"
|
||||
dangerouslySetInnerHTML={{ __html: config.beachPage?.rulesText || "" }}
|
||||
/>
|
||||
|
||||
<div className="flex items-center gap-3 text-[#cc8124] mt-6">
|
||||
<FaUsers size={24} />
|
||||
<h4 className="font-beachday text-2xl uppercase tracking-[0.05em] text-black">Klasser</h4>
|
||||
</div>
|
||||
<div className="text-gray-700 text-sm space-y-3">
|
||||
<p className="leading-snug">Turneringen kommer att delas upp i flera olika klasser beroende på antal anmälda lag och dess nivå:</p>
|
||||
<p className="leading-snug">{config.beachPage?.classesIntroText}</p>
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{classesData.map((c: any, i: number) => (
|
||||
{classesData.map((c: { name: string; color: string; desc?: string }, i: number) => (
|
||||
<span
|
||||
key={i}
|
||||
className="px-2.5 py-1 rounded-md font-bold border text-xs tracking-wider"
|
||||
@@ -153,7 +156,7 @@ export default function BeachClientPage({ config, turnstileSiteKey }: { config:
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<p className="italic text-xs text-gray-500">Gör en gissning på er nivå i anmälan – skriv gärna något extra om ni är osäkra. Vi meddelar om det skulle bli ändringar.</p>
|
||||
<p className="italic text-xs text-gray-500">{config.beachPage?.classesOutroText}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -233,6 +236,6 @@ export default function BeachClientPage({ config, turnstileSiteKey }: { config:
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
@@ -6,8 +6,9 @@ import { Turnstile, TurnstileInstance } from '@marsidev/react-turnstile';
|
||||
import React, { useRef, useActionState, useEffect } from 'react';
|
||||
import { FaUser, FaEnvelope, FaPhone, FaUsers, FaTrophy, FaCheckCircle, FaExclamationTriangle } from "react-icons/fa";
|
||||
import { submitRegistration } from './actions';
|
||||
import { SiteConfig } from '../lib/config';
|
||||
|
||||
export default function BeachRegistrationForm({ config, turnstileSiteKey }: { config: any, turnstileSiteKey: string }) {
|
||||
export default function BeachRegistrationForm({ config, turnstileSiteKey }: { config: SiteConfig, turnstileSiteKey: string }) {
|
||||
const [state, formAction, isPending] = useActionState(submitRegistration, null);
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const turnstileRef = useRef<TurnstileInstance>(null);
|
||||
@@ -107,7 +108,7 @@ export default function BeachRegistrationForm({ config, turnstileSiteKey }: { co
|
||||
<div className="flex-2">
|
||||
<label className="font-bold text-[#39979f] mb-3 block text-sm uppercase">Välj klass</label>
|
||||
<div className={`grid grid-cols-2 md:grid-cols-${Math.min(classesData.length, 3)} gap-3`}>
|
||||
{classesData.map((c: any) => (
|
||||
{classesData.map((c: { name: string; color: string; desc?: string }) => (
|
||||
<LevelButton
|
||||
key={c.name}
|
||||
value={c.name}
|
||||
@@ -130,7 +131,7 @@ export default function BeachRegistrationForm({ config, turnstileSiteKey }: { co
|
||||
|
||||
<input type="text" name="website" className="hidden" tabIndex={-1} />
|
||||
|
||||
<div className="flex justify-center py-2"><Turnstile ref={turnstileRef} siteKey={turnstileSiteKey} options={{ theme: 'light' }}/></div>
|
||||
<div className="flex justify-center py-2"><Turnstile ref={turnstileRef} siteKey={turnstileSiteKey} options={{ theme: 'light' }} /></div>
|
||||
|
||||
{state && (
|
||||
<div className={`flex items-center gap-3 p-5 rounded-2xl font-bold transition-all ${state.success ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'}`}>
|
||||
@@ -153,7 +154,7 @@ export default function BeachRegistrationForm({ config, turnstileSiteKey }: { co
|
||||
}
|
||||
|
||||
// Uppdaterad med defaultChecked support
|
||||
function LevelButton({ value, label, desc, color, defaultChecked }: any) {
|
||||
function LevelButton({ value, label, desc, color, defaultChecked }: { value: string; label: string; desc?: string; color: string; defaultChecked?: boolean }) {
|
||||
return (
|
||||
<label className="cursor-pointer flex-1 relative" style={{ '--class-color': color } as React.CSSProperties}>
|
||||
<input
|
||||
@@ -173,7 +174,7 @@ function LevelButton({ value, label, desc, color, defaultChecked }: any) {
|
||||
);
|
||||
}
|
||||
|
||||
function InputGroup({ icon, ...props }: any) {
|
||||
function InputGroup({ icon, ...props }: React.InputHTMLAttributes<HTMLInputElement> & { icon: React.ReactNode }) {
|
||||
return (
|
||||
<div className="relative group">
|
||||
<div className="absolute left-4 top-1/2 -translate-y-1/2 text-[#e6be8a] group-focus-within:text-[#39979f] transition-colors">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import nodemailer from 'nodemailer';
|
||||
|
||||
export async function submitRegistration(prevState: any, formData: FormData) {
|
||||
export async function submitRegistration(prevState: unknown, formData: FormData) {
|
||||
// 1. Spara all rådata direkt för att kunna skicka tillbaka den vid fel
|
||||
const rawData = {
|
||||
name: formData.get('name') as string,
|
||||
|
||||
Reference in New Issue
Block a user