mirror of
https://github.com/PeterMaquiran/tvone.git
synced 2026-04-22 20:15:51 +00:00
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
// Importe o componente que criámos (ajuste o caminho se necessário)
|
// Importe o componente que criámos (ajuste o caminho se necessário)
|
||||||
import MultiAspectEditor from '../../../components/MultiAspectEditor';
|
import MultiAspectEditor from '../../../components/MultiAspectEditor';
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
import { getFlat, type Category } from "@/lib/categories.api";
|
||||||
// import { keycloak } from '@/app/feature/auth/keycloak-config';
|
// import { keycloak } from '@/app/feature/auth/keycloak-config';
|
||||||
const Editor = dynamic(
|
const Editor = dynamic(
|
||||||
() => import("@tinymce/tinymce-react").then((mod) => mod.Editor),
|
() => import("@tinymce/tinymce-react").then((mod) => mod.Editor),
|
||||||
@@ -69,8 +70,30 @@ export const CreateNewsPage = () => {
|
|||||||
picture?: string;
|
picture?: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
const [categories, setCategories] = useState<Category[]>([]);
|
||||||
|
const [categoriesLoading, setCategoriesLoading] = useState(true);
|
||||||
|
const [categoryId, setCategoryId] = useState<string>("");
|
||||||
|
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
|
(async () => {
|
||||||
|
setCategoriesLoading(true);
|
||||||
|
try {
|
||||||
|
const list = await getFlat();
|
||||||
|
if (!cancelled) setCategories(list);
|
||||||
|
} catch {
|
||||||
|
if (!cancelled) setCategories([]);
|
||||||
|
} finally {
|
||||||
|
if (!cancelled) setCategoriesLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
// 2. Lógica de Upload
|
// 2. Lógica de Upload
|
||||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
if (e.target.files && e.target.files.length > 0) {
|
if (e.target.files && e.target.files.length > 0) {
|
||||||
@@ -191,10 +214,20 @@ export const CreateNewsPage = () => {
|
|||||||
<label className="flex items-center gap-2 text-xs font-bold uppercase text-slate-400 mb-3">
|
<label className="flex items-center gap-2 text-xs font-bold uppercase text-slate-400 mb-3">
|
||||||
<Tag size={14}/> Categoria
|
<Tag size={14}/> Categoria
|
||||||
</label>
|
</label>
|
||||||
<select className="w-full bg-slate-50 border border-slate-100 rounded-lg px-3 py-2 text-sm outline-none">
|
<select
|
||||||
<option>Negócios</option>
|
value={categoryId}
|
||||||
<option>Tecnologia</option>
|
onChange={(e) => setCategoryId(e.target.value)}
|
||||||
<option>Desporto</option>
|
disabled={categoriesLoading}
|
||||||
|
className="w-full bg-slate-50 border border-slate-100 rounded-lg px-3 py-2 text-sm outline-none disabled:opacity-60"
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
{categoriesLoading ? "A carregar categorias…" : "Selecione uma categoria"}
|
||||||
|
</option>
|
||||||
|
{categories.map((c) => (
|
||||||
|
<option key={c.id} value={c.id}>
|
||||||
|
{c.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,7 @@
|
|||||||
import CreateNewsPage from './create-news';
|
import CreateNewsPage from './create-news';
|
||||||
import { AdminHeaderPage } from '@/app/components/layout/admin/header';
|
|
||||||
import { AdminSideBar } from '@/app/components/layout/admin/sidebar';
|
|
||||||
|
|
||||||
|
|
||||||
const CreateNews = () => {
|
const CreateNews = () => {
|
||||||
return (
|
return <CreateNewsPage />;
|
||||||
<div className="flex h-screen bg-slate-100/50 text-slate-900 font-sans">
|
|
||||||
|
|
||||||
{/* Sidebar Lateral */}
|
|
||||||
<AdminSideBar />
|
|
||||||
|
|
||||||
{/* Main Content Area */}
|
|
||||||
<main className="flex-1 overflow-y-auto">
|
|
||||||
<AdminHeaderPage />
|
|
||||||
<CreateNewsPage />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreateNews;
|
export default CreateNews;
|
||||||
@@ -2,25 +2,16 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
Newspaper,
|
Newspaper,
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
Eye,
|
|
||||||
Clock,
|
Clock,
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
Edit3,
|
Edit3,
|
||||||
Trash2,
|
Trash2,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { AdminHeaderPage } from '@/app/components/layout/admin/header';
|
|
||||||
import { AdminSideBar } from '@/app/components/layout/admin/sidebar';
|
|
||||||
|
|
||||||
const DashboardMain = () => {
|
const DashboardMain = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen bg-[#F1F5F9] text-slate-900 font-sans">
|
<div className="p-8 space-y-8 min-h-full bg-[#F1F5F9]">
|
||||||
<AdminSideBar />
|
|
||||||
|
|
||||||
<main className="flex-1 overflow-y-auto flex flex-col min-h-0">
|
|
||||||
<AdminHeaderPage />
|
|
||||||
|
|
||||||
<div className="p-8 space-y-8 flex-1">
|
|
||||||
<div className="grid grid-cols-4 gap-6">
|
<div className="grid grid-cols-4 gap-6">
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Artigos Publicados"
|
label="Artigos Publicados"
|
||||||
@@ -111,8 +102,6 @@ const DashboardMain = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { AdminHeaderPage } from '@/app/components/layout/admin/header';
|
||||||
|
import { AdminSideBar } from '@/app/components/layout/admin/sidebar';
|
||||||
|
|
||||||
|
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="flex h-screen bg-slate-100/50 text-slate-900 font-sans overflow-hidden">
|
||||||
|
<AdminSideBar />
|
||||||
|
|
||||||
|
<main className="flex-1 min-w-0 min-h-0 overflow-y-auto flex flex-col">
|
||||||
|
<AdminHeaderPage />
|
||||||
|
<div className="flex-1 min-h-0">{children}</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,5 @@
|
|||||||
import { AdminHeaderPage } from '@/app/components/layout/admin/header';
|
|
||||||
import { AdminSideBar } from '@/app/components/layout/admin/sidebar';
|
|
||||||
import ManageCategoryClient from './manage-category-client';
|
import ManageCategoryClient from './manage-category-client';
|
||||||
|
|
||||||
export default function ManageCategoryPage() {
|
export default function ManageCategoryPage() {
|
||||||
return (
|
return <ManageCategoryClient />;
|
||||||
<div className="flex h-screen bg-slate-50 text-slate-900">
|
|
||||||
<AdminSideBar />
|
|
||||||
|
|
||||||
<div className="flex-1 flex flex-col min-h-0 overflow-hidden">
|
|
||||||
<AdminHeaderPage />
|
|
||||||
<ManageCategoryClient />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,5 @@
|
|||||||
import { AdminHeaderPage } from '@/app/components/layout/admin/header';
|
|
||||||
import { AdminSideBar } from '@/app/components/layout/admin/sidebar';
|
|
||||||
import PanelEditor from './panel-editor';
|
import PanelEditor from './panel-editor';
|
||||||
|
|
||||||
export default function PanelPage() {
|
export default function PanelPage() {
|
||||||
return (
|
return <PanelEditor />;
|
||||||
<div className="flex h-screen bg-slate-100 text-slate-900 font-sans overflow-hidden">
|
|
||||||
<AdminSideBar />
|
|
||||||
|
|
||||||
<div className="flex-1 flex flex-col min-h-0 min-w-0">
|
|
||||||
<AdminHeaderPage />
|
|
||||||
<div className="flex-1 min-h-0 overflow-hidden">
|
|
||||||
<PanelEditor />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user