├── movie-review ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── postcss.config.js ├── README.md ├── tailwind.config.js ├── src │ ├── index.js │ ├── index.css │ ├── components │ │ ├── firebase │ │ │ └── firebase.js │ │ ├── Header.js │ │ ├── Detail.js │ │ ├── Cards.js │ │ ├── authentication │ │ │ ├── Login.js │ │ │ └── Signup.js │ │ ├── Reviews.js │ │ └── AddMovie.js │ └── App.js └── package.json ├── record-keeper ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── components │ │ ├── header │ │ │ ├── header.scss │ │ │ └── Header.js │ │ └── form │ │ │ ├── form.scss │ │ │ └── Form.js │ ├── App.css │ ├── App.js │ ├── index.js │ └── index.css └── package.json ├── redux-starter ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── components │ │ ├── header │ │ │ ├── header.scss │ │ │ └── Header.js │ │ └── counter │ │ │ ├── counter.scss │ │ │ └── Counter.js │ ├── App.css │ ├── states │ │ ├── store.js │ │ └── reducers │ │ │ └── index.js │ ├── App.js │ ├── index.js │ └── index.css └── package.json ├── README.md └── .gitignore /movie-review/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /record-keeper/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /redux-starter/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /movie-review/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/movie-review/public/favicon.ico -------------------------------------------------------------------------------- /movie-review/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/movie-review/public/logo192.png -------------------------------------------------------------------------------- /movie-review/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/movie-review/public/logo512.png -------------------------------------------------------------------------------- /record-keeper/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/record-keeper/public/favicon.ico -------------------------------------------------------------------------------- /record-keeper/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/record-keeper/public/logo192.png -------------------------------------------------------------------------------- /record-keeper/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/record-keeper/public/logo512.png -------------------------------------------------------------------------------- /redux-starter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/redux-starter/public/favicon.ico -------------------------------------------------------------------------------- /redux-starter/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/redux-starter/public/logo192.png -------------------------------------------------------------------------------- /redux-starter/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utshabkg/react-projects/HEAD/redux-starter/public/logo512.png -------------------------------------------------------------------------------- /movie-review/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Some ReactJS Projects 2 | 3 | Deployed Links: 4 | 5 | 1. Movie Review (Film Universe) 6 | -------------------------------------------------------------------------------- /movie-review/README.md: -------------------------------------------------------------------------------- 1 | ### Film Universe Project 2 | 3 | Deployed here: Movie Review (Film Universe) 4 | -------------------------------------------------------------------------------- /record-keeper/src/components/header/header.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | color: white; 3 | background-color: purple; 4 | padding: 14px; 5 | width: 100% 6 | } -------------------------------------------------------------------------------- /redux-starter/src/components/header/header.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | color: white; 3 | background-color: purple; 4 | padding: 14px; 5 | width: 100%; 6 | } -------------------------------------------------------------------------------- /movie-review/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{html,js}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /record-keeper/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .h1 { 9 | margin: 0; 10 | padding: 14px; 11 | } 12 | -------------------------------------------------------------------------------- /redux-starter/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .h1 { 9 | margin: 0; 10 | padding: 14px; 11 | } 12 | -------------------------------------------------------------------------------- /redux-starter/src/states/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import counterReducer from "./reducers/index"; 3 | 4 | export default configureStore({ 5 | reducer: { 6 | counter: counterReducer, 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /record-keeper/src/components/header/Header.js: -------------------------------------------------------------------------------- 1 | import "./header.scss"; 2 | const Header = () => { 3 | return ( 4 |
5 |

Record Keeper

