Compare commits

..

No commits in common. "59677e3d7fd841105c927674c20eddd1e312afa6" and "f4f40166408561395c287e7687fbc048d6f9a20b" have entirely different histories.

14 changed files with 25 additions and 146 deletions

View File

@ -1,16 +1,13 @@
import { PersonalData } from "./PersonalDataTypes"; import { PersonalData } from "./PersonalDataTypes";
export const personalData: PersonalData = { export const personalData: PersonalData = {
updatedDate: '2023-05-26',
name: "David Hrdina Němeček", name: "David Hrdina Němeček",
brief: "Software developer, people manager.", brief: "Software developer, people manager.",
contacts: [ contacts: [
{icon: 'browser-firefox', text: 'www.dejvino.cz'}, {icon: 'browser-firefox', text: 'www.dejvino.cz'},
{icon: 'envelope-at', text: 'explosive@dejvino.cz'}, {icon: 'envelope-at', text: 'explosive@dejvino.cz'},
{icon: 'git', text: 'https://git.dejvino.cz'}, {icon: 'git', text: 'https://git.dejvino.cz'}
{icon: 'telephone', text: '+420 111 222 333'},
{icon: 'geo-alt', text: 'Brno, Czechia'}
], ],
jobs: { jobs: {
current: { current: {
@ -28,20 +25,9 @@ export const personalData: PersonalData = {
} }
] ]
}, },
education: {
previous: [
{
position: 'Information Technology (unfinished)',
company: 'University of Benimoto',
timerange: '2010 - 2017',
description: '',
}
]
},
skills: { skills: {
primary: ['Java', 'TypeScript', 'JavaScript'], primary: ['Java', 'TypeScript', 'JavaScript'],
secondary: ['Kotlin', 'Go'], secondary: ['Kotlin', 'Go'],
languages: ['Czech (native)', 'English (proficient)', 'German (elementary)'],
others: ['Driver\'s license (B)'] others: ['Driver\'s license (B)']
}, },
interests: ['Guitars and Heavy Metal', 'Mazda MX-5', 'DIY electronics'], interests: ['Guitars and Heavy Metal', 'Mazda MX-5', 'DIY electronics'],

View File

@ -15,22 +15,17 @@ export type Jobs = {
previous?: Job[] previous?: Job[]
} }
export type Education = Jobs;
export type Skills = { export type Skills = {
primary: string[], primary: string[],
secondary?: string[], secondary?: string[],
languages?: string[],
others?: string[] others?: string[]
} }
export type PersonalData = { export type PersonalData = {
updatedDate: string,
name: string, name: string,
brief: string, brief: string,
contacts: Contact[], contacts: Contact[],
jobs: Jobs, jobs: Jobs,
education?: Education,
skills: Skills, skills: Skills,
interests: string[] interests: string[]
} }

View File

