Compare commits
	
		
			4 Commits
		
	
	
		
			a73b035932
			...
			1798313c9c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1798313c9c | |||
| 1957927896 | |||
| 7d4167b33d | |||
| 8453a7ccfe | 
							
								
								
									
										
											BIN
										
									
								
								public/photo.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/photo.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 697 KiB | 
| @ -3,13 +3,14 @@ import { PersonalData } from "./PersonalDataTypes"; | |||||||
| export const personalData: PersonalData = { | export const personalData: PersonalData = { | ||||||
|     updatedDate: '2023-05-26', |     updatedDate: '2023-05-26', | ||||||
|     name: "David Hrdina Němeček", |     name: "David Hrdina Němeček", | ||||||
|     brief: "Software developer, people manager.", |     brief: "Software developer. Engineering lead & 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: 'file-earmark-person', text: 'https://cv.dejvino.cz'}, | ||||||
|  |         {icon: 'telephone', text: '+420 775 26 26 32'}, | ||||||
|         {icon: 'geo-alt', text: 'Brno, Czechia'} |         {icon: 'geo-alt', text: 'Brno, Czechia'} | ||||||
|     ], |     ], | ||||||
| 
 | 
 | ||||||
| @ -64,7 +65,7 @@ export const personalData: PersonalData = { | |||||||
|             position: `Personal projects`, |             position: `Personal projects`, | ||||||
|             description: `Various hardware and software projects. Usually open sourced and published on [projects.dejvino.com](https://projects.dejvino.com) .
 |             description: `Various hardware and software projects. Usually open sourced and published on [projects.dejvino.com](https://projects.dejvino.com) .
 | ||||||
|             These include video games, utilities, 3D models, devices with embedded microcontrollers etc.`,
 |             These include video games, utilities, 3D models, devices with embedded microcontrollers etc.`,
 | ||||||
|             tags: ['Java', 'Python', 'C/C++', 'Embedded devices', 'OpenSCAD', 'TypeScript', 'Linux', 'Git', 'Self-hosting'] |             tags: ['Java', 'Python', 'C/C++', 'Embedded Software', 'OpenSCAD', 'TypeScript', 'Linux', 'Open Source', 'Git', 'Self-hosting'] | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
| @ -75,21 +76,23 @@ export const personalData: PersonalData = { | |||||||
|                 company: `Faculty of Informatics, Masaryk University Brno`, |                 company: `Faculty of Informatics, Masaryk University Brno`, | ||||||
|                 timerange: '2011 - 2013', |                 timerange: '2011 - 2013', | ||||||
|                 description: `Master's thesis: Efficient computation and visualization of correlations in medical signals.`, |                 description: `Master's thesis: Efficient computation and visualization of correlations in medical signals.`, | ||||||
|  |                 tags: ['C/C++', 'Supercomputers', 'OpenMPI', 'Python', 'Visualization', 'Data science'] | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 position: `Bachelor's degree, Parallel and Distributed Systems`, |                 position: `Bachelor's degree, Parallel and Distributed Systems`, | ||||||
|                 company: `Faculty of Informatics, Masaryk University Brno`, |                 company: `Faculty of Informatics, Masaryk University Brno`, | ||||||
|                 timerange: '2008 - 2011', |                 timerange: '2008 - 2011', | ||||||
|                 description: `Bachelor's thesis: Parallel implementation of force-field decompression algorithm.`, |                 description: `Bachelor's thesis: Parallel implementation of force-field decompression algorithm.`, | ||||||
|  |                 tags: ['C/C++', 'Supercomputers', 'OpenMPI', 'Data science'] | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     skills: { |     skills: { | ||||||
|         primary: ['Java', 'TypeScript', 'JavaScript', 'Engineering leadership', 'Linux'], |         primary: ['Java', 'TypeScript', 'JavaScript', 'Linux', 'Engineering Leadership'], | ||||||
|         secondary: ['SQL', 'Kotlin', 'Go', 'C/C++', 'NodeJs', 'Git', 'Preact', 'Embedded devices'], |         secondary: ['SQL', 'Kotlin', 'C/C++', 'NodeJs', 'Git', 'Preact', 'Embedded Software'], | ||||||
|         languages: ['Czech (native)', 'English (proficient)', 'German (elementary)'], |         languages: ['Czech (native)', 'English (proficient)', 'German (elementary)'], | ||||||
|         others: ['Driver\'s license (B)'] |         //others: ['Driver\'s license (B)']
 | ||||||
|     }, |     }, | ||||||
|     interests: ['Guitars', 'Heavy Metal', 'Mazda MX-5', 'DIY electronics', 'Linux', 'Open source'], |     interests: ['Guitars', 'Heavy Metal', 'Mazda MX-5', 'DIY electronics', 'Linux', 'Open source'], | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ export default function AboutBrief() { | |||||||
|     const person = usePersonContext() |     const person = usePersonContext() | ||||||
|     return ( |     return ( | ||||||
|       <Container className='about-brief' fluid> |       <Container className='about-brief' fluid> | ||||||
|         <h1>{person.name}</h1> |         <h1 className='person-name'>{person.name}</h1> | ||||||
|         <div className='brief'>{md(person.brief)}</div> |         <div className='brief'>{md(person.brief)}</div> | ||||||
|       </Container> |       </Container> | ||||||
|     ) |     ) | ||||||
|  | |||||||
| @ -3,6 +3,6 @@ import Image from 'react-bootstrap/Image' | |||||||
| 
 | 
 | ||||||
| export default function Photo() { | export default function Photo() { | ||||||
|     return ( |     return ( | ||||||
|       <Image alt='Photograph of the person' rounded fluid src='photo.png'></Image> |       <Image className="photo" alt='Photograph of the person' rounded fluid src='photo.png'></Image> | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ import TagCloud from './TagCloud'; | |||||||
| export default function Skills() { | export default function Skills() { | ||||||
|     const person = useContext(PersonContext) |     const person = useContext(PersonContext) | ||||||
|     return ( |     return ( | ||||||
|     <Container className='skills'> |     <Container className='skills' fluid> | ||||||
|         <h2>Skills</h2> |         <h2>Skills</h2> | ||||||
|         <TagCloud title='Primary' icon='bookmark-star' style='primary' tags={person.skills.primary} /> |         <TagCloud title='Primary' icon='bookmark-star' style='primary' tags={person.skills.primary} /> | ||||||
|         {person.skills.secondary && ( |         {person.skills.secondary && ( | ||||||
|  | |||||||
| @ -12,9 +12,9 @@ export type Props = { | |||||||
| export default function TagCloud(props: Props) { | export default function TagCloud(props: Props) { | ||||||
|     const containerClasses = ['tag-cloud', 'cloud-' + (props.style || 'standard')] |     const containerClasses = ['tag-cloud', 'cloud-' + (props.style || 'standard')] | ||||||
|     return ( |     return ( | ||||||
|         <Container className={containerClasses.join(' ')}> |         <Container className={containerClasses.join(' ')} fluid> | ||||||
|             <h4>{props.icon && (<i className={'bi-' + props.icon}> </i>)}{props.title}</h4> |             <h4>{props.icon && (<i className={'bi-' + props.icon}> </i>)}{props.title}</h4> | ||||||
|             <Container className='tag-badges'> |             <Container className='tag-badges' fluid> | ||||||
|                 {props.tags.map((tag: string) => (<Tag key={tag} text={tag} />) )} |                 {props.tags.map((tag: string) => (<Tag key={tag} text={tag} />) )} | ||||||
|             </Container> |             </Container> | ||||||
|         </Container> |         </Container> | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| 
 | 
 | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import Container from 'react-bootstrap/Container'; | import Container from 'react-bootstrap/Container'; | ||||||
| import useSize from '../../hooks/Size'; | import useInWidthRange from '../../hooks/InWidthRange'; | ||||||
| import { JobListProps } from './types'; | import { JobListProps } from './types'; | ||||||
| import JobsAccordion from './JobsAccordion'; | import JobsAccordion from './JobsAccordion'; | ||||||
| import JobsCards, { JobsCardsPlaceholder } from './JobsCards'; | import JobsCards, { JobsCardsPlaceholder } from './JobsCards'; | ||||||
| @ -10,19 +10,14 @@ export type Props = { | |||||||
|   heading: string, |   heading: string, | ||||||
| } & JobListProps | } & JobListProps | ||||||
| 
 | 
 | ||||||
| const defaultProps = { |  | ||||||
|   entriesPerRow: 2, |  | ||||||
|   currentHeading: 'Currently', |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export default function JobHistory(props: Props) { | export default function JobHistory(props: Props) { | ||||||
|   const {SizeWrapper, size} = useSize() |   const {SizeWrapper, inRange} = useInWidthRange(600) | ||||||
|   |   | ||||||
|   const jobsList = size.width === 0 ? <JobsCardsPlaceholder /> : ( |   const jobsList = inRange === undefined ? <JobsCardsPlaceholder /> : ( | ||||||
|     size.width < 600 ? <JobsAccordion {...props} /> : <JobsCards {...props} />) |     inRange ? <JobsAccordion {...props} /> : <JobsCards {...props} />) | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Container> |     <Container fluid> | ||||||
|       <h2>{props.heading}</h2> |       <h2>{props.heading}</h2> | ||||||
|       <SizeWrapper> |       <SizeWrapper> | ||||||
|         {jobsList} |         {jobsList} | ||||||
|  | |||||||
| @ -8,6 +8,19 @@ body { | |||||||
|     padding-top: 1rem; |     padding-top: 1rem; | ||||||
|     padding-bottom: 0.2rem; |     padding-bottom: 0.2rem; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .person-name { | ||||||
|  |     margin-top: calc(min(6vw, 5rem)); | ||||||
|  |     font-weight: bold; | ||||||
|  |     font-size: calc(1.375rem + min(1.4vw, 1rem)); | ||||||
|  | } | ||||||
|  | .brief { | ||||||
|  |     font-size: 120%; | ||||||
|  | } | ||||||
|  | .contacts { | ||||||
|  |     margin-top: 2rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .footer { | .footer { | ||||||
|     margin-top: 2rem; |     margin-top: 2rem; | ||||||
|     filter: opacity(75%) |     filter: opacity(75%) | ||||||
| @ -17,7 +30,7 @@ body { | |||||||
|     filter: opacity(75%) |     filter: opacity(75%) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .container > h2, h3, h4 { | .container > h2, .container-fluid > h2, h3, h4 { | ||||||
|     margin-top: 1em; |     margin-top: 1em; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -55,6 +68,7 @@ body { | |||||||
| } | } | ||||||
| .tag-badges > span { | .tag-badges > span { | ||||||
|     margin: 0.4em; |     margin: 0.4em; | ||||||
|  |     color: #222; | ||||||
| } | } | ||||||
| .contacts .contact { | .contacts .contact { | ||||||
|     margin: 0.75em; |     margin: 0.75em; | ||||||
| @ -65,6 +79,14 @@ body { | |||||||
| .accordion { | .accordion { | ||||||
|     margin: 1rem; |     margin: 1rem; | ||||||
| } | } | ||||||
|  | .main-container .accordion-button:not(.collapsed) { | ||||||
|  |     color: #222; | ||||||
|  |     background-color: RGBA(217, 216, 216, 0.3); | ||||||
|  | } | ||||||
|  | .main-container .accordion-button.collapsed { | ||||||
|  |     color: #0e489d; | ||||||
|  |     background-color: RGBA(153, 165, 213, 0.3); | ||||||
|  | } | ||||||
| .multiline { | .multiline { | ||||||
|     white-space: pre-line; |     white-space: pre-line; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								src/app/hooks/InWidthRange.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/app/hooks/InWidthRange.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | import React, { ForwardedRef, ReactNode, forwardRef, useEffect, useLayoutEffect, useRef, useState } from "react"; | ||||||
|  | 
 | ||||||
|  | export default function useInWidthRange(threshold: number) { | ||||||
|  |     const areaRef = useRef<HTMLDivElement>(null) | ||||||
|  |     const [inRange, setInRange] = useState<boolean | undefined>(undefined) | ||||||
|  |      | ||||||
|  |     function SizeWrapper(props: {children: ReactNode }) { | ||||||
|  |         return ( | ||||||
|  |             <div ref={areaRef}>{props.children}</div> | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  |        | ||||||
|  |     useEffect(() => { | ||||||
|  |         function updateState() { | ||||||
|  |             if (areaRef.current) { | ||||||
|  |                 const width = areaRef.current.offsetWidth | ||||||
|  |                 setInRange(width <= threshold) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         updateState() | ||||||
|  |         addEventListener("resize", updateState); | ||||||
|  |         return () => { | ||||||
|  |             removeEventListener("resize", updateState) | ||||||
|  |         }; | ||||||
|  |     }, [areaRef, threshold, setInRange]) | ||||||
|  | 
 | ||||||
|  |     return {SizeWrapper, inRange} | ||||||
|  | } | ||||||
| @ -1,30 +0,0 @@ | |||||||
| import React, { ForwardedRef, ReactNode, forwardRef, useEffect, useLayoutEffect, useRef, useState } from "react"; |  | ||||||
| 
 |  | ||||||
| export default function useSize() { |  | ||||||
|     const areaRef = useRef<HTMLDivElement>(null) |  | ||||||
|     const [size, setSize] = useState({ width: 0, height: 0 }) |  | ||||||
|      |  | ||||||
|     function SizeWrapper(props: {children: ReactNode }) { |  | ||||||
|         return ( |  | ||||||
|             <div ref={areaRef}>{props.children}</div> |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
|        |  | ||||||
|     useEffect(() => { |  | ||||||
|         function updateSize() { |  | ||||||
|             if (areaRef.current) { |  | ||||||
|                 setSize({ |  | ||||||
|                     width: areaRef.current.offsetWidth, |  | ||||||
|                     height: areaRef.current.offsetHeight |  | ||||||
|                     }) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         updateSize() |  | ||||||
|         addEventListener("resize", updateSize); |  | ||||||
|         return () => { |  | ||||||
|             removeEventListener("resize", updateSize) |  | ||||||
|         }; |  | ||||||
|     }, [areaRef, setSize]) |  | ||||||
| 
 |  | ||||||
|     return {SizeWrapper, size} |  | ||||||
| } |  | ||||||
| @ -16,13 +16,9 @@ export default function Home() { | |||||||
| 
 | 
 | ||||||
|     <Container className='main-container' fluid='xxl'> |     <Container className='main-container' fluid='xxl'> | ||||||
|       <Row> |       <Row> | ||||||
|         <Col xs={'auto'} sm={4} lg={2}><Photo /></Col> |         <Col xs={3} sm={3} lg={2}><Photo /></Col> | ||||||
|         <Col> |         <Col xs={9} sm={9} lg={5}><AboutBrief /></Col> | ||||||
|           <Row> |         <Col xs={12} lg={5}><Contacts /></Col> | ||||||
|             <Col xs={'auto'} lg={6}><AboutBrief /></Col> |  | ||||||
|             <Col xs={'auto'} lg={6}><Contacts /></Col> |  | ||||||
|           </Row> |  | ||||||
|         </Col> |  | ||||||
|       </Row> |       </Row> | ||||||
|       <Row> |       <Row> | ||||||
|         <Col xs={12} xl={7}> |         <Col xs={12} xl={7}> | ||||||
| @ -31,7 +27,7 @@ export default function Home() { | |||||||
|           <Row><Education /></Row> |           <Row><Education /></Row> | ||||||
|         </Col> |         </Col> | ||||||
|         <Col> |         <Col> | ||||||
|           <Row><Skills /></Row> |           <Skills /> | ||||||
|         </Col> |         </Col> | ||||||
|       </Row> |       </Row> | ||||||
|       <Row><Footer /></Row> |       <Row><Footer /></Row> | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user