fix(admin): restore description fields on Learn English course and module forms

Re-add description inputs to course create/edit and module create/edit dialogs so descriptions are sent to the API instead of empty strings.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Yared Yemane 2026-06-10 08:51:02 -07:00
parent a10d7684d5
commit c9959cce23
3 changed files with 73 additions and 6 deletions

View File

@ -21,6 +21,7 @@ import {
DialogTitle,
} from "../../components/ui/dialog";
import { Input } from "../../components/ui/input";
import { Textarea } from "../../components/ui/textarea";
import { cn } from "../../lib/utils";
import spinnerSrc from "../../assets/Circular-indeterminate progress indicator.svg";
import alertSrc from "../../assets/Alert.svg";
@ -162,6 +163,7 @@ export function CourseDetailPage() {
const [editingModule, setEditingModule] =
useState<TopLevelCourseModuleItem | null>(null);
const [editModuleName, setEditModuleName] = useState("");
const [editModuleDescription, setEditModuleDescription] = useState("");
const [editModuleSortOrder, setEditModuleSortOrder] = useState("");
const [editModuleIcon, setEditModuleIcon] = useState("");
const [editModuleIconUploadBusy, setEditModuleIconUploadBusy] =
@ -197,6 +199,7 @@ export function CourseDetailPage() {
const openEditModule = (module: TopLevelCourseModuleItem) => {
setEditingModule(module);
setEditModuleName(module.name ?? "");
setEditModuleDescription(module.description ?? "");
setEditModuleSortOrder(String(module.sort_order ?? 0));
setEditModuleIcon(module.icon?.trim() ?? "");
setEditModuleIconUploadBusy(false);
@ -460,7 +463,7 @@ export function CourseDetailPage() {
try {
await updateTopLevelCourseModule(editingModule.id, {
name,
description: editingModule.description?.trim() ?? "",
description: editModuleDescription.trim(),
icon: editModuleIcon.trim(),
sort_order,
});
@ -618,7 +621,7 @@ export function CourseDetailPage() {
<DialogHeader className="shrink-0 space-y-1.5 border-b border-grayScale-100 px-6 pb-4 pt-6 pr-12">
<DialogTitle>Edit module</DialogTitle>
<DialogDescription>
Update name, sort order, and icon (upload or URL).
Update name, description, sort order, and icon (upload or URL).
</DialogDescription>
</DialogHeader>
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4">
@ -635,6 +638,19 @@ export function CourseDetailPage() {
disabled={savingModuleEdit}
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-grayScale-700">
Description
</label>
<Textarea
value={editModuleDescription}
onChange={(e) => setEditModuleDescription(e.target.value)}
rows={4}
className="min-h-[100px] resize-y rounded-xl"
placeholder="Short summary of the module"
disabled={savingModuleEdit || editModuleIconUploadBusy}
/>
</div>
<div className="space-y-2">
<label
htmlFor="edit-module-sort-order"

View File

@ -14,6 +14,7 @@ import {
DialogTrigger,
} from "../../components/ui/dialog";
import { Input } from "../../components/ui/input";
import { Textarea } from "../../components/ui/textarea";
import uploadIcon from "../../assets/icons/upload.png";
import spinnerSrc from "../../assets/Circular-indeterminate progress indicator.svg";
import alertSrc from "../../assets/Alert.svg";
@ -64,6 +65,7 @@ export function ProgramCoursesPage() {
null,
);
const [editName, setEditName] = useState("");
const [editDescription, setEditDescription] = useState("");
const [editSortOrder, setEditSortOrder] = useState("");
const [editThumbnail, setEditThumbnail] = useState("");
const [savingEdit, setSavingEdit] = useState(false);
@ -72,6 +74,7 @@ export function ProgramCoursesPage() {
const [createCourseOpen, setCreateCourseOpen] = useState(false);
const [createName, setCreateName] = useState("");
const [createDescription, setCreateDescription] = useState("");
const [createSortOrder, setCreateSortOrder] = useState("");
const [createThumbnail, setCreateThumbnail] = useState("");
const [createSaving, setCreateSaving] = useState(false);
@ -218,6 +221,7 @@ export function ProgramCoursesPage() {
const openEditCourse = (course: ProgramCourseListItem) => {
setEditingCourse(course);
setEditName(course.name ?? "");
setEditDescription(course.description?.trim() ?? "");
setEditThumbnail(
course.thumbnail?.trim() || course.thumbnail_url?.trim() || "",
);
@ -227,6 +231,7 @@ export function ProgramCoursesPage() {
const closeEditCourse = () => {
setEditingCourse(null);
setEditName("");
setEditDescription("");
setEditSortOrder("");
setEditThumbnail("");
setUploadingEditThumbnail(false);
@ -291,7 +296,7 @@ export function ProgramCoursesPage() {
try {
await updateTopLevelCourse(editingCourse.id, {
name,
description: editingCourse.description?.trim() ?? "",
description: editDescription.trim(),
thumbnail: editThumbnail.trim(),
sort_order,
});
@ -311,6 +316,7 @@ export function ProgramCoursesPage() {
const clearCreateCourseForm = () => {
setCreateName("");
setCreateDescription("");
setCreateSortOrder("");
setCreateThumbnail("");
setCreateUploadingThumbnail(false);
@ -381,7 +387,7 @@ export function ProgramCoursesPage() {
try {
await createProgramCourse(programId, {
name,
description: "",
description: createDescription.trim(),
thumbnail: createThumbnail.trim(),
sort_order,
});
@ -509,6 +515,20 @@ export function ProgramCoursesPage() {
/>
</div>
<div className="space-y-2">
<label className="text-[15px] font-medium text-grayScale-700">
Description
</label>
<Textarea
value={createDescription}
onChange={(e) => setCreateDescription(e.target.value)}
placeholder="Short summary of the course"
rows={3}
className="min-h-[88px] resize-y rounded-xl"
disabled={createSaving || createUploadingThumbnail}
/>
</div>
<div className="space-y-2">
<label
htmlFor="create-course-sort-order"
@ -822,7 +842,7 @@ export function ProgramCoursesPage() {
<DialogHeader className="shrink-0 space-y-1.5 border-b border-grayScale-100 px-6 pb-4 pt-6 pr-12">
<DialogTitle>Edit course</DialogTitle>
<DialogDescription>
Update name, sort order, and thumbnail.
Update name, description, sort order, and thumbnail.
</DialogDescription>
</DialogHeader>
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4">
@ -839,6 +859,19 @@ export function ProgramCoursesPage() {
disabled={savingEdit || uploadingEditThumbnail}
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium text-grayScale-700">
Description
</label>
<Textarea
value={editDescription}
onChange={(e) => setEditDescription(e.target.value)}
rows={4}
className="min-h-[100px] resize-y rounded-xl"
placeholder="Short summary of the course"
disabled={savingEdit || uploadingEditThumbnail}
/>
</div>
<div className="space-y-2">
<label
htmlFor="edit-course-sort-order"

View File

@ -9,6 +9,7 @@ import {
DialogClose,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import { Textarea } from "../../../components/ui/textarea";
import { toast } from "sonner";
import { createTopLevelCourseModule } from "../../../api/courses.api";
import { ModuleIconUploadField } from "./ModuleIconUploadField";
@ -27,6 +28,7 @@ export function AddModuleModal({
onCreated,
}: AddModuleModalProps) {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [sortOrder, setSortOrder] = useState("");
const [icon, setIcon] = useState("");
const [submitting, setSubmitting] = useState(false);
@ -35,6 +37,7 @@ export function AddModuleModal({
useEffect(() => {
if (isOpen) {
setName("");
setDescription("");
setSortOrder("");
setIcon("");
setSubmitting(false);
@ -44,6 +47,7 @@ export function AddModuleModal({
const resetAndClose = () => {
setName("");
setDescription("");
setSortOrder("");
setIcon("");
setIconUploadBusy(false);
@ -82,7 +86,7 @@ export function AddModuleModal({
try {
await createTopLevelCourseModule(courseId, {
name: trimmedName,
description: "",
description: description.trim(),
icon: icon.trim(),
sort_order,
});
@ -149,6 +153,20 @@ export function AddModuleModal({
/>
</div>
<div className="space-y-2">
<label className="text-[15px] font-medium text-grayScale-700">
Description
</label>
<Textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Short summary of the module"
rows={3}
className="min-h-[88px] resize-y rounded-xl"
disabled={submitting || iconUploadBusy}
/>
</div>
<div className="space-y-2">
<label
htmlFor="create-module-sort-order"