more questions
This commit is contained in:
parent
2154c0b6d1
commit
3b7d669a5d
5 changed files with 437 additions and 3 deletions
|
|
@ -64,6 +64,61 @@ function createFakeDb(trackReleaseDate: Date | null) {
|
||||||
} as unknown as Db;
|
} as unknown as Db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createDetailedTrackDb() {
|
||||||
|
const tracks = [
|
||||||
|
{
|
||||||
|
id: "track-1",
|
||||||
|
albumId: "album-1",
|
||||||
|
platform: "spotify",
|
||||||
|
platform_id: "spotify:track:one",
|
||||||
|
name: "First Track",
|
||||||
|
popularity: 1,
|
||||||
|
duration: 180000,
|
||||||
|
explicit: false,
|
||||||
|
disc_number: 1,
|
||||||
|
track_number: 1,
|
||||||
|
album: { name: "First Album", release_date: new Date("2001-01-01") },
|
||||||
|
artists: [{ id: "artist-1", name: "Shared Artist" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "track-2",
|
||||||
|
albumId: "album-2",
|
||||||
|
platform: "spotify",
|
||||||
|
platform_id: "spotify:track:two",
|
||||||
|
name: "Second Track",
|
||||||
|
popularity: 1,
|
||||||
|
duration: 240000,
|
||||||
|
explicit: false,
|
||||||
|
disc_number: 1,
|
||||||
|
track_number: 1,
|
||||||
|
album: { name: "Second Album", release_date: new Date("2010-01-01") },
|
||||||
|
artists: [{ id: "artist-1", name: "Shared Artist" }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
query: {
|
||||||
|
track: {
|
||||||
|
findFirst: vi.fn(async () => tracks[0]),
|
||||||
|
findMany: vi.fn(async ({ where }: { where?: { name?: string } } = {}) =>
|
||||||
|
tracks.filter((track) => !where?.name || track.name === where.name),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
artist: {
|
||||||
|
findFirst: vi.fn(async () => ({
|
||||||
|
id: "artist-1",
|
||||||
|
name: "Shared Artist",
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: vi.fn(() => ({
|
||||||
|
from: () => ({
|
||||||
|
where: async () => [],
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
} as unknown as Db;
|
||||||
|
}
|
||||||
|
|
||||||
function makeSong(id: string, platformId: string, name: string): Song {
|
function makeSong(id: string, platformId: string, name: string): Song {
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
|
@ -234,6 +289,66 @@ describe("question generation", () => {
|
||||||
expect(question).toBeNull();
|
expect(question).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("builds a numeric release-year question for a track", async () => {
|
||||||
|
const randomSpy = vi.spyOn(Math, "random").mockReturnValue(0);
|
||||||
|
const analytics = {
|
||||||
|
storyClusters: [
|
||||||
|
{
|
||||||
|
tracks: [
|
||||||
|
{
|
||||||
|
name: "First Track",
|
||||||
|
artists: [{ name: "Shared Artist" }],
|
||||||
|
albumName: "First Album",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Second Track",
|
||||||
|
artists: [{ name: "Shared Artist" }],
|
||||||
|
albumName: "Second Album",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
artists: [{ name: "Shared Artist" }],
|
||||||
|
genres: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
groupSummary: { mostSharedGenres: [] },
|
||||||
|
} as PartyAnalytics;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const question = await buildNumericQuestion({
|
||||||
|
db: createDetailedTrackDb(),
|
||||||
|
analytics,
|
||||||
|
index: 0,
|
||||||
|
members: [
|
||||||
|
{ userId: "a", name: "A" },
|
||||||
|
{ userId: "b", name: "B" },
|
||||||
|
],
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
questionIndex: 0,
|
||||||
|
question: {
|
||||||
|
type: "numeric",
|
||||||
|
text: "What's the release year of First Album?",
|
||||||
|
correct: 2001,
|
||||||
|
startTimestamp: 1,
|
||||||
|
endTimestamp: 2,
|
||||||
|
points: 10,
|
||||||
|
range: { min: 1991, max: 2011 },
|
||||||
|
questionKey: "numeric:album-year:First Album",
|
||||||
|
subjectKey: "album:First Album",
|
||||||
|
},
|
||||||
|
responses: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(question?.text).toBe('What year did "First Track" come out?');
|
||||||
|
expect(question?.correct).toBe(2001);
|
||||||
|
expect(question?.questionKey).toBe("numeric:track-year:First Track");
|
||||||
|
} finally {
|
||||||
|
randomSpy.mockRestore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("skips social fallback names for duplicate members", async () => {
|
it("skips social fallback names for duplicate members", async () => {
|
||||||
const db = createFakeDb(null);
|
const db = createFakeDb(null);
|
||||||
const members: PartyQuestionMember[] = [
|
const members: PartyQuestionMember[] = [
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,47 @@ import {
|
||||||
resolveQuestionSong,
|
resolveQuestionSong,
|
||||||
} from "./question-utils";
|
} from "./question-utils";
|
||||||
|
|
||||||
|
type TrackDetails = {
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
platform_id: string | null;
|
||||||
|
duration: number | null;
|
||||||
|
album?: { name: string | null; release_date: Date | null } | null;
|
||||||
|
artists?: { name: string }[] | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getDetailedTopTracks(
|
||||||
|
dbClient: typeof Db,
|
||||||
|
analytics: PartyAnalytics,
|
||||||
|
): Promise<TrackDetails[]> {
|
||||||
|
const tracks: TrackDetails[] = [];
|
||||||
|
const seen = new Set<string>();
|
||||||
|
|
||||||
|
for (const topTrack of getTopClusterTracks(analytics)) {
|
||||||
|
const dbTracks = (await dbClient.query.track.findMany({
|
||||||
|
where: { name: topTrack.name },
|
||||||
|
with: { album: true, artists: true },
|
||||||
|
})) as TrackDetails[];
|
||||||
|
const sortedTracks = dbTracks.slice().sort((a, b) => {
|
||||||
|
const aArtists = a.artists?.map((artist) => artist.name) ?? [];
|
||||||
|
const bArtists = b.artists?.map((artist) => artist.name) ?? [];
|
||||||
|
const topArtists = topTrack.artists?.map((artist) => artist.name) ?? [];
|
||||||
|
const score = (track: typeof a, artistNames: string[]) =>
|
||||||
|
(track.album?.name === topTrack.albumName ? 2 : 0) +
|
||||||
|
(topArtists.some((name) => artistNames.includes(name)) ? 2 : 0);
|
||||||
|
return score(b, bArtists) - score(a, aArtists);
|
||||||
|
});
|
||||||
|
const track = sortedTracks[0];
|
||||||
|
if (!track || !isUsableText(track.name)) continue;
|
||||||
|
const key = track.platform_id ?? track.id;
|
||||||
|
if (seen.has(key)) continue;
|
||||||
|
seen.add(key);
|
||||||
|
tracks.push(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
|
||||||
export async function buildAudioMetadataQuestion(
|
export async function buildAudioMetadataQuestion(
|
||||||
dbClient: typeof Db,
|
dbClient: typeof Db,
|
||||||
analytics: PartyAnalytics,
|
analytics: PartyAnalytics,
|
||||||
|
|
@ -114,6 +155,120 @@ export async function buildAudioMetadataQuestion(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const topTrack of topTracks) {
|
||||||
|
const correctArtist = topTrack.artists?.find((artist) =>
|
||||||
|
isUsableText(artist.name),
|
||||||
|
)?.name;
|
||||||
|
if (!topTrack.albumName || !correctArtist) continue;
|
||||||
|
const artistOptions = buildOptionsWithCorrect(correctArtist, topArtists, 4);
|
||||||
|
if (artistOptions) {
|
||||||
|
questions.push({
|
||||||
|
key: `audio:album-artist:${topTrack.albumName}:${correctArtist}`,
|
||||||
|
subjectKey: `album:${topTrack.albumName}`,
|
||||||
|
question: {
|
||||||
|
type: "choice",
|
||||||
|
text: `Which artist appears on "${topTrack.albumName}"?`,
|
||||||
|
options: artistOptions,
|
||||||
|
correct: 0,
|
||||||
|
points: 10,
|
||||||
|
song: topSong ?? undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const detailedTracks = await getDetailedTopTracks(dbClient, analytics);
|
||||||
|
const datedTracks = detailedTracks.filter(
|
||||||
|
(track) => track.album?.release_date,
|
||||||
|
);
|
||||||
|
if (datedTracks.length >= 2) {
|
||||||
|
const sortedByRelease = datedTracks
|
||||||
|
.slice()
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
Number(a.album?.release_date ?? 0) -
|
||||||
|
Number(b.album?.release_date ?? 0),
|
||||||
|
);
|
||||||
|
const earliest = sortedByRelease[0];
|
||||||
|
const latest = sortedByRelease.at(-1);
|
||||||
|
const trackNames = sortedByRelease
|
||||||
|
.map((track) => track.name)
|
||||||
|
.filter((name): name is string => isUsableText(name));
|
||||||
|
|
||||||
|
if (earliest?.name) {
|
||||||
|
const options = buildOptionsWithCorrect(earliest.name, trackNames, 4);
|
||||||
|
if (options) {
|
||||||
|
questions.push({
|
||||||
|
key: `audio:release-first:${earliest.name}`,
|
||||||
|
subjectKey: `track:${earliest.name}`,
|
||||||
|
question: {
|
||||||
|
type: "choice",
|
||||||
|
text: "Which of these tracks came out first?",
|
||||||
|
options,
|
||||||
|
correct: 0,
|
||||||
|
points: 10,
|
||||||
|
song: topSong ?? undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latest?.name && latest.name !== earliest?.name) {
|
||||||
|
const options = buildOptionsWithCorrect(latest.name, trackNames, 4);
|
||||||
|
if (options) {
|
||||||
|
questions.push({
|
||||||
|
key: `audio:release-last:${latest.name}`,
|
||||||
|
subjectKey: `track:${latest.name}`,
|
||||||
|
question: {
|
||||||
|
type: "choice",
|
||||||
|
text: "Which of these tracks came out most recently?",
|
||||||
|
options,
|
||||||
|
correct: 0,
|
||||||
|
points: 10,
|
||||||
|
song: topSong ?? undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tracksByArtist = new Map<string, TrackDetails[]>();
|
||||||
|
for (const track of detailedTracks) {
|
||||||
|
if (!track.duration) continue;
|
||||||
|
for (const artist of track.artists ?? []) {
|
||||||
|
if (!isUsableText(artist.name)) continue;
|
||||||
|
const artistTracks = tracksByArtist.get(artist.name) ?? [];
|
||||||
|
artistTracks.push(track);
|
||||||
|
tracksByArtist.set(artist.name, artistTracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [artistName, artistTracks] of tracksByArtist) {
|
||||||
|
if (artistTracks.length < 2) continue;
|
||||||
|
const longest = artistTracks
|
||||||
|
.slice()
|
||||||
|
.sort((a, b) => (b.duration ?? 0) - (a.duration ?? 0))[0];
|
||||||
|
if (!longest?.name) continue;
|
||||||
|
const trackNames = artistTracks
|
||||||
|
.map((track) => track.name)
|
||||||
|
.filter((name): name is string => isUsableText(name));
|
||||||
|
const options = buildOptionsWithCorrect(longest.name, trackNames, 4);
|
||||||
|
if (options) {
|
||||||
|
questions.push({
|
||||||
|
key: `audio:artist-longest-track:${artistName}:${longest.name}`,
|
||||||
|
subjectKey: `artist:${artistName}`,
|
||||||
|
question: {
|
||||||
|
type: "choice",
|
||||||
|
text: `What's the longest track by ${artistName}?`,
|
||||||
|
options,
|
||||||
|
correct: 0,
|
||||||
|
points: 10,
|
||||||
|
song: topSong ?? undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const topTrack of topTracks) {
|
for (const topTrack of topTracks) {
|
||||||
const trackSong = await resolveQuestionSong(dbClient, analytics, {
|
const trackSong = await resolveQuestionSong(dbClient, analytics, {
|
||||||
trackName: topTrack.name,
|
trackName: topTrack.name,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,14 @@ type NumericQuestion = Omit<
|
||||||
"startTimestamp" | "endTimestamp"
|
"startTimestamp" | "endTimestamp"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
type TrackDetails = {
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
platform_id: string | null;
|
||||||
|
album?: { name: string | null; release_date: Date | null } | null;
|
||||||
|
artists?: { name: string }[] | null;
|
||||||
|
};
|
||||||
|
|
||||||
type BuildNumericQuestionInput = {
|
type BuildNumericQuestionInput = {
|
||||||
db: typeof db;
|
db: typeof db;
|
||||||
analytics: PartyAnalytics;
|
analytics: PartyAnalytics;
|
||||||
|
|
@ -29,6 +37,43 @@ type BuildNumericQuestionInput = {
|
||||||
history: QuizRound[];
|
history: QuizRound[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function getDetailedTopTracks({
|
||||||
|
db,
|
||||||
|
analytics,
|
||||||
|
}: BuildNumericQuestionInput): Promise<TrackDetails[]> {
|
||||||
|
const tracks: TrackDetails[] = [];
|
||||||
|
const seen = new Set<string>();
|
||||||
|
|
||||||
|
for (const topTrack of analytics?.storyClusters?.flatMap(
|
||||||
|
(cluster) => cluster.tracks ?? [],
|
||||||
|
) ?? []) {
|
||||||
|
if (!isUsableText(topTrack.name)) continue;
|
||||||
|
const dbTracks = (await db.query.track.findMany({
|
||||||
|
where: { name: topTrack.name },
|
||||||
|
with: { album: true, artists: true },
|
||||||
|
})) as TrackDetails[];
|
||||||
|
const topArtists = topTrack.artists?.map((artist) => artist.name) ?? [];
|
||||||
|
const track = dbTracks.slice().sort((a, b) => {
|
||||||
|
const score = (candidate: typeof a) => {
|
||||||
|
const artistNames =
|
||||||
|
candidate.artists?.map((artist) => artist.name) ?? [];
|
||||||
|
return (
|
||||||
|
(candidate.album?.name === topTrack.albumName ? 2 : 0) +
|
||||||
|
(topArtists.some((name) => artistNames.includes(name)) ? 2 : 0)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return score(b) - score(a);
|
||||||
|
})[0];
|
||||||
|
if (!track || !isUsableText(track.name)) continue;
|
||||||
|
const key = track.platform_id ?? track.id;
|
||||||
|
if (seen.has(key)) continue;
|
||||||
|
seen.add(key);
|
||||||
|
tracks.push(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
|
||||||
async function getAlbumReleaseYear({
|
async function getAlbumReleaseYear({
|
||||||
db,
|
db,
|
||||||
analytics,
|
analytics,
|
||||||
|
|
@ -61,6 +106,76 @@ async function getAlbumReleaseYear({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getTrackReleaseYear(
|
||||||
|
input: BuildNumericQuestionInput,
|
||||||
|
): Promise<NumericQuestion | null> {
|
||||||
|
const tracks = await getDetailedTopTracks(input);
|
||||||
|
const track = tracks.find((track) => track.album?.release_date && track.name);
|
||||||
|
if (!track?.name || !track.album?.release_date) return null;
|
||||||
|
const song = await resolveQuestionSong(input.db, input.analytics, {
|
||||||
|
trackName: track.name,
|
||||||
|
artistNames: track.artists?.map((artist) => artist.name),
|
||||||
|
albumName: track.album?.name ?? undefined,
|
||||||
|
});
|
||||||
|
const correct = track.album.release_date.getFullYear();
|
||||||
|
return {
|
||||||
|
type: "numeric",
|
||||||
|
text: `What year did "${track.name}" come out?`,
|
||||||
|
correct,
|
||||||
|
range: getReleaseYearRange(correct),
|
||||||
|
points: 10,
|
||||||
|
song: song ?? undefined,
|
||||||
|
questionKey: `numeric:track-year:${track.name}`,
|
||||||
|
subjectKey: `track:${track.name}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getArtistFirstTrackReleaseYear(
|
||||||
|
input: BuildNumericQuestionInput,
|
||||||
|
): Promise<NumericQuestion | null> {
|
||||||
|
const tracks = await getDetailedTopTracks(input);
|
||||||
|
const tracksByArtist = new Map<string, TrackDetails[]>();
|
||||||
|
|
||||||
|
for (const track of tracks) {
|
||||||
|
if (!track.album?.release_date) continue;
|
||||||
|
for (const artist of track.artists ?? []) {
|
||||||
|
if (!isUsableText(artist.name)) continue;
|
||||||
|
const artistTracks = tracksByArtist.get(artist.name) ?? [];
|
||||||
|
artistTracks.push(track);
|
||||||
|
tracksByArtist.set(artist.name, artistTracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const artistEntry = Array.from(tracksByArtist.entries()).find(
|
||||||
|
([, artistTracks]) => artistTracks.length >= 2,
|
||||||
|
);
|
||||||
|
if (!artistEntry) return null;
|
||||||
|
const [artistName, artistTracks] = artistEntry;
|
||||||
|
const firstTrack = artistTracks
|
||||||
|
.slice()
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
Number(a.album?.release_date ?? 0) - Number(b.album?.release_date ?? 0),
|
||||||
|
)[0];
|
||||||
|
if (!firstTrack?.album?.release_date) return null;
|
||||||
|
const song = await resolveQuestionSong(input.db, input.analytics, {
|
||||||
|
trackName: firstTrack.name ?? undefined,
|
||||||
|
artistNames: [artistName],
|
||||||
|
albumName: firstTrack.album?.name ?? undefined,
|
||||||
|
});
|
||||||
|
const correct = firstTrack.album.release_date.getFullYear();
|
||||||
|
return {
|
||||||
|
type: "numeric",
|
||||||
|
text: `What year did ${artistName}'s first party track come out?`,
|
||||||
|
correct,
|
||||||
|
range: getReleaseYearRange(correct),
|
||||||
|
points: 10,
|
||||||
|
song: song ?? undefined,
|
||||||
|
questionKey: `numeric:artist-first-track-year:${artistName}`,
|
||||||
|
subjectKey: `artist:${artistName}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function countTopTrackListeners({
|
async function countTopTrackListeners({
|
||||||
db,
|
db,
|
||||||
analytics,
|
analytics,
|
||||||
|
|
@ -149,6 +264,26 @@ export async function buildNumericQuestion(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trackYearQ = await getTrackReleaseYear(input);
|
||||||
|
if (trackYearQ) {
|
||||||
|
questions.push({
|
||||||
|
key: trackYearQ.questionKey ?? `numeric:track-year:${trackYearQ.text}`,
|
||||||
|
subjectKey: trackYearQ.subjectKey,
|
||||||
|
question: trackYearQ,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const artistFirstTrackYearQ = await getArtistFirstTrackReleaseYear(input);
|
||||||
|
if (artistFirstTrackYearQ) {
|
||||||
|
questions.push({
|
||||||
|
key:
|
||||||
|
artistFirstTrackYearQ.questionKey ??
|
||||||
|
`numeric:artist-first-track-year:${artistFirstTrackYearQ.text}`,
|
||||||
|
subjectKey: artistFirstTrackYearQ.subjectKey,
|
||||||
|
question: artistFirstTrackYearQ,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const topTrackQ = await countTopTrackListeners(input);
|
const topTrackQ = await countTopTrackListeners(input);
|
||||||
if (topTrackQ) {
|
if (topTrackQ) {
|
||||||
questions.push({
|
questions.push({
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,12 @@
|
||||||
import { useParty } from "#/hooks/use-party";
|
import { useParty } from "#/hooks/use-party";
|
||||||
|
import {
|
||||||
|
Empty,
|
||||||
|
EmptyContent,
|
||||||
|
EmptyDescription,
|
||||||
|
EmptyHeader,
|
||||||
|
EmptyTitle,
|
||||||
|
} from "../ui/empty";
|
||||||
|
import { Spinner } from "../ui/spinner";
|
||||||
import { Question } from "./question";
|
import { Question } from "./question";
|
||||||
import { QuestionReview } from "./question-review";
|
import { QuestionReview } from "./question-review";
|
||||||
import { Results } from "./results";
|
import { Results } from "./results";
|
||||||
|
|
@ -6,7 +14,26 @@ import { SpotifyPlayback } from "./spotify-playback";
|
||||||
|
|
||||||
export function PartyView() {
|
export function PartyView() {
|
||||||
const { party } = useParty();
|
const { party } = useParty();
|
||||||
if (!party?.data) return null;
|
if (!party) return null;
|
||||||
|
if (!party.data) {
|
||||||
|
if (party.status !== "started") return null;
|
||||||
|
return (
|
||||||
|
<Empty>
|
||||||
|
<EmptyHeader>
|
||||||
|
<EmptyTitle>Preparing party</EmptyTitle>
|
||||||
|
<EmptyDescription>
|
||||||
|
Analyzing everyone's music taste and building the first question.
|
||||||
|
</EmptyDescription>
|
||||||
|
</EmptyHeader>
|
||||||
|
<EmptyContent>
|
||||||
|
<div className="flex items-center gap-2 text-muted-foreground">
|
||||||
|
<Spinner />
|
||||||
|
<span>This can take a moment.</span>
|
||||||
|
</div>
|
||||||
|
</EmptyContent>
|
||||||
|
</Empty>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
switch (party.data.status) {
|
switch (party.data.status) {
|
||||||
case "running":
|
case "running":
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,10 @@ function App() {
|
||||||
<DeviceChoice />
|
<DeviceChoice />
|
||||||
{!user?.lastSyncAt && <SyncButton />}
|
{!user?.lastSyncAt && <SyncButton />}
|
||||||
{user && party?.data?.status !== "running" && <PartyQr />}
|
{user && party?.data?.status !== "running" && <PartyQr />}
|
||||||
{party && !party.data && members.length > 1 && <StartParty />}
|
{party?.status === "created" && !party.data && members.length > 1 && (
|
||||||
{party?.data && <PartyView />}
|
<StartParty />
|
||||||
|
)}
|
||||||
|
{party && (party.data || party.status === "started") && <PartyView />}
|
||||||
</MainContent>
|
</MainContent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue