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

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

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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125                                                                                                                                                                                                                                                         
import Link from 'next/link'
import DemoBanner from '@/components/tour/DemoBanner'
import {pageSession} from '@/lib/guard'
import {
  formatClock,
  parseClock,
  runningOrder,
  setSummary,
  timeRange,
} from '@/lib/gig'
import {DEMO_SETLIST as set} from '@/lib/tour-demo'
 
export const metadata = {title: 'Sample setlist'}
 
const inert = 'pointer-events-none'
 
/**
 * The tour's setlist: laid out like a real one (setlists/[id]), the same
 * for every band, saved nowhere. Its buttons are for show.
 */
export default async function TourSetlist() {
  await pageSession()
  const order = runningOrder(set.startTime, set.items)
  const songs = order.entries.filter((e) => e.kind === 'SONG').length
  const start = parseClock(set.startTime)
  return (
    <>
      <DemoBanner what="setlist" />
      <main className="mx-auto max-w-3xl px-4 pb-12 pt-4">
        <Link
          href="/setlists"
          className="text-sm text-muted no-underline hover:text-text"
        >
          ‹ Setlists
        </Link>
        <h1 className="mt-1 text-3xl font-extrabold">{set.name}</h1>
        <p className="mt-1 text-muted">
          {[
            set.date,
            start != null && formatClock(start, true),
            set.venue,
            `${songs} songs`,
          ]
            .filter(Boolean)
            .join(' · ')}
        </p>
 
        <div className="mt-4 flex flex-wrap gap-2">
          <span
            data-tour="perform"
            className="inline-flex min-h-11 items-center rounded-lg bg-accent px-4 font-extrabold text-on-accent"
          >
            ▶ Perform
          </span>
          <span
            className={`${inert} inline-flex min-h-11 items-center rounded-lg border border-line-2 px-4`}
          >
            PDF
          </span>
          <span
            className={`${inert} inline-flex min-h-11 items-center rounded-lg border border-line-2 px-4`}
          >
            Save for offline
          </span>
        </div>
 
        <p className="mt-5 whitespace-pre-wrap rounded-xl bg-panel px-4 py-3 text-[15px]">
          {set.notes}
        </p>
 
        <ol className="mt-5">
          {order.entries.map((e) => {
            if (e.kind === 'SET')
              return (
                <li
                  key={e.item.id}
                  className="mt-6 flex flex-wrap items-baseline gap-x-3 border-b-2 border-amber pb-1 first:mt-0"
                >
                  <h2 className="text-lg font-extrabold">{e.info.label}</h2>
                  <span className="font-mono">
                    {timeRange(e.info.start, e.info.end)}
                  </span>
                  <span className="text-sm text-muted">
                    {setSummary(e.info)}
                  </span>
                </li>
              )
            if (e.kind === 'BREAK')
              return (
                <li
                  key={e.item.id}
                  className="my-4 flex items-center gap-3 text-sm text-muted"
                >
                  <span className="h-px flex-1 bg-line-2" />
                  Break · {e.info.minutes} min ·{' '}
                  {timeRange(e.info.start, e.info.end)}
                  <span className="h-px flex-1 bg-line-2" />
                </li>
              )
            const i = e.item
            return (
              <li key={i.id} className="border-t border-line py-3">
                <div className="flex items-baseline gap-3">
                  <span className="w-6 shrink-0 font-mono text-sm text-faint">
                    {e.n}
                  </span>
                  <span className="min-w-0 flex-1 text-lg font-semibold">
                    {i.song?.title}
                  </span>
                  <span className="shrink-0 font-mono font-bold text-amber">
                    {i.key}
                  </span>
                </div>
                {i.note && (
                  <p className="mt-1 pl-9 text-[15px] text-warn-fg">{i.note}</p>
                )}
              </li>
            )
          })}
        </ol>
      </main>
    </>
  )
}