diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..e5d84f2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/package-lock.json b/package-lock.json index 81c241f..2ce7055 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@types/styled-components": "^5.1.25", "@vitejs/plugin-react": "^1.0.7", "gh-pages": "^3.2.3", + "prettier": "^3.0.0", "typescript": "^4.5.4", "vite": "^2.9.0" } @@ -1662,6 +1663,21 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -3067,6 +3083,12 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true + }, "react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", diff --git a/package.json b/package.json index d64db99..e6390f8 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "deploy": "gh-pages -d dist", "dev": "vite", "build": "tsc && vite build", - "preview": "vite preview" + "preview": "vite preview", + "prettify": "prettier -w \"src/**/*{.ts,.tsx}\"" }, "dependencies": { "react": "^17.0.2", @@ -21,7 +22,8 @@ "@types/styled-components": "^5.1.25", "@vitejs/plugin-react": "^1.0.7", "gh-pages": "^3.2.3", + "prettier": "^3.0.0", "typescript": "^4.5.4", "vite": "^2.9.0" } -} +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index aca5d7e..0c82184 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,24 +1,26 @@ -import { Header } from './components/Header' -import { GlobalStyles } from './components/GlobalStyles' -import { About } from './components/About' -import { Contact } from './components/Contact' -import { ContentContainer, PageContainer } from './components/PageContainer' -import { Projects } from './components/Projects' +import { Header } from "./components/Header"; +import { GlobalStyles } from "./components/GlobalStyles"; +import { About } from "./components/About"; +import { Contact } from "./components/Contact"; +import { ContentContainer, PageContainer } from "./components/PageContainer"; +import { Projects } from "./components/Projects"; +import { Experience } from "./components/Experience"; function App() { - - return (<> - - - -
- - - - - - - ) + return ( + <> + + + +
+ + + {/* */} + + + + + ); } -export default App +export default App; diff --git a/src/components/About/index.tsx b/src/components/About/index.tsx index 867ed24..1d874f8 100644 --- a/src/components/About/index.tsx +++ b/src/components/About/index.tsx @@ -1,23 +1,26 @@ import { SectionContainer, SectionHeader, - SectionDescription, + SectionContent, Strong, -} from "../common.css" - +} from "../common.css"; export const About = () => { return ( Who am I? - - I am a web developer and a systems engineer with a passion for problem solving! - Graduating with a MSc in Big Data Science and Artificial Intelligence in 2020, on top of a BSc in Computer Science, I have a multi-faceted appreciation of all technologies. - - - I am always looking to make use of new and exciting technologies, frameworks, packages, and tools! - As such, I like to get stuck into a variety of different projects to get a wide scope of experience. - + + I am a web developer and a{" "} + systems engineer with a passion for + problem solving! Graduating with a MSc in Big Data Science and + Artificial Intelligence in 2020, on top of a BSc in Computer Science, I + have a multi-faceted appreciation of all technologies. + + + I am always looking to make use of new and exciting technologies, + frameworks, packages, and tools! As such, I like to get stuck into a + variety of different projects to get a wide scope of experience. + - ) -} \ No newline at end of file + ); +}; diff --git a/src/components/Contact/icons/Email.tsx b/src/components/Contact/icons/Email.tsx index 5d579b6..1618d48 100644 --- a/src/components/Contact/icons/Email.tsx +++ b/src/components/Contact/icons/Email.tsx @@ -1,7 +1,5 @@ -import { ContactIcon } from "../styles.css" +import { ContactIcon } from "../styles.css"; export const Email = () => { - return ( - - ) -} \ No newline at end of file + return ; +}; diff --git a/src/components/Contact/icons/LinkedIn.tsx b/src/components/Contact/icons/LinkedIn.tsx index ed61d4f..acbdcce 100644 --- a/src/components/Contact/icons/LinkedIn.tsx +++ b/src/components/Contact/icons/LinkedIn.tsx @@ -1,7 +1,5 @@ -import { ContactIcon } from "../styles.css" +import { ContactIcon } from "../styles.css"; export const LinkedIn = () => { - return ( - - ) -} \ No newline at end of file + return ; +}; diff --git a/src/components/Contact/index.tsx b/src/components/Contact/index.tsx index 4f9ec70..775f338 100644 --- a/src/components/Contact/index.tsx +++ b/src/components/Contact/index.tsx @@ -1,8 +1,11 @@ -import { SectionContainer, SectionHeader } from "../common.css" -import { Email } from "./icons/Email" -import { LinkedIn } from "./icons/LinkedIn" -import { ContactMethod, ContactMethodContainer, ContactText } from "./styles.css" - +import { SectionContainer, SectionHeader } from "../common.css"; +import { Email } from "./icons/Email"; +import { LinkedIn } from "./icons/LinkedIn"; +import { + ContactMethod, + ContactMethodContainer, + ContactText, +} from "./styles.css"; export const Contact = () => { return ( @@ -10,14 +13,14 @@ export const Contact = () => { Want to talk? - - via email - + + via email + - - via LinkedIn - + + via LinkedIn + - ) -} \ No newline at end of file + ); +}; diff --git a/src/components/Contact/styles.css.ts b/src/components/Contact/styles.css.ts index ad8c0b0..53a6819 100644 --- a/src/components/Contact/styles.css.ts +++ b/src/components/Contact/styles.css.ts @@ -1,5 +1,6 @@ import styled from "styled-components"; import { device } from "../../utils/media"; +import { theme } from "../common.css"; export const ContactMethodContainer = styled.div` display: flex; @@ -8,12 +9,13 @@ export const ContactMethodContainer = styled.div` `; export const ContactIcon = styled.i` - font-size: 2em; + font-size: 1.25em; padding: 8px; margin-right: 4px; width: 12px; ${device.tablet} { + font-size: 2em; margin-right: 8px; width: 24px; } @@ -21,6 +23,7 @@ export const ContactIcon = styled.i` margin-right: 12px; } ${device.desktop} { + font-size: 2.25em; margin-right: 16px; width: 28px; } @@ -32,8 +35,8 @@ export const ContactText = styled.span` border-bottom-right-radius: 4px; border-top-right-radius: 4px; padding: 0 4px; - background-color: #8888ff44; - border-left: 0px solid #8888ff88; + background-color: ${theme.colours.linkblue.background}; + border-left: 0px solid ${theme.colours.linkblue.foreground}; transition: border 100ms ease-in-out; @@ -59,10 +62,22 @@ export const ContactMethod = styled.a` height: 32px; text-decoration: none; - &:link { text-decoration: none; color: black; } - &:hover { text-decoration: none; color: black; } - &:visited { text-decoration: none; color: black; } - &:active { text-decoration: none; color: black; } + &:link { + text-decoration: none; + color: black; + } + &:hover { + text-decoration: none; + color: black; + } + &:visited { + text-decoration: none; + color: black; + } + &:active { + text-decoration: none; + color: black; + } &:hover ${ContactText} { border-left-width: 4px; @@ -80,4 +95,4 @@ export const ContactMethod = styled.a` ${device.laptop} { margin: 8px 0; } -`; \ No newline at end of file +`; diff --git a/src/components/Experience/experiences/Korelogic.tsx b/src/components/Experience/experiences/Korelogic.tsx new file mode 100644 index 0000000..9d3f16f --- /dev/null +++ b/src/components/Experience/experiences/Korelogic.tsx @@ -0,0 +1,47 @@ +import { SectionContent } from "../../common.css"; +import { + ExperienceHeaderRow, + ExperienceTitle, + ExperienceDates, + ExperienceDescription, + SkillRow, + SkillPill, +} from "../styles.css"; + +export const Korelogic = () => { + return ( + + + + Junior Javascript Developer - Korelogic Ltd + + Feb 2021 - Dec 2021 + + +
    +
  • Worked with external clients to deliver expected projects.
  • +
  • + Used work tracking tools and communicated progress with internal and + external teams on a daily basis. +
  • +
  • + Provided aide for the internal AWS architect for setting up and + maintaining project resources, IAM roles, and CloudFormation + templates +
  • +
  • + Developed new solutions using modern frameworks alongside + maintaining legacy systems +
  • +
