Files
app/app/admin/NoticeTab.tsx
T

115 lines
6.7 KiB
TypeScript

// app/admin/NoticeTab.tsx
"use client";
import { AlertCircle, AlertTriangle, BellRing, Info, Loader2, Save, CheckCircle } from 'lucide-react';
import React, { useEffect, useState } from 'react';
import { readJsonFile, writeJsonFile } from '../actions/jsonEditor';
interface NoticeData {
isActive: boolean;
type: 'notice' | 'warning' | 'important';
message: string;
}
export const NoticeTab = ({ isOffline }: { isOffline: boolean }) => {
const [notice, setNotice] = useState<NoticeData>({ isActive: false, type: 'warning', message: '' });
const [isLoading, setIsLoading] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [saveStatus, setSaveStatus] = useState<'idle' | 'success' | 'error'>('idle');
useEffect(() => {
const fetchNotice = async () => {
const res = await readJsonFile('notice.json');
if (res.success && res.data) {
setNotice(res.data);
}
setIsLoading(false);
};
fetchNotice();
}, []);
const handleSave = async () => {
setIsSaving(true);
setSaveStatus('idle');
const res = await writeJsonFile('notice.json', notice);
if (res.success) {
setSaveStatus('success');
setTimeout(() => setSaveStatus('idle'), 3000);
} else {
setSaveStatus('error');
}
setIsSaving(false);
};
if (isLoading) return <div className="flex justify-center py-10"><Loader2 className="animate-spin text-slate-teal" size={32} /></div>;
return (
<div className="space-y-6 animate-fade-in">
<div className="rounded-3xl shadow-sm transition-all duration-300 bg-white/40 backdrop-blur-md border border-white/40 p-3 sm:p-5 hover:shadow-md">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl font-black text-ebony uppercase tracking-widest flex items-center">
<div className="bg-white p-2.5 rounded-xl mr-3 text-slate-teal shadow-sm">
<BellRing size={24} />
</div>
Meddelande startsidan
</h2>
{/* Av/På Switch */}
<button
onClick={() => setNotice({ ...notice, isActive: !notice.isActive })}
disabled={isOffline}
className={`relative inline-flex h-7 w-12 shrink-0 items-center rounded-full transition-colors focus:outline-none shadow-inner disabled:opacity-50 ${notice.isActive ? 'bg-moss' : 'bg-slate-teal/20'}`}
>
<span className={`inline-block h-5 w-5 transform rounded-full bg-white transition-transform shadow-sm ${notice.isActive ? 'translate-x-6' : 'translate-x-1'}`} />
</button>
</div>
<div className={`transition-all duration-300 ${!notice.isActive ? 'opacity-40 grayscale pointer-events-none' : ''}`}>
<div className="space-y-6">
<div>
<label className="block text-sm font-black text-ebony/60 uppercase tracking-widest mb-2">Typ av meddelande</label>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<button onClick={() => setNotice({ ...notice, type: 'notice' })} className={`flex items-center p-3 rounded-xl border-2 transition-all font-bold text-sm ${notice.type === 'notice' ? 'bg-seafoam/10 border-seafoam text-slate-teal' : 'bg-white border-transparent text-ebony/60 hover:bg-white/80 shadow-sm'}`}>
<Info size={18} className="mr-2" /> Information
</button>
<button onClick={() => setNotice({ ...notice, type: 'warning' })} className={`flex items-center p-3 rounded-xl border-2 transition-all font-bold text-sm ${notice.type === 'warning' ? 'bg-goldenrod/10 border-goldenrod text-goldenrod' : 'bg-white border-transparent text-ebony/60 hover:bg-white/80 shadow-sm'}`}>
<AlertTriangle size={18} className="mr-2" /> Varning
</button>
<button onClick={() => setNotice({ ...notice, type: 'important' })} className={`flex items-center p-3 rounded-xl border-2 transition-all font-bold text-sm ${notice.type === 'important' ? 'bg-emergency/10 border-emergency text-emergency' : 'bg-white border-transparent text-ebony/60 hover:bg-white/80 shadow-sm'}`}>
<AlertCircle size={18} className="mr-2" /> Akut / Viktigt
</button>
</div>
</div>
<div>
<label className="block text-sm font-black text-ebony/60 uppercase tracking-widest mb-2">Text</label>
<textarea
value={notice.message}
onChange={(e) => setNotice({ ...notice, message: e.target.value })}
placeholder="Skriv ditt meddelande här..."
className="w-full h-32 bg-white border border-slate-teal/10 p-4 rounded-2xl text-sm font-bold resize-none focus:outline-none focus:border-slate-teal shadow-sm"
/>
</div>
</div>
</div>
<div className="mt-8 flex items-center justify-between border-t border-slate-teal/10 pt-6">
<p className="text-xs font-bold text-slate-teal/60">
{saveStatus === 'success' && <span className="text-moss flex items-center"><CheckCircle size={14} className="mr-1" /> Sparat och live!</span>}
{saveStatus === 'error' && <span className="text-emergency flex items-center"><AlertTriangle size={14} className="mr-1" /> Kunde inte spara.</span>}
{isOffline && "Du är offline. Går ej att uppdatera."}
</p>
<button
onClick={handleSave}
disabled={isOffline || isSaving}
className="bg-slate-teal text-eggshell font-black uppercase tracking-widest text-xs px-6 py-3 rounded-xl hover:bg-ebony transition-colors disabled:opacity-50 shadow-sm flex items-center gap-2"
>
{isSaving ? <Loader2 size={16} className="animate-spin" /> : <Save size={16} />}
Spara ändringar
</button>
</div>
</div>
</div>
);
};