From 76974503b769330ef5e2a20ef3982bbcfc900014 Mon Sep 17 00:00:00 2001 From: Eoin McCarthy Date: Wed, 16 Jan 2019 11:54:31 +0200 Subject: [PATCH] adds mock dashboard for freelancers related #21 #23 --- client/package.json | 1 + client/src/App.js | 35 ++++- client/src/components/EditableInput.js | 79 +++++++++-- client/src/components/FetchData.js | 48 +++++++ client/src/components/Request.js | 26 ++-- client/src/pages/DeveloperDashboard.js | 178 +++++++++++++++++++++++++ client/src/pages/GithubCallback.js | 2 +- client/src/pages/index.js | 3 +- client/src/styles/main.css | 7 + 9 files changed, 355 insertions(+), 24 deletions(-) create mode 100644 client/src/components/FetchData.js create mode 100644 client/src/pages/DeveloperDashboard.js diff --git a/client/package.json b/client/package.json index 117db32..ad7c4f2 100644 --- a/client/package.json +++ b/client/package.json @@ -16,6 +16,7 @@ "ramda": "^0.26.1", "react": "^16.6.3", "react-dom": "^16.6.3", + "react-input-autosize": "^2.2.1", "react-router-dom": "^4.3.1", "react-scripts": "2.1.1", "styled-components": "^4.1.2", diff --git a/client/src/App.js b/client/src/App.js index 840ceeb..8846bea 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,9 +1,9 @@ import React, { Component } from "react"; import { BrowserRouter as Router, Route } from "react-router-dom"; -import { Home, GithubCallback } from "./pages"; +import { Home, GithubCallback, DeveloperDashboard } from "./pages"; -import Request from "./components/Request"; +import FetchData from "./components/FetchData"; class App extends Component { renderPending = () => { @@ -18,16 +18,38 @@ class App extends Component { return ; }; + renderDeveloperDashboard = () => { + const mockProfile = { + name: "Eoin McCarthy", + jobTitle: "Full Stack Web Developer", + bio: + "Eoin, a member of the Founders and Coders network, joined the GSG team to lead the launch of the Digital Agency. Holding a masters in Applied Mathematics, Eoin worked as a web developer for 3 years, working for a number of startups in London across a diverse range of products, from FinTech to online publishing. Before joining GSG Eoin worked as a project lead on Founders and Coders commercial projects. Eoin has rich experience in tech education, previously serving as a mentor and Course Facilitator at the Founders and Coders campuses in London and Nazareth in addition to Gaza.", + employmentHistory: [ + { + title: "Engineering Manager", + company: "Gaza Sky Geeks", + dates: "January 2018 - current", + responsibilities: [ + "Creating Software outsourcing agency in the Gaza Strip", + "Creating custom software such as Gaza Talent" + ] + } + ] + }; + + return ; + }; + renderHome = () => { return ( - {listings => } - + ); }; @@ -40,6 +62,11 @@ class App extends Component { path="/github/callback" render={this.renderGithubCallback} /> + diff --git a/client/src/components/EditableInput.js b/client/src/components/EditableInput.js index 504c335..1fc38d6 100644 --- a/client/src/components/EditableInput.js +++ b/client/src/components/EditableInput.js @@ -1,10 +1,73 @@ import React from "react"; +import AutosizeInput from "react-input-autosize"; -export default ({ value, onClick, onSubmit, editable }) => - editable ? ( - - - - ) : ( - {value} - ); +export default class EditableInput extends React.Component { + constructor() { + super(); + + this.state = { + focused: false + }; + + this.onFocus = this.onFocus.bind(this); + this.onBlur = this.onBlur.bind(this); + } + + onFocus() { + this.setState({ + focused: true + }); + } + + onBlur() { + this.setState({ + focused: false + }); + } + + render() { + const { + props: { className, value, multiline }, + state: { focused } + } = this; + + return ( +
+ {focused ? ( + { + this.inputRef = i; + }} + inputStyle={{ + fontFamily: "inherit" + }} + type="text" + name={this.props.name} + onChange={this.props.onChange} + onBlur={this.onBlur} + placeholder={this.props.placeholder} + inputClassName={`mw-100 db input-reset outline-0 ba bw1 b--black ph2 pv0 ${className}`} + onKeyDown={e => { + console.log({ e, k: e.key }); + if (e.key === "Enter") this.onBlur(); + }} + /> + ) : ( + + {console.log(value, !!value, this.props.placeholder) || value !== "" + ? value + : this.props.placeholder} + + )} +
+ ); + } +} diff --git a/client/src/components/FetchData.js b/client/src/components/FetchData.js new file mode 100644 index 0000000..9018c99 --- /dev/null +++ b/client/src/components/FetchData.js @@ -0,0 +1,48 @@ +import { Component } from "react"; +import axios from "axios"; + +const PENDING = "PENDING"; +const ERROR = "ERROR"; +const DONE = "DONE"; + +export default class FetchData extends Component { + state = { + requestStatus: PENDING + }; + + componentDidMount() { + axios[this.props.method](this.props.url, { + headers: { + Authorization: `Bearer ${window.localStorage.getItem("jwt")}` + } + }).then( + response => { + this.setState({ + payload: response.data, + requestStatus: DONE + }); + }, + error => { + this.setState({ + error, + requestStatus: ERROR + }); + } + ); + } + + render() { + const { + state: { requestStatus, payload, error }, + props: { renderPending, renderError, children } + } = this; + + console.log("rendering", requestStatus); + + if (requestStatus === PENDING) return renderPending(); + + if (requestStatus === ERROR) return renderError(error); + + return children(payload); + } +} diff --git a/client/src/components/Request.js b/client/src/components/Request.js index 568eef3..e513b51 100644 --- a/client/src/components/Request.js +++ b/client/src/components/Request.js @@ -5,16 +5,23 @@ const PENDING = "PENDING"; const ERROR = "ERROR"; const DONE = "DONE"; -export default class Request extends Component { +export default class FetchData extends Component { + constructor(props) { + super(props); + + this.request = this.request.bind(this); + } + state = { requestStatus: PENDING }; - componentDidMount() { + request(payload) { axios[this.props.method](this.props.url, { headers: { Authorization: `Bearer ${window.localStorage.getItem("jwt")}` - } + }, + body: payload }).then( response => { this.setState({ @@ -37,12 +44,11 @@ export default class Request extends Component { props: { renderPending, renderError, children } } = this; - console.log("rendering", requestStatus); - - if (requestStatus === PENDING) return renderPending(); - - if (requestStatus === ERROR) return renderError(error); - - return children(payload); + return children({ + request: this.request, + payload, + status: requestStatus, + error + }); } } diff --git a/client/src/pages/DeveloperDashboard.js b/client/src/pages/DeveloperDashboard.js new file mode 100644 index 0000000..2733ee9 --- /dev/null +++ b/client/src/pages/DeveloperDashboard.js @@ -0,0 +1,178 @@ +import React from "react"; + +import EditableInput from "../components/EditableInput"; + +const Button = ({ children, onClick, className }) => { + return ( + + ); +}; + +const set = (o, k, v) => { + if (Array.isArray(o)) { + const i = parseInt(k, 10); + return [...o.slice(0, i), v, ...o.slice(i + 1)]; + } + + return { + ...o, + [k]: v + }; +}; + +const setIn = (o, p, v) => { + if (p.length === 0) { + console.error("Set in must be passed an array as a second paramiter"); + return o; + } + + if (p.length === 1) { + return set(o, p[0], v); + } + return set(o, p[0], setIn(o[p[0]], p.slice(1), v)); +}; + +export default class DeveloperDashboard extends React.Component { + constructor(props) { + super(props); + + this.state = { + profile: { + ...props.savedProfile + }, + focusedProperty: undefined + }; + + this.onChange = this.onChange.bind(this); + } + + onChange(e) { + const path = e.target.name.split("."); + this.setState({ + profile: setIn(this.state.profile, path, e.target.value) + }); + } + + render() { + const { + state: { + profile: { name, jobTitle, employmentHistory, bio } + }, + onChange + } = this; + + return ( +
+
+
+ +
+
+ +
+

+ Employment History +

+ {employmentHistory.map((employmentItem, i) => ( +
+
+ + {"-"} + +
+ +
    + {employmentItem.responsibilities.map((r, j) => ( +
  • + +
  • + ))} + +
+
+ ))} + +
+ + + +
+
+
+ ); + } +} diff --git a/client/src/pages/GithubCallback.js b/client/src/pages/GithubCallback.js index e3ebe0a..b2cf40f 100644 --- a/client/src/pages/GithubCallback.js +++ b/client/src/pages/GithubCallback.js @@ -11,7 +11,7 @@ class GithubCallback extends React.Component { axios.get(`/api/github/callback?code=${code}`).then(jwt => { window.localStorage.setItem("jwt", jwt.data.token); - this.props.history.push("/"); + this.props.history.push("/developer-dashboard"); }); } diff --git a/client/src/pages/index.js b/client/src/pages/index.js index 8045388..962fb9b 100644 --- a/client/src/pages/index.js +++ b/client/src/pages/index.js @@ -1,3 +1,4 @@ import Home from "./Home"; import GithubCallback from "./GithubCallback"; -export { Home, GithubCallback }; +import DeveloperDashboard from "./DeveloperDashboard"; +export { Home, GithubCallback, DeveloperDashboard }; diff --git a/client/src/styles/main.css b/client/src/styles/main.css index d58b368..95ed6b8 100644 --- a/client/src/styles/main.css +++ b/client/src/styles/main.css @@ -72,5 +72,12 @@ @import "tachyons-custom/src/_debug-children"; @import "tachyons-custom/src/_debug-grid"; +.pa05 { + padding: 0.125rem; +} +.bw05 { + padding: 0.0625rem; +} + /* Uncomment out the line below to help debug layout issues */ /* @import "tachyons-custom/src/_debug"; */