146 lines
4.0 KiB
TypeScript
146 lines
4.0 KiB
TypeScript
import { Box, Table, Text } from '@mantine/core'
|
|
import { IconCornerDownRight } from '@tabler/icons-react'
|
|
import { useState } from 'react'
|
|
import classes from './ProjectInvolvement.module.css'
|
|
|
|
interface Project {
|
|
name: string
|
|
sprints: Sprint[]
|
|
}
|
|
|
|
interface Sprint {
|
|
name: string
|
|
criterias: TableRow[]
|
|
}
|
|
|
|
interface TableRow {
|
|
criteria: string
|
|
note: string
|
|
createdBy: string
|
|
point: number
|
|
}
|
|
|
|
interface ExpandedProjects {
|
|
[projectName: string]: boolean
|
|
}
|
|
|
|
interface ExpandedSprints {
|
|
[projectName: string]: {
|
|
[sprintName: string]: boolean
|
|
}
|
|
}
|
|
|
|
interface ProjectInvolvementProps {
|
|
dataProfile: Project[]
|
|
page: string
|
|
}
|
|
|
|
type CriteriaTableProps = {
|
|
data: TableRow[]
|
|
page: string
|
|
}
|
|
|
|
const CriteriaTable: React.FC<CriteriaTableProps> = ({ data, page }) => (
|
|
<Table striped highlightOnHover withTableBorder withColumnBorders>
|
|
<Table.Thead>
|
|
<Table.Tr bg="#228be66b">
|
|
<Table.Th style={{ textAlign: 'center', width: '25%' }}>
|
|
Criteria
|
|
</Table.Th>
|
|
<Table.Th style={{ textAlign: 'center', width: '45%' }}>Note</Table.Th>
|
|
<Table.Th style={{ textAlign: 'center', width: '20%' }}>
|
|
Created by
|
|
</Table.Th>
|
|
{page == 'profile' ? (
|
|
''
|
|
) : (
|
|
<Table.Th style={{ textAlign: 'center', width: '10%' }}>
|
|
Point
|
|
</Table.Th>
|
|
)}
|
|
</Table.Tr>
|
|
</Table.Thead>
|
|
<Table.Tbody>
|
|
{data.map((row, index) => (
|
|
<Table.Tr key={index}>
|
|
<Table.Td style={{ textAlign: 'start' }}>{row.criteria}</Table.Td>
|
|
<Table.Td style={{ textAlign: 'start' }}>{row.note}</Table.Td>
|
|
<Table.Td style={{ textAlign: 'start' }}>{row.createdBy}</Table.Td>
|
|
{page == 'profile' ? (
|
|
''
|
|
) : (
|
|
<Table.Td>{row.point == 0 ? '' : row.point}</Table.Td>
|
|
)}
|
|
</Table.Tr>
|
|
))}
|
|
</Table.Tbody>
|
|
</Table>
|
|
)
|
|
|
|
const ProjectInvolvement = ({ dataProfile, page }: ProjectInvolvementProps) => {
|
|
const [expandedProjects, setExpandedProjects] = useState<ExpandedProjects>({})
|
|
const [expandedSprints, setExpandedSprints] = useState<ExpandedSprints>({})
|
|
|
|
const handleProjectToggle = (projectName: string) => {
|
|
setExpandedProjects((prev) => ({
|
|
...prev,
|
|
[projectName]: !prev[projectName], // Toggle state for this project
|
|
}))
|
|
}
|
|
|
|
const handleSprintToggle = (projectName: string, sprintName: string) => {
|
|
setExpandedSprints((prev) => ({
|
|
...prev,
|
|
[projectName]: {
|
|
...prev[projectName],
|
|
[sprintName]: !prev[projectName]?.[sprintName], // Toggle state for this sprint
|
|
},
|
|
}))
|
|
}
|
|
|
|
return (
|
|
<Box className={classes.project} mt="lg">
|
|
{dataProfile.map((project) => (
|
|
<div key={project.name}>
|
|
<Box
|
|
className={classes.projectHeader}
|
|
onClick={() => handleProjectToggle(project.name)}
|
|
>
|
|
<Text ml="sm" fw={600}>
|
|
{project.name}
|
|
</Text>
|
|
</Box>
|
|
|
|
{expandedProjects[project.name] && (
|
|
<Box className={classes.sprintList}>
|
|
{project.sprints.map((sprint) => (
|
|
<div key={sprint.name}>
|
|
<Box
|
|
className={classes.sprintHeader}
|
|
onClick={() =>
|
|
handleSprintToggle(project.name, sprint.name)
|
|
}
|
|
>
|
|
<IconCornerDownRight size={20} />
|
|
<Text ml="xs" className={classes.sprintHeader2} fw={600}>
|
|
{sprint.name}
|
|
</Text>
|
|
</Box>
|
|
|
|
{expandedSprints[project.name]?.[sprint.name] && (
|
|
<Box className={classes.criteriaTable}>
|
|
<CriteriaTable data={sprint.criterias} page={page} />
|
|
</Box>
|
|
)}
|
|
</div>
|
|
))}
|
|
</Box>
|
|
)}
|
|
</div>
|
|
))}
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
export default ProjectInvolvement
|