This commit is contained in:
Sebastian 2026-02-24 21:53:49 +01:00
parent d07a5bd9a8
commit 8c620abbe6
5 changed files with 147 additions and 97 deletions

View file

@ -20,7 +20,6 @@ public class ParticipantRegistrationRequest
public string? PhoneNumber { get; set; } public string? PhoneNumber { get; set; }
[EmailAddress]
public string? Email { get; set; } public string? Email { get; set; }
[Required] [Required]

View file

@ -15,6 +15,7 @@ interface EventContent {
rulesAndGdpr: string; rulesAndGdpr: string;
additionalInfo: string; additionalInfo: string;
registrationEnabled: boolean; registrationEnabled: boolean;
volunteerRegistrationEnabled?: boolean;
visitorOnly: boolean; visitorOnly: boolean;
volunteerAreas: string; volunteerAreas: string;
} }
@ -128,6 +129,19 @@ export default function AdminDashboard() {
Endast Besöks-registrering (Ingen Dator) Endast Besöks-registrering (Ingen Dator)
</label> </label>
</div> </div>
<div className="flex items-center">
<input
type="checkbox"
id="volunteerRegistrationEnabled"
name="volunteerRegistrationEnabled"
className="h-5 w-5 text-blue-600 focus:ring-blue-500 border-gray-300 rounded cursor-pointer"
checked={content.volunteerRegistrationEnabled ?? true}
onChange={(e) => setContent(prev => prev ? { ...prev, volunteerRegistrationEnabled: e.target.checked } : null)}
/>
<label htmlFor="volunteerRegistrationEnabled" className="ml-3 text-sm font-semibold text-gray-900 cursor-pointer">
Aktivera Funktionärs-anmälan
</label>
</div>
</div> </div>
<div className="col-span-2"> <div className="col-span-2">

View file

@ -15,6 +15,7 @@ interface EventContent {
rulesAndGdpr: string; rulesAndGdpr: string;
additionalInfo: string; additionalInfo: string;
registrationEnabled: boolean; registrationEnabled: boolean;
volunteerRegistrationEnabled?: boolean;
visitorOnly: boolean; visitorOnly: boolean;
volunteerAreas: string; volunteerAreas: string;
} }
@ -73,6 +74,15 @@ export default function LandingPage() {
{/* Info Section */} {/* Info Section */}
<main className="max-w-4xl mx-auto py-12 px-6 space-y-20"> <main className="max-w-4xl mx-auto py-12 px-6 space-y-20">
{!content.registrationEnabled ? (
<section className="flex flex-col items-center justify-center py-20 space-y-6">
<h2 className="text-4xl font-extrabold text-gray-900">Anmälan är stängd</h2>
<p className="text-xl text-gray-600 text-center max-w-lg">
Vi tar tyvärr inte emot fler anmälningar just nu. Håll utkik för framtida evenemang!
</p>
</section>
) : (
<>
{(content.eventDate || {(content.eventDate ||
content.eventTime || content.eventTime ||
content.locationName || content.locationName ||
@ -152,10 +162,13 @@ export default function LandingPage() {
</Link> </Link>
</section> </section>
)} )}
</>
)}
</main> </main>
{/* Footer */} {/* Footer */}
<footer className="bg-gray-50 py-12 text-center text-gray-500 border-t border-gray-100 relative"> <footer className="bg-gray-50 py-12 text-center text-gray-500 border-t border-gray-100 relative">
{(content.volunteerRegistrationEnabled ?? true) && (
<div className="mb-8"> <div className="mb-8">
<p className="text-gray-600 mb-4">Vill du hjälpa till?</p> <p className="text-gray-600 mb-4">Vill du hjälpa till?</p>
<Link <Link
@ -165,6 +178,7 @@ export default function LandingPage() {
Bli Funktionär Bli Funktionär
</Link> </Link>
</div> </div>
)}
<p>© 2026 Vbytes Gaming. Alla rättigheter förbehållna.</p> <p>© 2026 Vbytes Gaming. Alla rättigheter förbehållna.</p>
</footer> </footer>
</div> </div>

View file

@ -169,10 +169,6 @@ export default function RegisterPage() {
"Vårdnadshavarens e-postadress är ogiltig."; "Vårdnadshavarens e-postadress är ogiltig.";
} }
if (formData.email.trim() && !isValidEmail(formData.email.trim())) {
nextFieldErrors.email = "Din e-postadress är ogiltig.";
}
if (!formData.hasApprovedGdpr) { if (!formData.hasApprovedGdpr) {
nextFieldErrors.hasApprovedGdpr = "Du måste godkänna GDPR för att anmäla dig."; nextFieldErrors.hasApprovedGdpr = "Du måste godkänna GDPR för att anmäla dig.";
} }
@ -240,7 +236,9 @@ export default function RegisterPage() {
if (response.ok) { if (response.ok) {
setMessage({ setMessage({
type: "success", type: "success",
text: "Registreringen är klar! Du är nu anmäld till LAN:et.", text: isMember
? "Registreringen är klar! Du är nu anmäld till LAN:et."
: "Din anmälan är mottagen, men det återstår ett viktigt steg för att du ska få delta.",
}); });
setShowBecomeMemberCta(!isMember); setShowBecomeMemberCta(!isMember);
@ -300,19 +298,22 @@ export default function RegisterPage() {
{message.type === "success" && ( {message.type === "success" && (
<div className="mb-8 space-y-6"> <div className="mb-8 space-y-6">
<div className="p-6 rounded-lg text-center bg-green-50 text-green-800 border border-green-200"> <div className="p-6 rounded-lg text-center bg-green-50 text-green-800 border border-green-200">
<div className="text-4xl mb-4">🎉</div> <div className="text-4xl mb-4">{showBecomeMemberCta ? "⏳" : "🎉"}</div>
<h2 className="text-xl font-bold mb-2">Klart!</h2> <h2 className="text-xl font-bold mb-2">
{showBecomeMemberCta ? "Nästan Klart!" : "Klart!"}
</h2>
<p>{message.text}</p> <p>{message.text}</p>
</div> </div>
{showBecomeMemberCta && ( {showBecomeMemberCta && (
<div className="bg-gray-50 p-6 rounded-lg border border-gray-200"> <div className="bg-gray-50 p-6 rounded-lg border border-orange-200">
<h3 className="text-lg font-semibold text-gray-900 mb-2"> <h3 className="text-lg font-semibold text-gray-900 mb-2">
Du är inte medlem än Du är inte medlem än
</h3> </h3>
<p className="text-gray-600 mb-4"> <p className="text-gray-600 mb-4">
Vi hittade dig inte i vårt medlemsregister. Genom att bli Vi hittade dig inte i vårt medlemsregister. För att kunna
medlem i vBytes hjälper du oss att anordna fler och bättre delta LAN:et måste du vara medlem i vBytes. Medlemskapet är
gratis och hjälper oss dessutom att anordna fler och bättre
LAN! LAN!
</p> </p>
<a <a
@ -470,7 +471,7 @@ export default function RegisterPage() {
E-post E-post
</label> </label>
<input <input
type="email" type="text"
name="email" name="email"
id="email" id="email"
className={`mt-1 block w-full rounded-md shadow-sm sm:text-sm p-2 border text-gray-900 ${fieldErrors.email ? "border-red-500 focus:border-red-500 focus:ring-red-500" : "border-gray-300 focus:border-blue-500 focus:ring-blue-500"}`} className={`mt-1 block w-full rounded-md shadow-sm sm:text-sm p-2 border text-gray-900 ${fieldErrors.email ? "border-red-500 focus:border-red-500 focus:ring-red-500" : "border-gray-300 focus:border-blue-500 focus:ring-blue-500"}`}
@ -659,7 +660,7 @@ export default function RegisterPage() {
</div> </div>
</div> </div>
{message.text && ( {message.text && message.type !== "success" && (
<div <div
className={`p-4 rounded-md ${ className={`p-4 rounded-md ${
message.type === "success" message.type === "success"

View file

@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";
interface EventContent { interface EventContent {
volunteerAreas: string; volunteerAreas: string;
volunteerRegistrationEnabled?: boolean;
} }
const isValidEmail = (value: string) => const isValidEmail = (value: string) =>
@ -43,6 +44,27 @@ export default function VolunteerPage() {
.catch((err) => console.error("Failed to fetch content", err)); .catch((err) => console.error("Failed to fetch content", err));
}, []); }, []);
if (content && content.volunteerRegistrationEnabled === false) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4">
<div className="max-w-md w-full bg-white p-8 rounded-xl shadow-md text-center">
<h1 className="text-2xl font-bold text-gray-900 mb-4">
Anmälan är stängd
</h1>
<p className="text-gray-600 mb-6">
Vi tar tyvärr inte emot fler funktionärsanmälningar just nu.
</p>
<button
onClick={() => router.push("/")}
className="text-blue-600 hover:underline"
>
tillbaka till startsidan
</button>
</div>
</div>
);
}
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, type, checked } = e.target; const { name, value, type, checked } = e.target;
setFormData((prev) => ({ setFormData((prev) => ({