fix: Resolve multiple mobile UX issues including swiping and header layouts
All checks were successful
Automated Container Build / build-and-push (push) Successful in 50s

This commit is contained in:
Elijah 2026-06-28 11:58:47 -07:00
parent 4ea58da3cd
commit 7d2c466e9b
4 changed files with 74 additions and 29 deletions

View file

@ -92,7 +92,7 @@ export default function DeckStudyPage() {
return (
<div className="max-w-4xl mx-auto w-full py-2 md:py-4">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4 mb-6">
<div>
<button
onClick={() => router.push(`/${classSlug}/flashcards`)}

View file

@ -0,0 +1,65 @@
"use client";
import { useState } from "react";
import { FlashcardViewer } from "@/components/flashcards/FlashcardViewer";
import { QuizViewer } from "@/components/quizzes/QuizViewer";
interface SharedViewerProps {
type: string;
data: any;
}
export function SharedViewer({ type, data }: SharedViewerProps) {
const [restartKey, setRestartKey] = useState(0);
return (
<div>
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4 mb-8">
<div className="text-left">
<h1 className="text-2xl font-bold text-text-heading mb-2">
{data.name}
</h1>
<p className="text-text-secondary">
From class: <span className="font-medium text-text-heading">{data.class.name}</span>
</p>
{data.description && (
<p className="text-sm text-text-secondary mt-2 max-w-2xl">
{data.description}
</p>
)}
</div>
<div>
<button
onClick={() => setRestartKey(k => k + 1)}
className="p-1.5 rounded-lg text-text-muted hover:text-text-heading hover:bg-bg-surface-alt transition-all duration-200 cursor-pointer"
title="Restart Session"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
</div>
</div>
{type === "flashcards" ? (
<FlashcardViewer
key={restartKey}
cards={data.cards}
deckId={data.id}
isShared={true}
/>
) : (
<QuizViewer
key={restartKey}
quiz={{
...data,
progress: [], // Start fresh since it's shared
}}
retakeIds={null}
isShared={true}
/>
)}
</div>
);
}

View file

@ -1,9 +1,8 @@
import { getShareLink } from "@/services/shareService";
import { notFound } from "next/navigation";
import { FlashcardViewer } from "@/components/flashcards/FlashcardViewer";
import { QuizViewer } from "@/components/quizzes/QuizViewer";
import { ThemeToggle } from "@/components/ui/ThemeToggle";
import Link from "next/link";
import { SharedViewer } from "./SharedViewer";
interface SharedPageProps {
params: Promise<{
@ -52,7 +51,7 @@ export default async function SharedPage(props: SharedPageProps) {
<div className="flex items-center gap-4">
<ThemeToggle />
<div className="flex items-center gap-3">
<span className="text-sm font-medium px-3 py-1 bg-badge-bg text-badge-text rounded-full">
<span className="text-sm font-medium px-3 py-1 bg-badge-bg text-badge-text rounded-full hidden sm:inline-block">
Read Only
</span>
<Link
@ -70,29 +69,10 @@ export default async function SharedPage(props: SharedPageProps) {
{/* Main Content */}
<main className="flex-1 overflow-y-auto">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8 text-center">
<h1 className="text-2xl font-bold text-text-heading mb-2">
{link.deck ? link.deck.name : link.quizSet?.name}
</h1>
<p className="text-text-secondary">
From class: <span className="font-medium text-text-heading">{link.deck ? link.deck.class.name : link.quizSet?.class.name}</span>
</p>
</div>
{type === "flashcards" && link.deck && (
<FlashcardViewer cards={link.deck.cards} deckId={link.deck.id} isShared={true} />
)}
{type === "quizzes" && link.quizSet && (
<QuizViewer
quiz={{
...link.quizSet,
progress: [], // Start fresh since it's shared
}}
retakeIds={null}
isShared={true}
/>
)}
<SharedViewer
type={type}
data={type === "flashcards" ? link.deck : link.quizSet}
/>
</div>
</main>
</div>

View file

@ -146,7 +146,7 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
// Touch handlers for swipe
function handleTouchStart(e: React.TouchEvent) {
if (!isFlipped) return;
if (!hasFlippedOnce) return;
dragRef.current = {
startX: e.touches[0].clientX,
currentX: e.touches[0].clientX,
@ -350,7 +350,7 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
</ReactMarkdown>
</div>
<p className="mt-6 text-xs text-text-muted">
Tap or press Space to flip
Tap <span className="hidden md:inline">or press Space </span>to flip
</p>
</div>