diff --git a/app/admin/page.tsx b/app/admin/page.tsx index 03ab387..6ad32c8 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -3,13 +3,22 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import AdminGuard from '@/components/admin-guard'; -import { authApi, wishlistsApi, itemsApi, settingsApi, type Wishlist, type Settings } from '@/lib/api'; +import { + authApi, + wishlistsApi, + itemsApi, + settingsApi, + type Wishlist, + type Item, + type Settings, +} from '@/lib/api'; import Header from '@/components/header'; import Link from 'next/link'; -import StatsGrid from '@/components/admin/StatsGrid'; import SettingsSection from '@/components/admin/SettingsSection'; -import WishlistCard from '@/components/admin/WishlistCard'; -import CreateWishlistModal from '@/components/admin/CreateWishlistModal'; +import ItemCard from '@/components/admin/ItemCard'; +import ItemForm from '@/components/admin/ItemForm'; +import ImageUpload from '@/components/image-upload'; +import RichTextEditor from '@/components/RichTextEditor'; export default function AdminPage() { return ( @@ -21,53 +30,154 @@ export default function AdminPage() { function AdminPageContent() { const router = useRouter(); - const [wishlists, setWishlists] = useState([]); - const [itemCounts, setItemCounts] = useState>({}); + + // Single wishlist state + const [wishlist, setWishlist] = useState(null); + const [items, setItems] = useState([]); const [isLoading, setIsLoading] = useState(true); + + // Settings const [settings, setSettings] = useState({ siteTitle: 'Wishlist', - homepageSubtext: 'Browse and explore available wishlists', + homepageSubtext: '', }); + // Wishlist edit state + const [isEditingWishlist, setIsEditingWishlist] = useState(false); + const [editForm, setEditForm] = useState({ + name: '', + slug: '', + description: '', + preferences: '', + imageUrl: '', + isPublic: true, + }); + const [editError, setEditError] = useState(''); + const [isWishlistImageUploading, setIsWishlistImageUploading] = useState(false); + + // Item management state + const [editingItemId, setEditingItemId] = useState(null); + const [showAddItemForm, setShowAddItemForm] = useState(false); + const [newItemError, setNewItemError] = useState(''); + const logout = async () => { await authApi.logout(); router.push('/'); }; - const [showCreateModal, setShowCreateModal] = useState(false); - const [createError, setCreateError] = useState(''); useEffect(() => { - fetchWishlists(); - fetchSettings(); + fetchData(); }, []); - const fetchSettings = async () => { + const fetchData = async () => { try { - const data = await settingsApi.getSettings(); - setSettings(data); + const [lists, settingsData] = await Promise.all([ + wishlistsApi.getAll(), + settingsApi.getSettings(), + ]); + setSettings(settingsData); + if (lists.length > 0) { + const w = lists[0]; + setWishlist(w); + const itemsData = await itemsApi.getAll(w.id); + setItems(itemsData.sort((a, b) => a.sortOrder - b.sortOrder)); + } } catch (error) { - console.error('Failed to fetch settings:', error); + console.error('Failed to fetch data:', error); + } finally { + setIsLoading(false); } }; - const fetchWishlists = async () => { - try { - const data = await wishlistsApi.getAll(); - setWishlists(data); + const refreshItems = async () => { + if (!wishlist) return; + const itemsData = await itemsApi.getAll(wishlist.id); + setItems(itemsData.sort((a, b) => a.sortOrder - b.sortOrder)); + }; - // Fetch item counts for each wishlist - const counts: Record = {}; - await Promise.all( - data.map(async (w) => { - const items = await itemsApi.getAll(w.id); - counts[w.id] = items.length; - }) - ); - setItemCounts(counts); - } catch (error) { - console.error('Failed to fetch wishlists:', error); - } finally { - setIsLoading(false); + // Wishlist edit handlers + const startEditingWishlist = () => { + if (!wishlist) return; + setEditForm({ + name: wishlist.name, + slug: wishlist.slug, + description: wishlist.description || '', + preferences: wishlist.preferences || '', + imageUrl: wishlist.imageUrl || '', + isPublic: wishlist.isPublic, + }); + setEditError(''); + setIsEditingWishlist(true); + }; + + const handleUpdateWishlist = async (e: React.FormEvent) => { + e.preventDefault(); + if (!wishlist) return; + setEditError(''); + try { + const updated = await wishlistsApi.update(wishlist.id, editForm); + setWishlist(updated); + setIsEditingWishlist(false); + } catch (error: any) { + setEditError(error.message || 'Failed to update wishlist'); + } + }; + + // Item handlers + const handleCreateItem = async (itemData: Partial) => { + if (!wishlist) return; + setNewItemError(''); + try { + await itemsApi.create(wishlist.id, itemData); + setShowAddItemForm(false); + await refreshItems(); + } catch (error: any) { + setNewItemError(error.message || 'Failed to create item'); + throw error; + } + }; + + const handleUpdateItem = async (itemData: Partial) => { + if (!editingItemId) return; + try { + await itemsApi.update(editingItemId, itemData); + setEditingItemId(null); + await refreshItems(); + } catch (error: any) { + alert(error.message || 'Failed to update item'); + throw error; + } + }; + + const handleDeleteItem = async (itemId: string) => { + if (!confirm('Tem certeza que deseja excluir este item?')) return; + try { + await itemsApi.delete(itemId); + await refreshItems(); + } catch { + alert('Failed to delete item'); + } + }; + + const handleMoveItemUp = async (itemId: string) => { + const currentIndex = items.findIndex((item) => item.id === itemId); + if (currentIndex <= 0) return; + try { + await itemsApi.reorder(itemId, currentIndex - 1); + await refreshItems(); + } catch (error: any) { + alert(error?.message || 'Failed to reorder item'); + } + }; + + const handleMoveItemDown = async (itemId: string) => { + const currentIndex = items.findIndex((item) => item.id === itemId); + if (currentIndex === -1 || currentIndex === items.length - 1) return; + try { + await itemsApi.reorder(itemId, currentIndex + 1); + await refreshItems(); + } catch (error: any) { + alert(error?.message || 'Failed to reorder item'); } }; @@ -76,172 +186,251 @@ function AdminPageContent() { setSettings(updatedSettings); }; - const handleCreateWishlist = async (data: any) => { - setCreateError(''); - try { - await wishlistsApi.create(data); - setShowCreateModal(false); - fetchWishlists(); - } catch (error: any) { - setCreateError(error.message || 'Failed to create wishlist'); - throw error; - } - }; - - const handleUpdateWishlist = async (id: string, data: Partial) => { - await wishlistsApi.update(id, data); - fetchWishlists(); - }; - - const handleDeleteWishlist = async (id: string) => { - if (!confirm('Are you sure you want to delete this wishlist?')) return; - - try { - await wishlistsApi.delete(id); - fetchWishlists(); - } catch (error) { - alert('Failed to delete wishlist'); - } - }; - - const handleMoveWishlistUp = async (wishlistId: string) => { - const currentIndex = wishlists.findIndex((w) => w.id === wishlistId); - if (currentIndex <= 0) return; - - try { - await wishlistsApi.reorder(wishlistId, currentIndex - 1); - await fetchWishlists(); - } catch (error: any) { - alert(`Error: ${error?.message || 'Failed to reorder wishlist'}`); - } - }; - - const handleMoveWishlistDown = async (wishlistId: string) => { - const currentIndex = wishlists.findIndex((w) => w.id === wishlistId); - if (currentIndex === -1 || currentIndex === wishlists.length - 1) return; - - try { - await wishlistsApi.reorder(wishlistId, currentIndex + 1); - await fetchWishlists(); - } catch (error: any) { - alert(`Error: ${error?.message || 'Failed to reorder wishlist'}`); - } - }; - - const stats = { - totalWishlists: wishlists.length, - publicWishlists: wishlists.filter((w) => w.isPublic).length, - totalItems: Object.values(itemCounts).reduce((sum, count) => sum + count, 0), - }; + const editingItem = items.find((item) => item.id === editingItemId); return ( - <> -
-
+
+ + Reservas + + + Convidados + + + + } + /> + +
+
+ {isLoading ? ( +
+

Carregando...

+
+ ) : ( <> - - Reservas - - - Convidados - - - - } - /> + {/* Settings Section */} + -
-
- {isLoading ? ( -
-

Loading...

-
- ) : ( - <> - {/* Stats Grid */} - + {/* Wishlist Info Section */} + {wishlist && ( +
+
+ {isEditingWishlist ? ( +
+

+ Editar Lista +

+ {editError && ( +
+ {editError} +
+ )} + + setEditForm((prev) => ({ ...prev, imageUrl: url })) + } + onUploadStateChange={setIsWishlistImageUploading} + type="wishlist" + label="Imagem da Lista" + /> +
+ + + setEditForm((prev) => ({ ...prev, name: e.target.value })) + } + className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white" + /> +
+
+ +