Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | export const dynamic = 'force-dynamic' import Link from 'next/link' import {prisma} from '@/lib/db' import {pageAdmin} from '@/lib/guard' import {iconUrl} from '@/lib/band' import VoteThreshold from '@/components/VoteThreshold' import BandSettings from '@/components/BandSettings' export const metadata = {title: 'Admin'} export default async function AdminPage() { const {band, user} = await pageAdmin() const [members, noPassword, songs, versions] = await Promise.all([ prisma.membership.count({where: {bandId: band.id}}), prisma.membership.count({ where: {bandId: band.id, user: {passwordHash: null}}, }), prisma.song.count({where: {bandId: band.id}}), prisma.chartVersion.count({where: {song: {bandId: band.id}}}), ]) const cards = [ { href: '/members', title: 'Band members', body: `${members} members${noPassword ? ` · ${noPassword} without a password yet` : ''}. Add people, send passwords, make admins.`, }, { href: '/activity', title: 'Recent changes', body: 'Everything anyone has changed, newest first.', }, { href: '/songs/new', title: 'Add a song', body: `${songs} songs, ${versions} chart versions so far.`, }, ] return ( <main className="mx-auto max-w-3xl px-4 pb-12 pt-5"> <h1 className="text-3xl font-extrabold">Admin</h1> <p className="mt-1 text-muted">{band.name}</p> <div className="mt-5 grid gap-3 sm:grid-cols-3"> {cards.map((c) => ( <Link key={c.href} href={c.href} className="rounded-xl border border-line-2 bg-panel p-4 no-underline hover:border-text" > <span className="block font-bold">{c.title} ›</span> <span className="mt-1 block text-sm text-muted">{c.body}</span> </Link> ))} </div> <section aria-labelledby="band-h" className="mt-8"> <h2 id="band-h" className="text-xs font-bold uppercase tracking-widest text-muted" > The band </h2> <BandSettings initial={{ scheduling: band.scheduling, name: band.name, appName: band.appName, timezone: band.timezone, chatUrl: band.chatUrl ?? '', tributeTo: band.tributeTo ?? '', }} iconSrc={iconUrl(band)} hasIcon={Boolean(band.iconAt)} /> </section> <section aria-labelledby="vote-h" className="mt-8"> <h2 id="vote-h" className="text-xs font-bold uppercase tracking-widest text-muted" > Proposals </h2> <VoteThreshold initial={band.voteThreshold} max={members || 6} /> </section> {user.isOwner && ( <p className="mt-8 text-sm"> <Link href="/bands/manage" className="text-sky"> All bands on this site and their web addresses › </Link> </p> )} </main> ) } |