+ + TypeScript + Project Management + AWS + Team Communication + Business-to-business (B2B) + +
+
+ ); +}; diff --git a/src/components/Experience/experiences/ShopAppy.tsx b/src/components/Experience/experiences/ShopAppy.tsx new file mode 100644 index 0000000..10fa69c --- /dev/null +++ b/src/components/Experience/experiences/ShopAppy.tsx @@ -0,0 +1,67 @@ +import { SectionContent } from "../../common.css"; +import { + ExperienceHeaderRow, + ExperienceTitle, + ExperienceDates, + ExperienceDescription, + SkillRow, + SkillPill, +} from "../styles.css"; + +export const ShopAppy = () => { + return ( + + + Lead Software Engineer - ShopAppy Ltd + Dec 2021 - Aug 2023 + + +

+ This role threw me into the deep-end in regards to responsibility, + workload, and expectations. Despite this, I managed to perform above + and beyond, leading the business to make huge savings by cutting off + an external agency, significantly improve the performance and + stability of their platform, lead new exciting projects to boost their + offerings, and more. +

+ Notable Achievements: +
    +
  • + Brought development in-house from previous usage of external + agencies. +
  • +
  • + Led a system-wide re-platforming, while managing external developers + to ensure deadlines were met. +
  • +
  • + Built a multi-purpose hub for integrating data with various external + systems +
  • +
  • + Developed a multi-environment infrastructure stack using AWS-CDK +
  • +
  • + Despite working remotely, built up a strong relationship with the + team and became the single source of truth across multiple layers of + the company. +
  • +
  • + Responsibility for maintaining site stability with responsive + action. +
  • +
+ + PHP + Project Management + TypeScript + Magento 2 + Team Communication + AWS + Business-to-business (B2B) + CI/CD + +
+
+ ); +}; diff --git a/src/components/Experience/index.tsx b/src/components/Experience/index.tsx new file mode 100644 index 0000000..9b16b1a --- /dev/null +++ b/src/components/Experience/index.tsx @@ -0,0 +1,26 @@ +import { + SectionContainer, + SectionContent, + SectionHeader, + Link, +} from "../common.css"; +import { Korelogic } from "./experiences/Korelogic"; +import { ShopAppy } from "./experiences/ShopAppy"; +import { + ExperienceHeaderRow, + ExperienceDates, + ExperienceDescription, + ExperienceTitle, + SkillRow, + SkillPill, +} from "./styles.css"; + +export const Experience = () => { + return ( + + Where have I been? + + + + ); +}; diff --git a/src/components/Experience/styles.css.ts b/src/components/Experience/styles.css.ts new file mode 100644 index 0000000..544d7f6 --- /dev/null +++ b/src/components/Experience/styles.css.ts @@ -0,0 +1,79 @@ +import styled, { css } from "styled-components"; +import { device } from "../../utils/media"; +import { theme } from "../common.css"; + +export const ExperienceHeaderRow = styled.div` + width: 100%; + display: flex; + flex-direction: column; + margin-bottom: 8px; + ${device.tablet} { + flex-direction: row; + align-items: center; + justify-content: space-between; + } +`; + +export const ExperienceTitle = styled.h3` + font-weight: 500; + font-size: 18px; + margin: 0; + + ${device.laptop} { + font-size: 22px; + } +`; + +export const ExperienceDates = styled.div` + float: right; + font-style: italic; + font-size: 14px; + color: ${theme.colours.darkgrey.foreground}; + ${device.laptop} { + font-size: 18px; + } +`; + +export const ExperienceDescription = styled.div` + width: 100%; + text-align: left; + + ${device.laptop} { + padding-left: 4px; + width: calc(100% - 4px); + } +`; + +export const SkillRow = styled.div` + display: flex; + flex-flow: row wrap; + justify-content: center; + ${device.tablet} { + justify-content: flex-start; + } +`; + +export const SkillPill = styled.div<{ colour?: keyof typeof theme.colours }>` + padding: 0 2px; + margin: 4px; + border-radius: 8px; + font-weight: 500; + font-size: 14px; + + ${device.laptop} { + padding: 0 4px; + font-size: 16px; + } + + ${(props) => + props.colour + ? css` + background-color: ${theme.colours[props.colour].background}; + ` + : css` + background-color: ${theme.colours.blue.background}; + &:nth-child(odd) { + background-color: ${theme.colours.green.background}; + } + `} +`; diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 10b3dd1..431afc6 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,7 +1,6 @@ -import { HeaderImage, HeaderName, HeaderRow } from "./styles.css" -import HeaderImageSource from "../../img/me.png" -import { useEffect, useRef, useState } from "react" - +import { HeaderImage, HeaderName, HeaderRow } from "./styles.css"; +import HeaderImageSource from "../../img/me.png"; +import { useEffect, useRef, useState } from "react"; export const Header = () => { const [fxStrength, setFxStrength] = useState(0); @@ -13,17 +12,19 @@ export const Header = () => { if (!ticking) { ticking = true; window.requestAnimationFrame(function () { - const value = headerRowRef.current ? Math.min(scrollY / headerRowRef.current.clientHeight, 1) : 0; + const value = headerRowRef.current + ? Math.min(scrollY / headerRowRef.current.clientHeight, 1) + : 0; setFxStrength(value); ticking = false; }); } - }) - }, []) + }); + }, []); return ( Ollie Beckwith - ) -} \ No newline at end of file + ); +}; diff --git a/src/components/Header/styles.css.ts b/src/components/Header/styles.css.ts index d593305..150f150 100644 --- a/src/components/Header/styles.css.ts +++ b/src/components/Header/styles.css.ts @@ -3,7 +3,7 @@ import { device } from "../../utils/media"; export const HeaderImage = styled.img` transition: all 100ms ease-in-out; - + box-sizing: border-box; border: 4px solid white; border-radius: 16px; @@ -29,12 +29,13 @@ export const HeaderRow = styled.div<{ effectStrength: number }>` padding: 16px 0; width: 100%; max-width: 1920px; - + ${device.laptop} { flex-direction: row; } - filter: blur(${props => props.effectStrength * 8}px) grayscale(${props => props.effectStrength}); + filter: blur(${(props) => props.effectStrength * 8}px) + grayscale(${(props) => props.effectStrength}); `; export const HeaderName = styled.h1` @@ -48,4 +49,4 @@ export const HeaderName = styled.h1` ${device.desktop} { font-size: 64px; } -`; \ No newline at end of file +`; diff --git a/src/components/PageContainer/index.ts b/src/components/PageContainer/index.ts index df355a1..3578d03 100644 --- a/src/components/PageContainer/index.ts +++ b/src/components/PageContainer/index.ts @@ -18,4 +18,4 @@ export const ContentContainer = styled.div` min-height: 100vh; box-shadow: 0 0 16px grey; } -`; \ No newline at end of file +`; diff --git a/src/components/Projects/index.tsx b/src/components/Projects/index.tsx index 35952b6..4401ddc 100644 --- a/src/components/Projects/index.tsx +++ b/src/components/Projects/index.tsx @@ -1,21 +1,23 @@ import { SectionContainer, - SectionDescription, + SectionContent, SectionHeader, Link, -} from "../common.css" +} from "../common.css"; export const Projects = () => { return ( What do I do? - + {"Most of my public projects are available to nosey through on "} GitHub - {". I also have various projects on the go that aren't public where I trial different technologies, frameworks, and more."} - + { + ". I also have various projects on the go that aren't public where I trial different technologies, frameworks, and more." + } + - ) -} \ No newline at end of file + ); +}; diff --git a/src/components/common.css.ts b/src/components/common.css.ts index 0dc76e2..0e89bc5 100644 --- a/src/components/common.css.ts +++ b/src/components/common.css.ts @@ -1,6 +1,31 @@ -import styled from "styled-components" +import styled, { css } from "styled-components"; import { device } from "../utils/media"; +export const theme = { + colours: { + linkblue: { + foreground: "#88bbff88", + background: "#88bbff44", + }, + blue: { + foreground: "#8888ff88", + background: "#8888ff44", + }, + green: { + foreground: "#44bb4488", + background: "#44bb4444", + }, + red: { + foreground: "#ff888888", + background: "#ff888844", + }, + darkgrey: { + foreground: "#444444ff", + background: "#44444444", + }, + }, +}; + export const SectionContainer = styled.div` padding: 0 8px; @@ -29,7 +54,7 @@ export const SectionHeader = styled.h2` } `; -export const SectionDescription = styled.p` +export const SectionContent = styled.p` line-height: 22px; text-align: center; font-size: 14px; @@ -49,34 +74,26 @@ export const SectionDescription = styled.p` } `; -export const Strong = styled.strong` - background-color: #8888ff44; +export const Strong = styled.strong<{ colour?: keyof typeof theme.colours }>` + ${props => props.colour ? css` + background-color: ${theme.colours[props.colour].background}; + ` : css` + background-color: ${theme.colours.green.background}; + `} white-space: nowrap; padding: 0 2px; - border-bottom: 0px solid #8888ff88; - border-top-left-radius: 4px; - border-top-right-radius: 4px; + border-radius: 4px; box-sizing: content-box; transition: border 100ms ease-in-out; font-weight: 500; - - &:hover { - border-bottom-width: 2px; - ${device.tablet} { - border-bottom-width: 3px; - } - ${device.desktop} { - border-bottom-width: 4px; - } - } `; export const Link = styled.a` cursor: pointer; - background-color: #8888ff44; + background-color: ${theme.colours.linkblue.background}; white-space: nowrap; padding: 0 2px; - border-bottom: 0px solid #8888ff88; + border-bottom: 0px solid ${theme.colours.linkblue.foreground}; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: content-box; @@ -84,7 +101,9 @@ export const Link = styled.a` font-weight: 500; text-decoration: none; color: black; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { text-decoration: none; color: black; } @@ -98,4 +117,4 @@ export const Link = styled.a` border-bottom-width: 4px; } } -`; \ No newline at end of file +`; diff --git a/src/main.tsx b/src/main.tsx index 432dac6..b1ef1c0 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,10 +1,10 @@ -import React from 'react' -import ReactDOM from 'react-dom' -import App from './App' +import React from "react"; +import ReactDOM from "react-dom"; +import App from "./App"; ReactDOM.render( , - document.getElementById('root') -) + document.getElementById("root") +); diff --git a/src/utils/media.ts b/src/utils/media.ts index b37b2c9..2cffe7e 100644 --- a/src/utils/media.ts +++ b/src/utils/media.ts @@ -4,7 +4,7 @@ export const breakpoint = { laptop: 768, desktop: 1024, widescreen: 1440, -} +}; /** Preset media queries for some basic min-width breakpoints */ export const device = { @@ -17,5 +17,5 @@ export const device = { /** Min width 1024px */ desktop: `@media (min-width: ${breakpoint.desktop}px)`, /** Min width 1440px */ - widescreen: `@media (min-width: ${breakpoint.widescreen}px)` -}; \ No newline at end of file + widescreen: `@media (min-width: ${breakpoint.widescreen}px)`, +};