Skip to content

Commit

Permalink
[Lecture 7]
Browse files Browse the repository at this point in the history
- add styles
- update slides
- add homework description
- update codebase to React-router 6
- add hw-7 video presentation
  • Loading branch information
Artem Halas committed May 5, 2022
1 parent a82d6fd commit ccf6f03
Show file tree
Hide file tree
Showing 15 changed files with 1,018 additions and 1,808 deletions.
34 changes: 34 additions & 0 deletions homework/weather/exercise7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Homework 7 - The Weather Widget

**All installation, running, style, and submission requirements from Homework 5 still apply.**

## Prerequisites
* Server application is running on [https://forecast-ut-88jlk.ondigitalocean.app/](https://forecast-ut-88jlk.ondigitalocean.app/) host
* Please go through [API documentation](https://github.com/artem-galas/forecast-ut#api)

## Add functionality to Weather Widget ( 10 / 10 points)

Adding routes to you application

* `/` route - where is simple display dashboard from previous homework
* `/widgets` routes - displays list of the widgets (just city name)
* `/widgets/:id` - will display **detailed** weather information
* `/history` - display history of used cities
* Not found cases should be covered

Click on "History" button will navigate to `/history` page
Click on "All Widgets" button will navigate to `/widgets` page
Click on "+ Add Widget" button will navigate to dashboard `/`

**NOTE:**
For routing [React-Router](https://reactrouter.com/docs/en/v6/getting-started/installation) should be installed

## Submission

* Requirements which cannot be validated due to missing dependencies from package.json will be awarded 0 points

## Sanity check

* Delete node_modules/ directory and JavaScript and CSS files from the public/ directory
* Run `yarn install && yarn lint && yarn test` and check that your tests pass
* Run `yarn start` and check that your application works as expected
56 changes: 56 additions & 0 deletions lecture_7/css/elements.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
input {
box-shadow: inset 0 0.0625em 0.125em rgb(10 10 10 / 5%);
max-width: 100%;
background-color: #fff;
border-radius: 4px;
color: #363636;
align-items: center;
border: 1px solid #dbdbdb;
display: inline-flex;
font-size: 16px;
justify-content: flex-start;
padding: 7px 11px;
position: relative;
vertical-align: top;
}

button {
font-size: 16px;
background-color: #485fc7;
border-radius: 4px;
border-color: transparent;
color: #fff;
cursor: pointer;
justify-content: center;
padding: 8px;
text-align: center;
white-space: nowrap;

&:disabled {
opacity: .5;
cursor: not-allowed;
}

&.green {
background-color: #48c78e;
}

&.red {
background-color: #f14668;
}
&.small {
font-size: 12px;
}
}

.notification {
border-radius: 4px;
position: relative;
padding: 8px 10px;

&.warning {
background-color: #ffe08a;
color: rgba(0,0,0,.7);
}
}

68 changes: 68 additions & 0 deletions lecture_7/css/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap');
@import "elements";

body {
margin: 0;
padding: 0;
}

* {
font-family: 'Lato', sans-serif;
box-sizing: border-box;
}

.app {
width: 500px;
margin: 0 auto;
}

.comment-form {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 16px;

h2 {
margin-bottom: 0;
}
}

.input__container {
width: 100%;

label {
display: inline-block;
margin-bottom: 8px;
}

input {
width: 100%;
}
}

.commentList {
margin: 16px 0;
}

.comment {
p {
margin: 0;
&.comment-author {
font-weight: bold;
margin-bottom: 8px;
}
}
+.comment {
margin-top: 16px;
}
&__action {
margin-top: 8px;
}
}

.filter {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}
9 changes: 4 additions & 5 deletions lecture_7/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@
"eslint-plugin-react": "^7.22.0",
"express": "^4.17.1",
"jest": "^27.4.7",
"postcss": "^8.2.6",
"postcss-import": "^14.0.0",
"prettier": "^2.2.1",
"rollup": "^2.39.1",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-scss": "^3.0.0",
"rollup-plugin-serve": "^1.1.0",
"sass": "^1.48.0",
"uuid": "^8.3.2"
},
"scripts": {
Expand All @@ -53,8 +52,8 @@
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"websocket": "^1.0.34"
}
}
1 change: 1 addition & 0 deletions lecture_7/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<head>
<meta charset="utf-8"/>
<title>DOM History API</title>
<link rel="stylesheet" href="/app.css">
<script type="text/javascript" src="/app.js" defer=true></script>
</head>
<body>
Expand Down
5 changes: 2 additions & 3 deletions lecture_7/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import replace from "@rollup/plugin-replace";
import { babel } from "@rollup/plugin-babel";
import postcss from "rollup-plugin-postcss";
import scss from "rollup-plugin-scss";
import serve from "rollup-plugin-serve";
import postCssImport from "postcss-import";
import livereload from "rollup-plugin-livereload";

const outputFolder = "public";
Expand All @@ -31,7 +30,7 @@ export default {
preventAssignment: true,
}),
babel({ babelHelpers: "bundled" }),
postcss({ plugins: [postCssImport] }),
scss({sourceMap: true}),
].concat(
watching
? [
Expand Down
29 changes: 16 additions & 13 deletions lecture_7/src/router-basics/components/App.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
import React, { useReducer } from "react";
import PropTypes from "prop-types";
import AppHeader from "../components/AppHeader";
import { BrowserRouter, Route } from "react-router-dom";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import {
reducer,
initializer,
filter,
filteredComments,
findCommentById,
filterSet,
filterSet
} from "../Comments";
import CommentFormWithServer from "./CommentFormWithServer";
import Filter from "./Filter";
import CommentListWithServer from "./CommentListWithServer";
import { ServerContext } from "../ServerContext";
import useServerBasedOnParams from "../hooks/UseServerBasedOnParams";
import { RoutedComment } from "./CommentOrNotFound";
import { CommentOrNotFound } from "./CommentOrNotFound";
import "../../../css/index.scss";

const CommentListWithFilter = ({ state, dispatch }) => {
const filterValue = filter(state);
const commentsRequestState = filteredComments(state);
const onFilterChange = (filterValue) => dispatch(filterSet(filterValue));
return (
<Route path="/comments">
<>
<Filter value={filterValue} onChange={onFilterChange} />
<CommentListWithServer
dispatch={dispatch}
requestState={commentsRequestState}
/>
</Route>
</>
);
};

CommentListWithFilter.propTypes = {
state: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired
};

const StateApp = () => {
Expand Down Expand Up @@ -84,14 +85,16 @@ const StateApp = () => {
* `Route`.
*/
return (
<div>
<div className="app">
<AppHeader />
<Route
path="/addComment"
render={() => <CommentFormWithServer dispatch={dispatch} />}
/>
<CommentListWithFilter state={state} dispatch={dispatch} />
<RoutedComment findCommentById={findComment} dispatch={dispatch} />
<Routes>
<Route
path="/addComment" element={<CommentFormWithServer dispatch={dispatch} />}
/>
<Route path="/comments" element={<CommentListWithFilter state={state} dispatch={dispatch} />} />
<Route path="/comments/:commentId"
element={<CommentOrNotFound findCommentById={findComment} dispatch={dispatch} />} />
</Routes>
</div>
);
};
Expand Down
10 changes: 5 additions & 5 deletions lecture_7/src/router-basics/components/Comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import PropTypes from "prop-types";

const Comment = (props) => {
return (
<div className="comment">
<h3 className="comment-author">{props.author} said:</h3>
{props.children}
<div>
<button onClick={props.onDelete}>DELETE</button>
<div className="comment" role="listitem">
<p className="comment-author">{props.author} said:</p>
<p>{props.children}</p>
<div className="comment__action">
<button className="red small" onClick={props.onDelete}>Delete</button>
</div>
</div>
);
Expand Down
40 changes: 22 additions & 18 deletions lecture_7/src/router-basics/components/CommentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,28 @@ const CommentForm = (props) => {
return (
<div className="comment-form" title="Comment form">
<h3>Comment form</h3>
<label htmlFor="author-input">Author</label>
<input
id="author-input"
name="author"
type="text"
placeholder="Your name"
value={author}
onChange={onAuthorChange}
/>
<label htmlFor="text-input">Text</label>
<input
id="text-input"
name="text"
type="text"
placeholder="Say something..."
value={text}
onChange={onTextChange}
/>
<div className="input__container">
<label htmlFor="author-input">Author</label>
<input
id="author-input"
name="author"
type="text"
placeholder="Your name"
value={author}
onChange={onAuthorChange}
/>
</div>
<div className="input__container">
<label htmlFor="text-input">Text</label>
<input
id="text-input"
name="text"
type="text"
placeholder="Say something..."
value={text}
onChange={onTextChange}
/>
</div>
<button type="submit" onClick={submit}>
Submit comment
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import CommentForm from "./CommentForm";
import { ServerContext } from "../ServerContext";
import { commentSubmitted } from "../Comments";
Expand All @@ -16,7 +16,7 @@ const CommentFormWithServer = ({ dispatch }) => {
*/
const server = useContext(ServerContext);

const history = useHistory();
const navigate = useNavigate();

/*
* In contrast to `CommentListWithServer`, this component captures the
Expand Down Expand Up @@ -54,7 +54,7 @@ const CommentFormWithServer = ({ dispatch }) => {
.then(({ id }) => {
setRequestState({ inFlight: false, error: null });
dispatch(commentSubmitted({ id, author, text }));
history.push("/comments");
navigate("/comments");
})
.catch((error) => {
if (!error.isCanceled) {
Expand All @@ -68,7 +68,7 @@ const CommentFormWithServer = ({ dispatch }) => {
return <h3>Posting comment...</h3>;
} else if (requestState.error) {
return (
<div>
<div className="notification warning">
<p>Failed to post comment</p>
<p>{requestState.error}</p>
<CommentForm onSubmit={onSubmit} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const CommentListWithServer = ({ requestState, dispatch }) => {
return <h3>Fetching comments...</h3>;
} else if (requestState.error) {
return (
<div>
<div className="notification warning">
<h3>Failed to fetch comments</h3>
<p>{requestState.error}</p>
{requestButton}
Expand Down
Loading

0 comments on commit ccf6f03

Please sign in to comment.