Compare commits
4 Commits
f4f4016640
...
59677e3d7f
Author | SHA1 | Date | |
---|---|---|---|
59677e3d7f | |||
e9a63461fb | |||
afff716c09 | |||
296b9862c9 |
@ -1,13 +1,16 @@
|
|||||||
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: {
|
||||||
@ -25,9 +28,20 @@ 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'],
|
||||||
|
@ -15,17 +15,22 @@ 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[]
|
||||||
}
|
}
|
||||||
|
@ -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'>
|
<Container className='about-brief' fluid>
|
||||||
<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>
|
||||||
|
@ -2,6 +2,7 @@ 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>
|
||||||
@ -21,10 +22,9 @@ 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 (
|
||||||
<span className='contact'>
|
<Col className='contact' xs={'auto'}>
|
||||||
<i className={'bi-' + props.icon}> </i>
|
<i className={'bi-' + props.icon}></i> {textElement}
|
||||||
{textElement}
|
</Col>
|
||||||
</span>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,11 +32,15 @@ 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'>
|
<Container ref={focus} className='contacts' fluid>
|
||||||
<h2>Contacts</h2>
|
<Row>
|
||||||
|
<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>
|
||||||
)
|
)
|
||||||
}
|
}
|
16
src/app/components/Education.tsx
Normal file
16
src/app/components/Education.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
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'
|
||||||
|
/>
|
||||||
|
) : <></>
|
||||||
|
}
|
13
src/app/components/Footer.tsx
Normal file
13
src/app/components/Footer.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
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>
|
||||||
|
)
|
||||||
|
}
|
@ -11,7 +11,7 @@ export type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function JobCard(props: Props) {
|
export default function JobCard(props: Props) {
|
||||||
const focusRef = useAutoFocus<HTMLDivElement>('position ' + [props.position, props.company].join(', '))
|
const focusRef = useAutoFocus<HTMLDivElement>([props.position, props.company, props.timerange].join(' - '))
|
||||||
return (
|
return (
|
||||||
<Card ref={focusRef} className='job-card'>
|
<Card ref={focusRef} className='job-card'>
|
||||||
{props.heading && (
|
{props.heading && (
|
||||||
|
@ -4,25 +4,35 @@ 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';
|
||||||
|
|
||||||
const entriesPerRow = 2
|
export type Props = {
|
||||||
|
jobs: Jobs,
|
||||||
|
heading: string,
|
||||||
|
entriesPerRow?: number,
|
||||||
|
currentHeading?: string,
|
||||||
|
}
|
||||||
|
|
||||||
export default function JobsHistory() {
|
const defaultProps = {
|
||||||
const person = usePersonContext()
|
entriesPerRow: 2,
|
||||||
|
currentHeading: 'Currently',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function JobHistory(props: Props) {
|
||||||
|
const jobs = props.jobs
|
||||||
|
const config = {...defaultProps, ...props}
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<h2>Experience</h2>
|
<h2>{config.heading}</h2>
|
||||||
{person.jobs.current && (
|
{jobs.current && (
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<JobCard heading={'Current position'} {...person.jobs.current} />
|
<JobCard heading={config.currentHeading} {...jobs.current} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
{partition(person.jobs.previous, entriesPerRow).map((jobs, index) => (
|
{partition(jobs.previous, config.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}>
|
8
src/app/components/Photo.tsx
Normal file
8
src/app/components/Photo.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
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>
|
||||||
|
)
|
||||||
|
}
|
@ -12,6 +12,9 @@ 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} />
|
||||||
)}
|
)}
|
||||||
|
@ -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>
|
||||||
|
16
src/app/components/WorkExperience.tsx
Normal file
16
src/app/components/WorkExperience.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
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'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@ -2,6 +2,25 @@
|
|||||||
@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;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
'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 fluid='xxl'>
|
<Container className='main-container' fluid='xxl'>
|
||||||
<AboutBrief />
|
<Row>
|
||||||
<Contacts />
|
<Col xs={'auto'} sm={4} lg={2}><Photo /></Col>
|
||||||
<JobsHistory />
|
<Col>
|
||||||
<Skills />
|
<Row>
|
||||||
|
<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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user