multi line paste for add course and edit course

This commit is contained in:
rgrgogu
2026-07-30 20:35:38 +08:00
parent f9616b7219
commit 3ccbda7a00
3 changed files with 47 additions and 5 deletions
@@ -56,7 +56,18 @@ function FieldError({ message }) {
// ─── Step 1 — Details ─────────────────────────────────────────────────────────── // ─── Step 1 — Details ───────────────────────────────────────────────────────────
function StepDetails({ register, errors, control }) { function StepDetails({ register, errors, control }) {
const { fields, append, remove } = useFieldArray({ control, name: "objectives" }); const { fields, append, remove, insert, update } = useFieldArray({ control, name: "objectives" });
const handleObjectivePaste = (e, index) => {
const text = e.clipboardData.getData("text");
const lines = text.split(/\r\n|\r|\n/).map((l) => l.trim()).filter(Boolean);
if (lines.length <= 1) return;
e.preventDefault();
update(index, { value: lines[0] });
lines.slice(1).forEach((line, i) => {
insert(index + 1 + i, { value: line });
});
};
return ( return (
<div className="space-y-6"> <div className="space-y-6">
@@ -101,7 +112,11 @@ function StepDetails({ register, errors, control }) {
{fields.map((field, index) => ( {fields.map((field, index) => (
<div key={field.id} className="flex items-start gap-2"> <div key={field.id} className="flex items-start gap-2">
<div className="flex-1 space-y-1"> <div className="flex-1 space-y-1">
<Input placeholder={`Objective ${index + 1}`} {...register(`objectives.${index}.value`)} /> <Input
placeholder={`Objective ${index + 1}`}
{...register(`objectives.${index}.value`)}
onPaste={(e) => handleObjectivePaste(e, index)}
/>
<FieldError message={errors.objectives?.[index]?.value?.message} /> <FieldError message={errors.objectives?.[index]?.value?.message} />
</div> </div>
<Button <Button
@@ -43,7 +43,18 @@ export default function EditLesson() {
defaultValues: { title: "", description: "", order: 0, objectives: [] }, defaultValues: { title: "", description: "", order: 0, objectives: [] },
}); });
const { fields, append, remove } = useFieldArray({ control, name: "objectives" }); const { fields, append, remove, insert, update } = useFieldArray({ control, name: "objectives" });
const handleObjectivePaste = (e, index) => {
const text = e.clipboardData.getData("text");
const lines = text.split(/\r\n|\r|\n/).map((l) => l.trim()).filter(Boolean);
if (lines.length <= 1) return;
e.preventDefault();
update(index, { value: lines[0] });
lines.slice(1).forEach((line, i) => {
insert(index + 1 + i, { value: line });
});
};
const { bypassOnce, dialog: unsavedChangesDialog } = useUnsavedChangesGuard(isDirty); const { bypassOnce, dialog: unsavedChangesDialog } = useUnsavedChangesGuard(isDirty);
@@ -154,6 +165,7 @@ export default function EditLesson() {
<Input <Input
placeholder={`Objective ${index + 1}`} placeholder={`Objective ${index + 1}`}
{...register(`objectives.${index}.value`)} {...register(`objectives.${index}.value`)}
onPaste={(e) => handleObjectivePaste(e, index)}
/> />
<FieldError message={errors.objectives?.[index]?.value?.message} /> <FieldError message={errors.objectives?.[index]?.value?.message} />
</div> </div>
@@ -126,14 +126,29 @@ function StepUnit({ register, errors, control, setValue, tierCategories }) {
// ─── Step 2 — Lessons ────────────────────────────────────────────────────────── // ─── Step 2 — Lessons ──────────────────────────────────────────────────────────
function LessonObjectives({ control, register, lessonIndex }) { function LessonObjectives({ control, register, lessonIndex }) {
const { fields, append, remove } = useFieldArray({ control, name: `lessons.${lessonIndex}.objectives` }); const { fields, append, remove, insert, update } = useFieldArray({ control, name: `lessons.${lessonIndex}.objectives` });
const handleObjectivePaste = (e, oi) => {
const text = e.clipboardData.getData("text");
const lines = text.split(/\r\n|\r|\n/).map((l) => l.trim()).filter(Boolean);
if (lines.length <= 1) return;
e.preventDefault();
update(oi, { value: lines[0] });
lines.slice(1).forEach((line, i) => {
insert(oi + 1 + i, { value: line });
});
};
return ( return (
<div className="space-y-2"> <div className="space-y-2">
<Label className="text-xs text-muted-foreground uppercase tracking-wide">Objectives</Label> <Label className="text-xs text-muted-foreground uppercase tracking-wide">Objectives</Label>
{fields.map((f, oi) => ( {fields.map((f, oi) => (
<div key={f.id} className="flex items-center gap-2"> <div key={f.id} className="flex items-center gap-2">
<Input {...register(`lessons.${lessonIndex}.objectives.${oi}.value`)} placeholder="Learning objective" /> <Input
{...register(`lessons.${lessonIndex}.objectives.${oi}.value`)}
placeholder="Learning objective"
onPaste={(e) => handleObjectivePaste(e, oi)}
/>
<Button <Button
type="button" type="button"
variant="ghost" variant="ghost"