├── src ├── App.css ├── lib │ └── firebase.entities.js ├── index.css ├── Components │ ├── card │ │ └── Card.jsx │ ├── FileInput │ │ └── FileInput.jsx │ ├── TextInput │ │ └── TextInput.jsx │ ├── Button │ │ └── Button.jsx │ ├── ImageActions │ │ └── ImageActions.jsx │ ├── ImageDisplay │ │ └── ImageDisplay.jsx │ ├── InputField │ │ └── InputField.jsx │ ├── ProductListing │ │ ├── components │ │ │ └── product │ │ │ │ └── ProductCard.jsx │ │ └── ProductListing.jsx │ └── Navbar.jsx ├── Pages │ ├── Dashborad │ │ ├── Dashboard.jsx │ │ ├── AddProduct.jsx │ │ └── AddProductForm.jsx │ ├── Home.jsx │ ├── SinglePage │ │ └── SinglePage.jsx │ └── registration │ │ ├── Signup.jsx │ │ └── Login.jsx ├── Router │ ├── protectRoute │ │ ├── DashboardProtect.jsx │ │ └── ProtectedRoute.jsx │ └── NavigationRouter.jsx ├── App.jsx ├── main.jsx ├── Firebase │ └── firebaseConfig.js └── services │ └── products.service.js ├── postcss.config.js ├── vite.config.js ├── tailwind.config.js ├── .gitignore ├── index.html ├── README.md ├── .env ├── .eslintrc.cjs └── package.json /src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/firebase.entities.js: -------------------------------------------------------------------------------- 1 | export const productEntity = 'products' -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/Components/card/Card.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function Card() { 4 | return ( 5 |
Card
6 | ) 7 | } 8 | 9 | export default Card -------------------------------------------------------------------------------- /src/Pages/Dashborad/Dashboard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function Dashboard() { 4 | return ( 5 |
Dashboard
6 | ) 7 | } 8 | 9 | export default Dashboard -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /src/Components/FileInput/FileInput.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const FileInput = ({ onChange }) => { 4 | return ; 5 | }; 6 | 7 | export default FileInput; 8 | -------------------------------------------------------------------------------- /src/Router/protectRoute/DashboardProtect.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function DashboardProtect() { 4 | return ( 5 |
DashboardProtect
6 | ) 7 | } 8 | 9 | export default DashboardProtect -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/**/*.{js,jsx,ts,tsx}", 5 | ], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [], 10 | } -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import NavigationRouter from './Router/NavigationRouter' 3 | 4 | function App() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default App -------------------------------------------------------------------------------- /src/Components/TextInput/TextInput.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const TextInput = ({ type, placeholder, value, onChange }) => { 4 | return ; 5 | }; 6 | 7 | export default TextInput; 8 | -------------------------------------------------------------------------------- /src/Components/Button/Button.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function Button({ onClick, className, children }) { 4 | return ( 5 | 8 | ); 9 | } 10 | 11 | export default Button; -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /src/Pages/Dashborad/AddProduct.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import AddProductForm from './AddProductForm' 3 | function AddProduct() { 4 | return ( 5 |
6 |

Add product

7 | 8 |
9 | ) 10 | } 11 | 12 | export default AddProduct -------------------------------------------------------------------------------- /src/Components/ImageActions/ImageActions.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const ImageActions = ({ onEdit, onDelete }) => { 4 | return ( 5 |
6 | 7 | 8 |
9 | ); 10 | }; 11 | 12 | export default ImageActions; 13 | -------------------------------------------------------------------------------- /src/Router/protectRoute/ProtectedRoute.jsx: -------------------------------------------------------------------------------- 1 | import { Navigate } from "react-router-dom"; 2 | 3 | export const ProtectedRoute = ({children}) => { 4 | const user = JSON.parse(localStorage.getItem('user')); 5 | 6 | if(user){ 7 | return children 8 | } 9 | else{ 10 | return 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/Components/ImageDisplay/ImageDisplay.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const ImageDisplay = ({ url, name, price }) => { 4 | return ( 5 |
6 | {`Image`} 7 |

Name: {name}

8 |

Price: {price}

9 |
10 | ); 11 | }; 12 | 13 | export default ImageDisplay; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/Components/InputField/InputField.jsx: -------------------------------------------------------------------------------- 1 | // TextInput.js 2 | 3 | import React from "react"; 4 | 5 | function TextInput({ type, placeholder, value, onChange }) { 6 | return ( 7 | 13 | ); 14 | } 15 | 16 | export default TextInput; 17 | -------------------------------------------------------------------------------- /src/Pages/Home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Navbar from '../Components/Navbar' 3 | import Card from '../Components/card/Card' 4 | import ProductListing from '../Components/ProductListing/ProductListing' 5 | function Home() { 6 | return ( 7 |
8 | 9 | 10 | 11 |
12 | ) 13 | } 14 | 15 | export default Home -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Components/ProductListing/components/product/ProductCard.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react' 2 | import { Link } from 'react-router-dom' 3 | 4 | function ProductCard(props) { 5 | const { name, price, pid } = props 6 | return ( 7 |
8 |

