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:
parent
a10d7684d5
commit
c9959cce23
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user