├── public ├── favicon.ico ├── manifest.json └── index.html ├── src ├── components │ ├── Logo │ │ ├── brain.png │ │ ├── Logo.css │ │ └── Logo.js │ ├── FaceRecognition │ │ ├── FaceRecognition.css │ │ └── FaceRecognition.js │ ├── Rank │ │ └── Rank.js │ ├── ImageLinkForm │ │ ├── ImageLinkForm.css │ │ └── ImageLinkForm.js │ ├── Navigation │ │ └── Navigation.js │ ├── Signin │ │ └── Signin.js │ └── Register │ │ └── Register.js ├── App.test.js ├── index.css ├── App.css ├── index.js ├── App.js └── registerServiceWorker.js ├── README.md ├── .gitignore └── package.json /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneagoie/smart-brain/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/components/Logo/brain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneagoie/smart-brain/HEAD/src/components/Logo/brain.png -------------------------------------------------------------------------------- /src/components/Logo/Logo.css: -------------------------------------------------------------------------------- 1 | .Tilt { 2 | background: linear-gradient(89deg, #FF5EDF 0%, #04C8DE 100%); /* w3c */ 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SmartBrain - Final 2 | Final project for ZTM course 3 | 4 | 5 | 1. Clone this repo 6 | 2. Run `npm install` 7 | 3. Run `npm start` 8 | 9 | *visist https://zerotomastery.io/ for more* 10 | 11 | -------------------------------------------------------------------------------- /src/components/FaceRecognition/FaceRecognition.css: -------------------------------------------------------------------------------- 1 | .bounding-box { 2 | position: absolute; 3 | box-shadow: 0 0 0 3px #149df2 inset; 4 | display: flex; 5 | flex-wrap: wrap; 6 | justify-content: center; 7 | cursor: pointer; 8 | } -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: "Courier New", Courier, monospace; 5 | background: linear-gradient(89deg, #FF5EDF 0%, #04C8DE 100%); /* w3c */ 6 | } 7 | 8 | button { 9 | cursor: pointer; 10 | } 11 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .center { 6 | display: flex; 7 | justify-content: center; 8 | } 9 | 10 | .particles { 11 | position: fixed; 12 | top: 0; 13 | right: 0; 14 | bottom: 0; 15 | left: 0; 16 | z-index: -1; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/Rank/Rank.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Rank = ({ name, entries }) => { 4 | return ( 5 |
6 |
7 | {`${name}, your current entry count is...`} 8 |
9 |
10 | {entries} 11 |
12 |
13 | ); 14 | } 15 | 16 | export default Rank; -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | // import registerServiceWorker from './registerServiceWorker'; 6 | import 'tachyons'; 7 | 8 | const root = createRoot(document.getElementById('root')); 9 | 10 | root.render() 11 | 12 | // If using React version lower than 18: 13 | // ReactDOM.render(, document.getElementById('root')); 14 | // registerServiceWorker(); 15 | -------------------------------------------------------------------------------- /src/components/FaceRecognition/FaceRecognition.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './FaceRecognition.css'; 3 | 4 | const FaceRecognition = ({ imageUrl, box }) => { 5 | return ( 6 |
7 |
8 | 9 |
10 |
11 |
12 | ); 13 | } 14 | 15 | export default FaceRecognition; -------------------------------------------------------------------------------- /src/components/Logo/Logo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import Tilt from 'react-tilt'; 3 | import Tilt from 'react-parallax-tilt'; 4 | import brain from './brain.png'; 5 | import './Logo.css'; 6 | 7 | const Logo = () => { 8 | return ( 9 |
10 | 11 |
12 | logo 13 |
14 |
15 |
16 | ); 17 | } 18 | 19 | export default Logo; -------------------------------------------------------------------------------- /src/components/ImageLinkForm/ImageLinkForm.css: -------------------------------------------------------------------------------- 1 | .form { 2 | width: 700px; 3 | background: 4 | radial-gradient(circle farthest-side at 0% 50%,#fb1 23.5%,rgba(240,166,17,0) 0)21px 30px, 5 | radial-gradient(circle farthest-side at 0% 50%,#B71 24%,rgba(240,166,17,0) 0)19px 30px, 6 | linear-gradient(#fb1 14%,rgba(240,166,17,0) 0, rgba(240,166,17,0) 85%,#fb1 0)0 0, 7 | linear-gradient(150deg,#fb1 24%,#B71 0,#B71 26%,rgba(240,166,17,0) 0,rgba(240,166,17,0) 74%,#B71 0,#B71 76%,#fb1 0)0 0, 8 | linear-gradient(30deg,#fb1 24%,#B71 0,#B71 26%,rgba(240,166,17,0) 0,rgba(240,166,17,0) 74%,#B71 0,#B71 76%,#fb1 0)0 0, 9 | linear-gradient(90deg,#B71 2%,#fb1 0,#fb1 98%,#B71 0%)0 0 #fb1; 10 | background-size:40px 60px; 11 | } -------------------------------------------------------------------------------- /src/components/ImageLinkForm/ImageLinkForm.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './ImageLinkForm.css'; 3 | 4 | const ImageLinkForm = ({ onInputChange, onButtonSubmit }) => { 5 | return ( 6 |
7 |

8 | {'This Magic Brain will detect faces in your pictures. Git it a try.'} 9 |

10 |
11 |
12 | 13 | 17 |
18 |
19 |
20 | ); 21 | } 22 | 23 | export default ImageLinkForm; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "facerecognitionbrain", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "particles-bg": "^2.5.5", 7 | "react": "^19.1.1", 8 | "react-dom": "^19.1.1", 9 | "react-parallax-tilt": "^1.7.309", 10 | "react-scripts": "^5.0.1", 11 | "tachyons": "^4.12.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test --env=jsdom", 17 | "eject": "react-scripts eject" 18 | }, 19 | "browserslist": { 20 | "production": [ 21 | ">0.2%", 22 | "not dead", 23 | "not op_mini all" 24 | ], 25 | "development": [ 26 | "last 1 chrome version", 27 | "last 1 firefox version", 28 | "last 1 safari version" 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/components/Navigation/Navigation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Navigation = ({ onRouteChange, isSignedIn }) => { 4 | if (isSignedIn) { 5 | return ( 6 | 9 | ); 10 | } else { 11 | return ( 12 | 16 | ); 17 | } 18 | } 19 | 20 | export default Navigation; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/components/Signin/Signin.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Signin extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | this.state = { 7 | signInEmail: '', 8 | signInPassword: '' 9 | } 10 | } 11 | 12 | onEmailChange = (event) => { 13 | this.setState({signInEmail: event.target.value}) 14 | } 15 | 16 | onPasswordChange = (event) => { 17 | this.setState({signInPassword: event.target.value}) 18 | } 19 | 20 | onSubmitSignIn = () => { 21 | fetch('http://localhost:3000/signin', { 22 | method: 'post', 23 | headers: {'Content-Type': 'application/json'}, 24 | body: JSON.stringify({ 25 | email: this.state.signInEmail, 26 | password: this.state.signInPassword 27 | }) 28 | }) 29 | .then(response => response.json()) 30 | .then(user => { 31 | if (user.id) { 32 | this.props.loadUser(user) 33 | this.props.onRouteChange('home'); 34 | } 35 | }) 36 | } 37 | 38 | render() { 39 | const { onRouteChange } = this.props; 40 | return ( 41 |
42 |
43 |
44 |
45 | Sign In 46 |
47 | 48 | 55 |
56 |
57 | 58 | 65 |
66 |
67 |
68 | 74 |
75 |
76 |

onRouteChange('register')} className="f6 link dim black db pointer">Register

77 |
78 |
79 |
80 |
81 | ); 82 | } 83 | } 84 | 85 | export default Signin; -------------------------------------------------------------------------------- /src/components/Register/Register.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Register extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | this.state = { 7 | email: '', 8 | password: '', 9 | name: '' 10 | } 11 | } 12 | 13 | onNameChange = (event) => { 14 | this.setState({name: event.target.value}) 15 | } 16 | 17 | onEmailChange = (event) => { 18 | this.setState({email: event.target.value}) 19 | } 20 | 21 | onPasswordChange = (event) => { 22 | this.setState({password: event.target.value}) 23 | } 24 | 25 | onSubmitSignIn = () => { 26 | fetch('http://localhost:3000/register', { 27 | method: 'post', 28 | headers: {'Content-Type': 'application/json'}, 29 | body: JSON.stringify({ 30 | email: this.state.email, 31 | password: this.state.password, 32 | name: this.state.name 33 | }) 34 | }) 35 | .then(response => response.json()) 36 | .then(user => { 37 | if (user.id) { 38 | this.props.loadUser(user) 39 | this.props.onRouteChange('home'); 40 | } 41 | }) 42 | } 43 | 44 | render() { 45 | return ( 46 |
47 |
48 |
49 |
50 | Register 51 |
52 | 53 | 60 |
61 |
62 | 63 | 70 |
71 |
72 | 73 | 80 |
81 |
82 |
83 | 89 |
90 |
91 |
92 |
93 | ); 94 | } 95 | } 96 | 97 | export default Register; -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | // import Particles from 'react-particles-js'; 3 | import ParticlesBg from 'particles-bg' 4 | import FaceRecognition from './components/FaceRecognition/FaceRecognition'; 5 | import Navigation from './components/Navigation/Navigation'; 6 | import Signin from './components/Signin/Signin'; 7 | import Register from './components/Register/Register'; 8 | import Logo from './components/Logo/Logo'; 9 | import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm'; 10 | import Rank from './components/Rank/Rank'; 11 | import './App.css'; 12 | 13 | const initialState = { 14 | input: '', 15 | imageUrl: '', 16 | box: {}, 17 | route: 'signin', 18 | isSignedIn: false, 19 | user: { 20 | id: '', 21 | name: '', 22 | email: '', 23 | entries: 0, 24 | joined: '' 25 | } 26 | } 27 | 28 | 29 | class App extends Component { 30 | constructor() { 31 | super(); 32 | this.state = initialState; 33 | } 34 | 35 | loadUser = (data) => { 36 | this.setState({user: { 37 | id: data.id, 38 | name: data.name, 39 | email: data.email, 40 | entries: data.entries, 41 | joined: data.joined 42 | }}) 43 | } 44 | 45 | calculateFaceLocation = (data) => { 46 | const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box; 47 | const image = document.getElementById('inputimage'); 48 | const width = Number(image.width); 49 | const height = Number(image.height); 50 | return { 51 | leftCol: clarifaiFace.left_col * width, 52 | topRow: clarifaiFace.top_row * height, 53 | rightCol: width - (clarifaiFace.right_col * width), 54 | bottomRow: height - (clarifaiFace.bottom_row * height) 55 | } 56 | } 57 | 58 | displayFaceBox = (box) => { 59 | this.setState({box: box}); 60 | } 61 | 62 | onInputChange = (event) => { 63 | this.setState({input: event.target.value}); 64 | } 65 | 66 | onButtonSubmit = () => { 67 | this.setState({imageUrl: this.state.input}); 68 | fetch('http://localhost:3000/imageurl', { 69 | method: 'post', 70 | headers: {'Content-Type': 'application/json'}, 71 | body: JSON.stringify({ 72 | input: this.state.input 73 | }) 74 | }) 75 | .then(response => response.json()) 76 | .then(response => { 77 | if (response) { 78 | fetch('http://localhost:3000/image', { 79 | method: 'put', 80 | headers: {'Content-Type': 'application/json'}, 81 | body: JSON.stringify({ 82 | id: this.state.user.id 83 | }) 84 | }) 85 | .then(response => response.json()) 86 | .then(count => { 87 | this.setState(Object.assign(this.state.user, { entries: count})) 88 | }) 89 | .catch(console.log) 90 | 91 | } 92 | this.displayFaceBox(this.calculateFaceLocation(response)) 93 | }) 94 | .catch(err => console.log(err)); 95 | } 96 | 97 | onRouteChange = (route) => { 98 | if (route === 'signout') { 99 | this.setState(initialState) 100 | } else if (route === 'home') { 101 | this.setState({isSignedIn: true}) 102 | } 103 | this.setState({route: route}); 104 | } 105 | 106 | render() { 107 | const { isSignedIn, imageUrl, route, box } = this.state; 108 | return ( 109 |
110 | 111 | 112 | { route === 'home' 113 | ?
114 | 115 | 119 | 123 | 124 |
125 | : ( 126 | route === 'signin' 127 | ? 128 | : 129 | ) 130 | } 131 |
132 | ); 133 | } 134 | } 135 | 136 | export default App; 137 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | const isLocalhost = Boolean( 12 | window.location.hostname === 'localhost' || 13 | // [::1] is the IPv6 localhost address. 14 | window.location.hostname === '[::1]' || 15 | // 127.0.0.1/8 is considered localhost for IPv4. 16 | window.location.hostname.match( 17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 18 | ) 19 | ); 20 | 21 | export default function register() { 22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 23 | // The URL constructor is available in all browsers that support SW. 24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 25 | if (publicUrl.origin !== window.location.origin) { 26 | // Our service worker won't work if PUBLIC_URL is on a different origin 27 | // from what our page is served on. This might happen if a CDN is used to 28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 29 | return; 30 | } 31 | 32 | window.addEventListener('load', () => { 33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 34 | 35 | if (isLocalhost) { 36 | // This is running on localhost. Lets check if a service worker still exists or not. 37 | checkValidServiceWorker(swUrl); 38 | } else { 39 | // Is not local host. Just register service worker 40 | registerValidSW(swUrl); 41 | } 42 | }); 43 | } 44 | } 45 | 46 | function registerValidSW(swUrl) { 47 | navigator.serviceWorker 48 | .register(swUrl) 49 | .then(registration => { 50 | registration.onupdatefound = () => { 51 | const installingWorker = registration.installing; 52 | installingWorker.onstatechange = () => { 53 | if (installingWorker.state === 'installed') { 54 | if (navigator.serviceWorker.controller) { 55 | // At this point, the old content will have been purged and 56 | // the fresh content will have been added to the cache. 57 | // It's the perfect time to display a "New content is 58 | // available; please refresh." message in your web app. 59 | console.log('New content is available; please refresh.'); 60 | } else { 61 | // At this point, everything has been precached. 62 | // It's the perfect time to display a 63 | // "Content is cached for offline use." message. 64 | console.log('Content is cached for offline use.'); 65 | } 66 | } 67 | }; 68 | }; 69 | }) 70 | .catch(error => { 71 | console.error('Error during service worker registration:', error); 72 | }); 73 | } 74 | 75 | function checkValidServiceWorker(swUrl) { 76 | // Check if the service worker can be found. If it can't reload the page. 77 | fetch(swUrl) 78 | .then(response => { 79 | // Ensure service worker exists, and that we really are getting a JS file. 80 | if ( 81 | response.status === 404 || 82 | response.headers.get('content-type').indexOf('javascript') === -1 83 | ) { 84 | // No service worker found. Probably a different app. Reload the page. 85 | navigator.serviceWorker.ready.then(registration => { 86 | registration.unregister().then(() => { 87 | window.location.reload(); 88 | }); 89 | }); 90 | } else { 91 | // Service worker found. Proceed as normal. 92 | registerValidSW(swUrl); 93 | } 94 | }) 95 | .catch(() => { 96 | console.log( 97 | 'No internet connection found. App is running in offline mode.' 98 | ); 99 | }); 100 | } 101 | 102 | export function unregister() { 103 | if ('serviceWorker' in navigator) { 104 | navigator.serviceWorker.ready.then(registration => { 105 | registration.unregister(); 106 | }); 107 | } 108 | } 109 | --------------------------------------------------------------------------------