2025-08-05 12:35:40 +07:00

152 lines
5.1 KiB
TypeScript

'use client'
// React Imports
import { useState } from 'react'
import type { ChangeEvent, SyntheticEvent } from 'react'
// MUI Imports
import { styled } from '@mui/material/styles'
import MuiAccordion from '@mui/material/Accordion'
import MuiAccordionSummary from '@mui/material/AccordionSummary'
import MuiAccordionDetails from '@mui/material/AccordionDetails'
import Typography from '@mui/material/Typography'
import Checkbox from '@mui/material/Checkbox'
import ListItem from '@mui/material/ListItem'
import List from '@mui/material/List'
import ListItemIcon from '@mui/material/ListItemIcon'
import type { AccordionProps } from '@mui/material/Accordion'
import type { AccordionSummaryProps } from '@mui/material/AccordionSummary'
import type { AccordionDetailsProps } from '@mui/material/AccordionDetails'
// Type Imports
import type { CourseContent } from '@/types/apps/academyTypes'
type ItemsType = {
title: string
time: string
isCompleted: boolean
}[]
// Styled component for Accordion component
export const Accordion = styled(MuiAccordion)<AccordionProps>({
margin: '0 !important',
boxShadow: 'none !important',
border: '1px solid var(--mui-palette-divider) !important',
borderRadius: '0 !important',
overflow: 'hidden',
background: 'none',
'&:not(:last-of-type)': {
borderBottom: '0 !important'
},
'&:before': {
display: 'none'
},
'&:first-of-type': {
borderTopLeftRadius: 'var(--mui-shape-borderRadius) !important',
borderTopRightRadius: 'var(--mui-shape-borderRadius) !important'
},
'&:last-of-type': {
borderBottomLeftRadius: 'var(--mui-shape-borderRadius) !important',
borderBottomRightRadius: 'var(--mui-shape-borderRadius) !important'
}
})
// Styled component for AccordionSummary component
export const AccordionSummary = styled(MuiAccordionSummary)<AccordionSummaryProps>(({ theme }) => ({
padding: theme.spacing(3, 6),
transition: 'none',
backgroundColor: 'var(--mui-palette-action-hover)',
borderBlockEnd: '0 !important',
'&.Mui-expanded': {
borderBlockEnd: '1px solid var(--mui-palette-divider) !important'
}
}))
// Styled component for AccordionDetails component
export const AccordionDetails = styled(MuiAccordionDetails)<AccordionDetailsProps>(({ theme }) => ({
padding: `${theme.spacing(4, 3)} !important`,
backgroundColor: 'var(--mui-palette-background-paper)'
}))
const Sidebar = ({ content }: { content?: CourseContent[] }) => {
// States
const [expanded, setExpanded] = useState<number | false>(0)
const [items, setItems] = useState<ItemsType[]>(content?.map(item => item.topics) ?? [])
const handleChange = (panel: number) => (event: SyntheticEvent, isExpanded: boolean) => {
setExpanded(isExpanded ? panel : false)
}
const handleCheckboxChange = (e: ChangeEvent<HTMLInputElement>, index1: number, index2: number) => {
setItems(
items.map((item, i) => {
if (i === index1) {
return item.map((topic, j) => {
if (j === index2) {
return { ...topic, isCompleted: e.target.checked }
}
return topic
})
}
return item
})
)
}
return (
<>
{content?.map((item, index) => {
const totalTime = items[index]
.reduce((sum, topic) => {
const time = parseFloat(topic.time || '0')
return sum + time
}, 0)
.toFixed(2)
const selectedTopics = items[index].filter(topic => topic.isCompleted).length
return (
<Accordion key={index} expanded={expanded === index} onChange={handleChange(index)}>
<AccordionSummary
id='customized-panel-header-1'
expandIcon={<i className='tabler-chevron-right text-textSecondary' />}
aria-controls={'sd'}
>
<div>
<Typography variant='h5'>{item.title}</Typography>
<Typography className='!font-normal !text-textSecondary'>{`${selectedTopics} / ${item.topics.length} | ${parseFloat(totalTime)} min`}</Typography>
</div>
</AccordionSummary>
<AccordionDetails>
<List role='list' component='div' className='flex flex-col gap-4 plb-0'>
{item.topics.map((topic, i) => {
return (
<ListItem key={i} role='listitem' className='gap-3 p-0'>
<ListItemIcon>
<Checkbox
tabIndex={-1}
checked={items[index][i].isCompleted}
onChange={e => handleCheckboxChange(e, index, i)}
/>
</ListItemIcon>
<div>
<Typography className='font-medium !text-textPrimary'>{`${i + 1}. ${topic.title}`}</Typography>
<Typography variant='body2'>{topic.time}</Typography>
</div>
</ListItem>
)
})}
</List>
</AccordionDetails>
</Accordion>
)
})}
</>
)
}
export default Sidebar