├── .vscode └── settings.json ├── googleIcon.png ├── images └── logo.png ├── forgate.css ├── js ├── dashboard.js ├── logout.js ├── firebase.js ├── forgate.js ├── restaurant.js ├── registration.js ├── add-dishes.js ├── order.js └── dishes.js ├── registration.css ├── index.html ├── app.js ├── style.css ├── register.html ├── forgate.html ├── login.html ├── dashboard.html ├── orders.html ├── restaurants.html ├── add-dishes.html └── dishes.html /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /googleIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alirazaramejo/smit-batch-10-food-delivery-app/HEAD/googleIcon.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alirazaramejo/smit-batch-10-food-delivery-app/HEAD/images/logo.png -------------------------------------------------------------------------------- /forgate.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | main { 7 | display: flex; 8 | align-items: center; 9 | padding-top: 40px; 10 | padding-bottom: 40px; 11 | background-color: #f5f5f5; 12 | height: 100%; 13 | } 14 | 15 | .form-signin { 16 | max-width: 410px; 17 | padding: 15px; 18 | } 19 | -------------------------------------------------------------------------------- /js/dashboard.js: -------------------------------------------------------------------------------- 1 | import { auth, onAuthStateChanged } from "./firebase.js" 2 | 3 | onAuthStateChanged(auth, (user) => { 4 | if (user) { 5 | console.log(user.email) 6 | if (user.email !== "admin@gmail.com") { 7 | location.href = "login.html" 8 | } 9 | 10 | } else { 11 | location.href = "login.html" 12 | } 13 | }); -------------------------------------------------------------------------------- /js/logout.js: -------------------------------------------------------------------------------- 1 | 2 | import {signOut,auth} from "./firebase.js" 3 | export async function logOut() { 4 | await signOut(auth).then(() => { 5 | Swal.fire({ 6 | icon: 'success', 7 | title: 'Logout Successfully' 8 | }) 9 | location.href = "../login.html" 10 | }).catch((error) => { 11 | Swal.fire({ 12 | icon: 'error', 13 | title: 'Oops...', 14 | text: error 15 | }) 16 | }); 17 | } 18 | document.getElementById('logoutbtn').addEventListener("click", logOut); -------------------------------------------------------------------------------- /js/firebase.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; 2 | import { 3 | getAuth, 4 | signInWithEmailAndPassword, 5 | onAuthStateChanged, 6 | createUserWithEmailAndPassword, 7 | sendPasswordResetEmail, 8 | GoogleAuthProvider, 9 | signInWithPopup, 10 | signOut 11 | } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; 12 | import { 13 | getStorage, 14 | ref, 15 | uploadBytesResumable, 16 | getDownloadURL, 17 | } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-storage.js"; 18 | import { 19 | getFirestore, 20 | collection, 21 | addDoc, 22 | query, 23 | where, 24 | getDocs, 25 | getDoc, 26 | doc, 27 | setDoc, 28 | serverTimestamp, 29 | updateDoc, 30 | } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; 31 | 32 | const firebaseConfig = { 33 | apiKey: "AIzaSyDG6-ZhFAuf2xkIVjieFKPzYXylqsASeXU", 34 | authDomain: "smit-batch-10.firebaseapp.com", 35 | projectId: "smit-batch-10", 36 | storageBucket: "smit-batch-10.appspot.com", 37 | messagingSenderId: "333213670128", 38 | appId: "1:333213670128:web:b7d83af5afed979bafc035", 39 | }; 40 | 41 | const app = initializeApp(firebaseConfig); 42 | const auth = getAuth(app); 43 | const storage = getStorage(app); 44 | const db = getFirestore(app); 45 | const provider = new GoogleAuthProvider(); 46 | export { 47 | provider, 48 | auth, 49 | signInWithEmailAndPassword, 50 | onAuthStateChanged, 51 | storage, 52 | ref, 53 | uploadBytesResumable, 54 | getDownloadURL, 55 | db, 56 | collection, 57 | addDoc, 58 | query, 59 | where, 60 | getDocs, 61 | doc, 62 | getDoc, 63 | serverTimestamp, 64 | updateDoc, 65 | setDoc, 66 | createUserWithEmailAndPassword, 67 | GoogleAuthProvider, 68 | signInWithPopup, 69 | sendPasswordResetEmail, 70 | signOut 71 | }; 72 | -------------------------------------------------------------------------------- /js/forgate.js: -------------------------------------------------------------------------------- 1 | import {auth,onAuthStateChanged,sendPasswordResetEmail} from "./firebase.js" 2 | 3 | const usr_email = document.getElementById('user_email'); 4 | const usr_passwd = document.getElementById('user_passwd'); 5 | 6 | export function validEmail() { 7 | var uemail = document.getElementById('user_email'); 8 | var emailerr = document.getElementById('email_err'); 9 | if (uemail.value == "" || uemail.value == null) { 10 | uemail.classList.remove("is-valid"); 11 | uemail.classList.add("is-invalid"); 12 | emailerr.innerHTML = "E-mail Address is required"; 13 | return false; 14 | } else { 15 | uemail.classList.remove("is-invalid"); 16 | uemail.classList.add("is-valid"); 17 | emailerr.innerHTML = ""; 18 | return true; 19 | } 20 | } 21 | 22 | export async function checkBeforeAuth() { 23 | await onAuthStateChanged(auth, (user) => { 24 | if (user) { 25 | location.href = "dashboard.html"; 26 | } 27 | }); 28 | } 29 | export async function resetPassword() { 30 | await sendPasswordResetEmail(auth, usr_email.value) 31 | .then(() => { 32 | Swal.fire({ 33 | icon: 'success', 34 | title: 'Password Reset Email Sent Successfully', 35 | showDenyButton: false, 36 | showCancelButton: false, 37 | confirmButtonText: 'ok', 38 | }).then((result) => { 39 | if (result.isConfirmed) { 40 | location.href = "index.html"; 41 | } 42 | }) 43 | }) 44 | .catch((error) => { 45 | const errorCode = error.code; 46 | Swal.fire({ 47 | icon: 'error', 48 | title: 'Oops...', 49 | text: errorCode 50 | }) 51 | }); 52 | } -------------------------------------------------------------------------------- /registration.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | height: 100vh; 6 | background-color: #4070f4; 7 | } 8 | 9 | .containerDiv { 10 | background-color: white; 11 | border-radius: 10px; 12 | padding: 40px 20px; 13 | width: 400px; 14 | } 15 | 16 | button { 17 | width: 100%; 18 | background-color: #ff2806 !important; 19 | } 20 | .form-label span { 21 | color: red; 22 | } 23 | #errorPara { 24 | color: red; 25 | } 26 | 27 | #alreadyAccountPara { 28 | text-align: center; 29 | } 30 | 31 | .hr-text { 32 | line-height: 1em; 33 | position: relative; 34 | outline: 0; 35 | border: 0; 36 | color: black; 37 | text-align: center; 38 | height: 1.5em; 39 | opacity: 0.5; 40 | 41 | &:before { 42 | content: ""; 43 | /* // use the linear-gradient for the fading effect 44 | // use a solid background color for a solid bar */ 45 | background: linear-gradient(to right, transparent, #000000, transparent); 46 | position: absolute; 47 | left: 0; 48 | top: 50%; 49 | width: 100%; 50 | height: 1px; 51 | } 52 | 53 | &:after { 54 | content: attr(data-content); 55 | position: relative; 56 | display: inline-block; 57 | color: black; 58 | 59 | padding: 0 0.5em; 60 | line-height: 1.5em; 61 | /* // this is really the only tricky part, you need to specify the background color of the container element... */ 62 | color: #818078; 63 | background-color: #fcfcfa; 64 | } 65 | } 66 | 67 | #googleSignInBtn { 68 | background: transparent !important; 69 | border: none; 70 | display: flex; 71 | align-items: center; 72 | justify-content: center; 73 | gap: 20px; 74 | border: 1px solid #cdcbcb; 75 | padding: 5px 0; 76 | } 77 | 78 | #googleSignInBtn img { 79 | width: 35px; 80 | } 81 | 82 | @media (max-width: 330px) { 83 | body { 84 | padding: 20px; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Foodara 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 38 | 39 |
40 |
41 | Loading... 42 |
43 |
44 | 45 |
46 | 47 | 48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | import { 2 | auth, 3 | signInWithEmailAndPassword, 4 | db, 5 | collection, 6 | getDocs, 7 | onAuthStateChanged, 8 | } from "./js/firebase.js"; 9 | 10 | const login = () => { 11 | const email = document.getElementById("email"); 12 | const password = document.getElementById("password"); 13 | signInWithEmailAndPassword(auth, email.value, password.value) 14 | .then((userCredential) => { 15 | const user = userCredential.user; 16 | console.log(user); 17 | if (user.email === "admin@gmail.com") { 18 | location.href = "dashboard.html"; 19 | } else { 20 | } 21 | }) 22 | .catch((error) => { 23 | const errorCode = error.code; 24 | const errorMessage = error.message; 25 | console.log("err->", errorMessage); 26 | }); 27 | }; 28 | 29 | const loginBtn = document.getElementById("loginBtn"); 30 | 31 | loginBtn && loginBtn.addEventListener("click", login); 32 | 33 | const pageSpinner = document.getElementById("page-spinner"); 34 | 35 | const getAllRestaurants = async () => { 36 | const resList = document.getElementById("res-list"); 37 | resList.innerHTML = ""; 38 | const q = collection(db, "restaurants"); 39 | const querySnapshot = await getDocs(q); 40 | let index = 0; 41 | pageSpinner.style.display = "none"; 42 | querySnapshot.forEach((doc) => { 43 | console.log(doc.id, " => ", doc.data()); 44 | resList.innerHTML += ` 45 |
46 |
47 | ... 49 |
50 |
${doc.data().name}
51 |

All variety are available 52 |

53 |

54 | Biryani 55 | Karahi 56 | Drinks 57 |

58 | View all dishes 60 |
61 |
62 |
63 | `; 64 | }); 65 | }; 66 | 67 | onAuthStateChanged(auth, (user) => { 68 | if ( 69 | (user && location.pathname.indexOf("restaurants") !== -1) || 70 | location.pathname === "/" 71 | ) { 72 | getAllRestaurants(); 73 | } 74 | }); 75 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | background-color: #fff; 3 | box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .12), inset 0 -1px 0 0 #dadce0; 4 | height: 70px; 5 | } 6 | 7 | .btn-primary { 8 | background-color: #ff2806; 9 | border-color: #ff2806; 10 | } 11 | 12 | 13 | .btn-primary:hover { 14 | background-color: #ff2806; 15 | border-color: #ff2806; 16 | } 17 | 18 | 19 | .btn-primary:active { 20 | background-color: #ff2806; 21 | border-color: #ff2806; 22 | opacity: 0.5; 23 | } 24 | 25 | .btn-outline-primary { 26 | border-color: #00ff00; 27 | color: #00ff00; 28 | } 29 | 30 | .btn-outline-primary:hover { 31 | background-color: #fff; 32 | border-color: #00ff00; 33 | color: #00ff00; 34 | } 35 | 36 | .btn-outline-primary:active { 37 | background-color: #fff; 38 | border-color: #00ff00; 39 | color: #00ff00; 40 | opacity: 0.5; 41 | } 42 | 43 | .text-bg-primary { 44 | background-color: #fbe50a !important; 45 | color: #000 !important; 46 | } 47 | 48 | .dish-image { 49 | width: 100px; 50 | height: 100px; 51 | object-fit: cover; 52 | border-radius: 10px; 53 | } 54 | 55 | 56 | .dish-card>div>div>div>div>.card-title { 57 | font-size: 14px; 58 | } 59 | 60 | .dish-card>div>div>div>div>p { 61 | font-size: 12px; 62 | } 63 | 64 | .dish-card>div>div>div>a { 65 | font-size: 12px; 66 | height: fit-content; 67 | } 68 | 69 | .qty-btn { 70 | background-color: #fff; 71 | border: 1px solid #ff2806; 72 | height: 30px; 73 | width: 30px; 74 | border-radius: 15px; 75 | display: flex; 76 | justify-content: center; 77 | align-items: center; 78 | font-size: 12px; 79 | font-weight: bold; 80 | } 81 | 82 | .socail-icons>i { 83 | font-size: 28px; 84 | color: #ff2806; 85 | } 86 | 87 | .fit-height { 88 | height: fit-content; 89 | } 90 | 91 | .slected-logo { 92 | display: none; 93 | } 94 | 95 | .spinner-border { 96 | width: 20px; 97 | height: 20px; 98 | font-size: 10px; 99 | } 100 | 101 | #submit-restaurant, 102 | #addDish { 103 | display: flex; 104 | align-items: center; 105 | gap: 4px; 106 | } 107 | 108 | #restaurant-spinner, 109 | #dish-spinner { 110 | display: none; 111 | } 112 | 113 | .res-logo-image, 114 | .dish-image { 115 | width: 30px; 116 | height: 30px; 117 | border-radius: 15px; 118 | } 119 | 120 | .card-img-top { 121 | width: 100%; 122 | height: 200px; 123 | object-fit: cover; 124 | } 125 | 126 | .page-spinner { 127 | width: 200px; 128 | height: 200px; 129 | } -------------------------------------------------------------------------------- /register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Signup 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Signup

17 |
18 |
19 | 20 | 21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 |
37 | 38 | 39 |
40 |
41 | 42 |

43 |

Already have an account? Login

44 | 45 |
46 | 50 |
51 |
52 | 53 | 54 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /forgate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Forgot Password | Firebase Auth Using JavaScript 8 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 41 | 42 |
43 |
44 | 45 | 69 | 70 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /js/restaurant.js: -------------------------------------------------------------------------------- 1 | import { storage, ref, uploadBytesResumable, getDownloadURL, db, collection, addDoc, getDocs } from "./firebase.js" 2 | 3 | const logo = document.getElementById("restaurant-logo"); 4 | const selectedLogo = document.getElementById("selected-logo"); 5 | let file; 6 | 7 | logo && logo.addEventListener("change", (e) => { 8 | file = e.target.files[0]; 9 | selectedLogo.style.display = "flex"; 10 | selectedLogo.src = URL.createObjectURL(e.target.files[0]) 11 | }) 12 | 13 | 14 | let uploadFile = (file, name) => { 15 | return new Promise((resolve, reject) => { 16 | const storageRef = ref(storage, `images/${name.split(" ").join("-")}`); 17 | const uploadTask = uploadBytesResumable(storageRef, file); 18 | uploadTask.on('state_changed', 19 | (snapshot) => { 20 | const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; 21 | console.log('Upload is ' + progress + '% done'); 22 | switch (snapshot.state) { 23 | case 'paused': 24 | console.log('Upload is paused'); 25 | break; 26 | case 'running': 27 | console.log('Upload is running'); 28 | break; 29 | } 30 | }, 31 | (error) => { 32 | reject(error) 33 | }, 34 | () => { 35 | 36 | getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { 37 | console.log('File available at', downloadURL); 38 | resolve(downloadURL) 39 | }); 40 | } 41 | ); 42 | }) 43 | } 44 | 45 | const getAllRestaurants = async () => { 46 | const resList = document.getElementById("res-list"); 47 | resList.innerHTML = ""; 48 | const q = collection(db, "restaurants"); 49 | const querySnapshot = await getDocs(q); 50 | let index = 0; 51 | querySnapshot.forEach((doc) => { 52 | console.log(doc.id, " => ", doc.data()); 53 | index++ 54 | resList.innerHTML += ` 55 | 56 | ${index} 57 | 58 | ${doc.data().name} 59 | ${doc.data().address} 60 | 61 | ` 62 | }); 63 | } 64 | 65 | getAllRestaurants() 66 | 67 | 68 | const submitRestaurant = document.getElementById("submit-restaurant"); 69 | 70 | 71 | submitRestaurant && submitRestaurant.addEventListener('click', async () => { 72 | const closeBtn = document.getElementById("close-btn") 73 | const spinner = document.getElementById("restaurant-spinner"); 74 | const name = document.getElementById("restaurant-name"); 75 | const address = document.getElementById("restaurant-address"); 76 | spinner.style.display = "block" 77 | const image = await uploadFile(file, name.value) 78 | const docRef = await addDoc(collection(db, "restaurants"), { 79 | name: name.value, 80 | address: address.value, 81 | image 82 | }); 83 | spinner.style.display = "none" 84 | name.value = ""; 85 | address.value = ""; 86 | logo.value = ""; 87 | selectedLogo.style.display = "none"; 88 | console.log("Document written with ID: ", docRef.id); 89 | getAllRestaurants(); 90 | closeBtn.click() 91 | }) 92 | 93 | export { uploadFile }; -------------------------------------------------------------------------------- /login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 39 | 40 |
41 |
42 |
43 |
44 | 45 | 46 |
We'll never share your email with anyone else.
47 |
48 |
49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 |
57 |
58 |
Don't have account?
59 | Register now 60 |
61 |
62 |
Don't remember password?
63 | forgat password 64 |
65 | 66 | 67 |
68 |
69 |
70 |
71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /js/registration.js: -------------------------------------------------------------------------------- 1 | 2 | import {auth,createUserWithEmailAndPassword,provider,onAuthStateChanged,signInWithPopup,db,doc,setDoc} from './firebase.js'; 3 | 4 | 5 | 6 | let sbtn = document.querySelector("#sbtn"); // get signin btn 7 | let errorPara = document.querySelector("#errorPara"); // get error paragraph 8 | 9 | sbtn.addEventListener("click", () => { 10 | let Email = document.querySelector("#semail"); // get email to signin user 11 | let password = document.querySelector("#spassword"); // get password to signin user 12 | let name = document.querySelector("#sname"); // get name of a user 13 | let phoneNumber = document.querySelector("#pNumber"); // get name of a user 14 | let Address = document.querySelector("#Address"); // get name of a user 15 | 16 | if (name.value == "") { 17 | errorPara.innerText = "Please fill name field!"; 18 | setTimeout(() => { 19 | errorPara.innerHTML = ""; 20 | }, 3000); 21 | } else { 22 | // storing data in a array 23 | let userData = { 24 | fullName: name.value,//s mean save 25 | Email: Email.value, 26 | password: password.value, 27 | phoneNumber : phoneNumber.value, 28 | Address:Address.value 29 | }; 30 | // creating user with eamil and password 31 | createUserWithEmailAndPassword(auth, userData.Email, userData.password) 32 | // email value , password value 33 | .then(async (userCredential) => { 34 | const user = userCredential.user; // getting user from firebase 35 | await setDoc(doc(db, "users", user.uid), { 36 | // collection name, unique id of user 37 | ...userData, // setting array in a database 38 | userId: user.uid, // also user id in the database 39 | }); 40 | location.href = "../login.html"; 41 | }) 42 | .catch((error) => { 43 | const errorCode = error.code; 44 | const errorMessage = errorCode.slice(5).toUpperCase(); 45 | const errMessage = errorMessage.replace(/-/g, " "); 46 | errorPara.innerText = errMessage; 47 | setTimeout(() => { 48 | errorPara.innerHTML = ""; 49 | }, 3000); 50 | }); 51 | } 52 | }); 53 | 54 | password.addEventListener("keypress", (e) => { 55 | if (e.key == "Enter") { 56 | sbtn.click(); 57 | } 58 | }); 59 | 60 | const googleSignInBtn = document.getElementById("googleSignInBtn"); 61 | 62 | googleSignInBtn.addEventListener("click", () => { 63 | signInWithPopup(auth, provider) 64 | .then(async (result) => { 65 | const credential = GoogleAuthProvider.credentialFromResult(result); 66 | const token = credential.accessToken; 67 | 68 | const user = result.user; 69 | 70 | let userData = { 71 | name: user.displayName, 72 | Email: user.email, 73 | }; 74 | 75 | await setDoc(doc(db, "users", user.uid), { 76 | // collection name, unique id of user 77 | ...userData, // setting array in a database 78 | userId: user.uid, // also user id in the database 79 | }); 80 | 81 | localStorage.setItem("userUid", user.uid); 82 | 83 | location.href = "../index.html"; 84 | }) 85 | .catch((error) => { 86 | // Handle Errors here. 87 | const errorCode = error.code; 88 | const errorMessage = error.message; 89 | // The email of the user's account used. 90 | const email = error.customData.email; 91 | // The AuthCredential type that was used. 92 | const credential = GoogleAuthProvider.credentialFromError(error); 93 | 94 | if (email) { 95 | errorPara.innerText = email; 96 | setTimeout(() => { 97 | errorPara.innerHTML = ""; 98 | }, 3000); 99 | } 100 | }); 101 | }); 102 | 103 | onAuthStateChanged(auth, (user) => { 104 | if (user) { 105 | const userUid = user.uid; 106 | } else { 107 | localStorage.removeItem("userUid"); 108 | } 109 | }); 110 | 111 | if (localStorage.getItem("userUid")) { 112 | location.href = "../index.html"; 113 | } 114 | -------------------------------------------------------------------------------- /dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 52 | 53 |
54 |
55 |
56 |
57 |
Total restaurants
58 |
500
59 |
60 |
61 |
62 |
63 |
64 |
65 |
Total dishes
66 |
3000
67 |
68 |
69 |
70 |
71 |
72 |
73 |
Total orders
74 |
10000
75 |
76 |
77 |
78 |
79 |
80 |
81 |
Total users
82 |
10
83 |
84 |
85 |
86 |
87 |
88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /js/add-dishes.js: -------------------------------------------------------------------------------- 1 | import { storage, ref, uploadBytesResumable, getDownloadURL, db, collection, addDoc, getDocs } from "./firebase.js" 2 | 3 | let uploadFile = (file, name) => { 4 | return new Promise((resolve, reject) => { 5 | const storageRef = ref(storage, `images/${name.split(" ").join("-")}`); 6 | const uploadTask = uploadBytesResumable(storageRef, file); 7 | uploadTask.on('state_changed', 8 | (snapshot) => { 9 | const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; 10 | console.log('Upload is ' + progress + '% done'); 11 | switch (snapshot.state) { 12 | case 'paused': 13 | console.log('Upload is paused'); 14 | break; 15 | case 'running': 16 | console.log('Upload is running'); 17 | break; 18 | } 19 | }, 20 | (error) => { 21 | reject(error) 22 | }, 23 | () => { 24 | 25 | getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { 26 | console.log('File available at', downloadURL); 27 | resolve(downloadURL) 28 | }); 29 | } 30 | ); 31 | }) 32 | } 33 | 34 | const getAllRestaurants = async () => { 35 | try { 36 | const q = collection(db, "restaurants"); 37 | const querySnapshot = await getDocs(q); 38 | const resSelect = document.getElementById("restaurant-name"); 39 | let index = 0; 40 | let restaurants = []; 41 | resSelect.innerHTML = `` 42 | querySnapshot.forEach((doc) => { 43 | restaurants.push({ ...doc.data(), id: doc.id }) 44 | index++ 45 | resSelect.innerHTML += ` 46 | 47 | ` 48 | }); 49 | return new Promise((resolve, reject) => { 50 | resolve(restaurants) 51 | }) 52 | } catch (err) { 53 | console.log("err", err) 54 | } 55 | } 56 | 57 | getAllRestaurants() 58 | 59 | const getAllDishes = async () => { 60 | const restaurants = await getAllRestaurants(); 61 | const allDishes = document.getElementById("all-dishes"); 62 | const q = collection(db, "dishes"); 63 | const querySnapshot = await getDocs(q); 64 | let index = 0; 65 | let restaurantNames = {}; 66 | for (var i = 0; i < restaurants.length; i++) { 67 | restaurantNames[restaurants[i].id] = restaurants[i].name 68 | } 69 | console.log("restaurantNames", restaurantNames) 70 | allDishes.innerHTML = `` 71 | querySnapshot.forEach((doc) => { 72 | index++; 73 | allDishes.innerHTML += ` 74 | 75 | 1 76 | 77 | ${doc.data().name} 78 | ${doc.data().price} 79 | ${doc.data().serving} 80 | ${restaurantNames[doc.data().restaurant]} 81 | 82 | ` 83 | }); 84 | } 85 | 86 | getAllDishes(); 87 | 88 | const addDish = document.getElementById("addDish"); 89 | 90 | addDish.addEventListener('click', async () => { 91 | const closeBtn = document.getElementById("close-btn") 92 | const spinner = document.getElementById("dish-spinner"); 93 | const resName = document.getElementById("restaurant-name"); 94 | const dishName = document.getElementById("dish-name"); 95 | const dishPrice = document.getElementById("dish-price"); 96 | const dishServing = document.getElementById("dish-serving"); 97 | const dishImage = document.getElementById("dish-image"); 98 | spinner.style.display = "block" 99 | const image = await uploadFile(dishImage.files[0], dishName.value) 100 | const dishDetail = { 101 | restaurant: resName.value, 102 | name: dishName.value, 103 | price: dishPrice.value, 104 | serving: dishServing.value, 105 | image 106 | } 107 | const docRef = await addDoc(collection(db, "dishes"), dishDetail); 108 | resName.value = ""; 109 | dishName.value = ""; 110 | dishPrice.value = ""; 111 | dishServing.value = ""; 112 | dishImage.value = ""; 113 | spinner.style.display = "none" 114 | closeBtn.click() 115 | getAllDishes() 116 | console.log(docRef) 117 | }) -------------------------------------------------------------------------------- /orders.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 13 | 14 | 15 | 20 | 24 | 25 | 26 | 27 | 28 |
29 | 79 | 80 |
81 |
82 | Loading... 83 |
84 |
85 | 109 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /js/order.js: -------------------------------------------------------------------------------- 1 | import { 2 | storage, 3 | ref, 4 | uploadBytesResumable, 5 | getDownloadURL, 6 | db, 7 | collection, 8 | addDoc, 9 | getDocs, 10 | serverTimestamp, 11 | doc, 12 | getDoc, 13 | updateDoc, 14 | } from "./firebase.js"; 15 | const placeOrder = document.getElementById("placeOrder"); 16 | 17 | placeOrder && 18 | placeOrder.addEventListener("click", async () => { 19 | const cartDiv = document.getElementById("cart"); 20 | const customerName = document.getElementById("customerName"); 21 | const customerContact = document.getElementById("customerContact"); 22 | const customerAddress = document.getElementById("customerAddress"); 23 | const cart = JSON.parse(localStorage.getItem("cart")); 24 | const sum = cart.reduce((a, b) => a + Number(b.price) * b.qty, 0); 25 | const totalAmount = document.getElementById("totalAmount"); 26 | const closeBtn = document.getElementById("closeBtn"); 27 | 28 | const orderDetails = { 29 | customerName: customerName.value, 30 | customerContact: customerContact.value, 31 | customerAddress: customerAddress.value, 32 | status: "pending", 33 | cart, 34 | timestamp: serverTimestamp(), 35 | orderAmount: sum, 36 | deliveryCharges: 100, 37 | totalAmount: sum + 100, 38 | }; 39 | await addDoc(collection(db, "orders"), orderDetails); 40 | Swal.fire({ 41 | position: "center-center", 42 | icon: "success", 43 | title: "Your order has been placed", 44 | showConfirmButton: false, 45 | timer: 1500, 46 | }); 47 | customerName.value = ""; 48 | customerContact.value = ""; 49 | customerAddress.value = ""; 50 | localStorage.removeItem("cart"); 51 | cartDiv.innerHTML = ""; 52 | totalAmount.innerHTML = ""; 53 | closeBtn.click(); 54 | }); 55 | 56 | const getAllOrders = async () => { 57 | const pageSpinner = document.getElementById("page-spinner"); 58 | const mainContent = document.getElementById("main-content"); 59 | const allOrders = document.getElementById("all-orders"); 60 | const q = collection(db, "orders"); 61 | const querySnapshot = await getDocs(q); 62 | let index = 0; 63 | querySnapshot.forEach((doc) => { 64 | index++; 65 | console.log("order", doc.data()); 66 | let status = doc.data().status; 67 | let statusColor = ""; 68 | if (status === "pending") { 69 | statusColor = "text-bg-warning"; 70 | } 71 | if (status === "delivered") { 72 | statusColor = "text-bg-success"; 73 | } 74 | allOrders.innerHTML += ` 75 | 76 | ${index} 77 | ${doc.data().customerName} 78 | ${doc.data().customerContact} 79 | ${doc.data().customerAddress} 80 | ${status} 81 | 82 | ${doc.data().totalAmount} 83 | 84 | 89 | 90 | 91 | `; 92 | }); 93 | pageSpinner.style.display = "none"; 94 | mainContent.style.display = "block"; 95 | }; 96 | 97 | getAllOrders(); 98 | 99 | let updateOrderId; 100 | 101 | const viewOrderDetail = async (id) => { 102 | updateOrderId = id; 103 | const cart = document.getElementById("cart"); 104 | const orderStatus = document.getElementById("orderStatus"); 105 | const docRef = doc(db, "orders", id); 106 | const docSnap = await getDoc(docRef); 107 | const cartItems = docSnap.data().cart; 108 | orderStatus.value = docSnap.data().status; 109 | cart.innerHTML = ""; 110 | for (var i = 0; i < cartItems.length; i++) { 111 | cart.innerHTML += ` 112 |
113 |
114 |
115 |
116 | 120 |
121 |
${ 122 | cartItems[i].name 123 | }
124 |

Rs: ${ 125 | cartItems[i].price 126 | } /- x ${ 127 | cartItems[i].qty 128 | } = ${cartItems[i].price * cartItems[i].qty}

129 |

Serves ${ 130 | cartItems[i].serving 131 | } 132 |

133 |
134 |
135 |
136 |
137 |
138 | `; 139 | } 140 | }; 141 | 142 | const updateOrder = document.getElementById("updateOrder"); 143 | 144 | updateOrder.addEventListener("click", async () => { 145 | const closeBtn = document.getElementById("close-btn"); 146 | const orderStatus = document.getElementById("orderStatus"); 147 | const docRef = doc(db, "orders", updateOrderId); 148 | await updateDoc(docRef, { 149 | status: orderStatus.value, 150 | }); 151 | closeBtn.click(); 152 | getAllOrders(); 153 | }); 154 | 155 | window.viewOrderDetail = viewOrderDetail; 156 | -------------------------------------------------------------------------------- /js/dishes.js: -------------------------------------------------------------------------------- 1 | import { 2 | collection, 3 | getDocs, 4 | db, 5 | where, 6 | query, 7 | doc, 8 | getDoc, 9 | } from "./firebase.js"; 10 | 11 | var urlParams = new URLSearchParams(window.location.search); 12 | let pageSpinner = document.getElementById("page-spinner"); 13 | let mainContent = document.getElementById("main-content"); 14 | 15 | const getRestaurantDetail = async () => { 16 | const resName = document.getElementById("res-name"); 17 | const resAddress = document.getElementById("res-address"); 18 | const resImage = document.getElementById("res-image"); 19 | const docRef = doc(db, "restaurants", urlParams.get("restaurant")); 20 | const docSnap = await getDoc(docRef); 21 | if (docSnap.exists()) { 22 | resName.innerHTML = docSnap.data().name; 23 | resAddress.innerHTML = docSnap.data().address; 24 | resImage.src = docSnap.data().image; 25 | console.log("Document data:", docSnap.data()); 26 | } else { 27 | // docSnap.data() will be undefined in this case 28 | console.log("No such document!"); 29 | } 30 | }; 31 | 32 | getRestaurantDetail(); 33 | 34 | let dishes = []; 35 | 36 | const getAllDishes = async () => { 37 | const allDishes = document.getElementById("all-dishes"); 38 | const q = query( 39 | collection(db, "dishes"), 40 | where("restaurant", "==", urlParams.get("restaurant")) 41 | ); 42 | const querySnapshot = await getDocs(q); 43 | pageSpinner.style.display = "none"; 44 | mainContent.style.display = "block"; 45 | allDishes.innerHTML = ``; 46 | querySnapshot.forEach((doc) => { 47 | dishes.push({ ...doc.data(), id: doc.id }); 48 | allDishes.innerHTML += ` 49 |
50 |
51 |
52 |
53 | 55 |
56 |
${doc.data().name}
57 |

Rs: ${doc.data().price} /-

58 |

Serves ${doc.data().serving} 59 |

60 |
61 |
62 |
63 | 66 | 1 67 | 70 | 71 | Add to cart 74 |
75 |
76 |
77 |
78 | `; 79 | }); 80 | }; 81 | 82 | getAllDishes(); 83 | 84 | const updateQty = (type, id) => { 85 | const qty = document.getElementById(id); 86 | if (Number(qty.innerHTML) < 2 && type === "-") { 87 | return; 88 | } 89 | if (type === "+") { 90 | qty.innerHTML = Number(qty.innerHTML) + 1; 91 | } else { 92 | qty.innerHTML = Number(qty.innerHTML) - 1; 93 | } 94 | }; 95 | 96 | const addToCart = (id) => { 97 | const cartItems = localStorage.getItem("cart"); 98 | const cart = cartItems ? JSON.parse(cartItems) : []; 99 | const qty = document.getElementById(id); 100 | const dish = dishes.filter((v) => v.id === id); 101 | cart.push({ ...dish[0], qty: Number(qty.innerHTML) }); 102 | localStorage.setItem("cart", JSON.stringify(cart)); 103 | console.log("cart", cart); 104 | const totalAmount = document.getElementById("totalAmount"); 105 | const sum = cart.reduce((a, b) => a + Number(b.price) * b.qty, 0); 106 | totalAmount.innerHTML = `Rs ${sum + 100} /-`; 107 | getCartItems(); 108 | }; 109 | 110 | const deleteCartItem = (i) => { 111 | const cartItems = JSON.parse(localStorage.getItem("cart")); 112 | cartItems.splice(Number(i), 1); 113 | localStorage.setItem("cart", JSON.stringify(cartItems)); 114 | const totalAmount = document.getElementById("totalAmount"); 115 | const sum = cartItems.reduce((a, b) => a + Number(b.price) * b.qty, 0); 116 | totalAmount.innerHTML = `Rs ${sum + 100} /-`; 117 | getCartItems(); 118 | }; 119 | 120 | const getCartItems = () => { 121 | const cartItems = JSON.parse(localStorage.getItem("cart")); 122 | const cart = document.getElementById("cart"); 123 | cart.innerHTML = ""; 124 | if (cartItems) { 125 | for (var i = 0; i < cartItems.length; i++) { 126 | console.log(cartItems[i]); 127 | cart.innerHTML += ` 128 |
129 |
130 |
131 |
132 | 134 |
135 |
${ 136 | cartItems[i].name 137 | }
138 |

Rs: ${ 139 | cartItems[i].price 140 | } /- x ${cartItems[i].qty} = ${ 141 | cartItems[i].price * cartItems[i].qty 142 | }

143 |

Serves ${ 144 | cartItems[i].serving 145 | } 146 |

147 |
148 |
149 | 150 |
151 |
152 |
153 | `; 154 | } 155 | } 156 | }; 157 | 158 | getCartItems(); 159 | 160 | window.updateQty = updateQty; 161 | window.addToCart = addToCart; 162 | window.deleteCartItem = deleteCartItem; 163 | -------------------------------------------------------------------------------- /restaurants.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 52 | 53 |
54 |
55 |

Restaurants

56 | 57 | 58 | 61 | 104 |
105 |
106 |
107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
#Restaurant imageRestaurant nameAddress
120 |
121 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /add-dishes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 52 | 53 |
54 |
55 |

Dishes

56 | 57 | 60 | 120 |
121 |
122 |
123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 |
#Dish imageDish namePriceServingRestaurant
138 |
139 |
140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /dishes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 13 | 14 | 15 | 20 | 24 | 25 | 26 | 27 | 28 |
29 | 60 | 61 |
62 |
63 | Loading... 64 |
65 |
66 | 67 | 210 |
211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | --------------------------------------------------------------------------------