diff --git a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/[[...subpage]]/edit.tsx b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/[[...subpage]]/edit.tsx
index 2a12fea7..c290d344 100644
--- a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/[[...subpage]]/edit.tsx
+++ b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/[[...subpage]]/edit.tsx
@@ -2,7 +2,7 @@
import React, { FC, use, useEffect, useReducer } from 'react'
import { swrFetcher } from "@services/utils/ts/requests";
import { getAPIUrl, getUriWithOrg } from '@services/config/config';
-import useSWR from 'swr';
+import useSWR, { mutate } from 'swr';
import { getCourseThumbnailMediaDirectory } from '@services/media/media';
import Link from 'next/link';
import CourseEdition from '../subpages/CourseEdition';
@@ -10,14 +10,18 @@ import CourseContentEdition from '../subpages/CourseContentEdition';
import ErrorUI from '@components/StyledElements/Error/Error';
import { updateChaptersMetadata } from '@services/courses/chapters';
import { Check, SaveAllIcon, Timer } from 'lucide-react';
+import Loading from '../../loading';
+import { updateCourse } from '@services/courses/courses';
function CourseEditClient({ courseid, subpage, params }: { courseid: string, subpage: string, params: any }) {
const { data: chapters_meta, error: chapters_meta_error, isLoading: chapters_meta_isloading } = useSWR(`${getAPIUrl()}chapters/meta/course_${courseid}`, swrFetcher);
- const { data: course_meta, error: course_meta_error, isLoading: course_meta_isloading } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`, swrFetcher);
+ const { data: course, error: course_error, isLoading: course_isloading } = useSWR(`${getAPIUrl()}courses/course_${courseid}`, swrFetcher);
const [courseChaptersMetadata, dispatchCourseChaptersMetadata] = useReducer(courseChaptersReducer, {});
+ const [courseState, dispatchCourseMetadata] = useReducer(courseReducer, {});
const [savedContent, dispatchSavedContent] = useReducer(savedContentReducer, true);
+
function courseChaptersReducer(state: any, action: any) {
switch (action.type) {
case 'updated_chapter':
@@ -28,6 +32,16 @@ function CourseEditClient({ courseid, subpage, params }: { courseid: string, sub
}
}
+ function courseReducer(state: any, action: any) {
+ switch (action.type) {
+ case 'updated_course':
+ // action will contain the entire state, just update the entire state
+ return action.payload;
+ default:
+ throw new Error();
+ }
+ }
+
function savedContentReducer(state: any, action: any) {
switch (action.type) {
case 'saved_content':
@@ -39,13 +53,16 @@ function CourseEditClient({ courseid, subpage, params }: { courseid: string, sub
}
}
- function saveCourse() {
+ async function saveCourse() {
if (subpage.toString() === 'content') {
- updateChaptersMetadata(courseid, courseChaptersMetadata)
+ await updateChaptersMetadata(courseid, courseChaptersMetadata)
dispatchSavedContent({ type: 'saved_content' })
+ await mutate(`${getAPIUrl()}chapters/meta/course_${courseid}`)
}
else if (subpage.toString() === 'general') {
- console.log('general')
+ await updateCourse(courseid, courseState)
+ dispatchSavedContent({ type: 'saved_content' })
+ await mutate(`${getAPIUrl()}courses/course_${courseid}`)
}
}
@@ -54,23 +71,27 @@ function CourseEditClient({ courseid, subpage, params }: { courseid: string, sub
dispatchCourseChaptersMetadata({ type: 'updated_chapter', payload: chapters_meta })
dispatchSavedContent({ type: 'saved_content' })
}
- }, [chapters_meta])
+ if (course) {
+ dispatchCourseMetadata({ type: 'updated_course', payload: course })
+ dispatchSavedContent({ type: 'saved_content' })
+ }
+ }, [chapters_meta, course])
return (
<>
- {course_meta_isloading &&
Loading...
}
- {course_meta && <>
+ {course_isloading &&
Loading...
}
+ {course && <>
-
-

+
+
Edit Course
-
{course_meta.course.name}
+
{course.name}
@@ -100,19 +121,22 @@ function CourseEditClient({ courseid, subpage, params }: { courseid: string, sub
-
+
>
)
}
-const CoursePageViewer = ({ subpage, courseid, orgslug, dispatchCourseChaptersMetadata, courseChaptersMetadata, dispatchSavedContent }: { subpage: string, courseid: string, orgslug: string, dispatchCourseChaptersMetadata: React.Dispatch
, dispatchSavedContent: React.Dispatch, courseChaptersMetadata: any }) => {
- if (subpage.toString() === 'general') {
- return
+const CoursePageViewer = ({ subpage, courseid, orgslug, dispatchCourseMetadata, dispatchCourseChaptersMetadata, courseChaptersMetadata, dispatchSavedContent, courseState }: { subpage: string, courseid: string, orgslug: string, dispatchCourseChaptersMetadata: React.Dispatch, dispatchCourseMetadata: React.Dispatch, dispatchSavedContent: React.Dispatch, courseChaptersMetadata: any, courseState: any }) => {
+ if (subpage.toString() === 'general' && Object.keys(courseState).length !== 0) {
+ return
}
- else if (subpage.toString() === 'content') {
+ else if (subpage.toString() === 'content' && Object.keys(courseChaptersMetadata).length !== 0) {
return
}
+ else if (subpage.toString() === 'content' || subpage.toString() === 'general') {
+ return
+ }
else {
return
}
diff --git a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/subpages/CourseEdition.tsx b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/subpages/CourseEdition.tsx
index a5c6d2ac..23b77f85 100644
--- a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/subpages/CourseEdition.tsx
+++ b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/edit/subpages/CourseEdition.tsx
@@ -1,9 +1,114 @@
-import React from 'react'
+"use client";
+import FormLayout, { ButtonBlack, FormField, FormLabel, FormLabelAndMessage, FormMessage, Input, Textarea } from '@components/StyledElements/Form/Form'
+import * as Form from '@radix-ui/react-form';
+import { useFormik } from 'formik';
+import { AlertTriangle } from "lucide-react";
+import React from "react";
+
+const validate = (values: any) => {
+ const errors: any = {};
+
+ if (!values.name) {
+ errors.name = 'Required';
+ }
+
+ if (values.name.length > 100) {
+ errors.name = 'Must be 80 characters or less';
+ }
+
+ if (!values.mini_description) {
+ errors.mini_description = 'Required';
+ }
+
+ if (values.mini_description.length > 200) {
+ errors.mini_description = 'Must be 200 characters or less';
+ }
+
+ if (!values.description) {
+ errors.description = 'Required';
+
+ }
+
+ if (values.description.length > 1000) {
+ errors.description = 'Must be 1000 characters or less';
+ }
+
+
+ if (!values.learnings) {
+ errors.learnings = 'Required';
+ }
+
+ return errors;
+};
+
+function CourseEdition(props: any) {
+ const [error, setError] = React.useState('');
+ const formik = useFormik({
+ initialValues: {
+ name: String(props.data.name),
+ mini_description: String(props.data.mini_description),
+ description: String(props.data.description),
+ learnings: String(props.data.learnings),
+ },
+ validate,
+ onSubmit: async values => {
+ },
+ });
+
+
+ React.useEffect(() => {
+ // This code will run whenever form values are updated
+ if (formik.values !== formik.initialValues) {
+ props.dispatchSavedContent({ type: 'unsaved_content' });
+ const updatedCourse = {
+ ...props.data,
+ name: formik.values.name,
+ mini_description: formik.values.mini_description,
+ description: formik.values.description,
+ learnings: formik.values.learnings.split(", "),
+ };
+ props.dispatchCourseMetadata({ type: 'updated_course', payload: updatedCourse });
+ }
+ }, [formik.values, formik.initialValues]);
+
-function CourseEdition() {
return (
)
}
diff --git a/front/services/courses/courses.ts b/front/services/courses/courses.ts
index 3cf1f13c..1f11ccaf 100644
--- a/front/services/courses/courses.ts
+++ b/front/services/courses/courses.ts
@@ -24,6 +24,12 @@ export async function getCourseMetadataWithAuthHeader(course_id: any, next: any,
return res;
}
+export async function updateCourse(course_id: any, data: any) {
+ const result: any = await fetch(`${getAPIUrl()}courses/course_${course_id}`, RequestBody("PUT", data, null));
+ const res = await errorHandling(result);
+ return res;
+}
+
export async function getCourse(course_id: string, next: any) {
const result: any = await fetch(`${getAPIUrl()}courses/${course_id}`, RequestBody("GET", null, next));
const res = await errorHandling(result);