Skip to content

Commit

Permalink
Add component with project stats
Browse files Browse the repository at this point in the history
  • Loading branch information
anarute committed Jan 18, 2024
1 parent b9da1fb commit 11d7a45
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 11 deletions.
108 changes: 108 additions & 0 deletions frontend/src/app/planner/[slug]/components/ProjectHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import Box from '@mui/joy/Box'
import Chip from '@mui/joy/Chip'

import Grid from '@mui/joy/Grid'
import Typography from '@mui/joy/Typography'
import { Project, ProjectStats } from '@/domain/Project'

type ProjectHeaderProps = {
project: Project
projectStats: ProjectStats
}

export const ProjectHeader = ({ project, projectStats }: ProjectHeaderProps) => {
return (
<Box
sx={{
textAlign: 'center',
padding: '2rem',
borderBottom: '1px solid #ebebeb',
borderTop: '1px solid #ebebeb',
backgroundColor: '#f7f7f7'
}}
>
<Typography
level="h1"
sx={{
textAlign: 'left',
marginBottom: '1rem'
}}
>
{project.description}
<Chip sx={{ ml: 1 }} color={project.isActive ? 'success' : 'danger'}>
{project.isActive ? 'Active' : 'Inactive'}
</Chip>
</Typography>
<Grid
container
spacing={2}
sx={{
flexGrow: 1
}}
>
<Grid
xs={4}
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
alignItems: 'center'
}}
>
<Typography
fontSize="xl4"
lineHeight={1}
endDecorator={
<Typography fontSize="lg" textColor="text.secondary">
h
</Typography>
}
>
{Number(projectStats.loggedHours)}/{Number(projectStats.plannedHours)}
</Typography>
<Typography>Actuals vs Planned</Typography>
</Grid>
<Grid
xs={4}
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Typography
fontSize="xl4"
lineHeight={1}
endDecorator={
<Typography fontSize="lg" textColor="text.secondary">
h
</Typography>
}
sx={{ alignItems: 'flex-start' }}
>
{Number(projectStats.plannedHours)}/{Number(project.estimatedHours)}
</Typography>
<Typography>Planned vs Sold</Typography>
</Grid>
<Grid
xs={4}
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Typography fontSize="xl4" lineHeight={1} sx={{ alignItems: 'flex-start' }}>
{Number(projectStats.avgFTE)}
</Typography>
<Typography>
Average <abbr title="full-time equivalent">FTE</abbr>s
</Typography>
</Grid>
</Grid>
</Box>
)
}
28 changes: 18 additions & 10 deletions frontend/src/app/planner/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { Breadcrumbs, Chip, Typography } from '@mui/joy'
import Link from 'next/link'

import { getProjectAllocation } from '@/infra/projectAllocation/getProjectAllocation'
import { getProjects } from '@/infra/project/getProjects'
import { Breadcrumbs, Chip, Link, Typography } from '@mui/joy'

import { makeGetProject } from '@/infra/project/getProject'
import { serverFetch } from '@/infra/lib/serverFetch'
import { Planner } from './components/Planner'
import { makeGetProjectStats } from '@/infra/project/getProjectStats'

const getPageData = async (id: string) => {
const apiClient = await serverFetch()
return await Promise.all([getProjectAllocation(apiClient, id), getProjects(apiClient)])
const getProject = makeGetProject(apiClient)
const getProjectStats = makeGetProjectStats(apiClient)
return await Promise.all([getProject(id), getProjectStats(id)])
}

export default async function Page({ params }: { params: { slug: string } }) {
const [projectAllocations, projects] = await getPageData(params.slug)

const project = projects.find((p) => p.id === Number(params.slug))
const projectStats = { plannedHours: projectAllocations?.plannedHours }
const [project, projectStats] = await getPageData(params.slug)

return (
<>
Expand All @@ -31,6 +29,16 @@ export default async function Page({ params }: { params: { slug: string } }) {
</Typography>
<Typography>Resource Planner</Typography>
</Breadcrumbs>
{project ? (
<Planner projectMetada={project} projectStats={projectStats} />
) : (
<div>
<p>Project not found.</p>
<Link href="/planner" underline="always">
Please select a Project.
</Link>
</div>
)}
</>
)
}
6 changes: 6 additions & 0 deletions frontend/src/domain/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ export type Project = {
projectType: string | null
scheduleType: string | null
}

export type ProjectStats = {
loggedHours: number
plannedHours: number
avgFTE: number
}
3 changes: 2 additions & 1 deletion frontend/src/infra/project/getProjectStats.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { format } from 'date-fns'
import { ApiClient } from '@/infra/lib/apiClient'
import { ProjectStats } from '@/domain/Project'

export const makeGetProjectStats =
(apiClient: ApiClient) =>
async (projectId: string): Promise<any> => {
async (projectId: string): Promise<ProjectStats> => {
const today = new Date()
// TODO start getting the date range dynamically
const firstDayOfYear = new Date(today.getFullYear(), 0, 1)
Expand Down

0 comments on commit 11d7a45

Please sign in to comment.