Compare commits

..

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

15 changed files with 42 additions and 128 deletions

View File

@ -1,7 +1,7 @@
import React, { useContext } from 'react'; 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 '../hooks/PersonContext'; import { usePersonContext } from './PersonContext';
import { Col, Row } from 'react-bootstrap'; import { Col, Row } from 'react-bootstrap';
export default function AboutBrief() { export default function AboutBrief() {

View File

@ -1,7 +1,7 @@
import React, { ReactNode } from 'react' import React, { ReactNode } from 'react'
import { usePersonContext } from '../hooks/PersonContext' import { usePersonContext } from './PersonContext'
import Container from 'react-bootstrap/esm/Container' import Container from 'react-bootstrap/esm/Container'
import { useAutoFocus } from '../hooks/FocusedElement' import { useAutoFocus } from '../FocusedElement'
import { Col, Row } from 'react-bootstrap' import { Col, Row } from 'react-bootstrap'
export function Contact(props: {icon?: string, text: string}) { export function Contact(props: {icon?: string, text: string}) {

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { usePersonContext } from '../hooks/PersonContext'; import { usePersonContext } from './PersonContext';
import JobHistory from './JobHistory'; import JobHistory from './JobHistory';
export default function WorkExperience() { export default function WorkExperience() {

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { Container } from 'react-bootstrap'; import { Container } from 'react-bootstrap';
import { usePersonContext } from '../hooks/PersonContext'; import { usePersonContext } from './PersonContext';
export default function Footer() { export default function Footer() {
const personalData = usePersonContext() const personalData = usePersonContext()

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import Card from 'react-bootstrap/Card'; import Card from 'react-bootstrap/Card';
import { useAutoFocus, useFocusedElement } from '../hooks/FocusedElement'; import { useAutoFocus, useFocusedElement } from '../FocusedElement';
export type Props = { export type Props = {
heading?: string, heading?: string,

View File

@ -5,90 +5,42 @@ 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 { partition } from '../utils'; import { partition } from '../utils';
import { Job, Jobs } from '@/PersonalDataTypes'; import { Jobs } from '@/PersonalDataTypes';
import useSize from '../hooks/Size';
import { Accordion } from 'react-bootstrap';
type JobListProps = { export type Props = {
jobs: Jobs, jobs: Jobs,
heading: string,
entriesPerRow?: number, entriesPerRow?: number,
currentHeading?: string, currentHeading?: string,
} }
export type Props = {
heading: string,
} & JobListProps
const defaultProps = { const defaultProps = {
entriesPerRow: 2, entriesPerRow: 2,
currentHeading: 'Currently', currentHeading: 'Currently',
} }
function FullList(props: JobListProps) {
const {jobs} = props
const config = {...defaultProps, ...props}
return (
<Container>
{jobs.current && (
<Row>
<Col>
<JobCard heading={config.currentHeading} {...jobs.current} />
</Col>
</Row>
)}
{partition(jobs.previous, config.entriesPerRow).map((jobs, index) => (
<Row key={index}>
{(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}>
<JobCard {...job} />
</Col>
)))}
</Row>
))}
</Container>
)
}
function SmallList(props: JobListProps) {
const {jobs} = props
const config = {...defaultProps, ...props}
function jobTitle(job: Job) {
return `${job.position} at ${job.company}, ${job.timerange}`
}
return (
<Accordion defaultActiveKey={jobs.current ? 'current' : 'previous-0'} alwaysOpen>
{jobs.current && (
<Accordion.Item eventKey="current">
<Accordion.Header>{config.currentHeading}:<br />{jobTitle(jobs.current)} </Accordion.Header>
<Accordion.Body>
{jobs.current.position}
</Accordion.Body>
</Accordion.Item>
)}
{jobs.previous?.map((job, index) => (
<Accordion.Item eventKey={`previous-${index}`} key={index}>
<Accordion.Header>{jobTitle(job)}</Accordion.Header>
<Accordion.Body>
{job.description}
</Accordion.Body>
</Accordion.Item>
))}
</Accordion>
)
}
export default function JobHistory(props: Props) { export default function JobHistory(props: Props) {
const {SizeWrapper, size} = useSize() const jobs = props.jobs
const jobs = props.jobs const config = {...defaultProps, ...props}
return (
const jobsList = size.width < 600 ? <SmallList {...props} /> : <FullList {...props} />
return (
<Container> <Container>
<h2>{props.heading}</h2> <h2>{config.heading}</h2>
<SizeWrapper> {jobs.current && (
{jobsList} <Row>
</SizeWrapper> <Col>
<JobCard heading={config.currentHeading} {...jobs.current} />
</Col>
</Row>
)}
{partition(jobs.previous, config.entriesPerRow).map((jobs, index) => (
<Row key={index}>
{(jobs.map((job, subindex) => (
<Col key={index + '_' + subindex}>
<JobCard {...job} />
</Col>
)))}
</Row>
))}
</Container> </Container>
) )
} }

View File

@ -1,15 +1,15 @@
'use client' 'use client'
import React, { ReactNode, useContext } from 'react'; import React, { useContext } from 'react';
import { createContext } from 'react'; import { createContext } from 'react';
import { personalData } from '../../PersonalData'; import { personalData } from '../../PersonalData';
import { PersonalData } from '../../PersonalDataTypes'; import { PersonalData } from '../../PersonalDataTypes';
export const PersonContext = createContext(personalData); export const PersonContext = createContext(personalData);
export function PersonProvider(props: { children: ReactNode }) { export function PersonProvider({ children }) {
return ( return (
<PersonContext.Provider value={personalData}> <PersonContext.Provider value={personalData}>
{props.children} {children}
</PersonContext.Provider> </PersonContext.Provider>
) )
} }

View File

@ -1,6 +1,6 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import Container from 'react-bootstrap/Container'; import Container from 'react-bootstrap/Container';
import { PersonContext } from '../hooks/PersonContext'; import { PersonContext } from './PersonContext';
import TagCloud from './TagCloud'; import TagCloud from './TagCloud';
export default function Skills() { export default function Skills() {

View File

@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import Container from 'react-bootstrap/Container'; import Container from 'react-bootstrap/Container';
import { useAutoFocus, useFocusedElement } from '../hooks/FocusedElement'; import { useAutoFocus, useFocusedElement } from '../FocusedElement';
export type Props = { export type Props = {
title: string, title: string,

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { usePersonContext } from '../hooks/PersonContext'; import { usePersonContext } from './PersonContext';
import JobHistory from './JobHistory'; import JobHistory from './JobHistory';
export default function WorkExperience() { export default function WorkExperience() {

View File

@ -17,8 +17,7 @@ body {
.tiny { .tiny {
font-size: 75%; font-size: 75%;
} }
h2, h3, h4 {
.container > h2, h3, h4 {
margin-top: 1em; margin-top: 1em;
} }

View File

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

View File

@ -2,7 +2,7 @@ import React from 'react'
import { Inter } from 'next/font/google' import { Inter } from 'next/font/google'
import './globals.css' import './globals.css'
import { PersonProvider } from './hooks/PersonContext' import { PersonProvider } from './components/PersonContext'
import { personalData } from '../PersonalData' import { personalData } from '../PersonalData'
const inter = Inter({ subsets: ['latin'] }) const inter = Inter({ subsets: ['latin'] })

View File

@ -1,5 +1,5 @@
'use client' 'use client'
import React, { ForwardedRef, ReactNode, RefObject, forwardRef } from 'react'; import React from 'react';
import Container from 'react-bootstrap/Container'; import Container from 'react-bootstrap/Container';
import AboutBrief from './components/AboutBrief'; import AboutBrief from './components/AboutBrief';
import Skills from './components/Skills'; import Skills from './components/Skills';
@ -9,7 +9,6 @@ import Education from './components/Education';
import { Col, Row } from 'react-bootstrap'; import { Col, Row } from 'react-bootstrap';
import Footer from './components/Footer'; import Footer from './components/Footer';
import Photo from './components/Photo'; import Photo from './components/Photo';
import useSize from './hooks/Size';
export default function Home() { export default function Home() {
return ( return (
@ -24,15 +23,9 @@ export default function Home() {
</Row> </Row>
</Col> </Col>
</Row> </Row>
<Row> <Row><WorkExperience /></Row>
<Col xs={12} xl={7}> <Row><Education /></Row>
<Row><WorkExperience /></Row> <Row><Skills /></Row>
<Row><Education /></Row>
</Col>
<Col>
<Row><Skills /></Row>
</Col>
</Row>
<Row><Footer /></Row> <Row><Footer /></Row>
</Container> </Container>
) )