171 lines
6.7 KiB
TypeScript
171 lines
6.7 KiB
TypeScript
import Link from 'next/link'
|
|
import { getPayload } from 'payload'
|
|
import configPromise from '@payload-config'
|
|
import { clearFrontendCache } from './admin-cache-actions'
|
|
|
|
const QUICK_LINKS = [
|
|
{
|
|
description: 'Manage hero modules, featured products, support panels, and homepage news surfaces.',
|
|
href: '/admin/globals/homepage',
|
|
title: 'Homepage',
|
|
},
|
|
{
|
|
description: 'Open core product records, templates, editor-driven pages, downloads, reviews, and videos.',
|
|
href: '/admin/collections/products',
|
|
title: 'Products',
|
|
},
|
|
{
|
|
description: 'Review firmware, manuals, online-upgrade entries, and release-note content.',
|
|
href: '/admin/collections/downloads',
|
|
title: 'Downloads',
|
|
},
|
|
{
|
|
description: 'Keep support landing copy, FAQ content, contact instructions, and warranty policy aligned.',
|
|
href: '/admin/globals/supportPage',
|
|
title: 'Support',
|
|
},
|
|
{
|
|
description: 'Track incoming after-sales, distributor, and OEM requests in one operations lane.',
|
|
href: '/admin/collections/afterServiceRequests',
|
|
title: 'Operations',
|
|
},
|
|
{
|
|
description: 'Publish news, maintain redirects, and keep site-wide branding settings consistent.',
|
|
href: '/admin/collections/news',
|
|
title: 'Publishing',
|
|
},
|
|
] as const
|
|
|
|
const WORKSTREAMS = [
|
|
'Template-backed products: keep local template assignments stable and manage hero/card media from the product record.',
|
|
'Editor-driven products: use the imported legacy HTML as the rebuild reference, then move final content into overview and structured fields.',
|
|
'Downloads: maintain release notes, package links, online-upgrade guidance, and product visibility together.',
|
|
'Social proof: attach videos and reviews directly to each product so the frontend tabs stay complete.',
|
|
] as const
|
|
|
|
function formatCount(value: number) {
|
|
return new Intl.NumberFormat('en-US').format(value)
|
|
}
|
|
|
|
async function getOverviewCounts() {
|
|
const payload = await getPayload({ config: configPromise })
|
|
|
|
const [
|
|
products,
|
|
downloads,
|
|
productVideos,
|
|
productReviews,
|
|
news,
|
|
faqs,
|
|
dealers,
|
|
afterServiceRequests,
|
|
distributorRequests,
|
|
oemRequests,
|
|
] = await Promise.all([
|
|
payload.count({ collection: 'products' }),
|
|
payload.count({ collection: 'downloads' }),
|
|
payload.count({ collection: 'productVideos' }),
|
|
payload.count({ collection: 'productReviews' }),
|
|
payload.count({ collection: 'news' }),
|
|
payload.count({ collection: 'faqs' }),
|
|
payload.count({ collection: 'dealers' }),
|
|
payload.count({ collection: 'afterServiceRequests' }),
|
|
payload.count({ collection: 'distributorRequests' }),
|
|
payload.count({ collection: 'oemRequests' }),
|
|
])
|
|
|
|
return [
|
|
{ eyebrow: 'Catalog', href: '/admin/collections/products', title: 'Products', value: products.totalDocs },
|
|
{ eyebrow: 'Catalog', href: '/admin/collections/downloads', title: 'Downloads', value: downloads.totalDocs },
|
|
{ eyebrow: 'Social Proof', href: '/admin/collections/productVideos', title: 'Product Videos', value: productVideos.totalDocs },
|
|
{ eyebrow: 'Social Proof', href: '/admin/collections/productReviews', title: 'Product Reviews', value: productReviews.totalDocs },
|
|
{ eyebrow: 'Publishing', href: '/admin/collections/news', title: 'News', value: news.totalDocs },
|
|
{ eyebrow: 'Support', href: '/admin/collections/faqs', title: 'FAQs', value: faqs.totalDocs },
|
|
{ eyebrow: 'Sales', href: '/admin/collections/dealers', title: 'Dealers', value: dealers.totalDocs },
|
|
{
|
|
eyebrow: 'Operations',
|
|
href: '/admin/collections/afterServiceRequests',
|
|
title: 'Requests',
|
|
value: afterServiceRequests.totalDocs + distributorRequests.totalDocs + oemRequests.totalDocs,
|
|
},
|
|
]
|
|
}
|
|
|
|
export async function AdminHome({ cacheCleared = false }: { cacheCleared?: boolean }) {
|
|
const stats = await getOverviewCounts()
|
|
|
|
return (
|
|
<div className="studio-home">
|
|
<section className="studio-home__hero">
|
|
<div>
|
|
<p className="studio-home__eyebrow">Eversolo Content Studio</p>
|
|
<h1 className="studio-home__title">A cleaner control room for products, publishing, and support.</h1>
|
|
<p className="studio-home__lede">
|
|
This workspace keeps template-backed products, CMS-built pages, firmware updates, reviews,
|
|
videos, and support operations in one place.
|
|
</p>
|
|
</div>
|
|
<div className="studio-home__actions">
|
|
<Link className="studio-home__primary" href="/admin/collections/products">
|
|
Open products
|
|
</Link>
|
|
<Link className="studio-home__secondary" href="/admin/globals/homepage">
|
|
Edit homepage
|
|
</Link>
|
|
<form action={clearFrontendCache}>
|
|
<input type="hidden" name="returnTo" value="/admin" />
|
|
<button className="studio-home__secondary studio-home__secondary--warm" type="submit">
|
|
Clear frontend cache
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
{cacheCleared ? (
|
|
<section className="studio-home__notice" aria-live="polite">
|
|
Frontend cache cleared. Refresh the storefront to confirm the latest content, ordering, and homepage feeds.
|
|
</section>
|
|
) : null}
|
|
|
|
<section className="studio-home__stats">
|
|
{stats.map((stat) => (
|
|
<Link key={stat.title} href={stat.href} className="studio-home__stat-card">
|
|
<span className="studio-home__stat-eyebrow">{stat.eyebrow}</span>
|
|
<strong className="studio-home__stat-value">{formatCount(stat.value)}</strong>
|
|
<span className="studio-home__stat-title">{stat.title}</span>
|
|
</Link>
|
|
))}
|
|
</section>
|
|
|
|
<section className="studio-home__grid">
|
|
<div className="studio-home__panel">
|
|
<div className="studio-home__panel-head">
|
|
<h2>Priority lanes</h2>
|
|
<p>Jump into the surfaces that drive the storefront most often.</p>
|
|
</div>
|
|
<div className="studio-home__link-list">
|
|
{QUICK_LINKS.map((item) => (
|
|
<Link key={item.href} className="studio-home__link-card" href={item.href}>
|
|
<strong>{item.title}</strong>
|
|
<span>{item.description}</span>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="studio-home__panel">
|
|
<div className="studio-home__panel-head">
|
|
<h2>Editorial guidance</h2>
|
|
<p>Keep the admin team working the same way across templates, downloads, and support.</p>
|
|
</div>
|
|
<ul className="studio-home__checklist">
|
|
{WORKSTREAMS.map((item) => (
|
|
<li key={item}>{item}</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
)
|
|
}
|