Compare commits
4 Commits
59677e3d7f
...
c881021532
Author | SHA1 | Date | |
---|---|---|---|
c881021532 | |||
b810ea1151 | |||
7dd0e13cd6 | |||
1744faed05 |
@ -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 './PersonContext';
|
import { usePersonContext } from '../hooks/PersonContext';
|
||||||
import { Col, Row } from 'react-bootstrap';
|
import { Col, Row } from 'react-bootstrap';
|
||||||
|
|
||||||
export default function AboutBrief() {
|
export default function AboutBrief() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { ReactNode } from 'react'
|
import React, { ReactNode } from 'react'
|
||||||
import { usePersonContext } from './PersonContext'
|
import { usePersonContext } from '../hooks/PersonContext'
|
||||||
import Container from 'react-bootstrap/esm/Container'
|
import Container from 'react-bootstrap/esm/Container'
|
||||||
import { useAutoFocus } from '../FocusedElement'
|
import { useAutoFocus } from '../hooks/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}) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { usePersonContext } from './PersonContext';
|
import { usePersonContext } from '../hooks/PersonContext';
|
||||||
import JobHistory from './JobHistory';
|
import JobHistory from './JobHistory';
|
||||||
|
|
||||||
export default function WorkExperience() {
|
export default function WorkExperience() {
|
||||||
|
@ -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 './PersonContext';
|
import { usePersonContext } from '../hooks/PersonContext';
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
const personalData = usePersonContext()
|
const personalData = usePersonContext()
|
||||||
|
@ -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 '../FocusedElement';
|
import { useAutoFocus, useFocusedElement } from '../hooks/FocusedElement';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
heading?: string,
|
heading?: string,
|
||||||
|
@ -5,42 +5,90 @@ 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 { Jobs } from '@/PersonalDataTypes';
|
import { Job, Jobs } from '@/PersonalDataTypes';
|
||||||
|
import useSize from '../hooks/Size';
|
||||||
|
import { Accordion } from 'react-bootstrap';
|
||||||
|
|
||||||
export type Props = {
|
type JobListProps = {
|
||||||
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',
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function JobHistory(props: Props) {
|
function FullList(props: JobListProps) {
|
||||||
const jobs = props.jobs
|
const {jobs} = props
|
||||||
const config = {...defaultProps, ...props}
|
const config = {...defaultProps, ...props}
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<h2>{config.heading}</h2>
|
{jobs.current && (
|
||||||
{jobs.current && (
|
<Row>
|
||||||
<Row>
|
<Col>
|
||||||
<Col>
|
<JobCard heading={config.currentHeading} {...jobs.current} />
|
||||||
<JobCard heading={config.currentHeading} {...jobs.current} />
|
</Col>
|
||||||
</Col>
|
</Row>
|
||||||
</Row>
|
)}
|
||||||
)}
|
{partition(jobs.previous, config.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}>
|
<JobCard {...job} />
|
||||||
<JobCard {...job} />
|
</Col>
|
||||||
</Col>
|
)))}
|
||||||
)))}
|
</Row>
|
||||||
</Row>
|
))}
|
||||||
))}
|
|
||||||
</Container>
|
</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) {
|
||||||
|
const {SizeWrapper, size} = useSize()
|
||||||
|
const jobs = props.jobs
|
||||||
|
|
||||||
|
const jobsList = size.width < 600 ? <SmallList {...props} /> : <FullList {...props} />
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<h2>{props.heading}</h2>
|
||||||
|
<SizeWrapper>
|
||||||
|
{jobsList}
|
||||||
|
</SizeWrapper>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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 './PersonContext';
|
import { PersonContext } from '../hooks/PersonContext';
|
||||||
import TagCloud from './TagCloud';
|
import TagCloud from './TagCloud';
|
||||||
|
|
||||||
export default function Skills() {
|
export default function Skills() {
|
||||||
|
@ -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 '../FocusedElement';
|
import { useAutoFocus, useFocusedElement } from '../hooks/FocusedElement';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { usePersonContext } from './PersonContext';
|
import { usePersonContext } from '../hooks/PersonContext';
|
||||||
import JobHistory from './JobHistory';
|
import JobHistory from './JobHistory';
|
||||||
|
|
||||||
export default function WorkExperience() {
|
export default function WorkExperience() {
|
||||||
|
@ -17,7 +17,8 @@ body {
|
|||||||
.tiny {
|
.tiny {
|
||||||
font-size: 75%;
|
font-size: 75%;
|
||||||
}
|
}
|
||||||
h2, h3, h4 {
|
|
||||||
|
.container > h2, h3, h4 {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useContext } from 'react';
|
import React, { ReactNode, 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({ children }) {
|
export function PersonProvider(props: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<PersonContext.Provider value={personalData}>
|
<PersonContext.Provider value={personalData}>
|
||||||
{children}
|
{props.children}
|
||||||
</PersonContext.Provider>
|
</PersonContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
30
src/app/hooks/Size.tsx
Normal file
30
src/app/hooks/Size.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
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}
|
||||||
|
}
|
@ -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 './components/PersonContext'
|
import { PersonProvider } from './hooks/PersonContext'
|
||||||
import { personalData } from '../PersonalData'
|
import { personalData } from '../PersonalData'
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] })
|
const inter = Inter({ subsets: ['latin'] })
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React from 'react';
|
import React, { ForwardedRef, ReactNode, RefObject, forwardRef } 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,6 +9,7 @@ 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 (
|
||||||
@ -23,9 +24,15 @@ export default function Home() {
|
|||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row><WorkExperience /></Row>
|
<Row>
|
||||||
<Row><Education /></Row>
|
<Col xs={12} xl={7}>
|
||||||
<Row><Skills /></Row>
|
<Row><WorkExperience /></Row>
|
||||||
|
<Row><Education /></Row>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Row><Skills /></Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row><Footer /></Row>
|
<Row><Footer /></Row>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user