transform admin panel with comprehensive professional UI
- migrate from SQLite to PostgreSQL with Drizzle ORM - implement comprehensive AdminLayout with expandable sidebar navigation - create professional dashboard with real-time charts and metrics - add advanced monitoring, reporting, and export functionality - fix menu alignment and remove non-existent pages - eliminate duplicate headers and improve UI consistency - add Tailwind CSS v3 for professional styling - expand database schema from 6 to 15 tables - implement role-based access control and API key management - create comprehensive settings, monitoring, and system info pages
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import type { NextPage } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import AdminLayout from '../../components/AdminLayout'
|
||||
import { TagIcon, PlusIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
interface Category {
|
||||
id: number
|
||||
@@ -51,78 +52,119 @@ const CategoriesManagement: NextPage = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Head>
|
||||
<title>Správa kategórií - Infohliadka</title>
|
||||
<title>Správa kategórií - Hliadka.sk Admin</title>
|
||||
</Head>
|
||||
<AdminLayout title="Správa kategórií">
|
||||
<div className="px-4 py-6 sm:px-6 lg:px-8">
|
||||
<div className="sm:flex sm:items-center">
|
||||
<div className="sm:flex-auto">
|
||||
<p className="text-sm text-gray-700">
|
||||
Spravujte kategórie a ich nastavenia pre klasifikáciu zdrojov
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
||||
<button
|
||||
type="button"
|
||||
className="btn-primary"
|
||||
>
|
||||
<PlusIcon className="h-4 w-4 mr-2" />
|
||||
Pridať kategóriu
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
|
||||
<h1>Správa kategórií</h1>
|
||||
|
||||
{loading ? (
|
||||
<div>Loading...</div>
|
||||
) : (
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse', marginTop: '20px' }}>
|
||||
<thead>
|
||||
<tr style={{ backgroundColor: '#f3f4f6' }}>
|
||||
<th style={{ padding: '12px', textAlign: 'left', border: '1px solid #d1d5db' }}>Názov</th>
|
||||
<th style={{ padding: '12px', textAlign: 'left', border: '1px solid #d1d5db' }}>Priorita</th>
|
||||
<th style={{ padding: '12px', textAlign: 'left', border: '1px solid #d1d5db' }}>Farba</th>
|
||||
<th style={{ padding: '12px', textAlign: 'left', border: '1px solid #d1d5db' }}>Aktívna</th>
|
||||
<th style={{ padding: '12px', textAlign: 'left', border: '1px solid #d1d5db' }}>Akcie</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{categories.map((category) => (
|
||||
<tr key={category.id}>
|
||||
<td style={{ padding: '12px', border: '1px solid #d1d5db' }}>
|
||||
<strong>{category.name}</strong>
|
||||
<div style={{ fontSize: '12px', color: '#6b7280' }}>
|
||||
{category.description}
|
||||
<div className="mt-8 flow-root">
|
||||
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
||||
<div className="card">
|
||||
{loading ? (
|
||||
<div className="p-6">
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="text-gray-500">Načítavanie...</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style={{ padding: '12px', border: '1px solid #d1d5db' }}>
|
||||
{category.priority}
|
||||
</td>
|
||||
<td style={{ padding: '12px', border: '1px solid #d1d5db' }}>
|
||||
<div style={{
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
backgroundColor: category.color,
|
||||
borderRadius: '4px',
|
||||
display: 'inline-block'
|
||||
}}></div>
|
||||
<span style={{ marginLeft: '8px' }}>{category.color}</span>
|
||||
</td>
|
||||
<td style={{ padding: '12px', border: '1px solid #d1d5db' }}>
|
||||
{category.is_active ? '✅' : '❌'}
|
||||
</td>
|
||||
<td style={{ padding: '12px', border: '1px solid #d1d5db' }}>
|
||||
<button
|
||||
onClick={() => toggleCategory(category.id, category.is_active)}
|
||||
style={{
|
||||
padding: '4px 8px',
|
||||
backgroundColor: category.is_active ? '#ef4444' : '#10b981',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
{category.is_active ? 'Deaktivovať' : 'Aktivovať'}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: '30px' }}>
|
||||
<Link href="/admin">← Späť na dashboard</Link>
|
||||
) : (
|
||||
<table className="min-w-full divide-y divide-gray-300">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" className="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||
Názov
|
||||
</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Priorita
|
||||
</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Farba
|
||||
</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Status
|
||||
</th>
|
||||
<th scope="col" className="relative py-3.5 pl-3 pr-4 sm:pr-6">
|
||||
<span className="sr-only">Akcie</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200 bg-white">
|
||||
{categories.map((category) => (
|
||||
<tr key={category.id} className="hover:bg-gray-50">
|
||||
<td className="whitespace-nowrap py-4 pl-4 pr-3 sm:pl-6">
|
||||
<div className="flex items-center">
|
||||
<TagIcon className="h-5 w-5 text-gray-400 mr-3" />
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-900">{category.name}</div>
|
||||
<div className="text-sm text-gray-500">{category.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
<span className="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">
|
||||
{category.priority}
|
||||
</span>
|
||||
</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
className="w-5 h-5 rounded border border-gray-300 mr-2"
|
||||
style={{ backgroundColor: category.color }}
|
||||
/>
|
||||
<span className="text-xs font-mono">{category.color}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
{category.is_active ? (
|
||||
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
|
||||
Aktívna
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
|
||||
Neaktívna
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
|
||||
<button
|
||||
onClick={() => toggleCategory(category.id, category.is_active)}
|
||||
className={`${
|
||||
category.is_active ? 'btn-danger' : 'btn-secondary'
|
||||
} text-xs px-3 py-1`}
|
||||
>
|
||||
{category.is_active ? 'Deaktivovať' : 'Aktivovať'}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user