Files
web/src/app/admin/(dashboard)/page.tsx
Eamon-meng b3cd22e1cf .hand
2025-06-07 11:28:36 +08:00

193 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Page from '@/components/page'
import Image from 'next/image'
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'
import {format} from 'date-fns'
import {merge} from '@/lib/utils'
import banner from './_assets/banner.webp'
import {listInitialization} from '@/actions/dashboard'
import Charts from './_client/charts'
import UserCenter from './_client/userCenter'
import soon from './_assets/coming-soon.svg'
import mask from './_assets/Mask group.webp'
export type DashboardPageProps = {}
export default async function DashboardPage(props: DashboardPageProps) {
const resp = await listInitialization({
page: 1,
size: 5,
})
if (!resp.success) {
return (
<div className="col-start-4 row-start-3 row-span-2 flex justify-center items-center">
</div>
)
}
const initData = resp.data
return (
<Page className={merge(
`flex-auto grid`,
`grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_300px]`,
`grid-rows-[150px_200px_minmax(150px,1fr)_minmax(150px,1fr)]`,
)}
>
{/* banner */}
<section className="col-start-1 row-start-1 col-span-3 relative rounded-lg overflow-hidden">
<Image src={banner} alt="banner image" className="w-full h-full inset-0 absolute object-cover"/>
<div className="flex flex-col absolute inset-0 justify-center px-8 gap-1">
<h3 className="text-2xl text-primary font-medium">IP资源</h3>
<p className="text-primary font-medium">//IP代理</p>
</div>
</section>
{/* 磁贴集 */}
{initData && (
<Pins
short_term={String(initData.short_term)}
short_term_monthly={String(initData.short_term_monthly)}
long_term={String(initData.long_term)}
long_term_monthly={String(initData.long_term_monthly)}
/>
)}
{/* 图表 */}
<Charts/>
{/* 信息 */}
<UserCenter/>
{/* 通知 */}
{initData && (
<Announcements list={initData.list}/>
)}
</Page>
)
}
type DashboardChartProps = {
short_term: string
short_term_monthly: string
long_term: string
long_term_monthly: string
}
function Pins(props: DashboardChartProps) {
return (
<>
{/* 短效 */}
<Card className="col-start-1 row-start-2 py-4">
<CardHeader>
<CardTitle>
<Image src={mask} alt="Mask group" width={35} height={35} priority/>
{' '}
</CardTitle>
</CardHeader>
<CardContent className="flex-auto flex flex-col gap-2">
<div className="flex-1 flex items-center justify-between">
<h4></h4>
<p className="flex flex-col items-end">
<span className="text-sm text-weak"></span>
<span className="text-lg">{props.short_term ? props.short_term : '1'}</span>
</p>
</div>
<div className="border-b"></div>
<div className="flex-1 flex items-center justify-between">
<h4></h4>
<p className="flex flex-col items-end">
<span className="text-sm text-weak"></span>
<span className="text-lg">{props.short_term_monthly}</span>
</p>
</div>
</CardContent>
</Card>
{/* 长效 */}
<Card className="col-start-2 row-start-2">
<CardHeader>
<CardTitle>
<Image src={mask} alt="Mask group" width={35} height={35} priority/>
{' '}
</CardTitle>
</CardHeader>
<CardContent className="flex-auto flex flex-col gap-2">
{/* <Image alt={`coming soon`} src={soon} />
<p>敬请期待</p> */}
<div className="flex-1 flex items-center justify-between">
<h4></h4>
<p className="flex flex-col items-end">
<span className="text-sm text-weak"></span>
<span className="text-lg">{props.long_term}</span>
</p>
</div>
<div className="border-b"></div>
<div className="flex-1 flex items-center justify-between">
<h4></h4>
<p className="flex flex-col items-end">
<span className="text-sm text-weak"></span>
<span className="text-lg">{props.long_term_monthly}</span>
</p>
</div>
</CardContent>
</Card>
{/* 固定 */}
<Card className="col-start-3 row-start-2 py-4">
<CardHeader className="px-4">
<CardTitle>IP套餐</CardTitle>
</CardHeader>
<CardContent className="flex-auto flex flex-col gap-2 items-center justify-center">
<Image alt="coming soon" src={soon}/>
<p></p>
</CardContent>
</Card>
</>
)
}
type Props = {
list: {
id: number
title: string
created_at: Date
} []
}
function Announcements(props: Props) {
return (
<Card className="col-start-4 row-start-3 row-span-2">
<CardHeader>
<div className="flex justify-between gap-2">
<CardTitle></CardTitle>
<span className="text-sm text-weak"></span>
</div>
</CardHeader>
<CardContent className="flex-auto p-0">
{!props.list.length
? (
<div className="flex flex-col items-center justify-center gap-2 h-full">
<Image alt="coming soon" src={soon}/>
<p></p>
</div>
)
: props.list.map(item => (
<div
key={item.id}
className={merge(
`transition-colors duration-150 ease-in-out`,
`flex flex-col gap-1 px-4 py-2`,
`hover:bg-muted cursor-pointer`,
)}
>
<h4>{item.title}</h4>
<p className="text-sm text-weak">{format(item.created_at, 'yyyy-MM-dd HH:mm')}</p>
</div>
))}
</CardContent>
</Card>
)
}