UNPKG

@selfcommunity/react-templates

Version:

React Templates Components to integrate a Community created with SelfCommunity.

198 lines (197 loc) • 12.1 kB
import { __rest } from "tslib"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import { useThemeProps } from '@mui/system'; import { Box, Icon, IconButton, Typography, useMediaQuery, useTheme, Alert, styled } from '@mui/material'; import { PREFIX } from './constants'; import { SCCourseJoinStatusType, SCCourseLessonCompletionStatusType } from '@selfcommunity/types'; import { SCRoutes, useSCFetchCourse, useSCFetchLesson, useSCRouting, Link } from '@selfcommunity/react-core'; import classNames from 'classnames'; import { CourseCompletedDialog, HiddenPlaceholder, LessonAppbar, LessonDrawer, LessonObject, SCLessonActionsType } from '@selfcommunity/react-ui'; import { CourseInfoViewType, CourseService } from '@selfcommunity/api-services'; import { FormattedMessage } from 'react-intl'; import { LoadingButton } from '@mui/lab'; import { useSnackbar } from 'notistack'; import { getUrlLesson } from '@selfcommunity/react-ui'; const classes = { root: `${PREFIX}-root`, containerRoot: `${PREFIX}-container-root`, navigation: `${PREFIX}-navigation`, navigationTitle: `${PREFIX}-navigation-title`, previewInfo: `${PREFIX}-preview-info`, button: `${PREFIX}-button` }; const Root = styled(Box, { name: PREFIX, slot: 'Root', overridesResolver: (_props, styles) => [styles.root] })(() => ({})); const Container = styled(Box, { name: PREFIX, slot: 'ContainerRoot', overridesResolver: (_props, styles) => styles.containerRoot, shouldForwardProp: (prop) => prop !== 'open' })(() => ({})); export default function Lesson(inProps) { var _a, _b, _c; // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { className = null, courseId, sectionId, lessonId, LessonAppbarProps = {}, LessonDrawerProps = {}, editMode = false, previewMode = false, onEditModeClose = null, onLessonChange = null, onActivePanelChange = null, onLessonStatusChange = null, lessonAction = null } = props, rest = __rest(props, ["className", "courseId", "sectionId", "lessonId", "LessonAppbarProps", "LessonDrawerProps", "editMode", "previewMode", "onEditModeClose", "onLessonChange", "onActivePanelChange", "onLessonStatusChange", "lessonAction"]); // HOOKS const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const [_lessonId, setLessonId] = useState(lessonId); const [_sectionId, setSectionId] = useState(sectionId); const { scLesson, setSCLesson } = useSCFetchLesson({ id: _lessonId, courseId, sectionId: _sectionId }); const { scCourse, refreshCourse } = useSCFetchCourse({ id: courseId, params: { view: editMode || previewMode ? CourseInfoViewType.EDIT : CourseInfoViewType.USER } }); const { enqueueSnackbar } = useSnackbar(); const scRoutingContext = useSCRouting(); // STATE const [activePanel, setActivePanel] = useState(lessonAction); const [settings, setSettings] = useState(null); const [updating, setUpdating] = useState(false); const [lessonContent, setLessonContent] = useState(''); const [lessonMedias, setLessonMedias] = useState((_a = scLesson === null || scLesson === void 0 ? void 0 : scLesson.medias) !== null && _a !== void 0 ? _a : []); const [loading, setLoading] = useState(false); const [completed, setCompleted] = useState(null); const availableLessons = useMemo(() => { if (!(scCourse === null || scCourse === void 0 ? void 0 : scCourse.sections)) return []; return scCourse.sections.flatMap((section) => section.lessons.map((lesson) => (Object.assign(Object.assign({}, lesson), { section })))); }, [scCourse]); const [currentLessonIndex, setCurrentLessonIndex] = useState(availableLessons.findIndex((lesson) => lesson.id === lessonId)); const isPrevDisabled = availableLessons.length === 0 || currentLessonIndex <= 0 || ((_b = availableLessons[currentLessonIndex - 1]) === null || _b === void 0 ? void 0 : _b.locked); const isNextDisabled = availableLessons.length === 0 || currentLessonIndex >= availableLessons.length - 1 || ((_c = availableLessons[currentLessonIndex + 1]) === null || _c === void 0 ? void 0 : _c.locked); const [openDialog, setOpenDialog] = useState(false); const isCourseAdmin = useMemo(() => scCourse && scCourse.join_status === SCCourseJoinStatusType.CREATOR, [scCourse]); //EFFECTS useEffect(() => { const index = availableLessons.findIndex((lesson) => lesson.id === lessonId); setCurrentLessonIndex(index); }, [lessonId, availableLessons]); useEffect(() => { if (scLesson) { setCompleted(scLesson.completion_status === SCCourseLessonCompletionStatusType.COMPLETED); } }, [scLesson]); // HANDLERS /** * Handles lesson settings change * @param newSettings */ const handleSettingsChange = (newSettings) => { setSettings(newSettings); }; const handleOpenDrawer = (panel) => { setActivePanel((prevPanel) => (prevPanel === panel ? null : panel)); onActivePanelChange && onActivePanelChange(panel); }; const handleCloseDrawer = () => { setActivePanel(null); onEditModeClose && onEditModeClose(); onActivePanelChange && onActivePanelChange(null); }; const handleLessonContentEdit = (html) => { setLessonContent(html); }; const handleLessonMediaEdit = (medias) => { setLessonMedias(medias); }; const handleChangeLesson = (l, s) => { setLessonId(l.id); setSectionId(s.id); onLessonChange && onLessonChange(l.id, s.id); }; /** * Handles Lesson Edit */ const handleLessonUpdate = () => { setUpdating(true); const mediaIds = lessonMedias.map((media) => media.id); const data = Object.assign(Object.assign({}, settings), { type: scLesson.type, name: scLesson.name, text: lessonContent, medias: mediaIds }); CourseService.updateCourseLesson(scCourse.id, sectionId, scLesson.id, data) .then((data) => { setUpdating(false); setSCLesson(data); enqueueSnackbar(_jsx(FormattedMessage, { id: "templates.lesson.save.success", defaultMessage: "templates.lesson.save.success" }), { variant: 'success', autoHideDuration: 3000 }); }) .catch((error) => { setUpdating(false); enqueueSnackbar(_jsx(FormattedMessage, { id: "templates.lesson.save.error", defaultMessage: "templates.lesson.save.error" }), { variant: 'error', autoHideDuration: 3000 }); console.log(error); }); }; /** * Handles prev lesson navigation */ const handlePrev = () => { if (isPrevDisabled) return; const newLessonIndex = currentLessonIndex - 1; const newLesson = availableLessons[newLessonIndex]; setCurrentLessonIndex(newLessonIndex); handleChangeLesson(newLesson, newLesson.section); }; /** * Handles next lesson navigation */ const handleNext = () => { if (isNextDisabled) return; const newLessonIndex = currentLessonIndex + 1; const newLesson = availableLessons[newLessonIndex]; setCurrentLessonIndex(newLessonIndex); handleChangeLesson(newLesson, newLesson.section); }; /** * Handles toggle lesson complete/uncompleted */ const toggleLessonCompletion = () => { setLoading(true); const service = completed ? () => CourseService.markLessonIncomplete(scLesson.course_id, scLesson.section_id, scLesson.id) : () => CourseService.markLessonComplete(scLesson.course_id, scLesson.section_id, scLesson.id); service() .then(() => { setCompleted(!completed); setLoading(false); refreshCourse(); if (!completed && scCourse.num_lessons === scCourse.num_lessons_completed + 1) { setOpenDialog(true); } onLessonStatusChange === null || onLessonStatusChange === void 0 ? void 0 : onLessonStatusChange(); }) .catch((error) => { setLoading(false); console.log(error); }); }; /** * Handles complete lesson dialog close */ const handleCloseDialog = useCallback(() => { setOpenDialog(false); }, [setOpenDialog]); /** * Rendering */ if (!scLesson || !scCourse) { return _jsx(HiddenPlaceholder, {}); } return (_jsxs(Fragment, { children: [_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: [_jsx(LessonAppbar, Object.assign({ showComments: scLesson.comments_enabled, editMode: editMode, activePanel: activePanel, title: scCourse.name, handleOpen: handleOpenDrawer, onSave: handleLessonUpdate, updating: updating }, LessonAppbarProps)), _jsxs(Container, Object.assign({ open: Boolean(activePanel) || editMode, className: classes.containerRoot }, { children: [previewMode && (_jsx(Alert, Object.assign({ severity: "info", className: classes.previewInfo }, { children: _jsx(Typography, Object.assign({ variant: "body1" }, { children: _jsx(FormattedMessage, { id: "templates.lesson.previewMode", defaultMessage: "templates.lesson.previewMode", values: { link: (...chunks) => (_jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.COURSE_LESSON_EDIT_ROUTE_NAME, getUrlLesson(scCourse, scLesson)) }, { children: chunks }))), linkBack: (...chunks) => _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.COURSE_DASHBOARD_ROUTE_NAME, scCourse) }, { children: chunks })) } }) })) }))), _jsx(Box, Object.assign({ className: classes.navigation }, { children: _jsx(Typography, Object.assign({ variant: "body2", color: "text.secondary" }, { children: _jsx(FormattedMessage, { id: "templates.lesson.number", defaultMessage: "templates.lesson.number", values: { from: currentLessonIndex + 1, to: availableLessons.length } }) })) })), _jsxs(Box, Object.assign({ className: classes.navigationTitle }, { children: [_jsx(Typography, Object.assign({ variant: "h5" }, { children: scLesson.name })), _jsxs(Box, { children: [_jsx(IconButton, Object.assign({ onClick: handlePrev, disabled: isPrevDisabled }, { children: _jsx(Icon, { children: "arrow_back" }) })), _jsx(IconButton, Object.assign({ onClick: handleNext, disabled: isNextDisabled }, { children: _jsx(Icon, { children: "arrow_next" }) }))] })] })), _jsx(LessonObject, { course: scCourse, lesson: scLesson, editMode: editMode, onContentChange: handleLessonContentEdit, onMediaChange: handleLessonMediaEdit }), !isCourseAdmin && !editMode && !previewMode && (_jsx(LoadingButton, Object.assign({ className: classes.button, loading: loading, size: "small", variant: completed ? 'outlined' : 'contained', startIcon: !completed && _jsx(Icon, { children: "arrow_next" }), endIcon: completed && _jsx(Icon, { children: "circle_checked" }), onClick: toggleLessonCompletion }, { children: completed ? (_jsx(FormattedMessage, { id: "templates.lesson.button.completed", defaultMessage: "templates.lesson.button.completed" })) : (_jsx(FormattedMessage, { id: "templates.lesson.button.complete", defaultMessage: "templates.lesson.button.complete" })) })))] })), _jsx(LessonDrawer, Object.assign({ course: scCourse, lesson: scLesson, editMode: isMobile ? activePanel === SCLessonActionsType.SETTINGS : editMode, previewMode: previewMode, activePanel: activePanel, handleClose: handleCloseDrawer, handleChangeLesson: handleChangeLesson, LessonEditFormProps: { lesson: scLesson, onSave: handleLessonUpdate, updating: updating, onSettingsChange: handleSettingsChange } }, LessonDrawerProps))] })), openDialog && _jsx(CourseCompletedDialog, { course: scCourse, onClose: handleCloseDialog })] })); }