{name}

9 |

{price}

10 | view 11 |
12 | ) 13 | } 14 | 15 | export default memo(ProductCard) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | 2 | # const firebaseConfig = { 3 | # apiKey: , 4 | # authDomain: , 5 | # databaseURL: , 6 | # projectId: , 7 | # storageBucket: , 8 | # messagingSenderId: , 9 | # appId: , 10 | # measurementId: "G-82NM2JZS9D" 11 | # }; 12 | 13 | 14 | VITE_API_KEY="AIzaSyAQjlwhuwWYJ-OdhhPP4XRxEgWSfQ5d3-o" 15 | VITE_AUTH_DOMAIN="ali-raza-518df.firebaseapp.com" 16 | VITE_DB_NAME="https://ali-raza-518df-default-rtdb.firebaseio.com" 17 | VITE_PROJECT_ID="ali-raza-518df" 18 | VITE_STORAGE_BUCKET="ali-raza-518df.appspot.com" 19 | VITE_MESSAGE_SENDER_ID="308309137877" 20 | VITE_APP_ID="1:308309137877:web:ac0be37dd3c2bb9544055c" 21 | 22 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/Components/ProductListing/ProductListing.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react" 2 | import { getAllProducts } from "../../services/products.service" 3 | import ProductCard from "./components/product/ProductCard" 4 | 5 | 6 | function ProductListing() { 7 | const [products, setProducts] = useState(null) 8 | useEffect(() => { 9 | (async () => { 10 | const productsResponse = await getAllProducts() 11 | setProducts(productsResponse) 12 | })() 13 | }, []) 14 | 15 | 16 | if (!products) return null 17 | 18 | return ( 19 | <> 20 |

Product Listing

