Skip to content

Commit

Permalink
Add Projects
Browse files Browse the repository at this point in the history
- implement Project component
  and use it on the main page (ProjectList) and the things page
  • Loading branch information
honzaflash committed Oct 14, 2023
1 parent 7032432 commit f1b9887
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/components/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { mergeSxProps } from '../utils'


export type SectionProps = {
title: string
title?: string
} & StackProps

export const Section = ({title, children, sx, ...rest}: SectionProps) => (
<Stack spacing={2} sx={mergeSxProps({ mt: 6 }, sx)} {...rest}>
<Typography variant="h5">{title}</Typography>
{title && <Typography variant="h5">{title}</Typography>}
{children}
</Stack>
)
87 changes: 87 additions & 0 deletions src/configs/projects.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"Pie-Hub": {
"relevancy": [
"fe",
"be"
],
"date": {
"start": 2021
},
"tech": [
"Raspberry Pi 4",
"General Purpose I/O",
"I2C",
"Python",
"Bash",
"UNIX services",
"Node.js",
"TypeScript"
],
"summary": "React app with back end running on a Raspberry Pi. Shows useful information in one place including: room temperature and humidity, task list from Notion, and time.",
"description": [
"React app hosted on a single-board computer (RPi) along with a RESTful API written with Express.js",
"Wrote a proxy service for Notion (the app then displays a task list)",
"Connected an indoor temperature and humidity sensor",
"Wired up a relay board to control appliances through software"
]
},
"Rychly Portfolio": {
"tech": [
"React"
],
"date": {
"start": 2023,
"ongoing": true
},
"summary": "Responsive React app that shows off who I am as a professional and a bit more.",
"description": [
"The 'Fast' Portfolio ([What does Rychly mean?](https://translate.google.com/details?sl=cs&tl=en&text=rychl%C3%BD&op=translate))",
"Responsive design, uses Material UI and React Router",
"Content can be easily updated through YAML configuration files",
"Main page filters content based on the selected type of developer"
]
},
"Game Development in Haskell": {
"relevancy": [
"fe",
"be"
],
"date": {
"finish": "May 2021"
},
"tech": [
"Haskell",
"apecs (Entity Component System)"
],
"summary": "Bachelor's thesis exploring the limits of functional programming when used in realtime applications, specifically games.",
"description": [
"Bachelor's thesis exploring the limits of functional programming when used in realtime applications, specifically games."
]
},
"pure-asteroids": {
"date": {
"finish": "Apr 2021"
},
"tech": [
"Haskell",
"SDL2"
],
"summary": "An atempt at a purely functional game engine focusing on type safety and clarity.",
"description": [
"An atempt at a purely functional game engine focusing on type safety and clarity."
]
},
"hAsteroids": {
"date": {
"finish": "Apr 2021"
},
"tech": [
"Haskell",
"SDL2"
],
"summary": "Game in Haskell built using the apecs library.",
"description": [
"Game in Haskell built using the apecs library."
]
}
}
64 changes: 64 additions & 0 deletions src/configs/projects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Pie-Hub:
relevancy: [fe, be]
date:
start: 2021
tech:
- Raspberry Pi 4
- General Purpose I/O
- I2C
- Python
- Bash
- UNIX services
- Node.js
- TypeScript
summary: "React app with back end running on a Raspberry Pi. Shows useful information in one place including: room temperature and humidity, task list from Notion, and time."
description:
- React app hosted on a single-board computer (RPi) along with a RESTful API written with Express.js
- Wrote a proxy service for Notion (the app then displays a task list)
- Connected an indoor temperature and humidity sensor
- Wired up a relay board to control appliances through software


