Fix Human Language level actions visibility and CEFR add-level guidance.

Avoid nested button markup so remove-level controls render reliably, keep level rows visible for all CEFR levels, and add clearer guidance/labeling for incremental level creation starting from A1.

Made-with: Cursor
This commit is contained in:
Yared Yemane 2026-04-07 07:29:54 -07:00
parent bf0dabbf05
commit 767637a5ef

View File

@ -313,14 +313,22 @@ export function HumanLanguagePage() {
</select> </select>
</div> </div>
</CardContent> </CardContent>
<CardContent className="pt-0"> <CardContent className="border-t border-grayScale-100 pt-4">
<div className="flex items-center justify-end"> <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
<p className="text-xs text-grayScale-500">
{selectedCourseId === "ALL"
? "Select a specific course above to enable adding the next CEFR level (starts at A1) and to use remove actions."
: levelsForSelectedCourse.length >= CEFR_LEVELS.length
? "All CEFR levels (A1C3) already have content for this course."
: `Next level to add: ${CEFR_LEVELS.find((l) => !levelsForSelectedCourse.includes(l)) ?? "—"}`}
</p>
<Button <Button
size="sm" size="sm"
className="shrink-0"
onClick={handleCreateNextLevel} onClick={handleCreateNextLevel}
disabled={selectedCourseId === "ALL" || levelsForSelectedCourse.length >= CEFR_LEVELS.length || creatingKey?.startsWith("next-level-")} disabled={selectedCourseId === "ALL" || levelsForSelectedCourse.length >= CEFR_LEVELS.length || creatingKey?.startsWith("next-level-")}
> >
{creatingKey?.startsWith("next-level-") ? "Creating level..." : "Add Next Level"} {creatingKey?.startsWith("next-level-") ? "Creating level..." : "Add next CEFR level"}
</Button> </Button>
</div> </div>
</CardContent> </CardContent>
@ -388,46 +396,43 @@ export function HumanLanguagePage() {
{availableCourses.length > 0 {availableCourses.length > 0
? CEFR_LEVELS.filter((l) => selectedLevel === "ALL" || l === selectedLevel).map((level) => { ? CEFR_LEVELS.filter((l) => selectedLevel === "ALL" || l === selectedLevel).map((level) => {
const modulesByCourse = selectedCourses const modulesByCourse = selectedCourses.map((course: HumanLanguageCourseTree) => {
.map((course: HumanLanguageCourseTree) => { const levelNode = course.levels.find((item) => item.level.toUpperCase() === level)
const levelNode = course.levels.find((item) => item.level.toUpperCase() === level) return {
return { course,
course, modules: levelNode?.modules ?? [],
modules: levelNode?.modules ?? [], }
} })
})
.filter((entry) => entry.modules.length > 0 || (selectedCourses.length > 0 && level === "A1"))
return ( return (
<Card key={level} className="overflow-hidden border-grayScale-200/80 shadow-sm"> <Card key={level} className="overflow-hidden border-grayScale-200/80 shadow-sm">
<button <div className="flex w-full flex-wrap items-center justify-between gap-2 border-b border-grayScale-100 bg-grayScale-50/60 px-4 py-3">
type="button" <button
className="flex w-full items-center justify-between border-b border-grayScale-100 bg-grayScale-50/60 px-4 py-3 text-left" type="button"
onClick={() => toggleLevel(level)} className="flex min-w-0 flex-1 items-center gap-2 text-left"
> onClick={() => toggleLevel(level)}
<div className="inline-flex items-center gap-2"> >
{collapsedLevels.includes(level) ? <ChevronRight className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />} {collapsedLevels.includes(level) ? <ChevronRight className="h-4 w-4 shrink-0" /> : <ChevronDown className="h-4 w-4 shrink-0" />}
<span className="text-sm font-semibold text-grayScale-900">{level}</span> <span className="text-sm font-semibold text-grayScale-900">{level}</span>
<span className="rounded-md bg-brand-100 px-2 py-0.5 text-xs font-medium text-brand-700"> <span className="rounded-md bg-brand-100 px-2 py-0.5 text-xs font-medium text-brand-700">
{modulesByCourse.reduce((sum, entry) => sum + entry.modules.length, 0)} module(s) {modulesByCourse.reduce((sum, entry) => sum + entry.modules.length, 0)} module(s)
</span> </span>
<Button </button>
size="sm" <Button
variant="outline" size="sm"
className="ml-3 border-red-200 text-red-600 hover:bg-red-50" variant="outline"
disabled={selectedCourseId === "ALL" || deletingKey === `level-${selectedCourseId}-${level}`} className="border-red-200 text-red-600 hover:bg-red-50"
onClick={(e) => { disabled={selectedCourseId === "ALL" || deletingKey === `level-${selectedCourseId}-${level}`}
e.stopPropagation() onClick={() => {
if (selectedCourseId === "ALL") return if (selectedCourseId === "ALL") return
const courseEntry = modulesByCourse.find((entry) => entry.course.course_id === selectedCourseId) const courseEntry = modulesByCourse.find((entry) => entry.course.course_id === selectedCourseId)
const ids = (courseEntry?.modules ?? []).flatMap((m) => m.sub_modules.map((s) => s.id)) const ids = (courseEntry?.modules ?? []).flatMap((m) => m.sub_modules.map((s) => s.id))
handleDeleteSubModules(ids, `level-${selectedCourseId}-${level}`, `Level ${level} removed`) handleDeleteSubModules(ids, `level-${selectedCourseId}-${level}`, `Level ${level} removed`)
}} }}
> >
<Trash2 className="h-3.5 w-3.5" /> <Trash2 className="h-3.5 w-3.5" />
Remove Level Remove level
</Button> </Button>
</div> </div>
</button>
{!collapsedLevels.includes(level) ? ( {!collapsedLevels.includes(level) ? (
<CardContent className="space-y-3 p-4"> <CardContent className="space-y-3 p-4">
{modulesByCourse.length === 0 ? ( {modulesByCourse.length === 0 ? (