Skip to content

Commit

Permalink
Portal frontend 25 (#30)
Browse files Browse the repository at this point in the history
* export results and args

* new js package

* add icon

* table components

* quick save

* extract id from body

* school name field

* ready for review

* only teachers

* fix rendering issue and create placeholder tabs

* merge from dev

* working order

* create sub view for leaving school

* merge from dev

* student dashboard

* Merge branch 'development' into portal-frontend-25

* new js package

* addressed feedback

* Merge branch 'development' into portal-frontend-25
  • Loading branch information
SKairinos authored Aug 13, 2024
1 parent c4d8ba1 commit a1baf2d
Show file tree
Hide file tree
Showing 10 changed files with 562 additions and 12 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"✅ Do add `devDependencies` below that are `peerDependencies` in the CFL package."
],
"dependencies": {
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.2.0",
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.2.1",
"crypto-js": "^4.2.0"
},
"devDependencies": {
Expand Down
55 changes: 55 additions & 0 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { type AnchorHTMLAttributes, type FC } from "react"
import {
Button,
type ButtonProps,
CardActions,
CardContent,
CardMedia,
type CardMediaProps,
Card as MuiCard,
type CardProps as MuiCardProps,
Typography,
} from "@mui/material"

export interface CardProps extends MuiCardProps {
title: string
description: string
mediaProps: {
image: NonNullable<CardMediaProps["image"]>
title: NonNullable<CardMediaProps["title"]>
}
buttonProps: ButtonProps & AnchorHTMLAttributes<HTMLAnchorElement>
}

const Card: FC<CardProps> = ({
title,
description,
mediaProps,
buttonProps,
style,
...otherCardProps
}) => {
return (
<MuiCard
style={{
display: "flex",
flexDirection: "column",
minHeight: "100%",
maxWidth: "400px",
...style,
}}
{...otherCardProps}
>
<CardMedia component="img" height={242} {...mediaProps} />
<CardContent sx={{ flexGrow: 1 }}>
<Typography variant="h5">{title}</Typography>
<Typography mb={0}>{description}</Typography>
</CardContent>
<CardActions>
<Button {...buttonProps} />
</CardActions>
</MuiCard>
)
}

export default Card
8 changes: 7 additions & 1 deletion src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import Card, { type CardProps } from "./Card"
import OpenInEmailButtons, {
type OpenInEmailButtonsProps,
} from "./OpenInEmailButtons"

export { OpenInEmailButtons, type OpenInEmailButtonsProps }
export {
OpenInEmailButtons,
type OpenInEmailButtonsProps,
Card,
type CardProps,
}
336 changes: 336 additions & 0 deletions src/images/RR_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/images/RR_logo_green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions src/pages/studentDashboard/Games.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Stack, Typography } from "@mui/material"
import { type FC } from "react"

import { Card } from "../../components"
import RRLogoGreenImage from "../../images/RR_logo_green.svg"
import { paths } from "../../router"

export interface GamesProps {
isStudent: boolean
}

const Games: FC<GamesProps> = ({ isStudent }) => {
return (
<Stack spacing={4} alignItems="center">
<Typography variant="h4" textAlign="center">
Your games
</Typography>
<Stack direction="row" gap={5}>
<Card
title="Rapid Router"
description="Rapid Router guides you, and makes learning to code easy and great fun. Using Blockly, you can advance through the levels to become an Ocado delivery hero."
mediaProps={{
title: "RapidRouter logo",
image: RRLogoGreenImage,
}}
buttonProps={{
children: "Play",
href: paths.rapidRouter._,
}}
/>
</Stack>
</Stack>
)
}

export default Games
56 changes: 56 additions & 0 deletions src/pages/studentDashboard/RapidRouterProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Stack, Typography } from "@mui/material"
import { ChevronRight as ChevronRightIcon } from "@mui/icons-material"
import { type FC } from "react"
import { Image } from "codeforlife/components"
import { LinkButton } from "codeforlife/components/router"

// import { useRetrieveUserQuery } from "../../api/rapidRouter"
import RRLogoImage from "../../images/RR_logo.svg"
import { paths } from "../../router"

