From 128234c7add0366df4964c1d6991f695709a71ba Mon Sep 17 00:00:00 2001 From: austinkelsay Date: Fri, 23 Aug 2024 20:21:29 -0500 Subject: [PATCH] Huge update with lessons and draftLessons and refactoring course forms, models, and api endpoints to account for these changes --- .../migration.sql | 63 +++-- prisma/schema.prisma | 173 +++++++------ .../content/dropdowns/ContentDropdownItem.js | 4 - src/components/forms/CourseForm.js | 243 ------------------ src/components/forms/course/CourseForm.js | 65 +++-- src/components/forms/course/LessonSelector.js | 11 +- src/db/models/courseDraftModels.js | 68 +++-- src/db/models/courseModels.js | 67 ++++- src/db/models/draftLessonModels.js | 74 ++++++ src/db/models/lessonModels.js | 74 ++++++ src/pages/api/courses/drafts/[slug].js | 11 +- src/pages/api/courses/drafts/index.js | 10 +- src/pages/api/lessons/[slug].js | 35 +++ src/pages/api/lessons/drafts/[slug].js | 35 +++ src/pages/api/lessons/drafts/index.js | 22 ++ src/pages/api/lessons/index.js | 22 ++ src/pages/course/[slug]/draft/index.js | 9 +- 17 files changed, 567 insertions(+), 419 deletions(-) rename prisma/migrations/{20240822032218_init => 20240823234011_init}/migration.sql (70%) delete mode 100644 src/components/forms/CourseForm.js create mode 100644 src/db/models/draftLessonModels.js create mode 100644 src/db/models/lessonModels.js create mode 100644 src/pages/api/lessons/[slug].js create mode 100644 src/pages/api/lessons/drafts/[slug].js create mode 100644 src/pages/api/lessons/drafts/index.js create mode 100644 src/pages/api/lessons/index.js diff --git a/prisma/migrations/20240822032218_init/migration.sql b/prisma/migrations/20240823234011_init/migration.sql similarity index 70% rename from prisma/migrations/20240822032218_init/migration.sql rename to prisma/migrations/20240823234011_init/migration.sql index df659aa..370fea9 100644 --- a/prisma/migrations/20240822032218_init/migration.sql +++ b/prisma/migrations/20240823234011_init/migration.sql @@ -32,6 +32,32 @@ CREATE TABLE "Purchase" ( CONSTRAINT "Purchase_pkey" PRIMARY KEY ("id") ); +-- CreateTable +CREATE TABLE "Lesson" ( + "id" TEXT NOT NULL, + "courseId" TEXT NOT NULL, + "resourceId" TEXT, + "draftId" TEXT, + "index" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Lesson_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "DraftLesson" ( + "id" TEXT NOT NULL, + "courseDraftId" TEXT NOT NULL, + "resourceId" TEXT, + "draftId" TEXT, + "index" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "DraftLesson_pkey" PRIMARY KEY ("id") +); + -- CreateTable CREATE TABLE "Course" ( "id" TEXT NOT NULL, @@ -48,8 +74,6 @@ CREATE TABLE "Course" ( CREATE TABLE "Resource" ( "id" TEXT NOT NULL, "userId" TEXT NOT NULL, - "courseId" TEXT, - "courseDraftId" TEXT, "price" INTEGER NOT NULL DEFAULT 0, "noteId" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -71,7 +95,6 @@ CREATE TABLE "Draft" ( "topics" TEXT[], "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, - "courseDraftId" TEXT, CONSTRAINT "Draft_pkey" PRIMARY KEY ("id") ); @@ -87,7 +110,6 @@ CREATE TABLE "CourseDraft" ( "topics" TEXT[], "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updatedAt" TIMESTAMP(3) NOT NULL, - "courseId" TEXT, CONSTRAINT "CourseDraft_pkey" PRIMARY KEY ("id") ); @@ -104,9 +126,6 @@ CREATE UNIQUE INDEX "Course_noteId_key" ON "Course"("noteId"); -- CreateIndex CREATE UNIQUE INDEX "Resource_noteId_key" ON "Resource"("noteId"); --- CreateIndex -CREATE UNIQUE INDEX "CourseDraft_courseId_key" ON "CourseDraft"("courseId"); - -- AddForeignKey ALTER TABLE "User" ADD CONSTRAINT "User_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "Role"("id") ON DELETE SET NULL ON UPDATE CASCADE; @@ -119,26 +138,32 @@ ALTER TABLE "Purchase" ADD CONSTRAINT "Purchase_courseId_fkey" FOREIGN KEY ("cou -- AddForeignKey ALTER TABLE "Purchase" ADD CONSTRAINT "Purchase_resourceId_fkey" FOREIGN KEY ("resourceId") REFERENCES "Resource"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- AddForeignKey +ALTER TABLE "Lesson" ADD CONSTRAINT "Lesson_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Lesson" ADD CONSTRAINT "Lesson_resourceId_fkey" FOREIGN KEY ("resourceId") REFERENCES "Resource"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Lesson" ADD CONSTRAINT "Lesson_draftId_fkey" FOREIGN KEY ("draftId") REFERENCES "Draft"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DraftLesson" ADD CONSTRAINT "DraftLesson_courseDraftId_fkey" FOREIGN KEY ("courseDraftId") REFERENCES "CourseDraft"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DraftLesson" ADD CONSTRAINT "DraftLesson_resourceId_fkey" FOREIGN KEY ("resourceId") REFERENCES "Resource"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "DraftLesson" ADD CONSTRAINT "DraftLesson_draftId_fkey" FOREIGN KEY ("draftId") REFERENCES "Draft"("id") ON DELETE SET NULL ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "Course" ADD CONSTRAINT "Course_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "Resource" ADD CONSTRAINT "Resource_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; --- AddForeignKey -ALTER TABLE "Resource" ADD CONSTRAINT "Resource_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Resource" ADD CONSTRAINT "Resource_courseDraftId_fkey" FOREIGN KEY ("courseDraftId") REFERENCES "CourseDraft"("id") ON DELETE SET NULL ON UPDATE CASCADE; - -- AddForeignKey ALTER TABLE "Draft" ADD CONSTRAINT "Draft_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; --- AddForeignKey -ALTER TABLE "Draft" ADD CONSTRAINT "Draft_courseDraftId_fkey" FOREIGN KEY ("courseDraftId") REFERENCES "CourseDraft"("id") ON DELETE SET NULL ON UPDATE CASCADE; - -- AddForeignKey ALTER TABLE "CourseDraft" ADD CONSTRAINT "CourseDraft_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "CourseDraft" ADD CONSTRAINT "CourseDraft_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2883aa1..0ead04f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,103 +2,124 @@ datasource db { provider = "postgresql" url = env("DATABASE_URL") } + generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" } model User { - id String @id @default(uuid()) - pubkey String @unique - username String? @unique - avatar String? - purchased Purchase[] - courses Course[] - resources Resource[] + id String @id @default(uuid()) + pubkey String @unique + username String? @unique + avatar String? + purchased Purchase[] + courses Course[] + resources Resource[] courseDrafts CourseDraft[] - drafts Draft[] - role Role? @relation(fields: [roleId], references: [id]) - roleId String? - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + drafts Draft[] + role Role? @relation(fields: [roleId], references: [id]) + roleId String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Role { - id String @id @default(uuid()) - subscribed Boolean @default(false) - users User[] + id String @id @default(uuid()) + subscribed Boolean @default(false) + users User[] } model Purchase { - id String @id @default(uuid()) - user User @relation(fields: [userId], references: [id]) - userId String - course Course? @relation(fields: [courseId], references: [id]) - courseId String? - resource Resource? @relation(fields: [resourceId], references: [id]) - resourceId String? - amountPaid Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(uuid()) + user User @relation(fields: [userId], references: [id]) + userId String + course Course? @relation(fields: [courseId], references: [id]) + courseId String? + resource Resource? @relation(fields: [resourceId], references: [id]) + resourceId String? + amountPaid Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Lesson { + id String @id @default(uuid()) + courseId String + course Course @relation(fields: [courseId], references: [id]) + resourceId String? + resource Resource? @relation(fields: [resourceId], references: [id]) + draftId String? + draft Draft? @relation(fields: [draftId], references: [id]) + index Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model DraftLesson { + id String @id @default(uuid()) + courseDraftId String + courseDraft CourseDraft @relation(fields: [courseDraftId], references: [id]) + resourceId String? + resource Resource? @relation(fields: [resourceId], references: [id]) + draftId String? + draft Draft? @relation(fields: [draftId], references: [id]) + index Int + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Course { - id String @id - userId String - user User @relation(fields: [userId], references: [id]) - price Int @default(0) - resources Resource[] - purchases Purchase[] - noteId String? @unique - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - courseDraft CourseDraft? + id String @id + userId String + user User @relation(fields: [userId], references: [id]) + price Int @default(0) + lessons Lesson[] + purchases Purchase[] + noteId String? @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Resource { - id String @id // Client generates UUID - userId String - user User @relation(fields: [userId], references: [id]) - course Course? @relation(fields: [courseId], references: [id]) - courseId String? - courseDraft CourseDraft? @relation(fields: [courseDraftId], references: [id]) - courseDraftId String? - price Int @default(0) - purchases Purchase[] - noteId String? @unique - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id // Client generates UUID + userId String + user User @relation(fields: [userId], references: [id]) + lessons Lesson[] + draftLessons DraftLesson[] + price Int @default(0) + purchases Purchase[] + noteId String? @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Draft { - id String @id @default(uuid()) - userId String - user User @relation(fields: [userId], references: [id]) - type String - title String - summary String - content String - image String? - price Int? @default(0) - topics String[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - courseDraft CourseDraft? @relation(fields: [courseDraftId], references: [id]) - courseDraftId String? + id String @id @default(uuid()) + userId String + user User @relation(fields: [userId], references: [id]) + type String + title String + summary String + content String + image String? + price Int? @default(0) + topics String[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + draftLessons DraftLesson[] + lessons Lesson[] } model CourseDraft { - id String @id @default(uuid()) - userId String - user User @relation(fields: [userId], references: [id]) - resources Resource[] - drafts Draft[] - title String - summary String - image String? - price Int? @default(0) - topics String[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - course Course? @relation(fields: [courseId], references: [id]) - courseId String? @unique + id String @id @default(uuid()) + userId String + user User @relation(fields: [userId], references: [id]) + draftLessons DraftLesson[] + title String + summary String + image String? + price Int? @default(0) + topics String[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } \ No newline at end of file diff --git a/src/components/content/dropdowns/ContentDropdownItem.js b/src/components/content/dropdowns/ContentDropdownItem.js index d715799..ad6fc1e 100644 --- a/src/components/content/dropdowns/ContentDropdownItem.js +++ b/src/components/content/dropdowns/ContentDropdownItem.js @@ -7,10 +7,6 @@ import { Button } from "primereact/button"; const ContentDropdownItem = ({ content, onSelect }) => { const { returnImageProxy } = useImageProxy(); - useEffect(() => { - console.log("content", content); - }, [content]); - return (
diff --git a/src/components/forms/CourseForm.js b/src/components/forms/CourseForm.js deleted file mode 100644 index 2497f23..0000000 --- a/src/components/forms/CourseForm.js +++ /dev/null @@ -1,243 +0,0 @@ -import React, { useEffect, useState } from "react"; -import axios from "axios"; -import { InputText } from "primereact/inputtext"; -import { InputNumber } from "primereact/inputnumber"; -import { InputSwitch } from "primereact/inputswitch"; -import { Button } from "primereact/button"; -import { Dropdown } from "primereact/dropdown"; -import { ProgressSpinner } from "primereact/progressspinner"; -import { v4 as uuidv4 } from 'uuid'; -import { useSession } from 'next-auth/react'; -import { useNDKContext } from "@/context/NDKContext"; -import { useRouter } from "next/router"; -import { useToast } from "@/hooks/useToast"; -import { useWorkshopsQuery } from "@/hooks/nostrQueries/content/useWorkshopsQuery"; -import { useResourcesQuery } from "@/hooks/nostrQueries/content/useResourcesQuery"; -import { useDraftsQuery } from "@/hooks/apiQueries/useDraftsQuery"; -import { NDKEvent } from "@nostr-dev-kit/ndk"; -import { parseEvent } from "@/utils/nostr"; -import ContentDropdownItem from "@/components/content/dropdowns/ContentDropdownItem"; -import SelectedContentItem from "@/components/content/SelectedContentItem"; -import 'primeicons/primeicons.css'; - - -// todo dont allow adding courses as resources -// todo need to update how I handle unpubbed resources -// todo add back topics -const CourseForm = ({ draft = null, isPublished = false }) => { - const [title, setTitle] = useState(''); - const [summary, setSummary] = useState(''); - const [isPaidCourse, setIsPaidCourse] = useState(draft?.price ? true : false); - const [price, setPrice] = useState(draft?.price || 0); - const [coverImage, setCoverImage] = useState(''); - const [selectedContent, setSelectedContent] = useState([]); - const [topics, setTopics] = useState(['']); - - const { resources, resourcesLoading, resourcesError } = useResourcesQuery(); - const { workshops, workshopsLoading, workshopsError } = useWorkshopsQuery(); - const { drafts, draftsLoading, draftsError } = useDraftsQuery(); - const { data: session, status } = useSession(); - const [user, setUser] = useState(null); - const { ndk, addSigner } = useNDKContext(); - const router = useRouter(); - const { showToast } = useToast(); - - useEffect(() => { - if (session) { - setUser(session.user); - } - }, [session]); - - useEffect(() => { - if (draft) { - console.log('draft:', draft); - setTitle(draft.title); - setSummary(draft.summary); - setIsPaidCourse(draft.price > 0); - setPrice(draft.price || 0); - setCoverImage(draft.image); - setSelectedContent(draft.resources.concat(draft.drafts) || []); - setTopics(draft.topics || ['']); - } - }, [draft]); - - const handlePriceChange = (value) => { - setPrice(value); - }; - - const handleSubmit = async (e) => { - e.preventDefault(); - - if (!user) { - showToast('error', 'Error', 'User not authenticated'); - return; - } - - try { - const courseDraftPayload = { - userId: user.id, - title, - summary, - image: coverImage, - price: price || 0, - topics, - resources: selectedContent.filter(content => content.kind === 30023 || content.kind === 30402).map(resource => resource.d), - drafts: selectedContent.filter(content => !content.kind).map(draft => draft.id), - }; - - const courseDraftResponse = await axios.post('/api/courses/drafts', courseDraftPayload); - const courseDraftId = courseDraftResponse.data.id; - - showToast('success', 'Success', 'Course draft saved successfully'); - router.push(`/course/${courseDraftId}/draft`); - } catch (error) { - console.error('Error saving course draft:', error); - showToast('error', 'Failed to save course draft', error.response?.data?.details || error.message); - } - }; - - const handleContentSelect = (content) => { - if (!selectedContent.some(item => item.id === content.id)) { - setSelectedContent([...selectedContent, content]); - } - }; - - const removeContent = (index) => { - const updatedContent = selectedContent.filter((_, i) => i !== index); - setSelectedContent(updatedContent); - }; - - const addTopic = () => { - setTopics([...topics, '']); - }; - - const removeTopic = (index) => { - const updatedTopics = topics.filter((_, i) => i !== index); - setTopics(updatedTopics); - }; - - const handleTopicChange = (index, value) => { - const updatedTopics = topics.map((topic, i) => i === index ? value : topic); - setTopics(updatedTopics); - }; - - const getContentOptions = () => { - if (resourcesLoading || !resources || workshopsLoading || !workshops || draftsLoading || !drafts) { - return []; - } - - const filterContent = (content) => { - const contentPrice = content.tags ? (content.tags.find(tag => tag[0] === 'price') ? parseInt(content.tags.find(tag => tag[0] === 'price')[1]) : 0) : (content.price || 0); - return isPaidCourse ? contentPrice > 0 : contentPrice === 0; - }; - - const draftOptions = drafts.filter(filterContent).map(draft => ({ - label: draft.title, - value: draft - })); - - const resourceOptions = resources.filter(filterContent).map(resource => { - const parsedResource = parseEvent(resource); - return { - label: parsedResource.title, - value: parsedResource - }; - }); - - const workshopOptions = workshops.filter(filterContent).map(workshop => { - const parsedWorkshop = parseEvent(workshop); - return { - label: parsedWorkshop.title, - value: parsedWorkshop - }; - }); - - return [ - { - label: 'Drafts', - items: draftOptions - }, - { - label: 'Resources', - items: resourceOptions - }, - { - label: 'Workshops', - items: workshopOptions - } - ]; - }; - - if (resourcesLoading || workshopsLoading || draftsLoading) { - return ; - } - - return ( -
-
- setTitle(e.target.value)} placeholder="Title" /> -
-
- setSummary(e.target.value)} placeholder="Summary" /> -
-
- setCoverImage(e.target.value)} placeholder="Cover Image URL" /> -
-
-

Paid Course

- setIsPaidCourse(e.value)} /> - {isPaidCourse && ( -
- handlePriceChange(e.value)} - placeholder="Price (sats)" - min={1} - /> -
- )} -
-
-
- {selectedContent.map((content, index) => ( -
- -
- ))} -
- handleContentSelect(e.value)} - placeholder="Select Content" - itemTemplate={(option) => } - optionLabel="label" - optionGroupLabel="label" - optionGroupChildren="items" - /> -
-
-
-
- {topics.map((topic, index) => ( -
- handleTopicChange(index, e.target.value)} placeholder={`Topic #${index + 1}`} className="w-full" /> - {index > 0 && ( -
- ))} -
-
-
-
- ); -} - -export default CourseForm; \ No newline at end of file diff --git a/src/components/forms/course/CourseForm.js b/src/components/forms/course/CourseForm.js index af28e8b..24096e2 100644 --- a/src/components/forms/course/CourseForm.js +++ b/src/components/forms/course/CourseForm.js @@ -20,7 +20,7 @@ const CourseForm = ({ draft = null }) => { const [price, setPrice] = useState(draft?.price || 0); const [coverImage, setCoverImage] = useState(draft?.image || ''); const [topics, setTopics] = useState(draft?.topics || ['']); - const [lessons, setLessons] = useState(draft?.resources || []); + const [lessons, setLessons] = useState(draft?.resources?.map((resource, index) => ({ ...resource, index })) || []); const [allContent, setAllContent] = useState([]); const { data: session } = useSession(); @@ -36,34 +36,59 @@ const CourseForm = ({ draft = null }) => { } }, [resources, workshops, drafts, resourcesLoading, workshopsLoading, draftsLoading]); - const handleSubmit = async (e) => { - e.preventDefault(); - - if (!session?.user) { - showToast('error', 'Error', 'User not authenticated'); - return; - } - + const handleSubmit = async (event) => { + event.preventDefault(); + try { - const courseDraftPayload = { - userId: session?.user.id, + // First, create the courseDraft + const courseDraftData = { + userId: session.user.id, title, summary, image: coverImage, - price: price || 0, + price: isPaidCourse ? price : 0, topics, - resources: lessons.filter(content => content.kind === 30023 || content.kind === 30402).map(resource => resource.d), - drafts: lessons.filter(content => !content.kind).map(draft => draft.id), }; - const response = await axios.post('/api/courses/drafts', courseDraftPayload); - const courseDraftId = response.data.id; + console.log('courseDraftData', courseDraftData); - showToast('success', 'Success', 'Course draft saved successfully'); - router.push(`/course/${courseDraftId}/draft`); + const courseDraftResponse = await axios.post('/api/courses/drafts', courseDraftData); + const createdCourseDraft = courseDraftResponse.data; + + // Now create all the lessonDrafts with the courseDraftId + const createdLessonDrafts = await Promise.all( + lessons.map(async (lessonDraft, index) => { + console.log('lessonDraft', lessonDraft); + const isResource = lessonDraft?.kind ? true : false; + let payload = {}; + if (isResource) { + payload = { + courseDraftId: createdCourseDraft.id, + resourceId: lessonDraft.d, + index: index + }; + } else { + payload = { + courseDraftId: createdCourseDraft.id, + draftId: lessonDraft.id, + index: index + }; + } + + const response = await axios.post('/api/lessons/drafts', payload); + console.log('Lesson draft created:', response.data); + return response.data; + }) + ); + + console.log('Course draft created:', createdCourseDraft); + console.log('Lesson drafts created:', createdLessonDrafts); + + showToast('success', 'Success', 'Course draft created successfully'); + router.push(`/course/${createdCourseDraft.id}/draft`); } catch (error) { - console.error('Error saving course draft:', error); - showToast('error', 'Failed to save course draft', error.response?.data?.details || error.message); + console.error('Error creating course draft:', error); + showToast('error', 'Error', 'Failed to create course draft'); } }; diff --git a/src/components/forms/course/LessonSelector.js b/src/components/forms/course/LessonSelector.js index 4d4629b..d8eaa66 100644 --- a/src/components/forms/course/LessonSelector.js +++ b/src/components/forms/course/LessonSelector.js @@ -84,22 +84,23 @@ const LessonSelector = ({ isPaidCourse, lessons, setLessons, allContent }) => { const handleContentSelect = (selectedContent) => { if (selectedContent && !lessons.some(lesson => lesson.id === selectedContent.id)) { - setLessons([...lessons, selectedContent]); + setLessons([...lessons, { ...selectedContent, index: lessons.length }]); } }; const removeLesson = (index) => { - const updatedLessons = lessons.filter((_, i) => i !== index); + const updatedLessons = lessons.filter((_, i) => i !== index) + .map((lesson, newIndex) => ({ ...lesson, index: newIndex })); setLessons(updatedLessons); }; const handleNewResourceSave = (newResource) => { - setLessons([...lessons, newResource]); + setLessons([...lessons, { ...newResource, index: lessons.length }]); setShowResourceForm(false); }; const handleNewWorkshopSave = (newWorkshop) => { - setLessons([...lessons, newWorkshop]); + setLessons([...lessons, { ...newWorkshop, index: lessons.length }]); setShowWorkshopForm(false); }; @@ -108,7 +109,7 @@ const LessonSelector = ({ isPaidCourse, lessons, setLessons, allContent }) => {

Lessons

{lessons.map((lesson, index) => (
- +