mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
multi line paste for add course and edit course
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user