All files / Bandstand/src/lib proposals.ts

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

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                                                                                                                                                                                                       
import {prisma} from './db'
import {displayName} from './songs'
import {avatarUrl} from './avatars'
 
export type BoardProposal = {
  id: string
  title: string
  artist: string
  youtubeUrl: string | null
  lyricsUrl: string | null
  proposer: string
  proposerAvatar: string | null
  proposedAt: string
  voters: {name: string; avatar: string | null}[]
  mine: boolean
}
 
/** Everything the Proposals page shows, in one query per list. */
export async function getBoard(
  userId: string,
  band: {id: string; voteThreshold: number},
) {
  const threshold = band.voteThreshold
  const who = {
    select: {
      id: true,
      name: true,
      displayName: true,
      email: true,
      avatarAt: true,
    },
  } as const
  const [pending, approved, archived] = await Promise.all([
    prisma.proposal.findMany({
      where: {bandId: band.id, status: 'PENDING'},
      orderBy: {createdAt: 'desc'},
      include: {
        proposer: who,
        votes: {include: {user: who}, orderBy: {createdAt: 'asc'}},
      },
    }),
    prisma.proposal.findMany({
      where: {bandId: band.id, status: 'APPROVED'},
      orderBy: {updatedAt: 'desc'},
      take: 8,
    }),
    prisma.proposal.findMany({
      where: {bandId: band.id, status: 'ARCHIVED'},
      orderBy: {updatedAt: 'desc'},
      take: 30,
      include: {proposer: who},
    }),
  ])
  // Link approved proposals to the song they became
  const songs = await prisma.song.findMany({
    where: {
      bandId: band.id,
      title: {in: approved.map((a) => a.title), mode: 'insensitive'},
    },
    select: {id: true, title: true},
  })
  const songByTitle = new Map(songs.map((s) => [s.title.toLowerCase(), s.id]))
 
  const toBoard = (p: (typeof pending)[number]): BoardProposal => ({
    id: p.id,
    title: p.title,
    artist: p.artist,
    youtubeUrl: p.youtubeUrl,
    lyricsUrl: p.lyricsUrl,
    proposer: displayName(p.proposer),
    proposerAvatar: avatarUrl(p.proposer),
    proposedAt: p.createdAt.toISOString(),
    voters: p.votes.map((v) => ({
      name: displayName(v.user),
      avatar: avatarUrl(v.user),
    })),
    mine: p.votes.some((v) => v.userId === userId),
  })
 
  return {
    threshold,
    pending: pending.map(toBoard),
    approved: approved.map((a) => ({
      id: a.id,
      title: a.title,
      artist: a.artist,
      approvedAt: a.updatedAt.toISOString(),
      songId: songByTitle.get(a.title.toLowerCase()) ?? null,
    })),
    archived: archived.map((a) => ({
      id: a.id,
      title: a.title,
      artist: a.artist,
      proposer: displayName(a.proposer),
    })),
  }
}
 
export type Board = Awaited<ReturnType<typeof getBoard>>