Commit 124b8d76 authored by janithgamage1.ed's avatar janithgamage1.ed

fix: update

Desc : update project
parent c5533a40
......@@ -70,7 +70,10 @@ const Tutorial = () => {
})
useEffect(() => {
setData(userProgress.curriculums![0].tutorials[0]);
const firstTutorial = userProgress?.curriculums?.[0]?.tutorials?.[0];
if (firstTutorial) {
setData(firstTutorial);
}
}, []);
const handleItemClick = (item: selectedCommonDataProps, backgroundColor: any) => {
......@@ -97,7 +100,7 @@ const Tutorial = () => {
useEffect(() => {
// Filter data based on selectedItem.title
if (selectedItem && data) {
const filteredItem = data.taskItems.find((item) => item.title === selectedItem.selectedCommonData?.title);
const filteredItem = data?.taskItems!.find((item) => item.title === selectedItem.selectedCommonData?.title);
setSelectedItemContent({
userId: selectedItem.selectedCommonData?.userId!,
curriculumCode: selectedItem.selectedCommonData?.curriculumCode!,
......@@ -373,7 +376,7 @@ const Tutorial = () => {
}
}}
>
{data?.taskItems.map((item, index) => {
{data?.taskItems?.map((item, index) => {
const isSelected = selectedItem.selectedCommonData?.title === item.title;
const backgroundColor = isSelected ? theme.palette.primary.lighter : 'white';
const iconColor = isSelected ? 'warning' : 'success';
......@@ -503,7 +506,7 @@ const Tutorial = () => {
</Grid>
<Grid item md={12}>
<ReportCard
primary={`Pass Mark : ${(selectedItemContent.taskItemMark * (85 / 100))?.toLocaleString('en-US', {
primary={`Pass Mark : ${(selectedItemContent?.taskItemMark! * (85 / 100))?.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`}
......
......@@ -53,10 +53,10 @@ const CurriculumSection = ({ curriculum }: { curriculum: curriculumTypeUserProgr
Your learning capacity is 80% as daily analytics
</Typography>
<Typography variant="h4" color="white" sx={{ pt: 8, pb: 1, zIndex: 1 }}>
{(curriculum.curriculumMarkUser / curriculum.curriculumMark) * 100}% Completed
{(curriculum?.curriculumMarkUser! / curriculum?.curriculumMark!) * 100}% Completed
</Typography>
<Box sx={{ maxWidth: '60%' }}>
<LinearProgress variant="determinate" color="success" value={(curriculum.curriculumMarkUser / curriculum.curriculumMark) * 100} />
<LinearProgress variant="determinate" color="success" value={(curriculum?.curriculumMarkUser! / curriculum?.curriculumMark!) * 100} />
</Box>
<Box
sx={{
......@@ -84,7 +84,7 @@ const CurriculumSection = ({ curriculum }: { curriculum: curriculumTypeUserProgr
</MainCard>
<MainCard title="Tutorials">
<Grid container spacing={2}>
{curriculum.tutorials.map((tutorial, index) => {
{curriculum.tutorials?.map((tutorial, index) => {
return (<TutorialSection tutorial={tutorial!} />)
})}
</Grid>
......
import { useState } from 'react';
import { useNavigate } from 'react-router';
import { useEffect, useState } from 'react';
// material-ui
import {
Box,
Button,
CircularProgress,
Grid,
Typography
} from '@mui/material';
......@@ -17,6 +17,10 @@ import MainCard from 'components/MainCard';
// assets
import { PlusOutlined, SendOutlined } from '@ant-design/icons';
import AnimateButton from 'components/@extended/AnimateButton';
import useAuth from 'hooks/useAuth';
import { useDispatch, useSelector } from 'store';
import { openSnackbar } from 'store/reducers/snackbar';
import { addUserProgress, toInitialState } from 'store/reducers/userProgress';
import { curriculumType } from 'types/curriculum';
import Animation from './Animation';
import CurriculumPreview from './CurriculumPreview';
......@@ -26,7 +30,9 @@ import CurriculumPreview from './CurriculumPreview';
// ==============================|| CURRICULUM - CARD ||============================== //
const CurriculumCard = ({ curriculum }: { curriculum: curriculumType }) => {
const navigate = useNavigate()
let dispatch = useDispatch()
const { error, success, isLoading } = useSelector(state => state.userProgress);
const { user } = useAuth();
const [open, setOpen] = useState(false);
......@@ -41,6 +47,96 @@ const CurriculumCard = ({ curriculum }: { curriculum: curriculumType }) => {
const [desc, setDesc] = useState(curriculum.curriculumDescription?.slice(0, 100))
const [readMore, setReadMore] = useState(false)
/**
* API Config
* User Progress API
*/
const FollowCurriculum = () => {
console.log(user);
if (!user) {
// User is missing
dispatch(
openSnackbar({
open: true,
message: 'User data is missing',
variant: 'alert',
alert: {
color: 'warning',
},
close: true,
})
);
} else if (!user.id) {
// User ID is missing
dispatch(
openSnackbar({
open: true,
message: 'User ID is missing',
variant: 'alert',
alert: {
color: 'warning',
},
close: true,
})
);
} else if (!curriculum) {
// Curriculum data is missing
dispatch(
openSnackbar({
open: true,
message: 'Curriculum data is missing',
variant: 'alert',
alert: {
color: 'warning',
},
close: true,
})
);
} else {
// All required data is present, dispatch addUserProgress
dispatch(addUserProgress(user.id, curriculum));
}
}
// handel error
useEffect(() => {
if (error != null) {
dispatch(
openSnackbar({
open: true,
//@ts-ignore
message: error ? error.Message : "Something went wrong ...",
variant: 'alert',
alert: {
color: 'error'
},
close: true
})
);
dispatch(toInitialState())
}
}, [error])
// handel success
useEffect(() => {
if (success != null) {
dispatch(
openSnackbar({
open: true,
message: success,
variant: 'alert',
alert: {
color: 'success'
},
close: true
})
);
dispatch(toInitialState())
}
}, [success])
return (
<>
<Animation
......@@ -81,10 +177,11 @@ const CurriculumCard = ({ curriculum }: { curriculum: curriculumType }) => {
variant="outlined"
endIcon={<PlusOutlined />}
sx={{ my: 2, width: "100%" }}
onClick={() => { navigate(`/learning-management/curriculums-subscribed`) }}
onClick={FollowCurriculum}
color='success'
disabled={isLoading}
>
Follow Curriculum
{isLoading ? <CircularProgress /> : 'Follow Curriculum'}
</Button>
</AnimateButton>
</Box>
......
......@@ -19,6 +19,7 @@ import snackbar from './snackbar';
import subscription from './subscription';
import tutorial from './tutorial';
import user from './user';
import userProgress from './userProgress';
// ==============================|| COMBINE REDUCERS ||============================== //
......@@ -44,7 +45,8 @@ const reducers = combineReducers({
marksCalculator,
tutorial,
curriculum,
user
user,
userProgress
});
export default reducers;
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import { axiosServices } from 'utils/axios';
import { dispatch } from '../index';
// types
import { DefaultRootStateProps, curriculumTypeUserProgress } from 'types/userProgress';
// ----------------------------------------------------------------------
const initialState: DefaultRootStateProps['userProgress'] = {
error: null,
success: null,
userProgresses: [],
userProgress: null,
isLoading: false
};
const slice = createSlice({
name: 'userProgress',
initialState,
reducers: {
// TO INITIAL STATE
hasInitialState(state) {
state.error = null;
state.success = null;
state.isLoading = false;
},
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
startLoading(state) {
state.isLoading = true;
},
finishLoading(state) {
state.isLoading = false;
},
// POST USER_PROGRESS
addUpdateUserProgressSuccess(state, action) {
// state.userProgresses.push(action.payload);
state.success = "User Progress created or updated successfully."
},
// GET USER_PROGRESS
fetchUserProgressSuccess(state, action) {
state.userProgress = action.payload;
state.success = null
},
// UPDATE USER_PROGRESS
updateUserProgressSuccess(state, action) {
// const updatedUserProgressIndex = state.userProgresses.findIndex(userProgress => userProgress._id === action.payload._id);
// if (updatedUserProgressIndex !== -1) {
// state.userProgresses[updatedUserProgressIndex] = action.payload;
// }
state.success = "UserProgress updated successfully."
},
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
/**
* TO INITIAL STATE
* @returns
*/
export function toInitialState() {
return async () => {
dispatch(slice.actions.hasInitialState())
}
}
/**
* POST USER_PROGRESS
* @param newUserProgress
* @returns
*/
export function addUserProgress(userId: string, curriculum: curriculumTypeUserProgress) {
return async () => {
dispatch(slice.actions.startLoading());
try {
const response = await axiosServices.post('/rest_node/user-progress/subscribe-curriculum', { userId, curriculum });
dispatch(slice.actions.addUpdateUserProgressSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
} finally {
dispatch(slice.actions.finishLoading());
}
};
}
/**
* GET USER_PROGRESS
* @param userId
* @returns
*/
export function fetchUserProgress(userId: string) {
return async () => {
dispatch(slice.actions.startLoading());
try {
const response = await axiosServices.get(`/rest_node/user-progress/${userId}`);
dispatch(slice.actions.fetchUserProgressSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
} finally {
dispatch(slice.actions.finishLoading());
}
};
}
/**
* UPDATE USER_PROGRESS
* @param updatedUserProgress
* @returns
*/
export function updateUserProgress(userId: string, curriculumCode: string, tutorialCode: string, taskItemTitle: string, taskItemMarkUser: string, taskItemSpentTime: string) {
return async () => {
dispatch(slice.actions.startLoading());
try {
const response = await axiosServices.put(`/rest_node/user-progress/update-task-item-progress`, { userId, curriculumCode, tutorialCode, taskItemTitle, taskItemMarkUser, taskItemSpentTime });
dispatch(slice.actions.updateUserProgressSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
} finally {
dispatch(slice.actions.finishLoading());
}
};
}
......@@ -3,15 +3,15 @@ import { tutorialType } from "./tutorial"
export interface curriculumType {
_id?: string
curriculumCode: string
curriculumLevel: number
curriculumTitle: string
curriculumDescription: string
curriculumImage: string
curriculumMark: number
tutorials: tutorialType[],
status: number
createdBy: string
createdAt: Date
curriculumLevel?: number
curriculumTitle?: string
curriculumDescription?: string
curriculumImage?: string
curriculumMark?: number
tutorials?: tutorialType[],
status?: number
createdBy?: string
createdAt?: Date
updatedBy?: string
updatedAt?: Date
}
......
export interface taskItemType {
_id?: string
title: string,
description: string,
howToDo: string[],
referenceImage: string,
referenceVideo: string,
taskItemMark: number
description?: string,
howToDo?: string[],
referenceImage?: string,
referenceVideo?: string,
taskItemMark?: number
}
\ No newline at end of file
......@@ -2,15 +2,15 @@ import { taskItemType } from "./taskItem"
export interface tutorialType {
_id?: string
tutorialCode?: string
tutorialCode: string
tutorialTitle?: string
tutorialDescription?: string
tutorialImage?: string
tutorialMark: number
taskItems: taskItemType[]
status: number
createdBy: string
createdAt: Date
tutorialMark?: number
taskItems?: taskItemType[]
status?: number
createdBy?: string
createdAt?: Date
updatedBy?: string
updatedAt?: Date
}
......
......@@ -14,34 +14,72 @@ export interface userProgressType {
export interface curriculumTypeUserProgress {
curriculumCode: string
curriculumLevel: number
curriculumTitle: string
curriculumDescription: string
curriculumImage: string
curriculumMark: number
curriculumMarkUser: number
curriculumSpentTime: number
tutorials: tutorialTypeUserProgress[],
curriculumLevel?: number
curriculumTitle?: string
curriculumDescription?: string
curriculumImage?: string
curriculumMark?: number
curriculumMarkUser?: number
curriculumSpentTime?: number
tutorials?: tutorialTypeUserProgress[],
}
export interface tutorialTypeUserProgress {
tutorialCode?: string
tutorialCode: string
tutorialTitle?: string
tutorialDescription?: string
tutorialImage?: string
tutorialMark: number
tutorialMarkUser: number
tutorialSpentTime: number
taskItems: taskItemTypeUserProgress[]
tutorialMark?: number
tutorialMarkUser?: number
tutorialSpentTime?: number
taskItems?: taskItemTypeUserProgress[]
}
export interface taskItemTypeUserProgress {
title: string,
description: string,
howToDo: string[],
referenceImage: string,
referenceVideo: string,
taskItemMark: number
taskItemMarkUser: number
taskItemSpentTime: number
description?: string,
howToDo?: string[],
referenceImage?: string,
referenceVideo?: string,
taskItemMark?: number
taskItemMarkUser?: number
taskItemSpentTime?: number
}
export type UserProgress = {
_id: string
userId: string
curriculums?: curriculumTypeUserProgress[]
totalCurriculumsMarks: number
totalCurriculumSpentTime: number
status: number
createdBy?: string
createdAt: Date
updatedBy?: string
updatedAt?: Date
};
export type UserProgresses = {
_id?: string
userId: string
curriculums?: curriculumTypeUserProgress[]
totalCurriculumsMarks: number
totalCurriculumSpentTime: number
status: number
createdBy?: string
createdAt: Date
updatedBy?: string
updatedAt?: Date
};
export interface UserProgressStateProps {
userProgresses: UserProgresses[];
userProgress: UserProgress | null;
error: object | string | null;
success: object | string | null;
isLoading: boolean
}
export interface DefaultRootStateProps {
userProgress: UserProgressStateProps;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment