Jobs history sourced from personal data

This commit is contained in:
Dejvino 2023-05-25 15:29:51 +02:00
parent 9edf9777a0
commit 2308c0394b
12 changed files with 120 additions and 47 deletions

View File

@ -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'],
};

29
src/PersonalData.ts Normal file
View File

@ -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'],
};

25
src/PersonalDataTypes.ts Normal file
View File

@ -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[]
}

View File

@ -52,7 +52,10 @@ export function useAutoFocus<ElementType extends HTMLElement>(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 = () => {

View File

@ -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 (
<Container className='about-brief'>
<Image alt='Photograph of the person' rounded={true} src='photo.png'></Image>

View File

@ -11,7 +11,7 @@ export type Props = {
};
export default function JobCard(props: Props) {
const focusRef = useAutoFocus<HTMLDivElement>([props.position, props.company].join(', '))
const focusRef = useAutoFocus<HTMLDivElement>('position ' + [props.position, props.company].join(', '))
return (
<Card ref={focusRef} className='job-card'>
{props.heading && (

View File

@ -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 <JobCard
heading={heading}
{...job}
/>
}
return (
<Container>
<h2>Experience</h2>
{person.jobs.current && (
<Row>
<Col >
<JobCard
heading='Current position'
position='Senior Software Development Manager - UI Toolkit'
timerange='2022 - present'
company='Oracle | NetSuite'
description='Team leadership Lorem Ipsum'
/></Col>
<Col>
{JobEntry(person.jobs.current, 'Current position')}
</Col>
</Row>
<Row lg={2}>
<Col><JobCard
position='Software Development Manager - UI Toolkit'
timerange='2020 - 2022'
company='Oracle | NetSuite'
description='Team leadership Lorem Ipsum'
/></Col>
<Col><JobCard
position='Software Development Manager - ERP Tax'
timerange='2015 - 2020'
company='Oracle | NetSuite'
description='Team leadership Lorem Ipsum'
/></Col>
)}
{partition(person.jobs.previous, entriesPerRow).map((jobs, index) => (
<Row key={index}>
{(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}>
{JobEntry(job)}
</Col>
)))}
</Row>
))}
</Container>
)
}

View File

@ -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 (
<PersonContext.Provider value={Person}>
<PersonContext.Provider value={personalData}>
{children}
</PersonContext.Provider>
)
}
export const usePersonContext = (): PersonalData => useContext(PersonContext)

View File

@ -9,9 +9,15 @@ export default function Skills() {
<Container className='skills'>
<h2>Skills</h2>
<TagCloud title='Primary' icon='bookmark-star' style='primary' tags={person.skills.primary} />
{person.skills.secondary && (
<TagCloud title='Secondary' icon='bookmark-plus' tags={person.skills.secondary} />
)}
{person.skills.others && (
<TagCloud title='Others' icon='bookmark' tags={person.skills.others} />
)}
{person.interests && (
<TagCloud title='Interests' icon='bookmark-heart' style='light' tags={person.interests} />
)}
</Container>
)
}

View File

@ -18,9 +18,10 @@ function Tag(props: {text: string}) {
}
export default function TagCloud(props: Props) {
const focusRef = useAutoFocus<HTMLDivElement>('tags ' + props.title)
const containerClasses = ['tag-cloud', 'cloud-' + (props.style || 'standard')]
return (
<Container className={containerClasses.join(' ')}>
<Container ref={focusRef} className={containerClasses.join(' ')}>
<h4>{props.icon && (<i className={'bi-' + props.icon}> </i>)}{props.title}</h4>
<Container className='tag-badges'>
{props.tags.map((tag: string) => (<Tag key={tag} text={tag} />) )}

View File

@ -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',
}

10
src/app/utils.ts Normal file
View File

@ -0,0 +1,10 @@
export function partition<T>(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
}, []) : []
}