Skip to content

Commit

Permalink
Add quiz example
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick91 committed Feb 26, 2024
1 parent 78ef09c commit bafc639
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 4 deletions.
12 changes: 8 additions & 4 deletions client/src/components/Playbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { fragmentRegistry } from '../apollo/fragmentRegistry';
import Skeleton from './Skeleton';
import LikeButton from './LikeButton';
import { withHighlight } from './LoadingStateHighlighter';
import SongQuiz from './SongQuiz';

const EPISODE_SKIP_FORWARD_AMOUNT = 15_000;

Expand Down Expand Up @@ -122,10 +123,13 @@ const Playbar = () => {
<Flex gap="1rem" alignItems="center">
<CoverPhoto size="4rem" image={coverPhoto} />
{playbackItem?.__typename === 'Track' ? (
<TrackPlaybackDetails
context={playbackState?.context ?? null}
track={playbackItem}
/>
<>
<TrackPlaybackDetails
context={playbackState?.context ?? null}
track={playbackItem}
/>
<SongQuiz id={playbackItem.id} />
</>
) : playbackItem?.__typename === 'Episode' ? (
<EpisodePlaybackDetails episode={playbackItem} />
) : null}
Expand Down
116 changes: 116 additions & 0 deletions client/src/components/SongQuiz.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import * as Dialog from '@radix-ui/react-dialog';
import Button from './Button';
import { X, Pizza } from 'lucide-react';
import { gql, useSuspenseQuery } from '@apollo/client';
import { Suspense, useState } from 'react';
import cx from 'classnames';

// TypedDocumentNode<
// CurrentUserQuery,
// CurrentUserQueryVariables
// >
const SONG_QUIZ_QUERY = gql`
query SongQuiz($trackId: ID!) {
track(id: $trackId) {
quiz {
question
options {
answer
label
}
correctAnswer
}
}
}
`;

const SongQuiz = ({ id }: { id: string }) => {
return (
<QuizDialog id={id}>
<Pizza size="1.2rem" className="cursor-pointer hover:stroke-green" />
</QuizDialog>
);
};

export default SongQuiz;

const QuizDialog = ({
id,
children,
}: React.PropsWithChildren<{ id: string }>) => {
return (
<Dialog.Root>
<Dialog.Trigger asChild>{children}</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="bg-surface/50 animate-fade-in fixed inset-0 [--animate-duration:200ms]" />
<Dialog.Content className="bg-surface animate-slide-left-fade fixed inset-2 left-1/3 rounded p-4 text-base shadow-2xl outline-0 [--animate-slide-distance:30px]">
<Dialog.Close asChild>
<Button
variant="ghost"
size="sm"
className="absolute right-4 top-4 !p-0"
>
<X size="1.5rem" />
</Button>
</Dialog.Close>
<div className="text-white px-4">
<Suspense fallback={<p>Loading...</p>}>
<QuizContent id={id} />
</Suspense>
</div>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
};

const QuizContent = ({ id }: { id: string }) => {
const [selectedAnswer, setSelectedAnswer] = useState<string | null>(null);
const [submitted, setSubmitted] = useState(false);

const { data } = useSuspenseQuery(SONG_QUIZ_QUERY, {
variables: { trackId: id },
});

// @ts-ignore - I should run codegen
const quiz = data?.track?.quiz as any;

const handleAnswer = () => {
setSubmitted(true);
};

return (
<>
<h1>{quiz.question}</h1>
<ul className="mb-4">
{quiz.options.map((option: any) => (
<li key={option.answer}>
<label
className={cx('cursor-pointer', {
'text-green': submitted && option.answer === quiz.correctAnswer,
'text-[#ff2a2a]':
submitted &&
option.answer !== quiz.correctAnswer &&
selectedAnswer === option.answer,
})}
>
<input
type="radio"
name="answer"
disabled={submitted}
value={option.answer}
checked={selectedAnswer === option.answer}
onChange={() => setSelectedAnswer(option.answer)}
/>{' '}
{option.label}
</label>
</li>
))}
</ul>

<Button variant="primary" onClick={handleAnswer}>
Submit
</Button>
</>
);
};

0 comments on commit bafc639

Please sign in to comment.