21 | { 22 | products.map((product, idx) => { 23 | return 24 | }) 25 | } 26 | 27 | ) 28 | } 29 | 30 | export default ProductListing 31 | -------------------------------------------------------------------------------- /src/Firebase/firebaseConfig.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getAuth } from "firebase/auth"; 3 | import { getFirestore } from 'firebase/firestore'; 4 | import { getStorage } from 'firebase/storage'; 5 | import {ref,getDatabase} from "firebase/database"; 6 | 7 | const firebaseConfig = { 8 | apiKey: import.meta.env.VITE_API_KEY, 9 | authDomain: import.meta.env.VITE_AUTH_DOMAIN, 10 | databaseURL: import.meta.env.VITE_DB_NAME, 11 | projectId: import.meta.env.VITE_PROJECT_ID, 12 | storageBucket: import.meta.env.VITE_STORAGE_BUCKET, 13 | messagingSenderId: import.meta.env.VITE_MESSAGE_SENDER_ID, 14 | appId: import.meta.env.VITE_APP_ID 15 | }; 16 | 17 | const app = initializeApp(firebaseConfig); 18 | const db = getDatabase(app); 19 | const auth = getAuth(app); 20 | const imageDb = getStorage(app) 21 | 22 | export { app, db, auth, imageDb,ref }; 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mini-task", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@reduxjs/toolkit": "^2.2.3", 14 | "antd": "^5.16.4", 15 | "firebase": "^10.11.0", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0", 18 | "react-form-hook": "^0.0.1", 19 | "react-hook-form": "^7.51.3", 20 | "react-redux": "^9.1.1", 21 | "react-router-dom": "^6.23.0", 22 | "react-toastify": "^10.0.5", 23 | "uuid": "^9.0.1" 24 | }, 25 | "devDependencies": { 26 | "@types/react": "^18.2.66", 27 | "@types/react-dom": "^18.2.22", 28 | "@vitejs/plugin-react": "^4.2.1", 29 | "autoprefixer": "^10.4.19", 30 | "eslint": "^8.57.0", 31 | "eslint-plugin-react": "^7.34.1", 32 | "eslint-plugin-react-hooks": "^4.6.0", 33 | "eslint-plugin-react-refresh": "^0.4.6", 34 | "postcss": "^8.4.38", 35 | "tailwindcss": "^3.4.3", 36 | "vite": "^5.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link, useNavigate } from 'react-router-dom' 3 | 4 | function Navbar() { 5 | const user = JSON.parse(localStorage.getItem('user')); 6 | // console.log(user) 7 | 8 | const navigate = useNavigate(); 9 | 10 | const logout = () =>{ 11 | localStorage.clear('user'); 12 | navigate('/login') 13 | } 14 | return ( 15 |
17 |
18 |
E-NoteBook
19 |
20 |
21 |
    22 | 23 |
  • Home
  • 24 | 25 | {user &&
  • logout
  • } 26 |
27 |
28 |
29 | ) 30 | } 31 | 32 | export default Navbar -------------------------------------------------------------------------------- /src/Pages/SinglePage/SinglePage.jsx: -------------------------------------------------------------------------------- 1 | // ProductDetailPage.js 2 | import React, { useEffect, useState } from 'react'; 3 | import { useParams } from 'react-router-dom'; 4 | import { getProductData } from '../../services/products.service'; 5 | 6 | function SinglePage() { 7 | const { id } = useParams(); 8 | const [productData, setProductData] = useState(null); 9 | 10 | 11 | useEffect(() => { 12 | const fetchData = async () => { 13 | try { 14 | const data = await getProductData(id); 15 | console.log(data) 16 | 17 | 18 | setProductData(data); 19 | } catch (error) { 20 | console.error('Error fetching product data:', error); 21 | } 22 | }; 23 | fetchData(); 24 | }, [id]); 25 | 26 | return ( 27 | <> 28 | {/* Render product data here */} 29 | {productData && ( 30 |
31 | {/* Render product details using productData */} 32 |

{productData[0]}

33 |

{productData[1]}

34 |

{productData[2]}

35 |

{productData[3]}

36 |

{productData[4]}

37 |

{productData[5]}

38 | {/* Add other product details rendering here */} 39 |
40 | )} 41 | 42 | ); 43 | } 44 | 45 | export default SinglePage; 46 | -------------------------------------------------------------------------------- /src/Router/NavigationRouter.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 3 | import Home from "../Pages/Home"; 4 | import Login from "../Pages/registration/Login"; 5 | import Signup from "../Pages/registration/Signup"; 6 | import { ProtectedRoute } from "./protectRoute/ProtectedRoute"; 7 | import Dashboard from "../Pages/Dashborad/Dashboard"; 8 | import DashboardProtect from "./protectRoute/DashboardProtect"; 9 | import SinglePage from "../Pages/SinglePage/SinglePage"; 10 | import AddProduct from "../Pages/Dashborad/AddProduct"; 11 | 12 | function NavigationRouter() { 13 | return ( 14 | 15 | 16 | 20 | 21 | 22 | } 23 | /> 24 | 28 | 29 | 30 | } 31 | /> 32 | 36 | 37 | 38 | } 39 | /> 40 | } /> 41 | } /> 42 | 43 | 44 | 45 | ); 46 | } 47 | 48 | export default NavigationRouter; 49 | -------------------------------------------------------------------------------- /src/Pages/Dashborad/AddProductForm.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Form, Input, InputNumber, Upload, Button } from 'antd'; 3 | import { UploadOutlined } from '@ant-design/icons'; 4 | import { addProduct } from '../../services/products.service'; 5 | const { TextArea } = Input; 6 | 7 | const AddProductForm = () => { 8 | const onFinish = async(data) => { 9 | console.log('Form data:', data); 10 | // console.log('Form data:', data.upload[0].originFileObj.name); 11 | const addProductResponse = await addProduct(data); 12 | }; 13 | 14 | return ( 15 |
20 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 41 |