header.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  2. <!-- <link rel="stylesheet" href="{{ " /css/main.css" | prepend: site.baseurl }}"> -->
  3. <style>
  4. .user-icon {
  5. display: inline-block;
  6. position: relative;
  7. }
  8. .dropdown {
  9. display: inline-block;
  10. position: relative;
  11. z-index: 1000;
  12. }
  13. .dropdown-content {
  14. display: none;
  15. position: absolute;
  16. width: auto;
  17. overflow: auto;
  18. box-shadow: 0px 10px 10px 0px rgba(0, 0, 0, 0.4);
  19. /* background-color: rgba(255, 255, 255, 0); */
  20. background-color: white;
  21. }
  22. .dropdown.active .dropdown-content {
  23. display: block;
  24. }
  25. .dropdown-content a {
  26. display: block;
  27. color: #000000;
  28. padding: 5px;
  29. text-decoration: none;
  30. }
  31. .dropdown-content a:hover {
  32. color: #FFFFFF;
  33. background-color: #FFC907;
  34. }
  35. .dropdown:hover {
  36. /* Resetting styles for hover state */
  37. border: none;
  38. box-shadow: none;
  39. display: block;
  40. /* Or any other appropriate display value */
  41. grid-template-columns: initial;
  42. /* Or any other appropriate value */
  43. }
  44. /* Container for buttons */
  45. .button-container {
  46. display: flex;
  47. justify-content: flex-end;
  48. /* Adjust as needed */
  49. }
  50. /* Style for modal buttons */
  51. /* Container for buttons */
  52. .button-container {
  53. display: flex;
  54. justify-content: flex-end;
  55. /* Adjust as needed */
  56. margin-top: 20px;
  57. /* Adjust as needed for spacing between content and buttons */
  58. }
  59. /* Style for the modal */
  60. #navBar.modal {
  61. display: flex;
  62. flex-direction: column;
  63. align-items: center;
  64. }
  65. #emailCode,
  66. #emailCodeVerify {
  67. display: flex;
  68. flex-direction: row;
  69. align-items: center;
  70. margin-bottom: 10px;
  71. }
  72. .modal {
  73. display: none;
  74. position: fixed;
  75. top: 50%;
  76. left: 50%;
  77. transform: translate(-50%, -50%);
  78. padding: 20px;
  79. background-color: white;
  80. border: 2px solid #ccc;
  81. z-index: 2000;
  82. width: 60%;
  83. height: 20%;
  84. text-align: center;
  85. font-family: Reforma2018, serif;
  86. font-size: 1em;
  87. }
  88. /* Additional styling for buttons */
  89. .btn {
  90. position: relative;
  91. border-radius: 4px;
  92. background-color: transparent;
  93. border: 1px solid #29335C;
  94. font-family: Reforma2018, serif;
  95. margin: 10px;
  96. padding-left: 2px;
  97. padding-right: 2px;
  98. }
  99. .btn.primary {
  100. background-color: #FFC907;
  101. color: black;
  102. border: 1px solid #d3a500;
  103. }
  104. .btn.is-large {
  105. font-size: 1em;
  106. text-align: center;
  107. }
  108. /* Rule App styles */
  109. .rule-app * {
  110. box-sizing: border-box;
  111. }
  112. </style>
  113. <header class="site-header">
  114. <div class="wrapper">
  115. <a class="site-title" href="{{ site.baseurl }}/">{{ site.title }}</a>
  116. <img src="{% link assets/elements/icon_do.svg %}" alt="do-ocracy icon"
  117. style="height:40px; padding: 5px 0 0 20px;" />
  118. <nav class="site-nav">
  119. <a href="#" class="menu-icon">
  120. <svg viewBox="0 0 18 15">
  121. <path fill="#424242"
  122. d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z" />
  123. <path fill="#424242"
  124. d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z" />
  125. <path fill="#424242"
  126. d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z" />
  127. </svg>
  128. </a>
  129. <div class="trigger" style="display: inline-block;">
  130. {% for my_page in site.pages %}
  131. {% if my_page.title %}
  132. <a class="page-link{% if page.url == my_page.url %} page-link-active{% endif %}"
  133. href="{{ my_page.url | prepend: site.baseurl }}">{{ my_page.title }}</a>
  134. {% endif %}
  135. {% endfor %}
  136. <div class="user-icon" id="loginLogoutButton">
  137. <div id="login">
  138. <button class="btn primary is-large" onclick="showLoginModal()"
  139. style="height: 42px; width: 100px; padding: 2px; text-align: center">
  140. <img src="{% link assets/tabler_icons/login.svg %}" alt="Login"> Login
  141. </button>
  142. </div>
  143. <div id="logout">
  144. <button class="btn primary is-large" onclick="toggleDropdown()"
  145. style="height: 40px; width: 40px; padding: 2px; text-align: center">
  146. <img src="{% link assets/tabler_icons/user.svg %}" alt="Login">
  147. </button>
  148. <div class="dropdown-content">
  149. <div id="emailText"
  150. style="padding: 10px; padding-top: 20px; margin-top: 1px; margin-bottom: 1px; height: 10 px">
  151. </div>
  152. <a href="#" style="padding: 10px; margin-top: 1px; margin-bottom: 1px; height: 10 px"
  153. @click="logout">Logout</a>
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. </div>
  159. <div id="navBar" class="modal" style="display: none;">
  160. <div id="emailCode" style="display:block; align-items: center;">
  161. <label for="emailInput">Enter your email:</label>
  162. <input type="email" id="emailInput" v-model="loginEmail" required>
  163. <button class="btn primary is-large" @click="sendOTP" style="text-align:center;">Send Code</button>
  164. </div>
  165. <div id="emailCodeVerify" style="display: none;">
  166. <label for="otpInput">Enter Code to Login:</label>
  167. <input type="text" id="otpInput" v-model="otpCode" required>
  168. <button class="btn primary is-large" @click="verifyOTP">Verify Code</button>
  169. <button class="btn primary is-large" @click="sendOTPAagin"> Send Code Again</button>
  170. </div>
  171. <button class="btn primary is-large" @click="closeModal">Close</button>
  172. </div>
  173. </div>
  174. </div>
  175. </nav>
  176. </div>
  177. </header>
  178. <script>
  179. function toggleDropdown() {
  180. var dropdown = document.getElementById('logout');
  181. dropdown.classList.toggle('active');
  182. var myDiv = document.getElementById('emailText'); // Get the div element by ID
  183. myDiv.textContent = localStorage.getItem('userEmail');
  184. }
  185. function showLoginModal() {
  186. // Show the modal and overlay
  187. document.getElementById('navBar').style.display = 'block';
  188. document.getElementById('overlay').style.display = 'block';
  189. }
  190. function logout() {
  191. // Remove email from local storage
  192. localStorage.removeItem('userEmail');
  193. // Hide the dropdown and overlay
  194. document.getElementById('login').style.display = 'block';
  195. document.getElementById('logout').style.display = 'none';
  196. document.getElementById('emailCode').style.display = 'block';
  197. document.getElementById('emailCodeVerify').style.display = 'none';
  198. window.location.reload();
  199. }
  200. function showLoginModal() {
  201. document.getElementById('navBar').style.display = 'block';
  202. // document.getElementById('overlay').style.display = 'block';
  203. }
  204. function hideLoginModal() {
  205. document.getElementById('navBar').style.display = 'none';
  206. document.getElementById('overlay').style.display = 'none';
  207. }
  208. function isValidEmail(email) {
  209. // Regular expression for a basic email validation
  210. const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  211. return emailRegex.test(email);
  212. }
  213. new Vue({
  214. el: '#loginLogoutButton',
  215. data: {
  216. email: localStorage.getItem('userEmail') || null,
  217. showDropdown: false,
  218. },
  219. mounted() {
  220. // Retrieve email from local storage on component mount
  221. this.email = localStorage.getItem('userEmail');
  222. if (this.email) {
  223. document.getElementById('login').style.display = 'none';
  224. document.getElementById('logout').style.display = 'block';
  225. } else {
  226. document.getElementById('login').style.display = 'block';
  227. document.getElementById('logout').style.display = 'none';
  228. }
  229. },
  230. });
  231. new Vue({
  232. el: '#navBar',
  233. data: {
  234. loginEmail: '',
  235. email: localStorage.getItem('userEmail'),
  236. otpCode: "",
  237. backendUrlOtp: "http://localhost:3000/api/send_otp",
  238. backendUrlValidateOtp: "http://localhost:3000/api/validate_otp"
  239. },
  240. methods: {
  241. sendOTPAagin() {
  242. document.getElementById('emailCode').style.display = 'block';
  243. document.getElementById('emailCodeVerify').style.display = 'none';
  244. },
  245. sendOTP() {
  246. const requestData = {
  247. email: this.loginEmail
  248. }
  249. if (isValidEmail(this.loginEmail)) {
  250. fetch(this.backendUrlOtp, {
  251. method: 'POST',
  252. headers: {
  253. 'Content-Type': 'application/json',
  254. 'Access-Control-Allow-Methods': 'POST',
  255. 'Access-Control-Allow-Headers': 'Content-Type'
  256. // Add any other headers you may need, such as authorization headers
  257. },
  258. body: JSON.stringify(requestData),
  259. }).then(response => {
  260. if (!response.ok) {
  261. alert('Error while sending OTP');
  262. } else {
  263. alert(`Code sent to: ${this.loginEmail}`);
  264. document.getElementById('emailCode').style.display = 'none';
  265. document.getElementById('emailCodeVerify').style.display = 'block';
  266. }
  267. })
  268. } else {
  269. alert(`Please enter valid email address`);
  270. }
  271. },
  272. verifyOTP() {
  273. const requestData = {
  274. email: this.loginEmail,
  275. otp: this.otpCode
  276. }
  277. fetch(this.backendUrlValidateOtp, {
  278. method: 'POST',
  279. headers: {
  280. 'Content-Type': 'application/json',
  281. 'Access-Control-Allow-Methods': 'POST',
  282. 'Access-Control-Allow-Headers': 'Content-Type'
  283. // Add any other headers you may need, such as authorization headers
  284. },
  285. body: JSON.stringify(requestData),
  286. }).then(response => {
  287. if (response.status == 500) {
  288. alert('Error while validating code');
  289. } else if (response.status == 200) {
  290. alert('Logged in successfully');
  291. localStorage.setItem('userEmail', this.loginEmail)
  292. document.getElementById('login').style.display = 'none';
  293. document.getElementById('logout').style.display = 'block';
  294. document.getElementById('logout').classList.remove('active');
  295. this.closeModal();
  296. } else {
  297. alert('Invalid code, please enter valid code');
  298. }
  299. })
  300. },
  301. closeModal() {
  302. document.getElementById('navBar').style.display = 'none';
  303. },
  304. },
  305. });
  306. </script>