113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import WerteForm from '@/components/WerteForm';
|
|
import WerteList from '@/components/WerteList';
|
|
import { WerteEntry } from '@/types/werte';
|
|
import packageJson from '@/package.json';
|
|
import LogoutButton from '@/components/LogoutButton';
|
|
|
|
export default function Home() {
|
|
const [entries, setEntries] = useState<WerteEntry[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [selectedEntry, setSelectedEntry] = useState<WerteEntry | null>(null);
|
|
|
|
const version = packageJson.version;
|
|
const buildDate = process.env.NEXT_PUBLIC_BUILD_DATE || new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
|
|
|
useEffect(() => {
|
|
let isMounted = true;
|
|
|
|
// Fetch initial data
|
|
(async () => {
|
|
try {
|
|
const response = await fetch('/api/werte?limit=14', {
|
|
cache: 'no-store',
|
|
headers: {
|
|
'Cache-Control': 'no-cache',
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
if (data.success && isMounted) {
|
|
setEntries(data.data);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching entries:', error);
|
|
}
|
|
if (isMounted) {
|
|
setIsLoading(false);
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, []);
|
|
|
|
const refreshEntries = async () => {
|
|
try {
|
|
const response = await fetch('/api/werte?limit=14', {
|
|
cache: 'no-store',
|
|
headers: {
|
|
'Cache-Control': 'no-cache',
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
setEntries(data.data);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching entries:', error);
|
|
}
|
|
};
|
|
|
|
const handleSuccess = () => {
|
|
setSelectedEntry(null);
|
|
// Small delay to ensure database commit is complete
|
|
setTimeout(() => {
|
|
refreshEntries();
|
|
}, 100);
|
|
};
|
|
|
|
const handleDelete = (id: number) => {
|
|
setEntries(entries.filter(entry => entry.ID !== id));
|
|
};
|
|
|
|
const handleEdit = (entry: WerteEntry) => {
|
|
setSelectedEntry(entry);
|
|
// Scroll to top
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white py-4 px-4">
|
|
<main className="max-w-6xl mx-auto border-2 border-black rounded-lg p-6 bg-[#FFFFDD]">
|
|
<h1 className="text-3xl font-bold text-center mb-6">Werte - Log</h1>
|
|
|
|
<div className="mb-8">
|
|
<h2 className="text-xl font-semibold mb-4">Eingabe</h2>
|
|
<WerteForm onSuccess={handleSuccess} selectedEntry={selectedEntry} />
|
|
</div>
|
|
|
|
<div className="bg-white border border-black rounded-lg shadow-md p-6">
|
|
<h2 className="text-xl font-semibold mb-4">Letzte 14 Einträge</h2>
|
|
{isLoading ? (
|
|
<div className="text-center py-4">Lade Daten...</div>
|
|
) : (
|
|
<WerteList entries={entries} onDelete={handleDelete} onEdit={handleEdit} />
|
|
)}
|
|
</div>
|
|
|
|
<footer className="mt-8 flex justify-between items-center text-sm text-gray-600 px-4">
|
|
<a href="mailto:rxf@gmx.de" className="hover:underline">
|
|
mailto:rxf@gmx.de
|
|
</a>
|
|
<div>
|
|
Version {version} - {buildDate}
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|