64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
import { Home, MessageSquare, Images, Users } from 'lucide-react'
|
||
import { prisma } from '@/lib/db'
|
||
import { MOCK_UNITS, MOCK_MESSAGES, MOCK_GALLERY } from '@/lib/mock'
|
||
|
||
const USE_MOCK = process.env.USE_MOCK === 'true'
|
||
|
||
async function getStats() {
|
||
if (USE_MOCK) {
|
||
return {
|
||
units: MOCK_UNITS.length,
|
||
messages: MOCK_MESSAGES.length,
|
||
unread: MOCK_MESSAGES.filter((m) => !m.read).length,
|
||
gallery: MOCK_GALLERY.length,
|
||
}
|
||
}
|
||
const [units, messages, gallery] = await Promise.all([
|
||
prisma.unit.count({ where: { deletedAt: null } }),
|
||
prisma.contactMessage.count({ where: { deletedAt: null } }),
|
||
prisma.gallery.count({ where: { deletedAt: null } }),
|
||
])
|
||
const unread = await prisma.contactMessage.count({ where: { deletedAt: null, read: false } })
|
||
return { units, messages, unread, gallery }
|
||
}
|
||
|
||
export default async function AdminDashboard() {
|
||
const stats = await getStats()
|
||
|
||
const cards = [
|
||
{ label: 'Daire Tipi', value: stats.units, icon: Home, color: 'bg-blue-50 text-blue-600' },
|
||
{
|
||
label: 'Mesaj',
|
||
value: stats.messages,
|
||
sub: `${stats.unread} okunmamış`,
|
||
icon: MessageSquare,
|
||
color: 'bg-amber-50 text-amber-600',
|
||
},
|
||
{ label: 'Galeri', value: stats.gallery, icon: Images, color: 'bg-green-50 text-green-600' },
|
||
{ label: 'Kullanıcı', value: 1, icon: Users, color: 'bg-purple-50 text-purple-600' },
|
||
]
|
||
|
||
return (
|
||
<div>
|
||
<h1 className="text-2xl font-semibold text-gray-900 mb-2">Dashboard</h1>
|
||
<p className="text-gray-400 text-sm mb-8">Vesta Muğla yönetim paneline hoş geldiniz.</p>
|
||
|
||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||
{cards.map((card) => {
|
||
const Icon = card.icon
|
||
return (
|
||
<div key={card.label} className="bg-white rounded-2xl p-6 shadow-sm">
|
||
<div className={`w-10 h-10 rounded-xl flex items-center justify-center mb-4 ${card.color}`}>
|
||
<Icon className="w-5 h-5" />
|
||
</div>
|
||
<p className="text-3xl font-semibold text-gray-900">{card.value}</p>
|
||
<p className="text-gray-400 text-sm mt-1">{card.label}</p>
|
||
{card.sub && <p className="text-xs text-amber-500 mt-1">{card.sub}</p>}
|
||
</div>
|
||
)
|
||
})}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|