6 |
7 | ); 8 | }; 9 | 10 | export default Header; 11 | -------------------------------------------------------------------------------- /redux-starter/src/components/header/Header.js: -------------------------------------------------------------------------------- 1 | import "./header.scss"; 2 | const Header = () => { 3 | return ( 4 |
5 |

Redux Starter

6 |
7 | ); 8 | }; 9 | 10 | export default Header; 11 | -------------------------------------------------------------------------------- /record-keeper/src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import Header from "./components/header/Header"; 3 | import Form from "./components/form/Form"; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 |
10 |
11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /record-keeper/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById("root")); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /redux-starter/src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import Header from "./components/header/Header"; 3 | import Counter from "./components/counter/Counter"; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | 10 |
11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /redux-starter/src/components/counter/counter.scss: -------------------------------------------------------------------------------- 1 | .main{ 2 | .buttons{ 3 | display: flex; 4 | justify-content: space-between; 5 | 6 | button{ 7 | width: 50px; 8 | margin: 5px; 9 | font-size: larger; 10 | } 11 | } 12 | h1{ 13 | color: hsl(16, 89%, 44%); 14 | } 15 | } -------------------------------------------------------------------------------- /movie-review/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import { BrowserRouter as Router } from "react-router-dom"; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById("root")); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /redux-starter/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import { Provider } from "react-redux"; 6 | import store from "./states/store"; 7 | 8 | const root = ReactDOM.createRoot(document.getElementById("root")); 9 | root.render( 10 | 11 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | */node_modules 5 | */.pnp 6 | *.pnp.js 7 | 8 | # testing 9 | */coverage 10 | 11 | # production 12 | */build 13 | 14 | # misc 15 | *.DS_Store 16 | .env 17 | *.env.local 18 | *.env.development.local 19 | *.env.test.local 20 | *.env.production.local 21 | 22 | *npm-debug.log* 23 | *yarn-debug.log* 24 | *yarn-error.log* 25 | -------------------------------------------------------------------------------- /record-keeper/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /redux-starter/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /redux-starter/src/states/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | 3 | export const counterSlice = createSlice({ 4 | name: "counter", 5 | initialState: 0, 6 | reducers: { 7 | Increment: (state, action) => { 8 | return (state += action.payload); 9 | }, 10 | 11 | Decrement: (state, action) => { 12 | return (state -= action.payload); 13 | }, 14 | }, 15 | }); 16 | 17 | export const { Increment, Decrement } = counterSlice.actions; 18 | export default counterSlice.reducer; 19 | -------------------------------------------------------------------------------- /movie-review/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | background-color: black; 7 | color: white; 8 | } 9 | 10 | .header { 11 | background-color: #020d3f; 12 | } 13 | 14 | .cards a { 15 | width: 220px; 16 | } 17 | 18 | .card { 19 | background-color: rgb(19, 19, 19); 20 | } 21 | 22 | .card img { 23 | width: 100%; 24 | height: 100%; 25 | object-fit: cover; 26 | object-position: center center; 27 | } 28 | 29 | .card-img { 30 | height: 300px; 31 | width: 100%; 32 | } 33 | -------------------------------------------------------------------------------- /record-keeper/src/components/form/form.scss: -------------------------------------------------------------------------------- 1 | .form { 2 | margin: 20px; 3 | 4 | .data { 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | margin-top: 14px; 9 | width: 100%; 10 | 11 | .data_value { 12 | display: flex; 13 | justify-content: space-between; 14 | align-items: center; 15 | width: 100%; 16 | padding: 0px 10px; 17 | box-shadow: rgba(100, 100, 111, 0.2) 0 7px 29px 0; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /movie-review/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 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /record-keeper/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 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /redux-starter/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 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /redux-starter/src/components/counter/Counter.js: -------------------------------------------------------------------------------- 1 | import "./counter.scss"; 2 | import React from "react"; 3 | import { useDispatch, useSelector } from "react-redux"; 4 | import { Increment, Decrement } from "../../states/reducers"; 5 | 6 | const Counter = () => { 7 | const curState = useSelector((state) => state.counter); 8 | const dispatch = useDispatch(); 9 | return ( 10 |
11 |

{curState}

12 |
13 | 14 | 15 |
16 |
17 | ); 18 | }; 19 | 20 | export default Counter; 21 | -------------------------------------------------------------------------------- /movie-review/src/components/firebase/firebase.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getFirestore, collection } from "firebase/firestore"; 3 | 4 | const firebaseConfig = { 5 | apiKey: process.env.REACT_APP_API_KEY, 6 | authDomain: process.env.REACT_APP_AUTH_DOMAIN, 7 | projectId: process.env.REACT_APP_PROJECT_ID, 8 | storageBucket: process.env.REACT_APP_STORAGE_BUCKET, 9 | messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID, 10 | appId: process.env.REACT_APP_ID, 11 | }; 12 | 13 | // Initialize Firebase 14 | const app = initializeApp(firebaseConfig); 15 | 16 | export const db = getFirestore(app); 17 | export const moviesRef = collection(db, "movies"); 18 | export const reviewsRef = collection(db, "reviews"); 19 | export const usersRef = collection(db, "users"); 20 | export default app; 21 | -------------------------------------------------------------------------------- /record-keeper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "record-keeper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.10.6", 7 | "@emotion/styled": "^11.10.6", 8 | "@mui/icons-material": "^5.11.11", 9 | "@mui/material": "^5.11.12", 10 | "@testing-library/jest-dom": "^5.16.5", 11 | "@testing-library/react": "^13.4.0", 12 | "@testing-library/user-event": "^13.5.0", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0", 15 | "react-scripts": "5.0.1", 16 | "sass": "^1.58.3", 17 | "web-vitals": "^2.1.4" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /movie-review/src/App.js: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from "react-router-dom"; 2 | import Header from "./components/Header"; 3 | import Cards from "./components/Cards"; 4 | import AddMovie from "./components/AddMovie"; 5 | import Detail from "./components/Detail"; 6 | import { createContext, useState } from "react"; 7 | import Login from "./components/authentication/Login"; 8 | import Signup from "./components/authentication/Signup"; 9 | 10 | const Appstate = createContext(); 11 | 12 | function App() { 13 | const [login, setLogin] = useState(false); 14 | const [userName, setUserName] = useState(false); 15 | 16 | return ( 17 | 18 |
19 |
20 | 21 | } /> 22 | } /> 23 | } /> 24 | } /> 25 | } /> 26 | 27 |
28 |
29 | ); 30 | } 31 | 32 | export default App; 33 | export { Appstate }; 34 | -------------------------------------------------------------------------------- /redux-starter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "record-keeper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.10.6", 7 | "@emotion/styled": "^11.10.6", 8 | "@mui/icons-material": "^5.11.11", 9 | "@mui/material": "^5.11.12", 10 | "@reduxjs/toolkit": "^1.9.3", 11 | "@testing-library/jest-dom": "^5.16.5", 12 | "@testing-library/react": "^13.4.0", 13 | "@testing-library/user-event": "^13.5.0", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "react-redux": "^8.0.5", 17 | "react-router-dom": "^6.8.2", 18 | "react-scripts": "5.0.1", 19 | "sass": "^1.58.3", 20 | "web-vitals": "^2.1.4" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /movie-review/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import AddIcon from "@mui/icons-material/Add"; 3 | import { Button } from "@mui/material"; 4 | import { Link } from "react-router-dom"; 5 | import { Appstate } from "../App"; 6 | 7 | const Header = () => { 8 | const useAppstate = useContext(Appstate); 9 | return ( 10 |
11 | 12 | 13 | Film Universe 14 | 15 | 16 | {useAppstate.login ? ( 17 | 18 |

19 | 23 |

24 | 25 | ) : ( 26 | 27 |

28 | 31 |

32 | 33 | )} 34 |
35 | ); 36 | }; 37 | 38 | export default Header; 39 | -------------------------------------------------------------------------------- /movie-review/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movie-review", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.10.6", 7 | "@emotion/styled": "^11.10.6", 8 | "@mui/icons-material": "^5.11.11", 9 | "@mui/material": "^5.11.13", 10 | "@testing-library/jest-dom": "^5.16.5", 11 | "@testing-library/react": "^13.4.0", 12 | "@testing-library/user-event": "^13.5.0", 13 | "bcrypt": "^5.1.0", 14 | "bcryptjs": "^2.4.3", 15 | "dom": "^0.0.3", 16 | "firebase": "^9.17.2", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0", 19 | "react-loader-spinner": "^5.3.4", 20 | "react-router": "^6.9.0", 21 | "react-router-dom": "^6.9.0", 22 | "react-scripts": "5.0.1", 23 | "react-stars": "^2.2.5", 24 | "sweetalert": "^2.1.2", 25 | "web-vitals": "^2.1.4" 26 | }, 27 | "scripts": { 28 | "start": "react-scripts start", 29 | "build": "react-scripts build", 30 | "test": "react-scripts test", 31 | "eject": "react-scripts eject" 32 | }, 33 | "eslintConfig": { 34 | "extends": [ 35 | "react-app", 36 | "react-app/jest" 37 | ] 38 | }, 39 | "browserslist": { 40 | "production": [ 41 | ">0.2%", 42 | "not dead", 43 | "not op_mini all" 44 | ], 45 | "development": [ 46 | "last 1 chrome version", 47 | "last 1 firefox version", 48 | "last 1 safari version" 49 | ] 50 | }, 51 | "devDependencies": { 52 | "autoprefixer": "^10.4.14", 53 | "postcss": "^8.4.21", 54 | "tailwindcss": "^3.2.7" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /record-keeper/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /redux-starter/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /movie-review/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Film Universe 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /movie-review/src/components/Detail.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/alt-text */ 2 | import React, { useEffect, useState } from "react"; 3 | import ReactStars from "react-stars"; 4 | import { useParams } from "react-router"; 5 | import { db } from "./firebase/firebase"; 6 | import { doc, getDoc } from "firebase/firestore"; 7 | import { Bars } from "react-loader-spinner"; 8 | import Reviews from "./Reviews"; 9 | 10 | const Detail = () => { 11 | const { id } = useParams(); 12 | const [data, setData] = useState({ 13 | title: "", 14 | year: "", 15 | image: "", 16 | description: "", 17 | rating: 0, 18 | number_of_ratings: 0, 19 | }); 20 | const [loading, setLoading] = useState(false); 21 | 22 | useEffect(() => { 23 | setLoading(true); 24 | async function getData() { 25 | const _doc = doc(db, "movies", id); 26 | const _data = await getDoc(_doc); 27 | setData(_data.data()); 28 | setLoading(false); 29 | } 30 | getData(); 31 | }, []); 32 | 33 | return ( 34 |
35 | {loading ? ( 36 |
37 | 38 |
39 | ) : ( 40 | <> 41 | 42 |
43 |

44 | {data.title} ({data.year}) 45 |

46 | 52 |

{data.description}

53 | 58 |
59 | 60 | )} 61 |
62 | ); 63 | }; 64 | 65 | export default Detail; 66 | -------------------------------------------------------------------------------- /movie-review/src/components/Cards.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/alt-text */ 2 | import React, { useEffect, useState } from "react"; 3 | import { Vortex } from "react-loader-spinner"; 4 | import ReactStars from "react-stars"; 5 | import { getDocs } from "firebase/firestore"; 6 | import { moviesRef } from "./firebase/firebase"; 7 | import { Link } from "react-router-dom"; 8 | 9 | const Cards = () => { 10 | const [data, setData] = useState([]); 11 | const [loading, setLoading] = useState(false); 12 | useEffect(() => { 13 | async function getData() { 14 | setLoading(true); 15 | const _data = await getDocs(moviesRef); 16 | _data.forEach((doc) => { 17 | setData((prev) => [...prev, { ...doc.data(), id: doc.id }]); 18 | }); 19 | setLoading(false); 20 | } 21 | getData(); 22 | }, []); 23 | 24 | return ( 25 |
26 | {loading ? ( 27 |
28 | 29 |
30 | ) : ( 31 | data.map((e, i) => { 32 | return ( 33 | 34 |
38 |
39 | 40 |
41 | 42 |
43 |

44 | Movie: {e.title} 45 |

46 |

47 | Rating: 48 | 54 |

55 |

56 | Year: {e.year} 57 |

58 |
59 |
60 | 61 | ); 62 | }) 63 | )} 64 |
65 | ); 66 | }; 67 | 68 | export default Cards; 69 | -------------------------------------------------------------------------------- /record-keeper/src/components/form/Form.js: -------------------------------------------------------------------------------- 1 | import "./form.scss"; 2 | import { TextField, Button, Stack } from "@mui/material"; 3 | import AddIcon from "@mui/icons-material/Add"; 4 | import BackspaceIcon from "@mui/icons-material/Backspace"; 5 | import { useState } from "react"; 6 | 7 | const Form = () => { 8 | const [form, setForm] = useState({}); 9 | const [data, setData] = useState([]); 10 | 11 | const addData = () => { 12 | setData([...data, form]); 13 | setForm({ name: "", email: "" }); 14 | }; 15 | const handlePress = (e) => { 16 | if (e.key === "Enter") { 17 | addData(); 18 | } 19 | }; 20 | 21 | const removeData = (index) => { 22 | let tempArr = data; 23 | tempArr.splice(index, 1); 24 | setData([...tempArr]); 25 | }; 26 | 27 | return ( 28 |
29 | 30 | handlePress(e)} 32 | value={form.name} 33 | onChange={(e) => setForm({ ...form, name: e.target.value })} 34 | id="outlined-basic" 35 | label="Name" 36 | variant="outlined" 37 | /> 38 | handlePress(e)} 40 | value={form.email} 41 | onChange={(e) => setForm({ ...form, email: e.target.value })} 42 | id="outlined-basic" 43 | label="Email" 44 | variant="outlined" 45 | /> 46 | 49 | 50 | 51 | {/* Data Showcase */} 52 |
53 |
54 |

