All files / Bandstand/src/app/(band)/admin page.tsx

0% Statements 0/84
0% Branches 0/1
0% Functions 0/1
0% Lines 0/84

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>
  )
}