Files
website/app/admin/AdminForm.tsx
T
2026-03-06 15:33:05 +01:00

192 lines
9.9 KiB
TypeScript

// app/admin/AdminForm.tsx
'use client';
import { useActionState, useEffect, useState } from 'react';
import { FaPlus, FaTrash, FaArrowUp, FaArrowDown } from 'react-icons/fa'; // Importera pilarna
import { saveConfigAction } from './actions';
export default function AdminForm({ initialConfig }: { initialConfig: any }) {
const [state, formAction, isPending] = useActionState(saveConfigAction, null);
const [showToast, setShowToast] = useState(false);
const [classes, setClasses] = useState<Array<{ name: string, color: string, desc: string }>>(
Array.isArray(initialConfig.beachPage.classes)
? initialConfig.beachPage.classes
: [
{ name: 'Grön', color: '#16a34a', desc: 'Nybörjare' },
{ name: 'Blå', color: '#2563eb', desc: 'Spelat lite' },
{ name: 'Svart', color: '#111827', desc: 'Spelat mycket' }
]
);
const addClass = () => setClasses([...classes, { name: '', color: '#406185', desc: '' }]);
const removeClass = (index: number) => {
setClasses(classes.filter((_, i) => i !== index));
};
const updateClass = (index: number, field: keyof typeof classes[0], value: string) => {
const newClasses = [...classes];
newClasses[index][field] = value;
setClasses(newClasses);
};
// Funktioner för att byta plats på klasserna
const moveUp = (index: number) => {
if (index === 0) return;
const newClasses = [...classes];
[newClasses[index - 1], newClasses[index]] = [newClasses[index], newClasses[index - 1]];
setClasses(newClasses);
};
const moveDown = (index: number) => {
if (index === classes.length - 1) return;
const newClasses = [...classes];
[newClasses[index + 1], newClasses[index]] = [newClasses[index], newClasses[index + 1]];
setClasses(newClasses);
};
useEffect(() => {
if (state?.success) {
setShowToast(true);
const timer = setTimeout(() => setShowToast(false), 3000);
return () => clearTimeout(timer);
}
}, [state]);
return (
<form action={formAction} className="flex flex-col gap-8">
{showToast && (
<div className="fixed top-5 right-5 bg-green-500 text-white px-6 py-3 rounded-lg shadow-2xl font-bold z-50 animate-bounce">
Ändringar sparade!
</div>
)}
{/* Startsida */}
<section className="border-b pb-6">
<h2 className="text-xl font-bold mb-4 border-l-4 border-[#fdb84b] pl-2 text-[#406185]">Startsida</h2>
<label className="flex items-center gap-2 cursor-pointer">
<input type="checkbox" name="showBeachPromo" defaultChecked={initialConfig.showBeachPromo} className="w-5 h-5 accent-[#406185]" />
<span className="font-semibold">Visa Beach-Promo bar</span>
</label>
</section>
{/* Beach-Turnering */}
<section className="flex flex-col gap-6">
<h2 className="text-xl font-bold border-l-4 border-[#fdb84b] pl-2 text-[#406185]">Beach-Turnering</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-bold mb-1">Matchstart</label>
<input type="datetime-local" name="matchStart" defaultValue={initialConfig.beachPage.matchStart} className="w-full border p-2 rounded focus:ring-2 focus:ring-[#406185] outline-none" />
</div>
<div>
<label className="block text-sm font-bold mb-1">Länk till Mat- & Sommarfesten</label>
<input name="festivalLink" defaultValue={initialConfig.beachPage.festivalLink} className="w-full border p-2 rounded focus:ring-2 focus:ring-[#406185] outline-none" />
</div>
</div>
<div>
<label className="block text-sm font-bold mb-1">Meddelande vid stängd anmälan</label>
<textarea name="closeReason" defaultValue={initialConfig.beachPage.closeReason} className="w-full border p-2 rounded h-20" />
</div>
<div>
<label className="block text-sm font-bold mb-1">Övrig info (en rad per punkt sajten)</label>
<textarea name="otherInfo" defaultValue={initialConfig.beachPage.otherInfo} className="w-full border p-2 rounded h-24" />
</div>
<div>
<label className="block text-sm font-bold mb-1">Pris-text (längst ner infosidan)</label>
<input name="prizesText" defaultValue={initialConfig.beachPage.prizesText} className="w-full border p-2 rounded" />
</div>
<label className="flex items-center gap-2 cursor-pointer text-red-600 bg-red-50 p-3 rounded-lg border border-red-100">
<input type="checkbox" name="isClosedOverride" defaultChecked={initialConfig.beachPage.isClosedOverride} className="w-5 h-5 accent-red-600" />
<span className="font-bold uppercase">Stäng anmälan manuellt</span>
</label>
</section>
{/* SPELKLASSER - Moderniserad för att matcha */}
<section className="flex flex-col gap-4">
<div className="flex justify-between items-center mb-2">
<h2 className="text-xl font-bold border-l-4 border-[#fdb84b] pl-2 text-[#406185]">Spelklasser</h2>
<button
type="button"
onClick={addClass}
className="flex items-center gap-2 text-sm font-bold text-white bg-[#406185] px-4 py-2 rounded hover:brightness-110 transition-all active:scale-95"
>
<FaPlus size={12} /> Lägg till
</button>
</div>
<div className="space-y-3">
{classes.map((c, index) => (
<div key={index} className="flex flex-col md:flex-row gap-3 items-center w-full">
{/* Sorteringspilar */}
<div className="flex md:flex-col gap-1 text-gray-400">
<button type="button" onClick={() => moveUp(index)} disabled={index === 0} className="hover:text-[#406185] disabled:opacity-30 disabled:hover:text-gray-400 p-1">
<FaArrowUp size={14} />
</button>
<button type="button" onClick={() => moveDown(index)} disabled={index === classes.length - 1} className="hover:text-[#406185] disabled:opacity-30 disabled:hover:text-gray-400 p-1">
<FaArrowDown size={14} />
</button>
</div>
<div className="flex-1 flex gap-2 w-full">
{/* Färgplockare som ser ut som ett vanligt inputfält */}
<div className="w-12 h-10 border rounded overflow-hidden shrink-0 focus-within:ring-2 focus-within:ring-[#406185]">
<input
type="color"
value={c.color}
onChange={(e) => updateClass(index, 'color', e.target.value)}
className="w-16 h-16 -m-2 cursor-pointer outline-none"
title="Välj färg"
/>
</div>
<input
type="text"
value={c.name}
onChange={(e) => updateClass(index, 'name', e.target.value)}
placeholder="Lagnamn (t.ex. Grön)"
required
className="w-1/3 border p-2 rounded focus:ring-2 focus:ring-[#406185] outline-none min-w-25"
/>
<input
type="text"
value={c.desc}
onChange={(e) => updateClass(index, 'desc', e.target.value)}
placeholder="Beskrivning (t.ex. Nybörjare)"
className="flex-1 border p-2 rounded focus:ring-2 focus:ring-[#406185] outline-none min-w-30"
/>
</div>
<button
type="button"
onClick={() => removeClass(index)}
className="text-gray-400 hover:text-red-500 p-2 rounded transition-colors self-end md:self-auto shrink-0"
title="Ta bort klass"
>
<FaTrash />
</button>
</div>
))}
{classes.length === 0 && (
<p className="text-gray-500 italic text-sm">Inga klasser inlagda. Besökarna kommer inte kunna välja nivå.</p>
)}
</div>
{/* Dold JSON-sträng för Server Action */}
<input type="hidden" name="classesJSON" value={JSON.stringify(classes)} />
</section>
<button type="submit" disabled={isPending} className="bg-[#406185] text-white py-4 mt-4 rounded-lg font-bold text-lg hover:bg-black transition-all active:scale-95 disabled:bg-gray-400 shadow-lg">
{isPending ? 'Sparar...' : 'Spara inställningar'}
</button>
</form>
);
}