Compare commits
+177
-45
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
'use server';
|
'use server';
|
||||||
|
|
||||||
import nodemailer from 'nodemailer';
|
|
||||||
|
|
||||||
export async function submitRegistration(prevState: unknown, 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
|
// 1. Spara all rådata direkt för att kunna skicka tillbaka den vid fel
|
||||||
const rawData = {
|
const rawData = {
|
||||||
@@ -21,9 +19,9 @@ export async function submitRegistration(prevState: unknown, formData: FormData)
|
|||||||
return { success: false, message: 'Spam detekterat.', values: rawData };
|
return { success: false, message: 'Spam detekterat.', values: rawData };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Hämta Turnstile Token och Secret (MATCHING .env NAME)
|
// 2. Hämta Turnstile Token och Secret
|
||||||
const turnstileToken = formData.get('cf-turnstile-response');
|
const turnstileToken = formData.get('cf-turnstile-response');
|
||||||
const secretKey = process.env.TURNSTILE_SECRET; // Matchar din .env exakt
|
const secretKey = process.env.TURNSTILE_SECRET;
|
||||||
|
|
||||||
if (!secretKey) {
|
if (!secretKey) {
|
||||||
console.error("Saknar TURNSTILE_SECRET i miljön.");
|
console.error("Saknar TURNSTILE_SECRET i miljön.");
|
||||||
@@ -73,43 +71,166 @@ export async function submitRegistration(prevState: unknown, formData: FormData)
|
|||||||
? `+46 (0)${cleanTel.substring(0, 2)}-${cleanTel.substring(2, 5)} ${cleanTel.substring(5, 7)} ${cleanTel.substring(7, 9)}`
|
? `+46 (0)${cleanTel.substring(0, 2)}-${cleanTel.substring(2, 5)} ${cleanTel.substring(5, 7)} ${cleanTel.substring(7, 9)}`
|
||||||
: rawData.tel;
|
: rawData.tel;
|
||||||
|
|
||||||
// 5. Nodemailer setup
|
// 5. Stalwart JMAP Setup
|
||||||
const transporter = nodemailer.createTransport({
|
const jmapUrl = process.env.STALWART_JMAP_URL;
|
||||||
host: process.env.SMTP_HOST,
|
const jmapToken = process.env.STALWART_API_TOKEN;
|
||||||
port: 587,
|
const accountId = process.env.STALWART_ACCOUNT_ID;
|
||||||
secure: false,
|
|
||||||
auth: {
|
if (!jmapUrl || !jmapToken || !accountId) {
|
||||||
user: process.env.SMTP_USER,
|
console.error("Saknar JMAP-konfiguration i miljön.");
|
||||||
pass: process.env.SMTP_PASS,
|
return {
|
||||||
},
|
success: false,
|
||||||
tls: {
|
message: 'E-postserver är inte konfigurerad. Kontakta administratör.',
|
||||||
rejectUnauthorized: false
|
values: rawData
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendMailJMAP(toEmail: string, replyToEmail: string, subject: string, htmlContent: string, fromName: string, fromEmail: string) {
|
||||||
|
// 1. Hämta Mapp-ID (Drafts/Utkast) och Identitets-ID från Stalwart
|
||||||
|
const setupPayload = {
|
||||||
|
using: ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:submission"],
|
||||||
|
methodCalls: [
|
||||||
|
["Mailbox/query", { accountId: accountId, filter: { role: "drafts" } }, "getMailbox"],
|
||||||
|
["Identity/get", { accountId: accountId }, "getIdentity"]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const setupRes = await fetch(jmapUrl as string, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jmapToken}` },
|
||||||
|
body: JSON.stringify(setupPayload)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const setupData = await setupRes.json();
|
||||||
|
const mailboxRes = setupData.methodResponses.find((r: any) => r[0] === "Mailbox/query");
|
||||||
|
const identityRes = setupData.methodResponses.find((r: any) => r[0] === "Identity/get");
|
||||||
|
|
||||||
|
let mailboxId = mailboxRes && mailboxRes[1].ids && mailboxRes[1].ids.length > 0 ? mailboxRes[1].ids[0] : null;
|
||||||
|
|
||||||
|
// ---- NY LOGIK HÄR: Hitta rätt identitet baserat på fromEmail ----
|
||||||
|
let identityId = null;
|
||||||
|
let actualFromEmail = fromEmail;
|
||||||
|
|
||||||
|
if (identityRes && identityRes[1].list) {
|
||||||
|
// Leta efter identiteten som matchar adressen vi vill skicka från
|
||||||
|
const matchedIdentity = identityRes[1].list.find((i: any) => i.email === fromEmail);
|
||||||
|
|
||||||
|
if (matchedIdentity) {
|
||||||
|
identityId = matchedIdentity.id;
|
||||||
|
} else if (identityRes[1].list.length > 0) {
|
||||||
|
// Fallback om den exakta adressen inte fanns i listan
|
||||||
|
identityId = identityRes[1].list[0].id;
|
||||||
|
actualFromEmail = identityRes[1].list[0].email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Om ingen mapp med rollen "drafts" finns, hämta första bästa mapp
|
||||||
|
if (!mailboxId) {
|
||||||
|
const fallbackRes = await fetch(jmapUrl as string, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${jmapToken}` },
|
||||||
|
body: JSON.stringify({
|
||||||
|
using: ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
|
||||||
|
methodCalls: [["Mailbox/query", { accountId: accountId }, "0"]]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const fallbackData = await fallbackRes.json();
|
||||||
|
mailboxId = fallbackData.methodResponses[0][1].ids[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mailboxId || !identityId) {
|
||||||
|
throw new Error("Kunde inte hitta mailboxId eller identityId i Stalwart.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Skapa och skicka mailet
|
||||||
|
const payload = {
|
||||||
|
using: [
|
||||||
|
"urn:ietf:params:jmap:core",
|
||||||
|
"urn:ietf:params:jmap:mail",
|
||||||
|
"urn:ietf:params:jmap:submission"
|
||||||
|
],
|
||||||
|
methodCalls: [
|
||||||
|
[
|
||||||
|
"Email/set",
|
||||||
|
{
|
||||||
|
accountId: accountId,
|
||||||
|
create: {
|
||||||
|
"draft-1": {
|
||||||
|
mailboxIds: { [mailboxId as string]: true },
|
||||||
|
from: [{ email: actualFromEmail, name: fromName }], // Nu använder vi rätt adress
|
||||||
|
to: [{ email: toEmail }],
|
||||||
|
replyTo: [{ email: replyToEmail }],
|
||||||
|
subject: subject,
|
||||||
|
bodyValues: {
|
||||||
|
"body-html": {
|
||||||
|
value: htmlContent,
|
||||||
|
isTruncated: false,
|
||||||
|
isEncodingProblem: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
htmlBody: [{ partId: "body-html", type: "text/html" }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"EmailSubmission/set",
|
||||||
|
{
|
||||||
|
accountId: accountId,
|
||||||
|
create: {
|
||||||
|
"sub-1": {
|
||||||
|
emailId: "#draft-1",
|
||||||
|
identityId: identityId // Nu använder vi rätt ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await fetch(jmapUrl as string, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${jmapToken}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
const hasErrors = data.methodResponses.some(
|
||||||
|
(response: any) =>
|
||||||
|
response[0] === "error" ||
|
||||||
|
(response[1] && response[1].notCreated)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasErrors) {
|
||||||
|
console.error("--- JMAP METHOD ERROR ---");
|
||||||
|
console.error(JSON.stringify(data.methodResponses, null, 2));
|
||||||
|
console.error("-------------------------");
|
||||||
|
throw new Error("JMAP accepterade anropet, men vägrade skapa/skicka mailet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Skapa och skicka mail
|
||||||
try {
|
try {
|
||||||
const dateStr = new Date().toLocaleString('sv-SE', {
|
const dateStr = new Date().toLocaleString('sv-SE', {
|
||||||
timeZone: 'Europe/Stockholm',
|
timeZone: 'Europe/Stockholm',
|
||||||
year: 'numeric',
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
||||||
month: '2-digit',
|
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit'
|
|
||||||
});
|
});
|
||||||
const cleanMessage = rawData.message ? rawData.message.replace(/[\r\n;]/g, " ") : "";
|
const cleanMessage = rawData.message ? rawData.message.replace(/[\r\n;]/g, " ") : "";
|
||||||
|
|
||||||
// Mail till klubben
|
// HTML för mail till klubben
|
||||||
await transporter.sendMail({
|
const mailTillKlubbHtml = `
|
||||||
from: `"Beach-anmälan: ${rawData.name}" <${process.env.SMTP_USER}>`,
|
|
||||||
to: 'beach@lerbergetsvolleyboll.se',
|
|
||||||
replyTo: rawData.email,
|
|
||||||
subject: `Anmälan: ${rawData.team}`,
|
|
||||||
html: `
|
|
||||||
<html>
|
<html>
|
||||||
<body style='font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; padding: 20px;'>
|
<body style='font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; padding: 20px;'>
|
||||||
<h2 style='color: #39979f;'>Beach-anmälan</h2>
|
<h2 style='color: #39979f;'>Beach-anmälan</h2>
|
||||||
|
|
||||||
<table style='width: 100%; max-width: 600px; border-collapse: collapse;'>
|
<table style='width: 100%; max-width: 600px; border-collapse: collapse;'>
|
||||||
<tr><td style='padding: 5px; font-weight: bold; width: 150px;'>Lagnamn:</td><td>${rawData.team}</td></tr>
|
<tr><td style='padding: 5px; font-weight: bold; width: 150px;'>Lagnamn:</td><td>${rawData.team}</td></tr>
|
||||||
<tr><td style='padding: 5px; font-weight: bold;'>Kontakt:</td><td>${rawData.name}</td></tr>
|
<tr><td style='padding: 5px; font-weight: bold;'>Kontakt:</td><td>${rawData.name}</td></tr>
|
||||||
@@ -119,14 +240,11 @@ export async function submitRegistration(prevState: unknown, formData: FormData)
|
|||||||
<tr><td style='padding: 5px; font-weight: bold;'>Nivå:</td><td>${rawData.level}</td></tr>
|
<tr><td style='padding: 5px; font-weight: bold;'>Nivå:</td><td>${rawData.level}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<p><strong>Meddelande:</strong><br>${rawData.message ? rawData.message.replace(/\n/g, '<br>') : '<em>Inget meddelande</em>'}</p>
|
<p><strong>Meddelande:</strong><br>${rawData.message ? rawData.message.replace(/\n/g, '<br>') : '<em>Inget meddelande</em>'}</p>
|
||||||
|
|
||||||
<hr style='border: none; border-top: 1px solid #ddd; margin: 30px 0;'>
|
<hr style='border: none; border-top: 1px solid #ddd; margin: 30px 0;'>
|
||||||
|
|
||||||
<details style="margin-top: 20px;">
|
<details style="margin-top: 20px;">
|
||||||
<summary style="background-color: #fdb84b; color: #fff; padding: 12px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; display: inline-block; font-size: 14px; text-transform: uppercase; letter-spacing: 1px;">
|
<summary style="background-color: #fdb84b; color: #fff; padding: 12px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; display: inline-block; font-size: 14px; text-transform: uppercase; letter-spacing: 1px;">
|
||||||
Visa kopierbar tabell för Excel
|
Visa kopierbar tabell för Excel
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
<div style="margin-top: 15px; overflow-x: auto;">
|
<div style="margin-top: 15px; overflow-x: auto;">
|
||||||
<table border='1' style='border-collapse: collapse; font-family: Calibri, sans-serif; font-size: 11pt; width: 100%; text-align: left;'>
|
<table border='1' style='border-collapse: collapse; font-family: Calibri, sans-serif; font-size: 11pt; width: 100%; text-align: left;'>
|
||||||
<tr style="background-color: #f9f9f9;">
|
<tr style="background-color: #f9f9f9;">
|
||||||
@@ -144,26 +262,40 @@ export async function submitRegistration(prevState: unknown, formData: FormData)
|
|||||||
</details>
|
</details>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`
|
`;
|
||||||
});
|
|
||||||
|
|
||||||
// Bekräftelse till användaren
|
// HTML för bekräftelse till användaren
|
||||||
await transporter.sendMail({
|
const mailTillAnvandareHtml = `
|
||||||
from: `"LVS" <${process.env.SMTP_USER}>`,
|
<div style="font-family: sans-serif; padding: 20px; color: #333;">
|
||||||
to: rawData.email,
|
|
||||||
replyTo: `"LVS Beach" <beach@lerbergetsvolleyboll.se>`,
|
|
||||||
subject: `Vi har tagit emot din anmälan för ${rawData.team}`,
|
|
||||||
html: `<div style="font-family: sans-serif; padding: 20px; color: #333;">
|
|
||||||
<h2 style="color: #39979f;">Hej ${rawData.name}!</h2>
|
<h2 style="color: #39979f;">Hej ${rawData.name}!</h2>
|
||||||
<p>Tack för din anmälan till beachturneringen. Vi återkommer så snart vi har granskat era uppgifter.</p>
|
<p>Tack för din anmälan till beachturneringen. Vi återkommer så snart vi har granskat era uppgifter.</p>
|
||||||
<p>Ses på stranden!<br><strong style="color: #fdb84b;">Lerbergets Volleybollsällskap</strong></p>
|
<p>Ses på stranden!<br><strong style="color: #fdb84b;">Lerbergets Volleybollsällskap</strong></p>
|
||||||
</div>`
|
</div>
|
||||||
});
|
`;
|
||||||
|
|
||||||
|
// Skicka mailen parallellt
|
||||||
|
await Promise.all([
|
||||||
|
sendMailJMAP(
|
||||||
|
'beach@lerbergetsvolleyboll.se', // To
|
||||||
|
rawData.email, // ReplyTo
|
||||||
|
`Anmälan: ${rawData.team}`, // Subject
|
||||||
|
mailTillKlubbHtml, // HTML Content
|
||||||
|
`Beach-anmälan: ${rawData.name}`,// From Name
|
||||||
|
'beach@lerbergetsvolleyboll.se' // From Email (VIKTIGT!)
|
||||||
|
),
|
||||||
|
sendMailJMAP(
|
||||||
|
rawData.email, // To
|
||||||
|
'beach@lerbergetsvolleyboll.se', // ReplyTo
|
||||||
|
`Vi har tagit emot din anmälan för ${rawData.team}`, // Subject
|
||||||
|
mailTillAnvandareHtml, // HTML Content
|
||||||
|
"LVS Beach", // From Name
|
||||||
|
'beach@lerbergetsvolleyboll.se' // From Email (VIKTIGT!)
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
// Returnerar INGA värden här, vilket gör att formuläret kan rensas rent
|
|
||||||
return { success: true, message: 'Tack! Din anmälan har skickats. Håll utkik i din inkorg efter bekräftelse.' };
|
return { success: true, message: 'Tack! Din anmälan har skickats. Håll utkik i din inkorg efter bekräftelse.' };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Nodemailer error:", e);
|
console.error("JMAP Fetch error:", e);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'Kunde inte skicka mail. Kontakta oss manuellt istället.',
|
message: 'Kunde inte skicka mail. Kontakta oss manuellt istället.',
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { FaFacebookSquare, FaInstagram } from "react-icons/fa";
|
|||||||
import { IoIosMail } from "react-icons/io";
|
import { IoIosMail } from "react-icons/io";
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import player from "../../public/images/player.svg";
|
import player from "../../public/images/player.svg";
|
||||||
import laget from "../../public/images/laget.se.svg";
|
import svenskalag from "../../public/images/svenskalag.se.png";
|
||||||
|
|
||||||
export default function HomeClientContent() {
|
export default function HomeClientContent() {
|
||||||
const [activeModal, setActiveModal] = useState<'member' | 'subscribe' | null>(null);
|
const [activeModal, setActiveModal] = useState<'member' | 'subscribe' | null>(null);
|
||||||
@@ -42,7 +42,7 @@ export default function HomeClientContent() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden md:flex md:relative w-64 md:w-75 player-animation">
|
<div className="hidden md:flex md:relative w-64 md:w-75 player-animation">
|
||||||
<Image src={player} alt="Spelare" className="w-full h-auto" />
|
<Image src={player} alt="Spelare" className="w-full h-auto" loading='eager' />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -52,9 +52,9 @@ export default function HomeClientContent() {
|
|||||||
<div className="flex flex-col items-center w-full my-7.5 gap-2">
|
<div className="flex flex-col items-center w-full my-7.5 gap-2">
|
||||||
<InfoCard
|
<InfoCard
|
||||||
title="Träningstider"
|
title="Träningstider"
|
||||||
description="Här hittar du alltid uppdaterade träningstider från Laget.se"
|
description="Här hittar du alltid uppdaterade träningstider från Svenskalag.se"
|
||||||
actionLabel="Se nästa träningstid"
|
actionLabel="Se nästa träningstid"
|
||||||
href="https://www.laget.se/LVS/Event/Month"
|
href="https://www.svenskalag.se/lerbergetsvs/kalender/"
|
||||||
/>
|
/>
|
||||||
<InfoCard
|
<InfoCard
|
||||||
title="Prenumerera på träningstider"
|
title="Prenumerera på träningstider"
|
||||||
@@ -78,15 +78,15 @@ export default function HomeClientContent() {
|
|||||||
<FaFacebookSquare className="h-20 w-20" />
|
<FaFacebookSquare className="h-20 w-20" />
|
||||||
</SocialIcon>
|
</SocialIcon>
|
||||||
|
|
||||||
<SocialIcon title="Laget.se" href="https://www.laget.se/LVS" aria-label="Kolla träningstider på Laget.se">
|
<SocialIcon title="Svenskalag.se" href="https://www.svenskalag.se/lerbergetsvs" aria-label="Kolla träningstider på Svenskalag.se">
|
||||||
<Image src={laget} alt="Laget.se" className="h-18 w-18" />
|
<Image src={svenskalag} alt="Svenskalag.se" className="h-18 w-18" />
|
||||||
</SocialIcon>
|
</SocialIcon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Kontaktinformation */}
|
{/* Kontaktinformation */}
|
||||||
<div className="text-center p-2.5 flex flex-col justify-center items-center">
|
<div className="text-center p-2.5 flex flex-col justify-center items-center">
|
||||||
<h3 className="uppercase font-bold text-[1.875rem] leading-[1.2] mb-4">Kontakta oss</h3>
|
<h3 className="uppercase font-bold text-[1.875rem] leading-[1.2] mb-4">Kontakta oss</h3>
|
||||||
<p className="text-[1rem] leading-[1.6] opacity-90">Vi finns på Instagram, Facebook och laget.se</p>
|
<p className="text-[1rem] leading-[1.6] opacity-90">Vi finns på Instagram, Facebook och Svenskalag.se</p>
|
||||||
|
|
||||||
{/* Klickbar Adress - Länkar till Google Maps */}
|
{/* Klickbar Adress - Länkar till Google Maps */}
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default function MemberModal({ onClose }: ModalProps) {
|
|||||||
<h2 className="text-[#406185] my-2.5 text-2xl font-bold uppercase">Registrera dig</h2>
|
<h2 className="text-[#406185] my-2.5 text-2xl font-bold uppercase">Registrera dig</h2>
|
||||||
<p className="text-[#406185] my-2.5">Trycka på knappen nedan för att starta registreringen. Du kommer att skickas till laget.se</p>
|
<p className="text-[#406185] my-2.5">Trycka på knappen nedan för att starta registreringen. Du kommer att skickas till laget.se</p>
|
||||||
|
|
||||||
<ModalAction href="https://www.laget.se/LVS/Member" className="mt-5">
|
<ModalAction href="https://www.svenskalag.se/lerbergetsvs/formular/borja-trana-i-lerbergets-volleybollsallskap/38396" className="mt-5">
|
||||||
Bli medlem
|
Bli medlem
|
||||||
</ModalAction>
|
</ModalAction>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ export default function SubscribeModal({ onClose }: ModalProps) {
|
|||||||
<p className="text-[#406185] my-2.5">Välj vilken LEVEL du vill prenumerera på.</p>
|
<p className="text-[#406185] my-2.5">Välj vilken LEVEL du vill prenumerera på.</p>
|
||||||
|
|
||||||
<div className="flex flex-row flex-wrap justify-center gap-6.25 mt-5 max-w-162.5">
|
<div className="flex flex-row flex-wrap justify-center gap-6.25 mt-5 max-w-162.5">
|
||||||
<ModalAction href="webcal://cal.laget.se/lvs-level-5-6.ics">Level 5-6</ModalAction>
|
<ModalAction href="webcal://cal.svenskalag.se/120351">Level 4-6</ModalAction>
|
||||||
<ModalAction href="webcal://cal.laget.se/lvs-level-7-8.ics">Level 7-8</ModalAction>
|
<ModalAction href="webcal://cal.svenskalag.se/120353">Level 7-9</ModalAction>
|
||||||
<ModalAction href="webcal://cal.laget.se/lvs-level-8-9.ics">Level 8-9</ModalAction>
|
<ModalAction href="webcal://cal.svenskalag.se/120355">Level 10</ModalAction>
|
||||||
<ModalAction href="webcal://cal.laget.se/lvs-level-10.ics">Level 10</ModalAction>
|
<ModalAction href="webcal://cal.svenskalag.se/120187">Hela klubben</ModalAction>
|
||||||
<ModalAction href="webcal://cal.laget.se/LVS.ics">Hela klubben</ModalAction>
|
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ export async function getConfig() {
|
|||||||
return {
|
return {
|
||||||
showBeachPromo: true,
|
showBeachPromo: true,
|
||||||
beachPage: {
|
beachPage: {
|
||||||
matchStart: "2026-06-13T10:00",
|
matchStart: "2027-06-12T10:00",
|
||||||
isClosedOverride: false,
|
isClosedOverride: false,
|
||||||
closeReason: "Det är hela 26 lag anmälda och vi kan tyvärr inte ta emot fler anmälningar.\r\n\r\nVi är glada över förväntan och bjuder in alla andra till att komma och kolla men vi har tyvärr inte kapaciteten till att ha med fler lag.",
|
closeReason: "Det är hela 26 lag anmälda och vi kan tyvärr inte ta emot fler anmälningar.\r\n\r\nVi är glada över förväntan och bjuder in alla andra till att komma och kolla men vi har tyvärr inte kapaciteten till att ha med fler lag.",
|
||||||
festivalLink: "https://www.kullahalvon.com/upptacka--uppleva/kultur--noje/evenemang-pa-kullahalvon/mat---sommarfesten.html",
|
festivalLink: "https://www.kullahalvon.com/upptacka--uppleva/kultur--noje/evenemang-pa-kullahalvon/mat---sommarfesten.html",
|
||||||
|
|||||||
+3
-3
@@ -2,6 +2,6 @@ TURNSTILE_SITE_KEY=1x00000000000000000000AA
|
|||||||
TURNSTILE_SECRET=1x0000000000000000000000000000000AA
|
TURNSTILE_SECRET=1x0000000000000000000000000000000AA
|
||||||
|
|
||||||
ADMIN_PASSWORD=PASSWORD
|
ADMIN_PASSWORD=PASSWORD
|
||||||
SMTP_HOST=smtp.example.com
|
STALWART_JMAP_URL=https://mail.example.com/jmap/
|
||||||
SMTP_USER=USER
|
STALWART_ACCOUNT_ID=ID
|
||||||
SMTP_PASS=PASSWORD
|
STALWART_API_TOKEN=API_XXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|||||||
Generated
+838
-679
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -11,7 +11,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@marsidev/react-turnstile": "^1.4.2",
|
"@marsidev/react-turnstile": "^1.4.2",
|
||||||
"next": "^16",
|
"next": "^16",
|
||||||
"nodemailer": "^8.0.1",
|
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3",
|
"react-dom": "19.2.3",
|
||||||
@@ -27,5 +26,9 @@
|
|||||||
"eslint-config-next": "16.1.6",
|
"eslint-config-next": "16.1.6",
|
||||||
"tailwindcss": "^4.2.1",
|
"tailwindcss": "^4.2.1",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"allowScripts": {
|
||||||
|
"sharp@0.34.5": true,
|
||||||
|
"unrs-resolver@1.12.2": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
Reference in New Issue
Block a user