diff --git a/package.json b/package.json
index 1178eb9..a95d346 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,9 @@
"dependencies": {
"inferno": "^3.9.0",
"inferno-component": "^3.9.0",
- "inferno-scripts": "4.2.0"
+ "inferno-router": "^3.9.0",
+ "inferno-scripts": "4.2.0",
+ "milligram": "^1.3.0"
},
"proxy": "http://localhost:3000",
"scripts": {
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index bd8fe9f..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,22 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 80px;
-}
-
-.App-header {
- background-color: #f8f8f8;
- height: 150px;
- padding: 20px;
- color: #3d464d;
-}
-
-.App-intro {
- font-size: large;
-}
-
-code {
- color: #e73a37;
-}
\ No newline at end of file
diff --git a/src/App.js b/src/App.js
index 8038db6..398e404 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,21 +1,17 @@
-import { version } from 'inferno';
import Component from 'inferno-component';
import './registerServiceWorker';
-import Logo from './logo';
-import './App.css';
+
+import Navbar from './Navbar';
class App extends Component {
- render() {
+ render({ children }) {
return (
-
-
-
-
{`Welcome to Inferno ${version}`}
-
-
- To get started, edit src/App.js
and save to reload.
-
-
+
+
+
+
);
}
}
diff --git a/src/Login/index.js b/src/Login/index.js
new file mode 100644
index 0000000..7116037
--- /dev/null
+++ b/src/Login/index.js
@@ -0,0 +1,35 @@
+import Component from 'inferno-component';
+
+class Login extends Component {
+ state = {
+ email: ''
+ }
+ onChange = e => {
+ this.setState({ email: e.target.value })
+ }
+ onSubmit = e => {
+ e.preventDefault();
+ const { email } = this.state;
+ window.email = email;
+ window.localStorage.setItem('email', email);
+ window.browserHistory.push('/')
+ }
+ render() {
+ const { email } = this.state;
+
+ return (
+
+
Login
+
+
+ )
+ }
+}
+
+export default Login;
diff --git a/src/Logout/index.js b/src/Logout/index.js
new file mode 100644
index 0000000..5fbe255
--- /dev/null
+++ b/src/Logout/index.js
@@ -0,0 +1,13 @@
+import Component from 'inferno-component';
+
+class Logout extends Component {
+ render() {
+ window.email = '';
+ window.localStorage.removeItem('email');
+ window.browserHistory.push('/')
+
+ return
+ }
+}
+
+export default Logout;
diff --git a/src/Navbar/index.js b/src/Navbar/index.js
new file mode 100644
index 0000000..044fd7f
--- /dev/null
+++ b/src/Navbar/index.js
@@ -0,0 +1,17 @@
+import './navbar.css';
+import { Link } from 'inferno-router';
+
+export default () => (
+
+)
diff --git a/src/Navbar/navbar.css b/src/Navbar/navbar.css
new file mode 100644
index 0000000..a427b25
--- /dev/null
+++ b/src/Navbar/navbar.css
@@ -0,0 +1,53 @@
+.navigation {
+ background:#f4f5f6;
+ border-bottom:.1rem solid #d1d1d1;
+ display:block;
+ height:5.2rem;
+ left:0;
+ max-width:100%;
+ position:fixed;
+ right:0;
+ top:0;
+ width:100%;
+ z-index:1
+}
+.navigation .container {
+ padding-bottom:0;
+ padding-top:0
+}
+.navigation .navigation-list {
+ list-style:none;
+ margin-bottom:0;
+ margin-right:5rem
+}
+@media (min-width:80rem) {
+ .navigation .navigation-list {
+ margin-right:0
+ }
+}
+.navigation .navigation-item {
+ float:left;
+ margin-bottom:0;
+ margin-left:2.5rem;
+ position:relative
+}
+.navigation .img {
+ fill:#9b4dca;
+ height:2rem;
+ position:relative;
+ top:.3rem
+}
+.navigation .navigation-title,.navigation .title {
+ color:#606c76;
+ position:relative
+}
+.navigation .navigation-link,.navigation .navigation-title,.navigation .title {
+ display:inline;
+ font-size:1.6rem;
+ line-height:5.2rem;
+ padding:0;
+ text-decoration:none
+}
+.navigation .navigation-link.active {
+ color:#606c76
+}
diff --git a/src/QuestionViewer/index.js b/src/QuestionViewer/index.js
new file mode 100644
index 0000000..cd35227
--- /dev/null
+++ b/src/QuestionViewer/index.js
@@ -0,0 +1,33 @@
+/* global fetchWithAuth */
+
+import Component from 'inferno-component';
+
+class QuestionViewer extends Component {
+ state = {
+ question: {},
+ loading: true,
+ error: '',
+ }
+ async componentDidMount() {
+ const { qno } = this.props.params;
+ var res = await fetchWithAuth(`/questions/${qno}`);
+ res = await res.json();
+ if (!res.error) this.setState({ question: res, loading: false })
+ else this.setState({ error: res.error, loading: false })
+ }
+ render() {
+ const { loading, question, error } = this.state
+ return (
+
+ {loading &&
Loading...
}
+
Q{question.qno}: {question.title}
+
+ {question.body}
+
+ {error &&
ERROR: {error}
}
+
+ )
+ }
+}
+
+export default QuestionViewer;
diff --git a/src/QuestionsList/index.js b/src/QuestionsList/index.js
new file mode 100644
index 0000000..b7806b2
--- /dev/null
+++ b/src/QuestionsList/index.js
@@ -0,0 +1,41 @@
+/* global fetchWithAuth */
+
+import Component from 'inferno-component';
+import { Link } from 'inferno-router';
+
+class QuestionsList extends Component {
+ state = {
+ questions: [],
+ loading: true,
+ error: '',
+ }
+ async componentDidMount() {
+ var res = await fetchWithAuth('/questions');
+ res = await res.json();
+ if (!res.error) this.setState({ questions: res, loading: false })
+ else this.setState({ error: res.error, loading: false })
+ }
+ render() {
+ const { loading, questions, error } = this.state
+ return (
+
+ {!window.email ?
+
+ :
+
+ }
+
Questions
+ {loading &&
Loading...
}
+
+ {questions.map(question => (
+ -
+ {question.title}
+
))}
+
+ {error &&
ERROR: {error}
}
+
+ )
+ }
+}
+
+export default QuestionsList;
diff --git a/src/fetchWithAuth.js b/src/fetchWithAuth.js
new file mode 100644
index 0000000..7769daa
--- /dev/null
+++ b/src/fetchWithAuth.js
@@ -0,0 +1,18 @@
+window.fetchWithAuth = (url, options = {}) => {
+ url = url.startsWith('/') ? url : '/' + url;
+ var body = options.body;
+ if (body && typeof body.getAll !== 'function') { // is not formdata
+ body = new FormData();
+ for ( var key in options.body ) {
+ body.append(key, options.body[key]);
+ }
+ }
+ return fetch(url, {
+ ...options,
+ body,
+ headers: {
+ ...options.headers,
+ email: window.email
+ }
+ })
+}
diff --git a/src/index.css b/src/index.css
index bac0002..d29c531 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,5 +1,19 @@
-body {
- margin: 0;
- padding: 0;
- font-family: "Open Sans", "lucida grande", "Segoe UI", arial, verdana, "lucida sans unicode", tahoma, sans-serif;
+@import "../node_modules/milligram/dist/milligram.min.css";
+
+.wrapper {
+ display:block;
+ overflow:hidden;
+ position:relative;
+ width:100%
+}
+.wrapper .container {
+ max-width:80rem
+}
+.wrapper>.container {
+ padding-bottom:7.5rem;
+ padding-top:7.5rem
+}
+
+.error {
+ color: red;
}
diff --git a/src/index.js b/src/index.js
index 1d556d4..8d6ccdb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,4 +2,30 @@ import { render } from 'inferno';
import App from './App';
import './index.css';
-render(, document.getElementById('app'));
+import { Router, Route, IndexRoute } from 'inferno-router';
+import createBrowserHistory from 'history/createBrowserHistory';
+
+import './fetchWithAuth';
+
+import Login from './Login';
+import Logout from './Logout';
+import QuestionsList from './QuestionsList';
+import QuestionViewer from './QuestionViewer';
+
+const browserHistory = createBrowserHistory();
+window.browserHistory = browserHistory;
+
+window.email = window.localStorage.getItem('email')
+
+const routes = (
+
+
+
+
+
+
+
+
+);
+
+render(routes, document.getElementById('app'));
diff --git a/src/logo.js b/src/logo.js
deleted file mode 100644
index de95269..0000000
--- a/src/logo.js
+++ /dev/null
@@ -1,23 +0,0 @@
-export default ({ width, height }) => {
- return (
-
- );
-};
diff --git a/yarn.lock b/yarn.lock
index dc070dc..1770c23 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2874,6 +2874,16 @@ he@1.1.x:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+history@^4.7.2:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
+ dependencies:
+ invariant "^2.2.1"
+ loose-envify "^1.2.0"
+ resolve-pathname "^2.2.0"
+ value-equal "^0.4.0"
+ warning "^3.0.0"
+
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -3042,7 +3052,7 @@ indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
-inferno-component@3.9.0, inferno-component@^3.7.0:
+inferno-component@3.9.0, inferno-component@^3.7.0, inferno-component@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/inferno-component/-/inferno-component-3.9.0.tgz#26a653bd9f055df49116facf54321ece990798f8"
dependencies:
@@ -3050,6 +3060,15 @@ inferno-component@3.9.0, inferno-component@^3.7.0:
inferno-shared "3.9.0"
inferno-vnode-flags "3.9.0"
+inferno-create-element@3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/inferno-create-element/-/inferno-create-element-3.9.0.tgz#7b7a15a2b3f9ae57e353b29640e01cc6e1abce7d"
+ dependencies:
+ inferno "3.9.0"
+ inferno-component "3.9.0"
+ inferno-shared "3.9.0"
+ inferno-vnode-flags "3.9.0"
+
inferno-dev-utils@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/inferno-dev-utils/-/inferno-dev-utils-3.2.0.tgz#cdddaf555658ffda48fd27473e73c6ca088556a1"
@@ -3084,6 +3103,19 @@ inferno-error-overlay@^2.2.0:
settle-promise "1.0.0"
source-map "0.5.6"
+inferno-router@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/inferno-router/-/inferno-router-3.9.0.tgz#15ae0263a8ab724ff939ab18e2f4fa8ccf47b3fb"
+ dependencies:
+ history "^4.7.2"
+ inferno "3.9.0"
+ inferno-component "3.9.0"
+ inferno-create-element "3.9.0"
+ inferno-shared "3.9.0"
+ inferno-vnode-flags "3.9.0"
+ path-to-regexp "^1.7.0"
+ path-to-regexp-es6 "0.0.2"
+
inferno-scripts@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/inferno-scripts/-/inferno-scripts-4.2.0.tgz#d9dba9c46712f900746f993def723bbeb99ab3a4"
@@ -3146,7 +3178,7 @@ inferno-vnode-flags@3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/inferno-vnode-flags/-/inferno-vnode-flags-3.9.0.tgz#8e358803b8c396788070d54786d86894cecd4a46"
-inferno@3.9.0, inferno@^3.7.0:
+inferno@3.9.0, inferno@^3.7.0, inferno@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/inferno/-/inferno-3.9.0.tgz#4e9a312e9929abb741dfe285630841b0d7e95e62"
dependencies:
@@ -3220,7 +3252,7 @@ interpret@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0"
-invariant@^2.2.2:
+invariant@^2.2.1, invariant@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
dependencies:
@@ -4005,7 +4037,7 @@ longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
-loose-envify@^1.0.0:
+loose-envify@^1.0.0, loose-envify@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -4133,6 +4165,12 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
+milligram@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/milligram/-/milligram-1.3.0.tgz#a5d980ef8eaf79337c96a8d7c7e176764931042c"
+ dependencies:
+ normalize.css "~5.0.0"
+
"mime-db@>= 1.29.0 < 2", mime-db@~1.30.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
@@ -4339,6 +4377,10 @@ normalize-url@^1.4.0:
query-string "^4.1.0"
sort-keys "^1.0.0"
+normalize.css@~5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-5.0.0.tgz#7cec875ce8178a5333c4de80b68ea9c18b9d7c37"
+
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -4595,11 +4637,21 @@ path-parse@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+path-to-regexp-es6@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/path-to-regexp-es6/-/path-to-regexp-es6-0.0.2.tgz#80cf615ce3220a29af9fe54f8862c730d9b56e0b"
+ dependencies:
+ path-to-regexp "*"
+
+path-to-regexp@*:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.0.0.tgz#b77a8168c2e78bc31f3d312d71b1ace97df23870"
+
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
-path-to-regexp@^1.0.1:
+path-to-regexp@^1.0.1, path-to-regexp@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
dependencies:
@@ -5362,6 +5414,10 @@ resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+resolve-pathname@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879"
+
resolve@1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
@@ -6179,6 +6235,10 @@ validate-npm-package-license@^3.0.1:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
+value-equal@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
+
vary@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
@@ -6207,6 +6267,12 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
+warning@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
+ dependencies:
+ loose-envify "^1.0.0"
+
watch@~0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc"