import { useState } from 'react'; import { useLiveBlogs } from '@/queries/live-blogs'; import { useArticles, useDeleteArticle, useArchiveArticle, usePublishArticle } from '@/queries/articles'; import { useDeleteLiveBlog, useArchiveLiveBlog, usePublishLiveBlog } from '@/queries/live-blogs'; import { Link } from '@tanstack/react-router'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { format } from 'date-fns'; import { mk } from 'date-fns/locale'; export function AdminDashboardComponent() { // State for confirmation dialog and filters const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [dialogType, setDialogType] = useState<'delete' | 'archive'>('delete'); const [itemToDelete, setItemToDelete] = useState<{ type: 'article' | 'liveBlog'; id: string; title: string; } | null>(null); const [isProcessing, setIsProcessing] = useState(false); const [showArchived, setShowArchived] = useState(false); const { data: liveBlogsData, isLoading: loadingLiveBlogs } = useLiveBlogs({ limit: 50, status: showArchived ? 'archived' : 'draft,live,ended' }); const { data: articlesData, isLoading: loadingArticles } = useArticles({ limit: 50, status: showArchived ? 'archived' : 'draft,published' }); const deleteArticleMutation = useDeleteArticle(); const deleteLiveBlogMutation = useDeleteLiveBlog(); const archiveArticleMutation = useArchiveArticle(); const archiveLiveBlogMutation = useArchiveLiveBlog(); const publishArticleMutation = usePublishArticle(); const publishLiveBlogMutation = usePublishLiveBlog(); const liveBlogs = liveBlogsData?.data || []; const articles = articlesData?.data || []; // No need to filter items - API already filters based on showArchived state const filteredLiveBlogs = liveBlogs; const filteredArticles = articles; const handleDeleteClick = (type: 'article' | 'liveBlog', id: string, title: string) => { setItemToDelete({ type, id, title }); setDialogType('delete'); setShowConfirmDialog(true); }; const handleArchiveClick = (type: 'article' | 'liveBlog', id: string, title: string) => { setItemToDelete({ type, id, title }); setDialogType('archive'); setShowConfirmDialog(true); }; const handlePublishClick = async (type: 'article' | 'liveBlog', id: string) => { setIsProcessing(true); try { if (type === 'article') { await publishArticleMutation.mutateAsync({ id, status: 'published' }); } else { await publishLiveBlogMutation.mutateAsync({ id, status: 'draft' }); } } catch (error) { console.error('Failed to publish:', error); } finally { setIsProcessing(false); } }; const handleConfirmAction = async () => { if (!itemToDelete) return; setIsProcessing(true); try { if (dialogType === 'delete') { if (itemToDelete.type === 'article') { await deleteArticleMutation.mutateAsync(itemToDelete.id); } else { await deleteLiveBlogMutation.mutateAsync(itemToDelete.id); } } else { // archive if (itemToDelete.type === 'article') { await archiveArticleMutation.mutateAsync(itemToDelete.id); } else { await archiveLiveBlogMutation.mutateAsync(itemToDelete.id); } } setShowConfirmDialog(false); setItemToDelete(null); } catch (error) { console.error(`Failed to ${dialogType}:`, error); } finally { setIsProcessing(false); } }; const handleCancelAction = () => { setShowConfirmDialog(false); setItemToDelete(null); }; const getStatusColor = (status: string) => { switch (status) { case 'published': case 'live': return 'bg-green-100 text-green-800 border-green-200'; case 'draft': return 'bg-yellow-100 text-yellow-800 border-yellow-200'; case 'archived': case 'ended': return 'bg-gray-100 text-gray-800 border-gray-200'; default: return 'bg-blue-100 text-blue-800 border-blue-200'; } }; const getStatusText = (status: string) => { switch (status) { case 'published': return 'Објавено'; case 'draft': return 'Нацрт'; case 'archived': return 'Архивирано'; case 'live': return 'Во живо'; case 'ended': return 'Завршено'; default: return status; } }; return (

Администраторски панел

Управување со сите написи и live блогови

{/* Live Blogs Section */} {showArchived ? 'Архивирани Live блогови' : 'Live блогови'} {filteredLiveBlogs.length || 0} Сите live блогови со статус и датум на креирање {loadingLiveBlogs ? (

Вчитување...

) : filteredLiveBlogs.length === 0 ? (

{showArchived ? 'Нема архивирани live блогови' : 'Нема live блогови'}

{!showArchived && ( )}
) : (
{filteredLiveBlogs.map((blog) => (
{blog.title} {getStatusText(blog.status)} {blog.isPinned && ( Закачено )}
Слаг: {blog.slug} Креирано: {format(new Date(blog.createdAt), 'dd MMM yyyy', { locale: mk })} Прегледи: {blog.viewCount}
{showArchived ? ( ) : ( )}
))}
)}
{/* Articles Section */} {showArchived ? 'Архивирани написи' : 'Написи'} {filteredArticles.length || 0} Сите написи со статус и датум на креирање {loadingArticles ? (

Вчитување...

) : filteredArticles.length === 0 ? (

{showArchived ? 'Нема архивирани написи' : 'Нема написи'}

{!showArchived && ( )}
) : (
{filteredArticles.map((article) => (
{article.title} {getStatusText(article.status)}
Слаг: {article.slug} Креирано: {format(new Date(article.createdAt), 'dd MMM yyyy', { locale: mk })} Прегледи: {article.views}
{article.excerpt && (

{article.excerpt}

)}
{showArchived ? ( ) : ( )}
))}
)}
{/* Quick Stats - Only show when not viewing archived items */} {!showArchived && (
{liveBlogs.filter(b => b.status === 'live').length || 0}

Активни live блогови

{articles.filter(a => a.status === 'published').length || 0}

Објавени написи

{liveBlogs.filter(b => b.isPinned).length || 0}

Закачени live блогови

{(liveBlogs.reduce((sum, b) => sum + b.viewCount, 0) || 0) + (articles.reduce((sum, a) => sum + a.views, 0) || 0)}

Вкупно прегледи

)} {/* Confirmation Dialog */} {showConfirmDialog && itemToDelete && (

{dialogType === 'delete' ? 'Потврди бришење' : 'Потврди архивирање'}

{dialogType === 'delete' ? `Дали сте сигурни дека сакате да го избришете "${itemToDelete.title}"?` : `Дали сте сигурни дека сакате да го архивирате "${itemToDelete.title}"?`}

)}
); }