feat(module): Add practice button on each lesson card
- VideoCard: optional onAddPractice for lesson-scoped CTA - ModuleDetailPage: navigate to add-practice with lessonId and lessonTitle - AddPracticeFlow: show context banner when opened from a lesson Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
77b71abfd8
commit
bb6680acfb
|
|
@ -23,6 +23,17 @@ export function AddPracticeFlow() {
|
|||
const backTo = searchParams.get("backTo");
|
||||
const courseId = searchParams.get("courseId");
|
||||
const moduleId = searchParams.get("moduleId");
|
||||
const lessonId = searchParams.get("lessonId");
|
||||
const lessonTitleRaw = searchParams.get("lessonTitle");
|
||||
const lessonTitleDisplay = (() => {
|
||||
const raw = lessonTitleRaw?.trim();
|
||||
if (!raw) return null;
|
||||
try {
|
||||
return decodeURIComponent(raw);
|
||||
} catch {
|
||||
return raw;
|
||||
}
|
||||
})();
|
||||
|
||||
const isModuleContext = backTo === "module";
|
||||
const isCourseContext = backTo === "modules";
|
||||
|
|
@ -251,6 +262,23 @@ export function AddPracticeFlow() {
|
|||
<p className="text-grayScale-400 text-base">
|
||||
Create a new immersive practice session for students.
|
||||
</p>
|
||||
{lessonId ? (
|
||||
<div className="mt-4 rounded-xl border border-violet-200 bg-violet-50/80 px-4 py-3 text-sm text-violet-950">
|
||||
<p className="font-semibold text-violet-900">Practice for this lesson</p>
|
||||
<p className="mt-1 text-violet-800/90">
|
||||
This session will be associated with lesson{" "}
|
||||
<span className="font-mono font-bold text-violet-950">#{lessonId}</span>
|
||||
{lessonTitleDisplay ? (
|
||||
<>
|
||||
{" "}
|
||||
— <span className="font-medium">{lessonTitleDisplay}</span>
|
||||
</>
|
||||
) : null}
|
||||
. The module-level flow still uses the same steps; use this context when naming and
|
||||
configuring the practice.
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-[70%] mb-12">
|
||||
|
|
|
|||
|
|
@ -398,6 +398,11 @@ export function ModuleDetailPage() {
|
|||
thumbnailGradient={LESSON_THUMB_GRADIENTS[i % LESSON_THUMB_GRADIENTS.length]}
|
||||
onEdit={() => openEditLesson(lesson)}
|
||||
onDelete={() => setDeletingLesson(lesson)}
|
||||
onAddPractice={() =>
|
||||
navigate(
|
||||
`/new-content/learn-english/${level}/courses/add-practice?backTo=module&courseId=${courseId}&moduleId=${moduleId}&lessonId=${lesson.id}&lessonTitle=${encodeURIComponent(lesson.title)}`,
|
||||
)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { MoreVertical, Edit2, Play, Pencil, Trash2 } from "lucide-react";
|
||||
import { MoreVertical, Edit2, Play, Pencil, Trash2, Calendar } from "lucide-react";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -38,6 +38,8 @@ interface VideoCardProps {
|
|||
hoverModuleActions?: boolean;
|
||||
onEdit?: () => void;
|
||||
onDelete?: () => void;
|
||||
/** When set (e.g. on module lesson cards), shows an "Add practice" control scoped to this lesson. */
|
||||
onAddPractice?: () => void;
|
||||
onPublish?: () => void;
|
||||
}
|
||||
|
||||
|
|
@ -51,6 +53,7 @@ export function VideoCard({
|
|||
onEdit,
|
||||
onDelete,
|
||||
onPublish,
|
||||
onAddPractice,
|
||||
hoverModuleActions = false,
|
||||
}: VideoCardProps) {
|
||||
const [thumbFailed, setThumbFailed] = useState(false);
|
||||
|
|
@ -342,6 +345,21 @@ export function VideoCard({
|
|||
{title}
|
||||
</h3>
|
||||
|
||||
{hoverModuleActions && onAddPractice ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="h-9 w-full shrink-0 rounded-lg border-brand-200 text-[12px] font-bold text-brand-600 hover:bg-brand-50"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onAddPractice();
|
||||
}}
|
||||
>
|
||||
<Calendar className="mr-1.5 h-3.5 w-3.5" aria-hidden />
|
||||
Add practice
|
||||
</Button>
|
||||
) : null}
|
||||
|
||||
{/* Actions (footer) — not used for API lesson cards with hover tools */}
|
||||
{!hoverModuleActions ? (
|
||||
<div className="pt-2 space-y-3 mt-auto">
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user