const GetRapidRouterScores: React.FC = () => {
// TODO: get real data from rapid-router endpoint.
// useRetrieveUserQuery()
const stats = {
completed_level_count: 0,
top_score_count: 0,
total_score: 0,
total_available_score: 0,
}

return (
<>
<Typography variant="h4">
You have completed {stats.completed_level_count} Rapid Router levels!
</Typography>
<Typography variant="h4">
You have {stats.top_score_count} top scores!
</Typography>
<Typography variant="h4">
You have a score of {stats.total_score}. There are{" "}
{stats.total_available_score} available points.
</Typography>
</>
)
}

export interface RapidRouterProgressProps {}

const RapidRouterProgress: FC<RapidRouterProgressProps> = () => {
return (
<Stack alignItems="center" textAlign="center">
<Image alt={"RR_logo"} src={RRLogoImage} maxWidth="200px" />
<GetRapidRouterScores />
<LinkButton
style={{ marginTop: 20 }}
endIcon={<ChevronRightIcon />}
// TODO: link to rapid router microservice.
to={paths.rapidRouter.scoreboard._}
>
Check scoreboard
</LinkButton>
</Stack>
)
}

export default RapidRouterProgress
56 changes: 56 additions & 0 deletions src/pages/studentDashboard/StudentDashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as page from "codeforlife/components/page"
import { type SessionMetadata, useQueryManager } from "codeforlife/hooks"
import { type FC } from "react"
import { Link } from "codeforlife/components/router"

import Games from "./Games"
import RapidRouterProgress from "./RapidRouterProgress"
import { paths } from "../../router"
import { useRetrieveUserQuery } from "../../api/user"

export interface StudentDashboardProps {
userType: "student" | "indy"
}

const BaseDashboard: FC<SessionMetadata> = ({ user_id, user_type }) => {
const isStudent = user_type === "student"

return useQueryManager(useRetrieveUserQuery, user_id, user => {
return (
<>
<page.Banner
header={`Welcome, ${user.first_name}`}
subheader={"This is where you can access your games"}
textAlign="center"
bgcolor={isStudent ? "tertiary" : "secondary"}
/>
<page.Notification bgcolor={isStudent ? "tertiary" : "secondary"}>
{isStudent ? (
<>You are logged in to class: {user.student!.klass}</>
) : (
<>
You are logged in as an independent student. If you want to join a
school, you need to&nbsp;
<Link to={paths.indy.dashboard.joinClass._} color="inherit">
request to join one
</Link>
.
</>
)}
</page.Notification>
<page.Section>
<Games isStudent={isStudent} />
</page.Section>
<page.Section boxProps={{ bgcolor: "info.main" }}>
<RapidRouterProgress />
</page.Section>
</>
)
})
}

const StudentDashboard: FC<StudentDashboardProps> = ({ userType }) => (
<page.Page session={{ userType }}>{BaseDashboard}</page.Page>
)

export default StudentDashboard
18 changes: 11 additions & 7 deletions src/router/routes/student.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
// import { Route } from 'react-router-dom';
import { Route } from "react-router-dom"

// import Student from '../../pages/student/Student';
// import StudentDashboard from '../../pages/studentDashboard/StudentDashboard';
// import paths from '../paths';
import StudentDashboard from "../../pages/studentDashboard/StudentDashboard"
import paths from "../paths"

const student = (
<>
{/* <Route path={paths.student._} element={<Student />} /> */}
{/* <Route
path={`${paths.student.dashboard._}/:type/:view?`}
element={<StudentDashboard />}
/> */}
<Route
path={paths.student.dashboard._}
element={<StudentDashboard userType="student" />}
/>
<Route
path={paths.indy.dashboard._}
element={<StudentDashboard userType="indy" />}
/>
</>
)

Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2650,9 +2650,9 @@ clsx@^2.1.0, clsx@^2.1.1:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==

"codeforlife@github:ocadotechnology/codeforlife-package-javascript#v2.2.0":
version "2.2.0"
resolved "https://codeload.github.com/ocadotechnology/codeforlife-package-javascript/tar.gz/f90ad0fa5206c8d78fc103b140609c2290f52417"
"codeforlife@github:ocadotechnology/codeforlife-package-javascript#v2.2.1":
version "2.2.1"
resolved "https://codeload.github.com/ocadotechnology/codeforlife-package-javascript/tar.gz/a0857b6fbf2801a110412f227c23b787b66a4fb0"
dependencies:
"@emotion/react" "^11.10.6"
"@emotion/styled" "^11.10.6"
Expand Down

0 comments on commit a1baf2d

Please sign in to comment.