mirror of https://github.com/mitchell/mjfs.us.git
Migrate project from JS+Flow to TypeScript
This commit is contained in:
parent
60a557f918
commit
356b95579e
|
@ -1,11 +0,0 @@
|
|||
extends:
|
||||
- 'standard'
|
||||
- 'plugin:react/recommended'
|
||||
- 'plugin:flowtype/recommended'
|
||||
- 'prettier'
|
||||
- 'prettier/flowtype'
|
||||
- 'prettier/react'
|
||||
- 'prettier/standard'
|
||||
plugins:
|
||||
- react
|
||||
- flowtype
|
12
.flowconfig
12
.flowconfig
|
@ -1,12 +0,0 @@
|
|||
[ignore]
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[lints]
|
||||
all=warn
|
||||
|
||||
[options]
|
||||
|
||||
[strict]
|
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
|
@ -3,13 +3,19 @@
|
|||
"version": "0.4.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome": "^1.1.8",
|
||||
"@fortawesome/fontawesome-free-solid": "^5.0.13",
|
||||
"@fortawesome/react-fontawesome": "^0.0.19",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.22",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.10.2",
|
||||
"@fortawesome/react-fontawesome": "^0.1.4",
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/node": "^12.7.3",
|
||||
"@types/react": "^16.9.2",
|
||||
"@types/react-dom": "^16.9.0",
|
||||
"@types/react-router-dom": "^4.3.5",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-scripts": "^3.0.1"
|
||||
"react-scripts": "^3.0.1",
|
||||
"typescript": "^3.5.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
@ -18,17 +24,9 @@
|
|||
"eject": "react-scripts eject"
|
||||
},
|
||||
"devDependencies": {
|
||||
"csslint": "^1.0.5",
|
||||
"eslint-config-prettier": "^2.10.0",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
"eslint-plugin-flowtype": "^2.50.3",
|
||||
"eslint-plugin-import": "^2.17.3",
|
||||
"eslint-plugin-node": "^6.0.1",
|
||||
"eslint-plugin-promise": "^3.8.0",
|
||||
"eslint-plugin-react": "^7.13.0",
|
||||
"eslint-plugin-standard": "^3.1.0",
|
||||
"flow-bin": "^0.76.0",
|
||||
"prettier": "^1.17.1"
|
||||
"prettier": "^1.17.1",
|
||||
"tslint": "^5.19.0",
|
||||
"tslint-config-prettier": "^1.18.0"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
|
||||
import Header from './components/Header'
|
||||
import Navbar from './components/Navbar'
|
||||
import Routes from './routes'
|
||||
|
||||
import './Website.css'
|
||||
|
||||
type Props = {}
|
||||
|
||||
class Website extends React.Component<Props> {
|
||||
render () {
|
||||
return (
|
||||
<div className='website'>
|
||||
<div className='main-container'>
|
||||
<Navbar />
|
||||
<Header />
|
||||
<Routes />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Website
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import Website from './Website.js'
|
||||
import React from "react"
|
||||
import ReactDOM from "react-dom"
|
||||
import Website from "./Website"
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div')
|
||||
it("renders without crashing", () => {
|
||||
const div = document.createElement("div")
|
||||
ReactDOM.render(<Website />, div)
|
||||
ReactDOM.unmountComponentAtNode(div)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import React from "react"
|
||||
|
||||
import Header from "./components/Header"
|
||||
import Navbar from "./components/Navbar"
|
||||
import Routes from "./routes"
|
||||
|
||||
import "./Website.css"
|
||||
|
||||
export default class Website extends React.Component {
|
||||
public render() {
|
||||
return (
|
||||
<div className="website">
|
||||
<div className="main-container">
|
||||
<Navbar />
|
||||
<Header />
|
||||
<Routes />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
|
||||
import './index.css'
|
||||
|
||||
type Props = {
|
||||
href: string,
|
||||
children: string
|
||||
}
|
||||
|
||||
class ClearButton extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return (
|
||||
<a className='clear-button' href={this.props.href}>
|
||||
{this.props.children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ClearButton
|
|
@ -0,0 +1,18 @@
|
|||
import React from "react"
|
||||
|
||||
import "./index.css"
|
||||
|
||||
type Props = {
|
||||
href: string
|
||||
children: string
|
||||
}
|
||||
|
||||
export default class ClearButton extends React.PureComponent<Props> {
|
||||
public render() {
|
||||
return (
|
||||
<a className="clear-button" href={this.props.href}>
|
||||
{this.props.children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
|
||||
import SmallText from '../SmallText'
|
||||
|
||||
import './index.css'
|
||||
|
||||
type Props = {}
|
||||
|
||||
class Header extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return (
|
||||
<div className='header-container'>
|
||||
<h2>Mitchell J. F. Simon</h2>
|
||||
<SmallText>
|
||||
Software engineer;
|
||||
<span style={{ display: 'inline-block' }}>
|
||||
cloud-native web services and clients
|
||||
</span>
|
||||
</SmallText>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Header
|
|
@ -0,0 +1,21 @@
|
|||
import React from "react"
|
||||
|
||||
import SmallText from "../SmallText"
|
||||
|
||||
import "./index.css"
|
||||
|
||||
export default class Header extends React.PureComponent {
|
||||
public render() {
|
||||
return (
|
||||
<div className="header-container">
|
||||
<h2>Mitchell J. F. Simon</h2>
|
||||
<SmallText>
|
||||
Software engineer;
|
||||
<span style={{ display: "inline-block" }}>
|
||||
cloud-native web services and clients
|
||||
</span>
|
||||
</SmallText>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
|
||||
import SmallText from '../../components/SmallText'
|
||||
import './index.css'
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
company: string,
|
||||
timeSpan: string,
|
||||
bullets: Array<string>
|
||||
}
|
||||
|
||||
class Experience extends React.PureComponent<Props> {
|
||||
listedBullets: Array<React.Element<string>>
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props)
|
||||
|
||||
this.listedBullets = this.props.bullets.map((bullet, index) => (
|
||||
<li key={index}>{bullet}</li>
|
||||
))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='job-container'>
|
||||
<div className='job-title'>{this.props.title}</div>
|
||||
<div className='job-company'>{this.props.company}</div>
|
||||
<SmallText>{this.props.timeSpan}</SmallText>
|
||||
<ul>{this.listedBullets}</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Experience
|
|
@ -0,0 +1,29 @@
|
|||
import * as React from "react"
|
||||
|
||||
import SmallText from "../../components/SmallText"
|
||||
import "./index.css"
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
company: string
|
||||
timeSpan: string
|
||||
bullets: string[]
|
||||
}
|
||||
|
||||
export default class Experience extends React.PureComponent<Props> {
|
||||
public render() {
|
||||
return (
|
||||
<div className="job-container">
|
||||
<div className="job-title">{this.props.title}</div>
|
||||
<div className="job-company">{this.props.company}</div>
|
||||
<SmallText>{this.props.timeSpan}</SmallText>
|
||||
<ul>{this.renderBullets()}</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
private renderBullets() {
|
||||
return this.props.bullets.map((bullet, index) => (
|
||||
<li key={index}>{bullet}</li>
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import FontAwesomeIcon from '@fortawesome/react-fontawesome'
|
||||
import faBars from '@fortawesome/fontawesome-free-solid/faBars'
|
||||
|
||||
import './index.css'
|
||||
import { routes } from '../../routes/routes.js'
|
||||
|
||||
const changeMenu = 800
|
||||
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
showMenu: boolean
|
||||
}
|
||||
|
||||
class Navbar extends React.Component<Props, State> {
|
||||
buttons: Array<NavLink<string>>
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props)
|
||||
|
||||
if (window.innerWidth <= changeMenu) {
|
||||
this.state = { showMenu: false }
|
||||
} else {
|
||||
this.state = { showMenu: true }
|
||||
}
|
||||
|
||||
this.buttons = routes.map(route => (
|
||||
<NavLink
|
||||
key={route.name}
|
||||
className='navbar-menu-button'
|
||||
activeClassName='active-button'
|
||||
exact={route.exact}
|
||||
to={route.path}
|
||||
onClick={this.closeMenu}
|
||||
>
|
||||
{route.name}
|
||||
</NavLink>
|
||||
))
|
||||
}
|
||||
|
||||
isMobile = () => window.innerWidth <= changeMenu
|
||||
|
||||
closeMenu = () => {
|
||||
window.scrollTo(0, 0)
|
||||
if (this.isMobile()) {
|
||||
this.setState({ showMenu: false })
|
||||
}
|
||||
}
|
||||
|
||||
toggleMenu = () => {
|
||||
if (this.isMobile() || !this.state.showMenu) {
|
||||
this.setState(prev => ({ showMenu: !prev.showMenu }))
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
let menuButton: ?React.Element<string>
|
||||
|
||||
if (this.isMobile()) {
|
||||
menuButton = (
|
||||
<div
|
||||
className={
|
||||
this.state.showMenu
|
||||
? 'navbar-button navbar-button-closed'
|
||||
: 'navbar-button'
|
||||
}
|
||||
onClick={this.toggleMenu}
|
||||
>
|
||||
<FontAwesomeIcon icon={faBars} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='navbar'>
|
||||
{menuButton}
|
||||
{this.state.showMenu ? (
|
||||
<div className='navbar-menu'>{this.buttons}</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Navbar
|
|
@ -0,0 +1,81 @@
|
|||
import { faBars } from "@fortawesome/free-solid-svg-icons"
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import * as React from "react"
|
||||
import { NavLink } from "react-router-dom"
|
||||
|
||||
import { routes } from "../../routes/routes"
|
||||
import "./index.css"
|
||||
|
||||
type State = {
|
||||
showMenu: boolean
|
||||
}
|
||||
|
||||
class Navbar extends React.Component<{}, State> {
|
||||
constructor(props: {}) {
|
||||
super(props)
|
||||
this.state = { showMenu: !this.isMobile() }
|
||||
}
|
||||
|
||||
public render() {
|
||||
let menuButton: JSX.Element | null = null
|
||||
|
||||
if (this.isMobile()) {
|
||||
menuButton = (
|
||||
<div
|
||||
className={
|
||||
this.state.showMenu
|
||||
? "navbar-button navbar-button-closed"
|
||||
: "navbar-button"
|
||||
}
|
||||
onClick={this.toggleMenu}
|
||||
>
|
||||
<FontAwesomeIcon icon={faBars} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="navbar">
|
||||
{menuButton}
|
||||
{this.state.showMenu ? (
|
||||
<div className="navbar-menu">{this.renderButtons()}</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private isMobile() {
|
||||
const mobileMenuMaximum = 800
|
||||
return window.innerWidth <= mobileMenuMaximum
|
||||
}
|
||||
|
||||
private toggleMenu() {
|
||||
if (this.isMobile() || !this.state.showMenu) {
|
||||
this.setState(prev => ({ showMenu: !prev.showMenu }))
|
||||
}
|
||||
}
|
||||
|
||||
private renderButtons() {
|
||||
return routes.map(route => (
|
||||
<NavLink
|
||||
key={route.name}
|
||||
className="navbar-menu-button"
|
||||
activeClassName="active-button"
|
||||
exact={route.exact}
|
||||
to={route.path}
|
||||
onClick={this.closeMenu}
|
||||
>
|
||||
{route.name}
|
||||
</NavLink>
|
||||
))
|
||||
}
|
||||
|
||||
private closeMenu() {
|
||||
window.scrollTo(0, 0)
|
||||
if (this.isMobile()) {
|
||||
this.setState({ showMenu: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Navbar
|
|
@ -1,42 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
|
||||
import ClearButton from '../../components/ClearButton'
|
||||
|
||||
import './index.css'
|
||||
|
||||
type Badge = {
|
||||
imgUrl: string,
|
||||
linkUrl: string,
|
||||
alt: string
|
||||
}
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
children: string,
|
||||
repoUrl: string,
|
||||
badges: Array<Badge>
|
||||
}
|
||||
|
||||
class Project extends React.PureComponent<Props> {
|
||||
renderBadges = (badges: Array<Badge>) => {
|
||||
return this.props.badges.map((badge, index) => (
|
||||
<a className='project-badge' href={badge.linkUrl} key={index}>
|
||||
<img src={badge.imgUrl} alt={badge.alt} />
|
||||
</a>
|
||||
))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='project-container'>
|
||||
<h4>{this.props.title}</h4>
|
||||
{this.renderBadges(this.props.badges)}
|
||||
<p>{this.props.children}</p>
|
||||
<ClearButton href={this.props.repoUrl}>Repository</ClearButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Project
|
|
@ -0,0 +1,39 @@
|
|||
import * as React from "react"
|
||||
|
||||
import ClearButton from "../../components/ClearButton"
|
||||
|
||||
import "./index.css"
|
||||
|
||||
type Badge = {
|
||||
imgUrl: string
|
||||
linkUrl: string
|
||||
alt: string
|
||||
}
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
children: string
|
||||
repoUrl: string
|
||||
badges: Badge[]
|
||||
}
|
||||
|
||||
export default class Project extends React.PureComponent<Props> {
|
||||
public render() {
|
||||
return (
|
||||
<div className="project-container">
|
||||
<h4>{this.props.title}</h4>
|
||||
{this.renderBadges(this.props.badges)}
|
||||
<p>{this.props.children}</p>
|
||||
<ClearButton href={this.props.repoUrl}>Repository</ClearButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderBadges(badges: Badge[]) {
|
||||
return this.props.badges.map((badge, index) => (
|
||||
<a className="project-badge" href={badge.linkUrl} key={index}>
|
||||
<img src={badge.imgUrl} alt={badge.alt} />
|
||||
</a>
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
|
||||
import './index.css'
|
||||
|
||||
type Props = {
|
||||
children: string
|
||||
}
|
||||
|
||||
class SmallText extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return <div className='small-text'>{this.props.children}</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default SmallText
|
|
@ -0,0 +1,10 @@
|
|||
// @flow
|
||||
import React from "react"
|
||||
|
||||
import "./index.css"
|
||||
|
||||
export default class SmallText extends React.PureComponent {
|
||||
public render() {
|
||||
return <div className="small-text">{this.props.children}</div>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
declare module "*.webp" {
|
||||
const value: any
|
||||
export default value
|
||||
}
|
15
src/index.js
15
src/index.js
|
@ -1,15 +0,0 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
|
||||
import './index.css'
|
||||
import Website from './Website'
|
||||
import registerServiceWorker from './registerServiceWorker'
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<Website />
|
||||
</BrowserRouter>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
registerServiceWorker()
|
|
@ -0,0 +1,15 @@
|
|||
import React from "react"
|
||||
import ReactDOM from "react-dom"
|
||||
import { BrowserRouter } from "react-router-dom"
|
||||
|
||||
import "./index.css"
|
||||
import registerServiceWorker from "./registerServiceWorker"
|
||||
import Website from "./Website"
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<Website />
|
||||
</BrowserRouter>,
|
||||
document.getElementById("root")
|
||||
)
|
||||
registerServiceWorker()
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="react-scripts" />
|
|
@ -1,40 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
|
||||
import { routes, redirects } from './routes.js'
|
||||
|
||||
type Props = {}
|
||||
|
||||
class Routes extends React.Component<Props> {
|
||||
routes: Array<Route>
|
||||
redirects: Array<Route>
|
||||
|
||||
constructor (props: Props) {
|
||||
super(props)
|
||||
|
||||
this.routes = routes.map(route => (
|
||||
<Route
|
||||
key={route.name}
|
||||
exact={route.exact}
|
||||
path={route.path}
|
||||
component={route.component}
|
||||
/>
|
||||
))
|
||||
|
||||
this.redirects = redirects.map(route => (
|
||||
<Route key={route.path} path={route.path} render={route.func} />
|
||||
))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Switch>
|
||||
{this.routes}
|
||||
{this.redirects}
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Routes
|
|
@ -0,0 +1,32 @@
|
|||
import React from "react"
|
||||
import { Route, Switch } from "react-router-dom"
|
||||
|
||||
import { redirects, routes } from "./routes"
|
||||
|
||||
export default class Routes extends React.Component {
|
||||
public render() {
|
||||
return (
|
||||
<Switch>
|
||||
{this.renderRoutes()}
|
||||
{this.renderRedirects()}
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
|
||||
private renderRoutes() {
|
||||
return routes.map(route => (
|
||||
<Route
|
||||
key={route.name}
|
||||
exact={route.exact}
|
||||
path={route.path}
|
||||
component={route.component}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
private renderRedirects() {
|
||||
return redirects.map(route => (
|
||||
<Route key={route.path} path={route.path} render={route.func} />
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// @flow
|
||||
import Home from '../screens/Home'
|
||||
import Projects from '../screens/Projects'
|
||||
import Contact from '../screens/Contact'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Home,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/projects',
|
||||
name: 'Projects',
|
||||
component: Projects,
|
||||
exact: false
|
||||
},
|
||||
{
|
||||
path: '/contact',
|
||||
name: 'Contact',
|
||||
component: Contact,
|
||||
exact: false
|
||||
}
|
||||
]
|
||||
|
||||
const redirects = [
|
||||
{
|
||||
path: '/linkedin',
|
||||
func: () => (window.location = 'https://linkedin.com/in/mitchelljfsimon')
|
||||
}
|
||||
]
|
||||
|
||||
export { routes, redirects }
|
|
@ -0,0 +1,34 @@
|
|||
import Contact from "../screens/Contact"
|
||||
import Home from "../screens/Home"
|
||||
import Projects from "../screens/Projects"
|
||||
|
||||
export const routes = [
|
||||
{
|
||||
component: Home,
|
||||
exact: true,
|
||||
name: "Home",
|
||||
path: "/"
|
||||
},
|
||||
{
|
||||
component: Projects,
|
||||
exact: false,
|
||||
name: "Projects",
|
||||
path: "/projects"
|
||||
},
|
||||
{
|
||||
component: Contact,
|
||||
exact: false,
|
||||
name: "Contact",
|
||||
path: "/contact"
|
||||
}
|
||||
]
|
||||
|
||||
export const redirects = [
|
||||
{
|
||||
func: () => {
|
||||
window.location.replace("https://linkedin.com/in/mitchelljfsimon")
|
||||
return null
|
||||
},
|
||||
path: "/linkedin"
|
||||
}
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
|
||||
import './index.css'
|
||||
import linkedIn from '../../images/In-2C-128px-TM.png'
|
||||
|
||||
type Props = {}
|
||||
|
||||
class Contact extends React.PureComponent<Props> {
|
||||
render () {
|
||||
return (
|
||||
<div className='contact-container'>
|
||||
<p>m@mjfs.us</p>
|
||||
<a href='https://www.linkedin.com/in/mitchelljfsimon/'>
|
||||
<img src={linkedIn} alt='LinkedIn' />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Contact
|
|
@ -0,0 +1,17 @@
|
|||
import React from "react"
|
||||
|
||||
import linkedIn from "../../images/In-2C-128px-TM.png"
|
||||
import "./index.css"
|
||||
|
||||
export default class Contact extends React.PureComponent {
|
||||
public render() {
|
||||
return (
|
||||
<div className="contact-container">
|
||||
<p>m@mjfs.us</p>
|
||||
<a href="https://www.linkedin.com/in/mitchelljfsimon/">
|
||||
<img src={linkedIn} alt="LinkedIn" />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
|
||||
import './index.css'
|
||||
import JobComponent from '../../components/Job'
|
||||
|
||||
import jobsData from '../../data/jobs.json'
|
||||
|
||||
type Props = {}
|
||||
|
||||
type Job = {
|
||||
timeSpan: string,
|
||||
title: string,
|
||||
company: string,
|
||||
bullets: Array<string>
|
||||
}
|
||||
|
||||
class Experience extends React.PureComponent<Props> {
|
||||
renderJobs = (jobs: Array<Job>) => {
|
||||
return jobs.map(job => (
|
||||
<JobComponent
|
||||
key={job.title}
|
||||
title={job.title}
|
||||
company={job.company}
|
||||
timeSpan={job.timeSpan}
|
||||
bullets={job.bullets}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='experience-container'>{this.renderJobs(jobsData)}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Experience
|
|
@ -0,0 +1,32 @@
|
|||
import * as React from "react"
|
||||
|
||||
import Job from "../../components/Job"
|
||||
import jobsData from "../../data/jobs.json"
|
||||
import "./index.css"
|
||||
|
||||
type JobData = {
|
||||
title: string
|
||||
company: string
|
||||
timeSpan: string
|
||||
bullets: string[]
|
||||
}
|
||||
|
||||
export default class Experience extends React.PureComponent {
|
||||
public render() {
|
||||
return (
|
||||
<div className="experience-container">{this.renderJobs(jobsData)}</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderJobs(jobs: JobData[]) {
|
||||
return jobs.map(job => (
|
||||
<Job
|
||||
key={job.title}
|
||||
title={job.title}
|
||||
company={job.company}
|
||||
timeSpan={job.timeSpan}
|
||||
bullets={job.bullets}
|
||||
/>
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,16 +1,13 @@
|
|||
// @flow
|
||||
import React from 'react'
|
||||
import * as React from "react"
|
||||
|
||||
import './index.css'
|
||||
import profile from '../../images/profile.webp'
|
||||
import profile from "../../images/profile.webp"
|
||||
import "./index.css"
|
||||
|
||||
type Props = {}
|
||||
|
||||
class Home extends React.PureComponent<Props> {
|
||||
render () {
|
||||
export default class Home extends React.PureComponent {
|
||||
public render() {
|
||||
return (
|
||||
<div className='home-container'>
|
||||
<img src={profile} alt='Profile' />
|
||||
<div className="home-container">
|
||||
<img src={profile} alt="Profile" />
|
||||
<p>Hello and welcome,</p>
|
||||
<p>
|
||||
I am a software developer, with most of my experience in web services.
|
||||
|
@ -32,10 +29,8 @@ class Home extends React.PureComponent<Props> {
|
|||
Thank you for reading my quick bio. If you would like to contact me
|
||||
visit the contact page for all of your options.
|
||||
</p>
|
||||
<p className='signature'>- Mitchell J. F. Simon, III</p>
|
||||
<p className="signature">- Mitchell J. F. Simon, III</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Home
|
|
@ -1,48 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react'
|
||||
|
||||
import ProjectComponent from '../../components/Project'
|
||||
|
||||
import './index.css'
|
||||
|
||||
import projectsData from '../../data/projects.json'
|
||||
|
||||
type Props = {}
|
||||
|
||||
type Badge = {
|
||||
imgUrl: string,
|
||||
linkUrl: string,
|
||||
alt: string
|
||||
}
|
||||
|
||||
type Project = {
|
||||
title: string,
|
||||
repoUrl: string,
|
||||
badges: Array<Badge>,
|
||||
description: string
|
||||
}
|
||||
|
||||
class Projects extends React.PureComponent<Props> {
|
||||
renderProjects = (projects: Array<Project>) => {
|
||||
return projects.map(project => (
|
||||
<ProjectComponent
|
||||
key={project.title}
|
||||
title={project.title}
|
||||
repoUrl={project.repoUrl}
|
||||
badges={project.badges}
|
||||
>
|
||||
{project.description}
|
||||
</ProjectComponent>
|
||||
))
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='projects-container'>
|
||||
{this.renderProjects(projectsData)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Projects
|
|
@ -0,0 +1,44 @@
|
|||
// @flow
|
||||
import * as React from "react"
|
||||
|
||||
import Project from "../../components/Project"
|
||||
|
||||
import "./index.css"
|
||||
|
||||
import projectsData from "../../data/projects.json"
|
||||
|
||||
type BadgeData = {
|
||||
imgUrl: string
|
||||
linkUrl: string
|
||||
alt: string
|
||||
}
|
||||
|
||||
type ProjectData = {
|
||||
title: string
|
||||
repoUrl: string
|
||||
badges: BadgeData[]
|
||||
description: string
|
||||
}
|
||||
|
||||
export default class Projects extends React.PureComponent {
|
||||
public render() {
|
||||
return (
|
||||
<div className="projects-container">
|
||||
{this.renderProjects(projectsData)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderProjects(projects: ProjectData[]) {
|
||||
return projects.map(project => (
|
||||
<Project
|
||||
key={project.title}
|
||||
title={project.title}
|
||||
repoUrl={project.repoUrl}
|
||||
badges={project.badges}
|
||||
>
|
||||
{project.description}
|
||||
</Project>
|
||||
))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "build/dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"jsx": "react",
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "src",
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build",
|
||||
"scripts",
|
||||
"acceptance-tests",
|
||||
"webpack",
|
||||
"jest",
|
||||
"src/setupTests.ts"
|
||||
],
|
||||
"types": ["typePatches"],
|
||||
"include": ["src"]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
||||
"defaultSeverity": "warning",
|
||||
"rules": {
|
||||
"semicolon": false,
|
||||
"resolve-json-module": true,
|
||||
"interface-over-type-literal": false
|
||||
},
|
||||
"linterOptions": {
|
||||
"exclude": ["config/**/*.js", "node_modules/**/*.ts"]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue