├── 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 |
--------------------------------------------------------------------------------