Name

55 |

Email

56 |

Remove

57 |
58 | {data.map((element, index) => { 59 | return ( 60 |
61 |

{element.name}

62 |

{element.email}

63 | 64 | 71 | 72 |
73 | ); 74 | })} 75 |
76 |
77 | ); 78 | }; 79 | 80 | export default Form; 81 | -------------------------------------------------------------------------------- /movie-review/src/components/authentication/Login.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from "react"; 2 | import { ThreeCircles } from "react-loader-spinner"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import { query, where, getDocs } from "firebase/firestore"; 5 | import { usersRef } from "../firebase/firebase"; 6 | import { Appstate } from "../../App"; 7 | import bcrypt from "bcryptjs"; 8 | import swal from "sweetalert"; 9 | 10 | const Login = () => { 11 | const navigate = useNavigate(); 12 | const useAppstate = useContext(Appstate); 13 | const [form, setForm] = useState({ 14 | mobile: "", 15 | password: "", 16 | }); 17 | const [loading, setLoading] = useState(false); 18 | 19 | const login = async () => { 20 | setLoading(true); 21 | try { 22 | const quer = query(usersRef, where("mobile", "==", form.mobile)); 23 | const querySnapshot = await getDocs(quer); 24 | 25 | querySnapshot.forEach((doc) => { 26 | const _data = doc.data(); 27 | const isUser = bcrypt.compareSync(form.password, _data.password); 28 | if (isUser) { 29 | useAppstate.setLogin(true); 30 | useAppstate.setUserName(_data.name); 31 | swal({ 32 | title: "Logged In", 33 | icon: "success", 34 | buttons: false, 35 | timer: 3000, 36 | }); 37 | navigate("/"); 38 | } else { 39 | swal({ 40 | title: "Invalid Credentials", 41 | icon: "error", 42 | buttons: false, 43 | timer: 3000, 44 | }); 45 | } 46 | }); 47 | } catch (error) { 48 | swal({ 49 | title: error.message, 50 | icon: "error", 51 | buttons: false, 52 | timer: 5000, 53 | }); 54 | } 55 | setLoading(false); 56 | }; 57 | 58 | return ( 59 |
60 |

Login

61 |
62 |
63 | 66 | setForm({ ...form, mobile: e.target.value })} 72 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 73 | /> 74 |
75 |
76 |
77 |
78 | 81 | setForm({ ...form, password: e.target.value })} 87 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 88 | /> 89 |
90 |
91 |
92 | 98 |
99 |
100 |

