Spaces:
Running
Running
Build a secure full-stack website for ZimProjects.co.zw using Next.js (frontend) and Node/Express with MongoDB (backend). Model it visually and structurally on https://www.constructionenquirer.com/ , including ad slots, article management, and project listings. Include JWT authentication, admin dashboard, and responsive ad placements. Use Tailwind CSS, optimize for SEO, and prepare for deployment on Vercel and AWS. Provide complete code architecture with modular file structure and setup instructions. This should easily be uploaded to the Cpanel.
9fc92d7 verified | import { useEffect, useState } from 'react' | |
| import AdminLayout from '../../components/AdminLayout' | |
| import { useAuth } from '../../context/AuthContext' | |
| import { fetchAdminStats } from '../../lib/api' | |
| export default function AdminDashboard() { | |
| const { user } = useAuth() | |
| const [stats, setStats] = useState(null) | |
| const [loading, setLoading] = useState(true) | |
| useEffect(() => { | |
| if (user && user.role === 'admin') { | |
| const loadStats = async () => { | |
| const data = await fetchAdminStats() | |
| setStats(data) | |
| setLoading(false) | |
| } | |
| loadStats() | |
| } | |
| }, [user]) | |
| if (!user || user.role !== 'admin') { | |
| return ( | |
| <div className="text-center py-20"> | |
| <h2 className="text-2xl font-bold">Unauthorized Access</h2> | |
| <p>You do not have permission to view this page</p> | |
| </div> | |
| ) | |
| } | |
| if (loading) return <div className="text-center py-20">Loading...</div> | |
| return ( | |
| <AdminLayout> | |
| <div className="bg-white rounded-lg shadow p-6"> | |
| <h2 className="text-2xl font-bold mb-6">Admin Dashboard</h2> | |
| <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> | |
| <div className="bg-blue-50 p-4 rounded-lg"> | |
| <h3 className="font-semibold text-blue-800">Total Articles</h3> | |
| <p className="text-3xl font-bold">{stats.articles}</p> | |
| </div> | |
| <div className="bg-green-50 p-4 rounded-lg"> | |
| <h3 className="font-semibold text-green-800">Active Projects</h3> | |
| <p className="text-3xl font-bold">{stats.projects}</p> | |
| </div> | |
| <div className="bg-purple-50 p-4 rounded-lg"> | |
| <h3 className="font-semibold text-purple-800">Current Tenders</h3> | |
| <p className="text-3xl font-bold">{stats.tenders}</p> | |
| </div> | |
| </div> | |
| <div className="mb-8"> | |
| <h3 className="text-xl font-semibold mb-4">Recent Articles</h3> | |
| <div className="space-y-4"> | |
| {stats.recentArticles.map(article => ( | |
| <div key={article.id} className="border-b pb-2"> | |
| <h4 className="font-medium">{article.title}</h4> | |
| <p className="text-sm text-gray-600">{new Date(article.createdAt).toLocaleDateString()}</p> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| </AdminLayout> | |
| ) | |
| } |