Rychly Portfolio:
tech:
- React
date:
start: 2023
ongoing: true
summary: Responsive React app that shows off who I am as a professional and a bit more.
description:
- The 'Fast' Portfolio ([What does Rychly mean?](https://translate.google.com/details?sl=cs&tl=en&text=rychl%C3%BD&op=translate))
- Responsive design, uses Material UI and React Router
- Content can be easily updated through YAML configuration files
- Main page filters content based on the selected type of developer

Game Development in Haskell:
relevancy: [fe, be]
date:
finish: May 2021
tech:
- Haskell
- apecs (Entity Component System)
summary: Bachelor's thesis exploring the limits of functional programming when used in realtime applications, specifically games.
description:
- Bachelor's thesis exploring the limits of functional programming when used in realtime applications, specifically games.

pure-asteroids:
date:
finish: Apr 2021
tech:
- Haskell
- SDL2
summary: An atempt at a purely functional game engine focusing on type safety and clarity.
description:
- An atempt at a purely functional game engine focusing on type safety and clarity.

hAsteroids:
date:
finish: Apr 2021
tech:
- Haskell
- SDL2
summary: Game in Haskell built using the apecs library.
description:
- Game in Haskell built using the apecs library.
3 changes: 2 additions & 1 deletion src/pages/LandingPage/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FilterSelector } from './FilterSelector'
import { ExperienceList } from './ExperienceList'
import { EducationList } from './EducationList'
import { Todo } from '../../components/Todo'
import { ProjectList } from './ProjectList'

export const LandingPage = () => (
<Grid container spacing={2} >
Expand Down Expand Up @@ -45,7 +46,7 @@ export const LandingPage = () => (
<EducationList />
</Grid>
<Grid item xs={12} md={12}>
<Todo name="Projects" />
<ProjectList />
</Grid>
</Grid>
)
4 changes: 1 addition & 3 deletions src/pages/LandingPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
import { LandingPage } from './LandingPage'

export { LandingPage }
export { LandingPage } from './LandingPage'
39 changes: 39 additions & 0 deletions src/pages/Things/Project.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Card, CardProps, Typography } from '@mui/material'
import { ListFromMd } from '../../components/ListFromMd'
import _ from 'lodash'
import { SpanFromMd } from '../../components/SpanFromMd'


// TODO flag for projects that are displayed on the landing page vs only on the things page
type ProjectDetails = {
name: string
summary: string
description: string[]
tech: string[]
date: {
start?: string | number
finish?: string | number
ongoing?: boolean
}
}

type ProjectProps = {
details: ProjectDetails
summary?: boolean
} & CardProps

export const Project = ({ details, summary, ...props }: ProjectProps) => (
<Card {...props}>
<Typography variant="h5">{details.name}</Typography>
<Typography variant="overline">
{[
details.date.start,
details.date.ongoing ? 'Ongoing' : details.date.finish,
].filter(_.identity).join('–')}
</Typography>
{summary
? <Typography><SpanFromMd markdown={details.summary} /></Typography>
: <ListFromMd items={details.description} />
}
</Card>
)
43 changes: 34 additions & 9 deletions src/pages/Things/Things.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
import { Box, Typography } from '@mui/material'
import { Todo } from '../../components/Todo'
import rawProjects from '../../configs/projects.json'
import { unKeyBy } from '../../utils'
import { useMemo } from 'react'
import { Project } from './Project'
import { Section } from '../../components/Section'


export const Things = () => (
<Box>
<Typography>I like people. They are what matters.</Typography>
<Typography>But as an engineer I like <em>things</em> even more. Designing them. Making them.</Typography>
<Typography>Here are some of my favorite things I have made, including software and hardware.</Typography>
<Todo name="My projects in details" />
</Box>
)
export const getProjects = () => unKeyBy(rawProjects, 'name')

export const Things = () => {
const projects = useMemo(getProjects, [])

return (
<Box>
<Typography variant="body1">I like people. They are what matters.</Typography>
<Typography variant="h4">
But as an engineer I like<br/>
<Typography
variant="h1"
color="primary"
sx={{ fontWeight: 700 }}
component="span"
>
Things
</Typography>
<br/>even more
</Typography>
<Typography variant="body1" sx={{ mt: 3 }}>
I enjoy designing them, making them, and improving them.
</Typography>
<Typography>Here are some of my favorites that I have made, including software and hardware.</Typography>
<Section>
{projects.map((project, i) => <Project details={project} key={i} />)}
</Section>
</Box>
)}
1 change: 1 addition & 0 deletions src/pages/Things/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Things } from './Things'
11 changes: 8 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import { Converter } from 'showdown'

type ObjectOfObjects = { [k: string]: object }

/** Sort of the reverse to `keyBy` from lodash */
export const unKeyBy = <T extends ObjectOfObjects>(obj: T, keyProp: string) =>
_.map(obj, (val, key) => ({...val, [keyProp]: key }))
/** Sort of the reverse of `keyBy` from lodash */
export const unKeyBy = <T extends ObjectOfObjects, KeyProp extends string>(
obj: T,
keyProp: KeyProp,
) => _.map(obj, (val, key) => (
{...val, [keyProp]: key }
) as T[keyof T] & { [K in KeyProp]: keyof T }
)

/** Mainly useful when we know `o` has a single key */
export const getFirstKey = <T, Obj extends Record<string | number | symbol, T>>(o: Obj) => Object.keys(o)[0]
Expand Down

0 comments on commit f1b9887

Please sign in to comment.