2025-08-26 14:52:01 +02:00

194 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from 'react';
import devlogData from '../../data/devlog.json';
export default function AdminPanel() {
const [entries, setEntries] = useState(devlogData);
const [selectedEntry, setSelectedEntry] = useState(null);
const emptyEntry = {
date: new Date().toLocaleDateString('de-DE'),
title: '',
description: '',
slug: '',
image: '',
content: []
};
const handleSave = async (entry, index = null) => {
// Entferne das 'index' Feld aus dem Entry bevor es gespeichert wird
const cleanEntry = { ...entry };
delete cleanEntry.index;
let updatedEntries;
if (index !== null) {
// Bearbeite bestehenden Eintrag
updatedEntries = entries.map((e, i) => i === index ? cleanEntry : e);
} else {
// Füge neuen Eintrag hinzu
updatedEntries = [...entries, cleanEntry];
}
try {
const response = await fetch('/api/update-devlog', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updatedEntries),
});
if (!response.ok) throw new Error('Fehler beim Speichern');
setEntries(updatedEntries);
setSelectedEntry(null);
} catch (error) {
console.error('Fehler:', error);
alert('Fehler beim Speichern der Änderungen');
}
};
const EntryForm = ({ entry, onSave }) => {
const [formData, setFormData] = useState(entry);
const [contentList, setContentList] = useState(entry.content || []);
const handleContentAdd = (type) => {
setContentList([...contentList, { type, value: '' }]);
};
const handleContentChange = (index, value) => {
const newContent = [...contentList];
newContent[index].value = value;
setContentList(newContent);
setFormData({ ...formData, content: newContent });
};
const handleContentRemove = (index) => {
setContentList(contentList.filter((_, i) => i !== index));
setFormData({
...formData,
content: contentList.filter((_, i) => i !== index)
});
};
return (
<div className="space-y-4 bg-white p-6 rounded-lg shadow">
<div className="grid grid-cols-1 gap-4">
<input
type="text"
placeholder="Titel"
value={formData.title}
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
className="w-full p-2 border rounded"
/>
<input
type="text"
placeholder="Beschreibung"
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
className="w-full p-2 border rounded"
/>
<input
type="text"
placeholder="URL-Slug"
value={formData.slug}
onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
className="w-full p-2 border rounded"
/>
<input
type="text"
placeholder="Bild-URL"
value={formData.image}
onChange={(e) => setFormData({ ...formData, image: e.target.value })}
className="w-full p-2 border rounded"
/>
<div className="space-y-4">
<h3 className="font-bold">Inhalt</h3>
{contentList.map((content, index) => (
<div key={index} className="flex space-x-2">
<textarea
value={content.value}
onChange={(e) => handleContentChange(index, e.target.value)}
className="w-full p-2 border rounded"
rows="3"
/>
<button
onClick={() => handleContentRemove(index)}
className="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600"
>
×
</button>
</div>
))}
<div className="flex space-x-2">
<button
onClick={() => handleContentAdd('text')}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
+ Text
</button>
<button
onClick={() => handleContentAdd('image')}
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
>
+ Bild
</button>
</div>
</div>
</div>
<div className="flex justify-end space-x-2 mt-4">
<button
onClick={() => setSelectedEntry(null)}
className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600"
>
Abbrechen
</button>
<button
onClick={() => onSave(formData)}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Speichern
</button>
</div>
</div>
);
};
return (
<div className="container mx-auto p-8">
<h1 className="text-3xl font-bold mb-8">DevLog Admin</h1>
{selectedEntry === null ? (
<div>
<button
onClick={() => setSelectedEntry(emptyEntry)}
className="mb-8 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
>
Neuen Beitrag erstellen
</button>
<div className="space-y-4">
{entries.map((entry, index) => (
<div key={index} className="bg-white p-4 rounded-lg shadow">
<h2 className="text-xl font-bold">{entry.title}</h2>
<p className="text-gray-600">{entry.date}</p>
<p className="mb-4">{entry.description}</p>
<button
onClick={() => setSelectedEntry({ ...entry, editIndex: index })}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Bearbeiten
</button>
</div>
))}
</div>
</div>
) : (
<EntryForm
entry={selectedEntry}
onSave={(formData) => handleSave(formData, selectedEntry.editIndex)}
/>
)}
</div>
);
}