├── .gitignore ├── babel.config.js ├── src ├── index.js ├── App.js ├── components │ ├── Header.js │ ├── PostItem.js │ └── PostList.js └── App.css ├── public ├── index.html └── bundle.js ├── webpack.config.js ├── package.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/preset-env", "@babel/preset-react"], 3 | plugins: ["@babel/plugin-proposal-class-properties"] 4 | }; 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "react-dom"; 3 | 4 | import App from "./App"; 5 | 6 | render(, document.getElementById("app")); 7 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.css"; 3 | 4 | import Header from "./components/Header"; 5 | import PostList from "./components/PostList"; 6 | 7 | function App() { 8 | return ( 9 | <> 10 |
11 | 12 | 13 | ); 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function Header() { 4 | return ( 5 |
6 | 13 |
14 | ); 15 | } 16 | 17 | export default Header; 18 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Facebook Clone 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | entry: path.resolve(__dirname, "src", "index.js"), 5 | output: { 6 | path: path.resolve(__dirname, "public"), 7 | filename: "bundle.js" 8 | }, 9 | devServer: { 10 | contentBase: path.resolve(__dirname, "public") 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.js$/, 16 | exclude: /node_modules/, 17 | use: { 18 | loader: "babel-loader" 19 | } 20 | }, 21 | { 22 | test: /.css$/, 23 | use: [{ loader: "style-loader" }, { loader: "css-loader" }] 24 | } 25 | ] 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "challenge-04-react-facebook", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "homepage": "https://matheus-beck.github.io/react-facebook-clone", 7 | "scripts": { 8 | "build": "webpack --mode production", 9 | "dev": "webpack-dev-server --mode development", 10 | "predeploy": "yarn run build", 11 | "deploy": "gh-pages -d public" 12 | }, 13 | "devDependencies": { 14 | "@babel/core": "^7.7.7", 15 | "@babel/plugin-proposal-class-properties": "^7.7.4", 16 | "@babel/preset-env": "^7.7.7", 17 | "@babel/preset-react": "^7.7.4", 18 | "babel-loader": "^8.0.6", 19 | "css-loader": "^3.4.1", 20 | "file-loader": "^5.0.2", 21 | "style-loader": "^1.1.2", 22 | "webpack": "^4.41.5", 23 | "webpack-cli": "^3.3.10", 24 | "webpack-dev-server": "^3.10.1" 25 | }, 26 | "dependencies": { 27 | "gh-pages": "^2.2.0", 28 | "react": "^16.12.0", 29 | "react-dom": "^16.12.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Matheus Beck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/PostItem.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function PostHeader({ author, date }) { 4 | return ( 5 |
6 | 7 |
8 | {author.name} 9 | {date} 10 |
11 |
12 | ); 13 | } 14 | 15 | function PostComments({ comments }) { 16 | return ( 17 |
18 |
19 | {comments.map(comment => ( 20 |
21 | 22 |

23 | {comment.author.name} 24 | {comment.content} 25 |

26 |
27 | ))} 28 |
29 | ); 30 | } 31 | 32 | function PostItem({ author, date, content, comments }) { 33 | return ( 34 |
35 | 36 |

{content}

37 | 38 |
39 | ); 40 | } 41 | 42 | export default PostItem; 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 👍 Minimalist Facebook Clone 2 | 3 |

4 | GitHub powered by 5 | GitHub language count 6 | GitHub top language 7 | GitHub repo size 8 | GitHub last commit 9 | GitHub 10 |

11 | 12 |

13 | 14 |