101 | Do not have account?{" "} 102 | 103 | Sign Up 104 | 105 |

106 |
107 |
108 | ); 109 | }; 110 | 111 | export default Login; 112 | -------------------------------------------------------------------------------- /movie-review/src/components/Reviews.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import ReactStars from "react-stars"; 3 | import { reviewsRef, db } from "./firebase/firebase"; 4 | import { 5 | addDoc, 6 | doc, 7 | updateDoc, 8 | query, 9 | where, 10 | getDocs, 11 | } from "firebase/firestore"; 12 | import { TailSpin, ThreeDots } from "react-loader-spinner"; 13 | import swal from "sweetalert"; 14 | import { Appstate } from "../App"; 15 | import { useNavigate } from "react-router"; 16 | 17 | const Reviews = ({ id, prevRating, number_of_users }) => { 18 | const [rating, setRating] = useState(0); 19 | const useAppstate = useContext(Appstate); 20 | const navigate = useNavigate(); 21 | const [loading, setLoading] = useState(false); 22 | const [reviewsLoading, setreviewsLoading] = useState(false); 23 | const [form, setForm] = useState(""); 24 | const [data, setData] = useState([]); 25 | const [newAdded, setNewAdded] = useState(0); 26 | 27 | const sendReview = async () => { 28 | setLoading(true); 29 | try { 30 | if (useAppstate.login) { 31 | await addDoc(reviewsRef, { 32 | movieid: id, 33 | name: useAppstate.userName, 34 | rating: rating, 35 | thought: form, 36 | timestamp: new Date().getTime(), 37 | }); 38 | 39 | const _doc = doc(db, "movies", id); 40 | await updateDoc(_doc, { 41 | rating: prevRating + rating, 42 | number_of_users: number_of_users + 1, 43 | }); 44 | 45 | setRating(0); 46 | setForm(""); 47 | setNewAdded(newAdded + 1); 48 | swal({ 49 | title: "Review Sent", 50 | icon: "success", 51 | buttons: false, 52 | timer: 2000, 53 | }); 54 | } else { 55 | navigate("/login"); 56 | swal({ 57 | title: "Please Login to Review movies.", 58 | icon: "info", 59 | buttons: false, 60 | timer: 5000, 61 | }); 62 | } 63 | } catch (error) { 64 | swal({ 65 | title: error.message, 66 | icon: "error", 67 | buttons: false, 68 | timer: 5000, 69 | }); 70 | } 71 | setLoading(false); 72 | }; 73 | 74 | useEffect(() => { 75 | async function getData() { 76 | setreviewsLoading(true); 77 | setData([]); 78 | let q = query(reviewsRef, where("movieid", "==", id)); 79 | const querySnapshot = await getDocs(q); 80 | 81 | querySnapshot.forEach((doc) => { 82 | setData((prev) => [...prev, doc.data()]); 83 | }); 84 | 85 | setreviewsLoading(false); 86 | } 87 | getData(); 88 | }, [newAdded]); 89 | 90 | return ( 91 |
92 | setRating(rate)} 97 | /> 98 | setForm(e.target.value)} 101 | placeholder="Share your thoughts..." 102 | className="w-full p-2 outline-none header" 103 | /> 104 | 110 | {reviewsLoading ? ( 111 |
112 | 113 |
114 | ) : ( 115 |
116 | {data.map((e, i) => { 117 | return ( 118 |
122 |
123 |

{e.name}

124 |

125 | ({new Date(e.timestamp).toLocaleString()}) 126 |

127 |
128 | 134 |

{e.thought}

135 |
136 | ); 137 | })} 138 |
139 | )} 140 |
141 | ); 142 | }; 143 | 144 | export default Reviews; 145 | -------------------------------------------------------------------------------- /movie-review/src/components/AddMovie.js: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from "react"; 2 | import { ThreeCircles } from "react-loader-spinner"; 3 | import { addDoc } from "firebase/firestore"; 4 | import { moviesRef } from "./firebase/firebase"; 5 | import swal from "sweetalert"; 6 | import { Appstate } from "../App"; 7 | import { useNavigate } from "react-router"; 8 | 9 | const AddMovie = () => { 10 | const useAppstate = useContext(Appstate); 11 | const navigate = useNavigate(); 12 | const [form, setForm] = useState({ 13 | title: "", 14 | year: "", 15 | image: "", 16 | description: "", 17 | }); 18 | 19 | const [loading, setLoading] = useState(false); 20 | 21 | const addMovie = async () => { 22 | setLoading(true); 23 | try { 24 | if (useAppstate.login) { 25 | await addDoc(moviesRef, form); 26 | swal({ 27 | title: "Succefully added", 28 | icon: "success", 29 | buttons: false, 30 | timer: 3000, 31 | }); 32 | setForm({ 33 | title: "", 34 | year: "", 35 | image: "", 36 | description: "", 37 | }); 38 | navigate("/"); 39 | } else { 40 | navigate("/login"); 41 | swal({ 42 | title: "Please Login to add movies.", 43 | icon: "info", 44 | buttons: false, 45 | timer: 5000, 46 | }); 47 | } 48 | } catch (error) { 49 | swal({ 50 | title: error.message, 51 | icon: "error", 52 | buttons: false, 53 | timer: 5000, 54 | }); 55 | } 56 | setLoading(false); 57 | }; 58 | 59 | return ( 60 |
61 |
62 |
63 |
64 |

65 | Add a New Movie 66 |

67 |
68 |
69 |
70 |
71 |
72 | 75 | 81 | setForm({ ...form, title: e.target.value }) 82 | } 83 | class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:bg-white focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 84 | /> 85 |
86 |
87 |
88 |
89 | 92 | setForm({ ...form, year: e.target.value })} 97 | class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:bg-white focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 98 | /> 99 |
100 |
101 |
102 |
103 | 106 | 111 | setForm({ ...form, image: e.target.value }) 112 | } 113 | class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:bg-white focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 114 | > 115 |
116 |
117 |
118 |
119 | 125 | 134 |
135 |
136 |
137 | 143 |
144 |
145 |
146 |
147 |
148 |
149 | ); 150 | }; 151 | 152 | export default AddMovie; 153 | -------------------------------------------------------------------------------- /movie-review/src/components/authentication/Signup.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { ThreeCircles } from "react-loader-spinner"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import { 5 | getAuth, 6 | RecaptchaVerifier, 7 | signInWithPhoneNumber, 8 | } from "firebase/auth"; 9 | import app from "../firebase/firebase"; 10 | import swal from "sweetalert"; 11 | import bcrypt from "bcryptjs"; 12 | import { addDoc } from "firebase/firestore"; 13 | import { usersRef } from "../firebase/firebase"; 14 | 15 | const auth = getAuth(app); 16 | const Signup = () => { 17 | const navigate = useNavigate(); 18 | const [form, setForm] = useState({ 19 | name: "", 20 | mobile: "", 21 | password: "", 22 | }); 23 | const [loading, setLoading] = useState(false); 24 | const [otpSent, setOtpSent] = useState(false); 25 | const [OTP, setOTP] = useState(""); 26 | 27 | const generateRecaptha = () => { 28 | window.recaptchaVerifier = new RecaptchaVerifier( 29 | "recaptcha-container", 30 | { 31 | size: "invisible", 32 | callback: (response) => {}, 33 | }, 34 | auth 35 | ); 36 | }; 37 | 38 | const requestOtp = () => { 39 | setLoading(true); 40 | generateRecaptha(); 41 | let appVerifier = window.recaptchaVerifier; 42 | signInWithPhoneNumber(auth, `+88${form.mobile}`, appVerifier) 43 | .then((confirmationResult) => { 44 | window.confirmationResult = confirmationResult; 45 | swal({ 46 | text: "OTP Sent", 47 | icon: "success", 48 | buttons: false, 49 | timer: 3000, 50 | }); 51 | setOtpSent(true); 52 | setLoading(false); 53 | }) 54 | .catch((error) => { 55 | console.log(error); 56 | }); 57 | }; 58 | 59 | const verifyOTP = () => { 60 | try { 61 | setLoading(true); 62 | window.confirmationResult.confirm(OTP).then((result) => { 63 | uploadData(); 64 | swal({ 65 | text: "Sucessfully Registered", 66 | icon: "success", 67 | buttons: false, 68 | timer: 3000, 69 | }); 70 | navigate("/login"); 71 | setLoading(false); 72 | }); 73 | } catch (error) { 74 | console.log(error); 75 | } 76 | }; 77 | 78 | const uploadData = async () => { 79 | try { 80 | const salt = bcrypt.genSaltSync(10); 81 | var hash = bcrypt.hashSync(form.password, salt); 82 | await addDoc(usersRef, { 83 | name: form.name, 84 | password: hash, 85 | mobile: form.mobile, 86 | }); 87 | } catch (err) { 88 | console.log(err); 89 | } 90 | }; 91 | 92 | return ( 93 |
94 |

Create an Account

95 | 96 | {otpSent ? ( 97 | <> 98 |
99 |
100 | 106 | setOTP(e.target.value)} 111 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 112 | > 113 |
114 |
115 |
116 | 126 |
127 | 128 | ) : ( 129 | <> 130 |
131 |
132 | 138 | setForm({ ...form, name: e.target.value })} 144 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 145 | > 146 |
147 |
148 |
149 |
150 | 156 | setForm({ ...form, mobile: e.target.value })} 163 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 164 | > 165 |
166 |
167 |
168 |
169 | 175 | setForm({ ...form, password: e.target.value })} 182 | class="w-full bg-purple-400 rounded border border-gray-300 focus:bg-purple-600 focus:ring-2 focus:ring-gray-200 text-base outline-none text-gray-100 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out" 183 | > 184 |
185 |
186 |
187 | 197 |
198 | 199 | )} 200 | 201 |
202 |

203 | Already have Account?{" "} 204 | 205 | Login 206 | 207 |

208 |
209 |
210 |
211 | ); 212 | }; 213 | 214 | export default Signup; 215 | --------------------------------------------------------------------------------