Better UI
This commit is contained in:
+115
-1
@@ -3,12 +3,50 @@
|
||||
'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);
|
||||
@@ -70,7 +108,83 @@ export default function AdminForm({ initialConfig }: { initialConfig: any }) {
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<button type="submit" disabled={isPending} className="bg-[#406185] text-white py-4 rounded-lg font-bold text-lg hover:bg-black transition-all active:scale-95 disabled:bg-gray-400">
|
||||
{/* 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>
|
||||
|
||||
Reference in New Issue
Block a user