15 | 16 | ReactJS app developed at RocketSeat to simulate a minimalist clone of Facebook 17 | You can check the app here: https://matheus-beck.github.io/react-facebook-clone/ 18 | 19 | # Front end: ReactJS app 20 | 21 | ## Dependencies used 22 | 23 | - "prop-types": "^15.7.2", 24 | - "react": "^16.12.0", 25 | - "react-dom": "^16.12.0" 26 | - "gh-pages": "^2.1.1", 27 | 28 | ## Getting started 29 | 30 | 1. Clone the project into your machine and install all dependencies inside the source folder using: 31 | 32 | ```console 33 | yarn install 34 | ``` 35 | 36 | 2. Now, run the server and see the result in http://localhost:8080/: 37 | 38 | ```console 39 | yarn dev 40 | ``` 41 | 42 | --- 43 | 44 | Made with ❤️ by Matheus Beck :wave: [Get in touch!](https://www.linkedin.com/in/matheus-beck/) 45 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/icon?family=Material+Icons"); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | outline: 0; 7 | box-sizing: border-box; 8 | } 9 | 10 | html, 11 | body, 12 | #root { 13 | height: 100%; 14 | } 15 | 16 | body { 17 | font-family: Arial, Helvetica, sans-serif; 18 | background: #f2f2f2; 19 | } 20 | 21 | header { 22 | background: #4a90e2; 23 | display: flex; 24 | justify-content: center; 25 | } 26 | 27 | header nav { 28 | display: flex; 29 | justify-content: space-between; 30 | align-items: center; 31 | height: 64px; 32 | padding: 0 42px; 33 | color: #fff; 34 | min-width: 980px; 35 | font-size: 14px; 36 | } 37 | 38 | nav img { 39 | height: 24px; 40 | } 41 | 42 | nav > span { 43 | font-size: 20px; 44 | font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; 45 | } 46 | 47 | nav > div { 48 | display: flex; 49 | align-items: center; 50 | } 51 | 52 | nav > div i { 53 | margin-left: 8px; 54 | } 55 | 56 | .postlist { 57 | width: 700px; 58 | margin: 0 auto 20px; 59 | } 60 | 61 | .post { 62 | margin-top: 20px; 63 | border-radius: 8px; 64 | background: white; 65 | padding: 20px; 66 | color: #3e3e3e; 67 | line-height: 20px; 68 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 69 | } 70 | 71 | .post-header { 72 | display: flex; 73 | align-items: center; 74 | } 75 | 76 | .post-header .details { 77 | margin-left: 10px; 78 | display: flex; 79 | flex-direction: column; 80 | font-size: 11px; 81 | color: #9a9a9a; 82 | line-height: 14px; 83 | } 84 | 85 | .post-header .details span:first-child { 86 | font-size: 14px; 87 | color: #4a4a4a; 88 | font-weight: bold; 89 | margin-bottom: 3px; 90 | } 91 | 92 | .avatar { 93 | min-height: 32px; 94 | min-width: 32px; 95 | height: 32px; 96 | width: 32px; 97 | border-radius: 50%; 98 | } 99 | 100 | .post-content { 101 | margin-top: 15px; 102 | font-size: 14px; 103 | } 104 | 105 | .divider { 106 | width: 100%; 107 | height: 1px; 108 | background: #eeeeee; 109 | } 110 | 111 | .post-comments { 112 | margin-top: 20px; 113 | } 114 | 115 | .comment { 116 | margin-top: 20px; 117 | display: flex; 118 | } 119 | 120 | .comment p { 121 | border-radius: 20px; 122 | background: #eeeeee; 123 | margin-left: 10px; 124 | padding: 15px; 125 | font-size: 13px; 126 | } 127 | 128 | .comment span { 129 | font-weight: bold; 130 | margin-right: 6px; 131 | } 132 | -------------------------------------------------------------------------------- /src/components/PostList.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import PostItem from "../components/PostItem"; 4 | 5 | class PostList extends Component { 6 | state = { 7 | posts: [ 8 | { 9 | id: 1, 10 | author: { 11 | name: "Vanessa Romero", 12 | avatar: "https://i.pravatar.cc/150?img=1" 13 | }, 14 | date: "04 Jun 2019", 15 | content: "Pessoal, alguém sabe se a Rocketseat está contratando?", 16 | comments: [ 17 | { 18 | id: 2, 19 | author: { 20 | name: "Diego Fernandes", 21 | avatar: "https://avatars2.githubusercontent.com/u/2254731?v=4" 22 | }, 23 | date: "04 Jun 2019", 24 | content: 25 | "A Rocketseat está sempre em busca de novos membros para o time, e geralmente ficamos de olho em quem se destaca no Bootcamp, inclusive 80% do nosso time de devs é composto por alunos do Bootcamp. Além disso, se você tem vontade de ensinar gravando vídeos e criando posts, pode me chamar no Discord! (Sério, me chamem mesmo, esse comentário é real)" 26 | } 27 | ] 28 | }, 29 | { 30 | id: 3, 31 | author: { 32 | name: "Neil Cook", 33 | avatar: "https://i.pravatar.cc/150?img=8" 34 | }, 35 | date: "04 Jun 2019", 36 | content: 37 | "Fala galera, beleza?\nEstou fazendo o Bootcamp GoStack e está sendo muito massa! Alguém mais aí fazendo? Comenta aí na publicação para trocarmos uma idéia", 38 | comments: [ 39 | { 40 | id: 4, 41 | author: { 42 | name: "Clara Lisboa", 43 | avatar: "https://i.pravatar.cc/150?img=5" 44 | }, 45 | date: "04 Jun 2019", 46 | content: 47 | "Também estou fazendo o Bootcamp e estou adorando! Estou no terceiro módulo sobre Node e já tenho minha API dos desafios construída!" 48 | }, 49 | { 50 | id: 5, 51 | author: { 52 | name: "Cézar Toledo", 53 | avatar: "https://i.pravatar.cc/150?img=11" 54 | }, 55 | date: "04 Jun 2019", 56 | content: 57 | "Que maaaaaassa! Estou pensando em me inscrever na próxima turma pra ver qual é desse Bootcamp GoStack, dizem que os devs saem de lá com super poderes" 58 | } 59 | ] 60 | }, 61 | { 62 | id: 6, 63 | author: { 64 | name: "Gabriel Lisboa", 65 | avatar: "https://i.pravatar.cc/150?img=51" 66 | }, 67 | date: "04 Jun 2019", 68 | content: 69 | "Fala galera, beleza?\nEstou fazendo o Bootcamp GoStack e está sendo muito massa! Alguém mais aí fazendo? Comenta aí na publicação para trocarmos uma idéia", 70 | comments: [ 71 | { 72 | id: 4, 73 | author: { 74 | name: "Clara Lisboa", 75 | avatar: "https://i.pravatar.cc/150?img=5" 76 | }, 77 | date: "04 Jun 2019", 78 | content: 79 | "Também estou fazendo o Bootcamp e estou adorando! Estou no terceiro módulo sobre Node e já tenho minha API dos desafios construída!" 80 | }, 81 | { 82 | id: 5, 83 | author: { 84 | name: "Cézar Toledo", 85 | avatar: "https://i.pravatar.cc/150?img=11" 86 | }, 87 | date: "04 Jun 2019", 88 | content: 89 | "Que maaaaaassa! Estou pensando em me inscrever na próxima turma pra ver qual é desse Bootcamp GoStack, dizem que os devs saem de lá com super poderes" 90 | } 91 | ] 92 | } 93 | ] 94 | }; 95 | 96 | render() { 97 | const { posts } = this.state; 98 | 99 | return ( 100 |
101 | {posts.map(post => ( 102 | 103 | ))} 104 |
105 | ); 106 | } 107 | } 108 | 109 | export default PostList; 110 | -------------------------------------------------------------------------------- /public/bundle.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var l=t[r]={i:r,l:!1,exports:{}};return e[r].call(l.exports,l,l.exports,n),l.l=!0,l.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)n.d(r,l,function(t){return e[t]}.bind(null,l));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}([function(e,t,n){"use strict";e.exports=n(3)},function(e,t,n){"use strict"; 2 | /* 3 | object-assign 4 | (c) Sindre Sorhus 5 | @license MIT 6 | */var r=Object.getOwnPropertySymbols,l=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;function o(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,i,u=o(e),c=1;cz.length&&z.push(e)}function R(e,t,n){return null==e?0:function e(t,n,r,l){var i=typeof t;"undefined"!==i&&"boolean"!==i||(t=null);var u=!1;if(null===t)u=!0;else switch(i){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case a:case o:u=!0}}if(u)return r(l,t,""===n?"."+F(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;c