├── assets ├── cover logo.jpg ├── header logo.png └── saylani favicon.png ├── config.js ├── style.css ├── app.js └── index.html /assets/cover logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alirazaramejo/saylani-form/HEAD/assets/cover logo.jpg -------------------------------------------------------------------------------- /assets/header logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alirazaramejo/saylani-form/HEAD/assets/header logo.png -------------------------------------------------------------------------------- /assets/saylani favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alirazaramejo/saylani-form/HEAD/assets/saylani favicon.png -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; 2 | 3 | const firebaseConfig = { 4 | apiKey: "AIzaSyAQjlwhuwWYJ-OdhhPP4XRxEgWSfQ5d3-o", 5 | authDomain: "ali-raza-518df.firebaseapp.com", 6 | databaseURL: "https://ali-raza-518df-default-rtdb.firebaseio.com", 7 | projectId: "ali-raza-518df", 8 | storageBucket: "ali-raza-518df.appspot.com", 9 | messagingSenderId: "308309137877", 10 | appId: "1:308309137877:web:ac0be37dd3c2bb9544055c", 11 | measurementId: "G-82NM2JZS9D" 12 | }; 13 | 14 | const app = initializeApp(firebaseConfig); 15 | 16 | export {app}; -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | .headerLogo { 8 | width: 100%; 9 | } 10 | 11 | .formContainer { 12 | display: flex; 13 | margin: 20px 0; 14 | } 15 | 16 | .formContainer label { 17 | width: 100%; 18 | } 19 | 20 | #formLabel { 21 | color: #0d6db7; 22 | } 23 | 24 | 25 | .selectInputDiv, 26 | .inputDiv { 27 | width: 100%; 28 | margin: 10px 0; 29 | } 30 | 31 | .selectInputDiv select { 32 | background-color: #fff; 33 | color: #bfbfbf !important; 34 | border-color: #8dc63f; 35 | border-radius: 5px; 36 | position: relative; 37 | transition: all .5s; 38 | width: 100%; 39 | height: 50px; 40 | padding: 0 10px; 41 | } 42 | 43 | .inputDiv input { 44 | border: 1px solid #8dc63f; 45 | width: 100%; 46 | height: 50px; 47 | padding: 0 10px; 48 | background-color: initial; 49 | border-radius: 5px; 50 | color: #666; 51 | outline: 0; 52 | font-size: 14px; 53 | transition: all .5s; 54 | } 55 | 56 | .inputDiv input:focus, 57 | .selectInputDiv select:focus-visible { 58 | border: 1px solid #0d6db7 !important; 59 | color: black; 60 | } 61 | 62 | /* Style for opened dropdown options */ 63 | .selectInputDiv select:focus, 64 | .selectInputDiv select:active, 65 | .selectInputDiv select:visited, 66 | .selectInputDiv select::target-text { 67 | color: black !important; 68 | outline: 0; 69 | } 70 | 71 | 72 | /* Style for the dropdown options */ 73 | .selectInputDiv select option { 74 | background-color: #fff; 75 | color: #333; 76 | transition: background-color 0.3s; 77 | /* Add transition for smooth color change */ 78 | } 79 | 80 | /* Style for the hovered option */ 81 | .selectInputDiv select option:hover { 82 | background-color: #0d6db7; 83 | color: #fff; 84 | /* Change text color on hover if needed */ 85 | } 86 | 87 | .col-12 { 88 | margin-top: 15px; 89 | } 90 | 91 | .uploadBtnDiv, 92 | .profilePicDiv { 93 | background-color: #fafafa; 94 | border: 1px dashed #d9d9d9; 95 | border-radius: 2px; 96 | cursor: pointer; 97 | height: 104px; 98 | margin-bottom: 8px; 99 | margin-right: 8px; 100 | text-align: center; 101 | transition: border-color .3s; 102 | vertical-align: top; 103 | width: 104px; 104 | } 105 | 106 | .uploadBtnDiv:hover, 107 | .profilePicDiv:hover { 108 | border-color: #1890ff; 109 | } 110 | 111 | .profilePicDiv { 112 | justify-content: center; 113 | align-items: center; 114 | display: none; 115 | } 116 | 117 | #profileImg { 118 | width: 100%; 119 | height: 100%; 120 | object-fit: cover; 121 | } 122 | 123 | .uploadBtnDiv .inputDiv { 124 | height: 100%; 125 | margin: 0; 126 | position: relative; 127 | } 128 | 129 | .uploadBtnDiv span { 130 | position: absolute; 131 | top: 50%; 132 | left: 50%; 133 | transform: translate(-50%, -50%); 134 | font-size: 14px; 135 | width: 65px; 136 | } 137 | 138 | .uploadBtnDiv input[type=file] { 139 | background-color: black; 140 | height: 100%; 141 | display: none; 142 | } 143 | 144 | .picRulesDiv ul { 145 | list-style: none; 146 | font-size: 14px; 147 | } 148 | 149 | .rulesDiv ol { 150 | font-size: 14px; 151 | } 152 | 153 | .separaterLine { 154 | margin: 24px 0; 155 | min-width: 100%; 156 | width: 100%; 157 | border-top: 1px solid rgba(0, 0, 0, 0.165); 158 | } 159 | 160 | .submitBtnDiv button { 161 | border: none; 162 | font-size: 14px !important; 163 | outline: none; 164 | padding: 10px 30px; 165 | width: 100%; 166 | } 167 | 168 | .submitBtnDiv { 169 | margin-bottom: 30px; 170 | } 171 | 172 | .submitBtn { 173 | border-color: #0a58ca; 174 | background-color: #0d6db7; 175 | color: #fff; 176 | } 177 | 178 | .submitBtn .spinner-border { 179 | width: 20px; 180 | height: 20px; 181 | } 182 | 183 | @media (max-width: 425px) { 184 | .upload-rulesDiv { 185 | flex-direction: column; 186 | } 187 | 188 | .upload-rulesDiv ul { 189 | padding: 0; 190 | } 191 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | import { app } from "./config.js"; 2 | 3 | import { 4 | getFirestore, 5 | collection, 6 | addDoc, 7 | setDoc, 8 | doc 9 | } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; 10 | 11 | import { 12 | getStorage, 13 | ref, 14 | uploadBytesResumable, 15 | getDownloadURL 16 | } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-storage.js"; 17 | 18 | const db = getFirestore(app); 19 | // Initialize Cloud Storage and get a reference to the service 20 | const storage = getStorage(); 21 | 22 | const picInputDiv = document.querySelector("#picInputDiv"); 23 | const picInput = document.querySelector("#picInput"); 24 | const profileImg = document.querySelector("#profileImg"); 25 | const profilePicDiv = document.querySelector(".profilePicDiv"); 26 | const submitBtn = document.querySelector(".submitBtn"); 27 | const loader = document.querySelector(".spinner-border"); 28 | let imgUrl; 29 | 30 | const downloadImageUrl = (file) => { 31 | return new Promise((resolve, reject) => { 32 | const profileImagesRef = ref(storage, `images/${file.name}/`); 33 | const uploadTask = uploadBytesResumable(profileImagesRef, file); 34 | 35 | uploadTask.on( 36 | 'state_changed', 37 | (snapshot) => { 38 | const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; 39 | switch (snapshot.state) { 40 | case 'paused': 41 | break; 42 | case 'running': 43 | profilePicDiv.innerHTML = ` 44 |
16 |