mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
fix: course edition bugs
This commit is contained in:
parent
ddbd413539
commit
9968fe23fa
3 changed files with 91 additions and 105 deletions
|
|
@ -5,43 +5,40 @@ import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
|||
import useSWR from 'swr'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
export const CourseContext = createContext(null) as any
|
||||
export const CourseDispatchContext = createContext(null) as any
|
||||
export const CourseContext = createContext(null)
|
||||
export const CourseDispatchContext = createContext(null)
|
||||
|
||||
export function CourseProvider({
|
||||
children,
|
||||
courseuuid,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
courseuuid: string
|
||||
}) {
|
||||
export function CourseProvider({ children, courseuuid }: any) {
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const { data: courseStructureData } = useSWR(
|
||||
`${getAPIUrl()}courses/${courseuuid}/meta`,
|
||||
(url) => swrFetcher(url, access_token)
|
||||
)
|
||||
const [courseStructure, dispatchCourseStructure] = useReducer(courseReducer, {
|
||||
courseStructure: courseStructureData ? courseStructureData : {},
|
||||
|
||||
const { data: courseStructureData, error } = useSWR(
|
||||
access_token ? `${getAPIUrl()}courses/${courseuuid}/meta` : null,
|
||||
url => swrFetcher(url, access_token)
|
||||
);
|
||||
|
||||
const initialState = {
|
||||
courseStructure: {},
|
||||
courseOrder: {},
|
||||
isSaved: true,
|
||||
})
|
||||
isLoading: true
|
||||
};
|
||||
|
||||
const [state, dispatch] = useReducer(courseReducer, initialState) as any;
|
||||
|
||||
// When courseStructureData is loaded, update the state
|
||||
useEffect(() => {
|
||||
if (courseStructureData) {
|
||||
dispatchCourseStructure({
|
||||
type: 'setCourseStructure',
|
||||
payload: courseStructureData,
|
||||
})
|
||||
dispatch({ type: 'setCourseStructure', payload: courseStructureData });
|
||||
dispatch({ type: 'setIsLoaded' });
|
||||
}
|
||||
}, [courseStructureData,session])
|
||||
}, [courseStructureData]);
|
||||
|
||||
if (!courseStructureData) return
|
||||
if (error) return <div>Failed to load course structure</div>;
|
||||
if (!courseStructureData) return <div>Loading...</div>;
|
||||
|
||||
return (
|
||||
<CourseContext.Provider value={courseStructure}>
|
||||
<CourseDispatchContext.Provider value={dispatchCourseStructure}>
|
||||
<CourseContext.Provider value={state}>
|
||||
<CourseDispatchContext.Provider value={dispatch}>
|
||||
{children}
|
||||
</CourseDispatchContext.Provider>
|
||||
</CourseContext.Provider>
|
||||
|
|
@ -66,6 +63,8 @@ function courseReducer(state: any, action: any) {
|
|||
return { ...state, isSaved: true }
|
||||
case 'setIsNotSaved':
|
||||
return { ...state, isSaved: false }
|
||||
case 'setIsLoaded':
|
||||
return { ...state, isLoading: false }
|
||||
default:
|
||||
throw new Error(`Unhandled action type: ${action.type}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ function EditCourseAccess(props: EditCourseAccessProps) {
|
|||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const course = useCourse() as any
|
||||
const course = useCourse() as any;
|
||||
const { isLoading, courseStructure } = course as any;
|
||||
const dispatchCourse = useCourseDispatch() as any
|
||||
const courseStructure = course.courseStructure
|
||||
const { data: usergroups } = useSWR(
|
||||
courseStructure ? `${getAPIUrl()}usergroups/resource/${courseStructure.course_uuid}` : null,
|
||||
(url) => swrFetcher(url, access_token)
|
||||
|
|
@ -33,7 +33,7 @@ function EditCourseAccess(props: EditCourseAccessProps) {
|
|||
|
||||
React.useEffect(() => {
|
||||
// This code will run whenever form values are updated
|
||||
if (isPublic !== courseStructure.public) {
|
||||
if ((isPublic !== courseStructure.public) && isLoading) {
|
||||
dispatchCourse({ type: 'setIsNotSaved' })
|
||||
const updatedCourse = {
|
||||
...courseStructure,
|
||||
|
|
@ -126,7 +126,7 @@ function UserGroupsSection({ usergroups }: { usergroups: any[] }) {
|
|||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const removeUserGroupLink = async (usergroup_id: number) => {
|
||||
const res = await unLinkResourcesToUserGroup(usergroup_id, course.courseStructure.course_uuid,access_token)
|
||||
const res = await unLinkResourcesToUserGroup(usergroup_id, course.courseStructure.course_uuid, access_token)
|
||||
if (res.status === 200) {
|
||||
toast.success('Successfully unliked from usergroup')
|
||||
mutate(`${getAPIUrl()}usergroups/resource/${course.courseStructure.course_uuid}`)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import FormLayout, {
|
|||
FormLabelAndMessage,
|
||||
Input,
|
||||
Textarea,
|
||||
} from '@components/StyledElements/Form/Form'
|
||||
import { useFormik } from 'formik'
|
||||
import { AlertTriangle } from 'lucide-react'
|
||||
import * as Form from '@radix-ui/react-form'
|
||||
import React from 'react'
|
||||
import { useCourse, useCourseDispatch } from '../../../Contexts/CourseContext'
|
||||
import ThumbnailUpdate from './ThumbnailUpdate'
|
||||
} from '@components/StyledElements/Form/Form';
|
||||
import { useFormik } from 'formik';
|
||||
import { AlertTriangle } from 'lucide-react';
|
||||
import * as Form from '@radix-ui/react-form';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useCourse, useCourseDispatch } from '../../../Contexts/CourseContext';
|
||||
import ThumbnailUpdate from './ThumbnailUpdate';
|
||||
|
||||
type EditCourseStructureProps = {
|
||||
orgslug: string
|
||||
|
|
@ -17,74 +17,78 @@ type EditCourseStructureProps = {
|
|||
}
|
||||
|
||||
const validate = (values: any) => {
|
||||
const errors: any = {}
|
||||
const errors = {} as any;
|
||||
|
||||
if (!values.name) {
|
||||
errors.name = 'Required'
|
||||
}
|
||||
|
||||
if (values.name.length > 100) {
|
||||
errors.name = 'Must be 100 characters or less'
|
||||
errors.name = 'Required';
|
||||
} else if (values.name.length > 100) {
|
||||
errors.name = 'Must be 100 characters or less';
|
||||
}
|
||||
|
||||
if (!values.description) {
|
||||
errors.description = 'Required'
|
||||
}
|
||||
|
||||
if (values.description.length > 1000) {
|
||||
errors.description = 'Must be 1000 characters or less'
|
||||
errors.description = 'Required';
|
||||
} else if (values.description.length > 1000) {
|
||||
errors.description = 'Must be 1000 characters or less';
|
||||
}
|
||||
|
||||
if (!values.learnings) {
|
||||
errors.learnings = 'Required'
|
||||
errors.learnings = 'Required';
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
return errors;
|
||||
};
|
||||
|
||||
function EditCourseGeneral(props: EditCourseStructureProps) {
|
||||
const [error, setError] = React.useState('')
|
||||
const course = useCourse() as any
|
||||
const dispatchCourse = useCourseDispatch() as any
|
||||
const [error, setError] = useState('');
|
||||
const course = useCourse();
|
||||
const dispatchCourse = useCourseDispatch() as any;
|
||||
const { isLoading, courseStructure } = course as any;
|
||||
|
||||
const courseStructure = course.courseStructure
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
name: String(courseStructure.name),
|
||||
description: String(courseStructure.description),
|
||||
about: String(courseStructure.about),
|
||||
learnings: String(courseStructure.learnings),
|
||||
tags: String(courseStructure.tags),
|
||||
public: String(courseStructure.public),
|
||||
name: courseStructure?.name || '',
|
||||
description: courseStructure?.description || '',
|
||||
about: courseStructure?.about || '',
|
||||
learnings: courseStructure?.learnings || '',
|
||||
tags: courseStructure?.tags || '',
|
||||
public: courseStructure?.public || '',
|
||||
},
|
||||
validate,
|
||||
onSubmit: async (values) => {},
|
||||
onSubmit: async values => {
|
||||
try {
|
||||
// Add your submission logic here
|
||||
dispatchCourse({ type: 'setIsSaved' });
|
||||
} catch (e) {
|
||||
setError('Failed to save course structure.');
|
||||
}
|
||||
},
|
||||
enableReinitialize: true,
|
||||
})
|
||||
}) as any;
|
||||
|
||||
React.useEffect(() => {
|
||||
// This code will run whenever form values are updated
|
||||
if (formik.values !== formik.initialValues) {
|
||||
dispatchCourse({ type: 'setIsNotSaved' })
|
||||
useEffect(() => {
|
||||
if (!isLoading) {
|
||||
const formikValues = formik.values as any;
|
||||
const initialValues = formik.initialValues as any;
|
||||
const valuesChanged = Object.keys(formikValues).some(
|
||||
key => formikValues[key] !== initialValues[key]
|
||||
);
|
||||
|
||||
if (valuesChanged) {
|
||||
dispatchCourse({ type: 'setIsNotSaved' });
|
||||
const updatedCourse = {
|
||||
...courseStructure,
|
||||
name: formik.values.name,
|
||||
description: formik.values.description,
|
||||
about: formik.values.about,
|
||||
learnings: formik.values.learnings,
|
||||
tags: formik.values.tags,
|
||||
public: formik.values.public,
|
||||
...formikValues,
|
||||
};
|
||||
dispatchCourse({ type: 'setCourseStructure', payload: updatedCourse });
|
||||
}
|
||||
dispatchCourse({ type: 'setCourseStructure', payload: updatedCourse })
|
||||
}
|
||||
}, [course, formik.values, formik.initialValues])
|
||||
}, [formik.values, isLoading]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{' '}
|
||||
<div className="h-6"></div>
|
||||
<div className="ml-10 mr-10 mx-auto bg-white rounded-xl shadow-sm px-6 py-5">
|
||||
{course.courseStructure && (
|
||||
{courseStructure && (
|
||||
<div className="editcourse-form">
|
||||
{error && (
|
||||
<div className="flex justify-center bg-red-200 rounded-md text-red-950 space-x-2 items-center p-4 transition-all shadow-sm">
|
||||
|
|
@ -94,10 +98,7 @@ function EditCourseGeneral(props: EditCourseStructureProps) {
|
|||
)}
|
||||
<FormLayout onSubmit={formik.handleSubmit}>
|
||||
<FormField name="name">
|
||||
<FormLabelAndMessage
|
||||
label="Name"
|
||||
message={formik.errors.name}
|
||||
/>
|
||||
<FormLabelAndMessage label="Name" message={formik.errors.name} />
|
||||
<Form.Control asChild>
|
||||
<Input
|
||||
style={{ backgroundColor: 'white' }}
|
||||
|
|
@ -110,26 +111,20 @@ function EditCourseGeneral(props: EditCourseStructureProps) {
|
|||
</FormField>
|
||||
|
||||
<FormField name="description">
|
||||
<FormLabelAndMessage
|
||||
label="Description"
|
||||
message={formik.errors.description}
|
||||
/>
|
||||
<FormLabelAndMessage label="Description" message={formik.errors.description} />
|
||||
<Form.Control asChild>
|
||||
<Input
|
||||
style={{ backgroundColor: 'white' }}
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.description}
|
||||
type='text'
|
||||
type="text"
|
||||
required
|
||||
/>
|
||||
</Form.Control>
|
||||
</FormField>
|
||||
|
||||
<FormField name="about">
|
||||
<FormLabelAndMessage
|
||||
label="About"
|
||||
message={formik.errors.about}
|
||||
/>
|
||||
<FormLabelAndMessage label="About" message={formik.errors.about} />
|
||||
<Form.Control asChild>
|
||||
<Textarea
|
||||
style={{ backgroundColor: 'white' }}
|
||||
|
|
@ -141,10 +136,7 @@ function EditCourseGeneral(props: EditCourseStructureProps) {
|
|||
</FormField>
|
||||
|
||||
<FormField name="learnings">
|
||||
<FormLabelAndMessage
|
||||
label="Learnings"
|
||||
message={formik.errors.learnings}
|
||||
/>
|
||||
<FormLabelAndMessage label="Learnings" message={formik.errors.learnings} />
|
||||
<Form.Control asChild>
|
||||
<Textarea
|
||||
style={{ backgroundColor: 'white' }}
|
||||
|
|
@ -156,10 +148,7 @@ function EditCourseGeneral(props: EditCourseStructureProps) {
|
|||
</FormField>
|
||||
|
||||
<FormField name="tags">
|
||||
<FormLabelAndMessage
|
||||
label="Tags"
|
||||
message={formik.errors.tags}
|
||||
/>
|
||||
<FormLabelAndMessage label="Tags" message={formik.errors.tags} />
|
||||
<Form.Control asChild>
|
||||
<Textarea
|
||||
style={{ backgroundColor: 'white' }}
|
||||
|
|
@ -176,14 +165,12 @@ function EditCourseGeneral(props: EditCourseStructureProps) {
|
|||
<ThumbnailUpdate />
|
||||
</Form.Control>
|
||||
</FormField>
|
||||
|
||||
|
||||
</FormLayout>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default EditCourseGeneral
|
||||
export default EditCourseGeneral;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue