From 2308c0394b949a2b3ea558f0ea1704608c5abe03 Mon Sep 17 00:00:00 2001 From: Dejvino Date: Thu, 25 May 2023 15:29:51 +0200 Subject: [PATCH] Jobs history sourced from personal data --- src/Person.ts | 11 ------ src/PersonalData.ts | 29 ++++++++++++++++ src/PersonalDataTypes.ts | 25 ++++++++++++++ src/app/FocusedElement.tsx | 5 ++- src/app/components/AboutBrief.tsx | 4 +-- src/app/components/JobCard.tsx | 2 +- src/app/components/JobsHistory.tsx | 50 ++++++++++++++++------------ src/app/components/PersonContext.tsx | 13 +++++--- src/app/components/Skills.tsx | 12 +++++-- src/app/components/TagCloud.tsx | 3 +- src/app/layout.tsx | 3 +- src/app/utils.ts | 10 ++++++ 12 files changed, 120 insertions(+), 47 deletions(-) delete mode 100644 src/Person.ts create mode 100644 src/PersonalData.ts create mode 100644 src/PersonalDataTypes.ts create mode 100644 src/app/utils.ts diff --git a/src/Person.ts b/src/Person.ts deleted file mode 100644 index 4347f9a..0000000 --- a/src/Person.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const Person = { - name: "David Hrdina Němeček", - brief: "Software developer, people manager.", - - skills: { - primary: ['Java', 'TypeScript', 'JavaScript'], - secondary: ['Kotlin', 'Go'], - others: ['Driver\'s license (B)'] - }, - interests: ['Guitars and Heavy Metal', 'Mazda MX-5', 'DIY electronics'], -}; diff --git a/src/PersonalData.ts b/src/PersonalData.ts new file mode 100644 index 0000000..aa1c7ec --- /dev/null +++ b/src/PersonalData.ts @@ -0,0 +1,29 @@ +import { PersonalData } from "./PersonalDataTypes"; + +export const personalData: PersonalData = { + name: "David Hrdina Němeček", + brief: "Software developer, people manager.", + + jobs: { + current: { + position: 'Janitor', + company: 'Cleaners Limited', + timerange: '2022 - present', + description: 'Cleanup duty 24/7.', + }, + previous: [ + { + position: 'CEO', + company: 'CryptoDancers', + timerange: '2019 - 2022', + description: 'Revolutionizing the crypto world.', + } + ] + }, + skills: { + primary: ['Java', 'TypeScript', 'JavaScript'], + secondary: ['Kotlin', 'Go'], + others: ['Driver\'s license (B)'] + }, + interests: ['Guitars and Heavy Metal', 'Mazda MX-5', 'DIY electronics'], +}; diff --git a/src/PersonalDataTypes.ts b/src/PersonalDataTypes.ts new file mode 100644 index 0000000..09d8c95 --- /dev/null +++ b/src/PersonalDataTypes.ts @@ -0,0 +1,25 @@ +export type Job = { + position: string, + company: string, + timerange: string, + description: string +} + +export type Jobs = { + current?: Job, + previous?: Job[] +} + +export type Skills = { + primary: string[], + secondary?: string[], + others?: string[] +} + +export type PersonalData = { + name: string, + brief: string, + jobs: Jobs, + skills: Skills, + interests: string[] +} diff --git a/src/app/FocusedElement.tsx b/src/app/FocusedElement.tsx index 13e4a94..10e2a10 100644 --- a/src/app/FocusedElement.tsx +++ b/src/app/FocusedElement.tsx @@ -52,7 +52,10 @@ export function useAutoFocus(elementKey: string let cleanup = () => {} if (elementRef.current) { const elem = elementRef.current - elem.onclick = focusElement + elem.onclick = (evt) => { + evt.stopPropagation() + focusElement() + } const classNameBackup = elem.className elem.className += ' ' + focusedClass cleanup = () => { diff --git a/src/app/components/AboutBrief.tsx b/src/app/components/AboutBrief.tsx index d682605..7f58dda 100644 --- a/src/app/components/AboutBrief.tsx +++ b/src/app/components/AboutBrief.tsx @@ -1,10 +1,10 @@ import React, { useContext } from 'react'; import Container from 'react-bootstrap/Container'; import Image from 'react-bootstrap/Image' -import { PersonContext } from './PersonContext'; +import { usePersonContext } from './PersonContext'; export default function AboutBrief() { - const person = useContext(PersonContext) + const person = usePersonContext() return ( Photograph of the person diff --git a/src/app/components/JobCard.tsx b/src/app/components/JobCard.tsx index d4f0ffd..5af9179 100644 --- a/src/app/components/JobCard.tsx +++ b/src/app/components/JobCard.tsx @@ -11,7 +11,7 @@ export type Props = { }; export default function JobCard(props: Props) { - const focusRef = useAutoFocus([props.position, props.company].join(', ')) + const focusRef = useAutoFocus('position ' + [props.position, props.company].join(', ')) return ( {props.heading && ( diff --git a/src/app/components/JobsHistory.tsx b/src/app/components/JobsHistory.tsx index aee6327..6f5bf02 100644 --- a/src/app/components/JobsHistory.tsx +++ b/src/app/components/JobsHistory.tsx @@ -4,35 +4,41 @@ import Container from 'react-bootstrap/Container'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import JobCard from './JobCard'; +import { usePersonContext } from './PersonContext'; +import { Job } from '../../PersonalDataTypes'; +import { partition } from '../utils'; + +const entriesPerRow = 2 export default function JobsHistory() { + const person = usePersonContext() + + function JobEntry(job: Job, heading?: string) { + return + } + return (

Experience

+ {person.jobs.current && ( - - + + {JobEntry(person.jobs.current, 'Current position')} + - - - + )} + {partition(person.jobs.previous, entriesPerRow).map((jobs, index) => ( + + {(jobs.map((job, subindex) => ( + + {JobEntry(job)} + + )))} -
+ ))} +
) } diff --git a/src/app/components/PersonContext.tsx b/src/app/components/PersonContext.tsx index 5c14173..2e47c7f 100644 --- a/src/app/components/PersonContext.tsx +++ b/src/app/components/PersonContext.tsx @@ -1,14 +1,17 @@ 'use client' -import React from 'react'; +import React, { useContext } from 'react'; import { createContext } from 'react'; -import { Person } from '../../Person'; +import { personalData } from '../../PersonalData'; +import { PersonalData } from '../../PersonalDataTypes'; -export const PersonContext = createContext(Person); +export const PersonContext = createContext(personalData); export function PersonProvider({ children }) { return ( - + {children} ) -} \ No newline at end of file +} + +export const usePersonContext = (): PersonalData => useContext(PersonContext) diff --git a/src/app/components/Skills.tsx b/src/app/components/Skills.tsx index 442101b..d6fc1d2 100644 --- a/src/app/components/Skills.tsx +++ b/src/app/components/Skills.tsx @@ -9,9 +9,15 @@ export default function Skills() {

Skills

- - - + {person.skills.secondary && ( + + )} + {person.skills.others && ( + + )} + {person.interests && ( + + )}
) } diff --git a/src/app/components/TagCloud.tsx b/src/app/components/TagCloud.tsx index 4ef0951..2302863 100644 --- a/src/app/components/TagCloud.tsx +++ b/src/app/components/TagCloud.tsx @@ -18,9 +18,10 @@ function Tag(props: {text: string}) { } export default function TagCloud(props: Props) { + const focusRef = useAutoFocus('tags ' + props.title) const containerClasses = ['tag-cloud', 'cloud-' + (props.style || 'standard')] return ( - +

{props.icon && ( )}{props.title}

{props.tags.map((tag: string) => () )} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 0e341da..a89aad6 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,11 +3,12 @@ import { Inter } from 'next/font/google' import './globals.css' import { PersonProvider } from './components/PersonContext' +import { personalData } from '../PersonalData' const inter = Inter({ subsets: ['latin'] }) export const metadata = { - title: 'David Hrdina Němeček | CV.', + title: personalData.name + ' | CV.', description: 'Curriculum Vitae', } diff --git a/src/app/utils.ts b/src/app/utils.ts new file mode 100644 index 0000000..8947d3a --- /dev/null +++ b/src/app/utils.ts @@ -0,0 +1,10 @@ +export function partition(array: T[]|undefined, entriesPerRow: number): T[][] { + return array ? array.reduce((accumulator: T[][], current: T, index) => { + if (index % entriesPerRow == 0) { + accumulator[accumulator.length] = [current] + } else { + accumulator[accumulator.length - 1] + } + return accumulator + }, []) : [] + }