@ -2,12 +2,12 @@ import React, { useContext } from 'react';
import Container from 'react-bootstrap/Container'; import Container from 'react-bootstrap/Container';
import Image from 'react-bootstrap/Image' import Image from 'react-bootstrap/Image'
import { usePersonContext } from './PersonContext'; import { usePersonContext } from './PersonContext';
import { Col, Row } from 'react-bootstrap';
export default function AboutBrief() { export default function AboutBrief() {
const person = usePersonContext() const person = usePersonContext()
return ( return (
<Container className='about-brief' fluid> <Container className='about-brief'>
<Image alt='Photograph of the person' rounded={true} src='photo.png'></Image>
<h1>{person.name}</h1> <h1>{person.name}</h1>
<p className='brief'>{person.brief}</p> <p className='brief'>{person.brief}</p>
</Container> </Container>

View File

@ -2,7 +2,6 @@ import React, { ReactNode } from 'react'
import { usePersonContext } from './PersonContext' import { usePersonContext } from './PersonContext'
import Container from 'react-bootstrap/esm/Container' import Container from 'react-bootstrap/esm/Container'
import { useAutoFocus } from '../FocusedElement' import { useAutoFocus } from '../FocusedElement'
import { Col, Row } from 'react-bootstrap'
export function Contact(props: {icon?: string, text: string}) { export function Contact(props: {icon?: string, text: string}) {
let textElement: ReactNode = <span className='contact-text'>{props.text}</span> let textElement: ReactNode = <span className='contact-text'>{props.text}</span>
@ -22,9 +21,10 @@ export function Contact(props: {icon?: string, text: string}) {
textElement = <a href={url} className='contact-link' target='_blank'>{props.text}</a> textElement = <a href={url} className='contact-link' target='_blank'>{props.text}</a>
} }
return ( return (
<Col className='contact' xs={'auto'}> <span className='contact'>
<i className={'bi-' + props.icon}></i>&nbsp;{textElement} <i className={'bi-' + props.icon}> </i>
</Col> {textElement}
</span>
) )
} }
@ -32,15 +32,11 @@ export function Contacts() {
const person = usePersonContext() const person = usePersonContext()
const focus = useAutoFocus<HTMLDivElement>('contacts') const focus = useAutoFocus<HTMLDivElement>('contacts')
return ( return (
<Container ref={focus} className='contacts' fluid> <Container ref={focus} className='contacts'>
<Row>
<h2>Contacts</h2> <h2>Contacts</h2>
</Row>
<Row>
{person.contacts.map((contact, index) => ( {person.contacts.map((contact, index) => (
<Contact key={index} {...contact} /> <Contact key={index} {...contact} />
))} ))}
</Row>
</Container> </Container>
) )
} }

View File

@ -1,16 +0,0 @@
import React from 'react';
import { usePersonContext } from './PersonContext';
import JobHistory from './JobHistory';
export default function WorkExperience() {
const person = usePersonContext()
return person.education ? (
<JobHistory
jobs={person.education}
heading='Education'
currentHeading='Currently studying'
/>
) : <></>
}

View File

@ -1,13 +0,0 @@
import React from 'react';
import { Container } from 'react-bootstrap';
import { usePersonContext } from './PersonContext';
export default function Footer() {
const personalData = usePersonContext()
return (
<Container fluid className="footer text-center">
<p><small>Created by {personalData.name}, last updated on {personalData.updatedDate}</small></p>
<p><small className='tiny'>CV engineered by <a href={'https://www.dejvino.cz/'} target={'_blank'}>Dejvino</a></small></p>
</Container>
)
}

View File

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

View File

@ -4,35 +4,25 @@ import Container from 'react-bootstrap/Container';
import Col from 'react-bootstrap/Col'; import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row'; import Row from 'react-bootstrap/Row';
import JobCard from './JobCard'; import JobCard from './JobCard';
import { usePersonContext } from './PersonContext';
import { partition } from '../utils'; import { partition } from '../utils';
import { Jobs } from '@/PersonalDataTypes';
export type Props = { const entriesPerRow = 2
jobs: Jobs,
heading: string,
entriesPerRow?: number,
currentHeading?: string,
}
const defaultProps = { export default function JobsHistory() {
entriesPerRow: 2, const person = usePersonContext()
currentHeading: 'Currently',
}
export default function JobHistory(props: Props) {
const jobs = props.jobs
const config = {...defaultProps, ...props}
return ( return (
<Container> <Container>
<h2>{config.heading}</h2> <h2>Experience</h2>
{jobs.current && ( {person.jobs.current && (
<Row> <Row>
<Col> <Col>
<JobCard heading={config.currentHeading} {...jobs.current} /> <JobCard heading={'Current position'} {...person.jobs.current} />
</Col> </Col>
</Row> </Row>
)} )}
{partition(jobs.previous, config.entriesPerRow).map((jobs, index) => ( {partition(person.jobs.previous, entriesPerRow).map((jobs, index) => (
<Row key={index}> <Row key={index}>
{(jobs.map((job, subindex) => ( {(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}> <Col key={index + '_' + subindex}>

View File

@ -1,8 +0,0 @@
import React from 'react';
import Image from 'react-bootstrap/Image'
export default function Photo() {
return (
<Image alt='Photograph of the person' rounded fluid src='photo.png'></Image>
)
}

View File

@ -12,9 +12,6 @@ export default function Skills() {
{person.skills.secondary && ( {person.skills.secondary && (
<TagCloud title='Secondary' icon='bookmark-plus' tags={person.skills.secondary} /> <TagCloud title='Secondary' icon='bookmark-plus' tags={person.skills.secondary} />
)} )}
{person.skills.languages && (
<TagCloud title='Languages' icon='bookmarks' tags={person.skills.languages} />
)}
{person.skills.others && ( {person.skills.others && (
<TagCloud title='Others' icon='bookmark' tags={person.skills.others} /> <TagCloud title='Others' icon='bookmark' tags={person.skills.others} />
)} )}

View File

@ -10,7 +10,7 @@ export type Props = {
} }
function Tag(props: {text: string}) { function Tag(props: {text: string}) {
const tagKey = 'tag ' + props.text; const tagKey = 'tag_' + props.text;
const elementRef = useAutoFocus(tagKey) const elementRef = useAutoFocus(tagKey)
return ( return (
<span ref={elementRef} className='badge text-bg-light'>{props.text}</span> <span ref={elementRef} className='badge text-bg-light'>{props.text}</span>

View File

@ -1,16 +0,0 @@
import React from 'react';
import { usePersonContext } from './PersonContext';
import JobHistory from './JobHistory';
export default function WorkExperience() {
const person = usePersonContext()
return (
<JobHistory
jobs={person.jobs}
heading='Work Experience'
currentHeading='Current position'
/>
)
}

View File

@ -2,25 +2,6 @@
@import 'bootstrap/dist/css/bootstrap.min.css'; @import 'bootstrap/dist/css/bootstrap.min.css';
@import 'bootstrap-icons/font/bootstrap-icons.min.css'; @import 'bootstrap-icons/font/bootstrap-icons.min.css';
body {
background-color: lightgrey;
}
.main-container {
background-color: white;
padding-top: 1rem;
padding-bottom: 0.2rem;
}
.footer {
margin-top: 2rem;
}
.tiny {
font-size: 75%;
}
h2, h3, h4 {
margin-top: 1em;
}
.job-card { .job-card {
margin-top: 1em; margin-top: 1em;
} }

View File

@ -1,32 +1,19 @@
'use client' 'use client'
import React from 'react'; import React from 'react';
import Container from 'react-bootstrap/Container'; import Container from 'react-bootstrap/Container';
import JobsHistory from './components/JobsHistory';
import AboutBrief from './components/AboutBrief'; import AboutBrief from './components/AboutBrief';
import Skills from './components/Skills'; import Skills from './components/Skills';
import { Contacts } from './components/Contacts'; import { Contacts } from './components/Contacts';
import WorkExperience from './components/WorkExperience';
import Education from './components/Education';
import { Col, Row } from 'react-bootstrap';
import Footer from './components/Footer';
import Photo from './components/Photo';
export default function Home() { export default function Home() {
return ( return (
<Container className='main-container' fluid='xxl'> <Container fluid='xxl'>
<Row> <AboutBrief />
<Col xs={'auto'} sm={4} lg={2}><Photo /></Col> <Contacts />
<Col> <JobsHistory />
<Row> <Skills />
<Col xs={'auto'} lg={6}><AboutBrief /></Col>
<Col xs={'auto'} lg={6}><Contacts /></Col>
</Row>
</Col>
</Row>
<Row><WorkExperience /></Row>
<Row><Education /></Row>
<Row><Skills /></Row>
<Row><Footer /></Row>
</Container> </Container>
) )
} }