update,
This commit is contained in:
18
_tecky/party-planner/backend/public/404.css
Normal file
18
_tecky/party-planner/backend/public/404.css
Normal file
@@ -0,0 +1,18 @@
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.word {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-weight: bold;
|
||||
font-size: 50px;
|
||||
margin: 30px;
|
||||
}
|
14
_tecky/party-planner/backend/public/404.html
Normal file
14
_tecky/party-planner/backend/public/404.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="/404.css" />
|
||||
<title>404 Not Found</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="word">404 Not Found</div>
|
||||
<img src="/asset/PngItem_6655441.png" />
|
||||
</body>
|
||||
</html>
|
59
_tecky/party-planner/backend/public/addNavbar.css
Normal file
59
_tecky/party-planner/backend/public/addNavbar.css
Normal file
@@ -0,0 +1,59 @@
|
||||
/* login nav css */
|
||||
|
||||
.header-nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 92px;
|
||||
background-color: #efefd0;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navbar-brand > img {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.navbar > .navbar-brand {
|
||||
font-size: 30px;
|
||||
font-family: 'Pacifico', cursive;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.navbar > .btn {
|
||||
font-size: 20px;
|
||||
color: #293241;
|
||||
}
|
||||
|
||||
.login-part {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.landing-Page-login-btn {
|
||||
font-size: 20px;
|
||||
color: #495871;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.landing-Page-login-btn > .bi {
|
||||
margin: 0px 10px 0px 2px;
|
||||
}
|
||||
|
||||
.login-part .dropdown-menu {
|
||||
color: #495871;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.logout {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 450px) {
|
||||
.navbar-logo-text {
|
||||
display: none;
|
||||
}
|
||||
}
|
BIN
_tecky/party-planner/backend/public/asset/PngItem_6655441.png
(Stored with Git LFS)
Normal file
BIN
_tecky/party-planner/backend/public/asset/PngItem_6655441.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
_tecky/party-planner/backend/public/asset/btn_google_signin_light_normal_web.png
(Stored with Git LFS)
Normal file
BIN
_tecky/party-planner/backend/public/asset/btn_google_signin_light_normal_web.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
_tecky/party-planner/backend/public/asset/party_icon.jpg
(Stored with Git LFS)
Normal file
BIN
_tecky/party-planner/backend/public/asset/party_icon.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
41
_tecky/party-planner/backend/public/asset/submit_button.svg
Normal file
41
_tecky/party-planner/backend/public/asset/submit_button.svg
Normal file
@@ -0,0 +1,41 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="161"
|
||||
height="72"
|
||||
fill="none"
|
||||
viewBox="0 0 161 72"
|
||||
>
|
||||
<g filter="url(#a)" opacity=".482">
|
||||
<rect
|
||||
width="56.047"
|
||||
height="7.606"
|
||||
x="52.31"
|
||||
y="47.698"
|
||||
fill="#F29559"
|
||||
rx="2"
|
||||
/>
|
||||
</g>
|
||||
<rect width="160.667" height="51.718" y=".543" fill="#F29559" rx="6" />
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M33.651 32.18c-1.32 0-2.454-.264-3.402-.792a5.468 5.468 0 0 1-2.16-2.268c-.504-.984-.756-2.142-.756-3.474 0-1.332.252-2.484.756-3.456a5.354 5.354 0 0 1 2.16-2.25c.948-.54 2.082-.81 3.402-.81.852 0 1.656.132 2.412.396.768.264 1.398.642 1.89 1.134l-.756 1.836c-.54-.456-1.092-.786-1.656-.99a5.04 5.04 0 0 0-1.818-.324c-1.284 0-2.262.39-2.934 1.17-.672.768-1.008 1.866-1.008 3.294s.336 2.532 1.008 3.312c.672.78 1.65 1.17 2.934 1.17.648 0 1.254-.102 1.818-.306.564-.216 1.116-.552 1.656-1.008l.756 1.836c-.492.48-1.122.858-1.89 1.134a7.264 7.264 0 0 1-2.412.396Zm6.097-.18v-8.802h2.196v1.548c.432-1.044 1.356-1.62 2.772-1.728l.684-.054.144 1.908-1.296.126c-1.476.144-2.214.9-2.214 2.268V32h-2.286Zm11.246.18c-.996 0-1.854-.186-2.574-.558a4.024 4.024 0 0 1-1.674-1.584c-.384-.684-.576-1.494-.576-2.43 0-.912.186-1.71.558-2.394a4.186 4.186 0 0 1 1.566-1.602c.672-.396 1.434-.594 2.286-.594 1.248 0 2.232.396 2.952 1.188.732.792 1.098 1.872 1.098 3.24v.666h-6.3c.168 1.572 1.068 2.358 2.7 2.358.492 0 .984-.072 1.476-.216a4.19 4.19 0 0 0 1.35-.72l.63 1.512c-.42.348-.948.624-1.584.828a6.216 6.216 0 0 1-1.908.306Zm-.324-7.632c-.66 0-1.194.204-1.602.612-.408.408-.654.96-.738 1.656h4.428c-.048-.732-.252-1.29-.612-1.674-.348-.396-.84-.594-1.476-.594Zm8.64 7.632c-.636 0-1.206-.12-1.71-.36a3.1 3.1 0 0 1-1.17-1.008 2.532 2.532 0 0 1-.414-1.422c0-.648.168-1.158.504-1.53.336-.384.882-.66 1.638-.828.756-.168 1.77-.252 3.042-.252h.63v-.378c0-.6-.132-1.032-.396-1.296s-.708-.396-1.332-.396a5.21 5.21 0 0 0-1.512.234 6.547 6.547 0 0 0-1.566.684l-.648-1.53a4.948 4.948 0 0 1 1.098-.558 7.248 7.248 0 0 1 1.35-.378c.48-.096.93-.144 1.35-.144 1.284 0 2.238.3 2.862.9.624.588.936 1.506.936 2.754V32h-2.106v-1.404a2.508 2.508 0 0 1-.972 1.17c-.444.276-.972.414-1.584.414Zm.468-1.548c.588 0 1.074-.204 1.458-.612.396-.408.594-.924.594-1.548v-.396h-.612c-1.128 0-1.914.09-2.358.27-.432.168-.648.48-.648.936 0 .396.138.72.414.972.276.252.66.378 1.152.378Zm10.51 1.548c-2.328 0-3.492-1.152-3.492-3.456V24.89h-1.692v-1.692h1.692V20.57h2.25v2.628h2.664v1.692h-2.664v3.708c0 .576.126 1.008.378 1.296.252.288.66.432 1.224.432.168 0 .342-.018.522-.054.18-.048.366-.096.558-.144l.342 1.656c-.216.12-.492.216-.828.288a4.39 4.39 0 0 1-.954.108Zm7.126 0c-.996 0-1.854-.186-2.574-.558a4.024 4.024 0 0 1-1.674-1.584c-.384-.684-.576-1.494-.576-2.43 0-.912.186-1.71.558-2.394a4.186 4.186 0 0 1 1.566-1.602c.672-.396 1.434-.594 2.286-.594 1.248 0 2.232.396 2.952 1.188.732.792 1.098 1.872 1.098 3.24v.666h-6.3c.168 1.572 1.068 2.358 2.7 2.358.492 0 .984-.072 1.476-.216a4.19 4.19 0 0 0 1.35-.72l.63 1.512c-.42.348-.948.624-1.584.828a6.216 6.216 0 0 1-1.908.306Zm-.324-7.632c-.66 0-1.194.204-1.602.612-.408.408-.654.96-.738 1.656h4.428c-.048-.732-.252-1.29-.612-1.674-.348-.396-.84-.594-1.476-.594Zm14.932 7.632c-.996 0-1.854-.186-2.574-.558a4.024 4.024 0 0 1-1.674-1.584c-.384-.684-.576-1.494-.576-2.43 0-.912.186-1.71.558-2.394a4.186 4.186 0 0 1 1.566-1.602c.672-.396 1.434-.594 2.286-.594 1.248 0 2.232.396 2.952 1.188.732.792 1.098 1.872 1.098 3.24v.666h-6.3c.168 1.572 1.068 2.358 2.7 2.358.492 0 .984-.072 1.476-.216a4.19 4.19 0 0 0 1.35-.72l.63 1.512c-.42.348-.948.624-1.584.828a6.216 6.216 0 0 1-1.908.306Zm-.324-7.632c-.66 0-1.194.204-1.602.612-.408.408-.654.96-.738 1.656h4.428c-.048-.732-.252-1.29-.612-1.674-.348-.396-.84-.594-1.476-.594ZM99.89 32l-3.816-8.802h2.394l2.448 6.156 2.538-6.156h2.25L101.835 32h-1.944Zm11.062.18c-.996 0-1.854-.186-2.574-.558a4.024 4.024 0 0 1-1.674-1.584c-.384-.684-.576-1.494-.576-2.43 0-.912.186-1.71.558-2.394a4.186 4.186 0 0 1 1.566-1.602c.672-.396 1.434-.594 2.286-.594 1.248 0 2.232.396 2.952 1.188.732.792 1.098 1.872 1.098 3.24v.666h-6.3c.168 1.572 1.068 2.358 2.7 2.358.492 0 .984-.072 1.476-.216a4.19 4.19 0 0 0 1.35-.72l.63 1.512c-.42.348-.948.624-1.584.828a6.216 6.216 0 0 1-1.908.306Zm-.324-7.632c-.66 0-1.194.204-1.602.612-.408.408-.654.96-.738 1.656h4.428c-.048-.732-.252-1.29-.612-1.674-.348-.396-.84-.594-1.476-.594ZM116.371 32v-8.802h2.196v1.368c.3-.504.702-.888 1.206-1.152a3.738 3.738 0 0 1 1.728-.396c2.076 0 3.114 1.206 3.114 3.618V32h-2.25v-5.256c0-.684-.132-1.182-.396-1.494-.252-.312-.648-.468-1.188-.468-.66 0-1.188.21-1.584.63-.384.408-.576.954-.576 1.638V32h-2.25Zm14.561.18c-2.328 0-3.492-1.152-3.492-3.456V24.89h-1.692v-1.692h1.692V20.57h2.25v2.628h2.664v1.692h-2.664v3.708c0 .576.126 1.008.378 1.296.252.288.66.432 1.224.432.168 0 .342-.018.522-.054.18-.048.366-.096.558-.144l.342 1.656c-.216.12-.492.216-.828.288a4.39 4.39 0 0 1-.954.108Z"
|
||||
/>
|
||||
<defs>
|
||||
<filter
|
||||
id="a"
|
||||
width="88.666"
|
||||
height="40.225"
|
||||
x="36.001"
|
||||
y="31.388"
|
||||
color-interpolation-filters="sRGB"
|
||||
filterUnits="userSpaceOnUse"
|
||||
>
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
|
||||
<feGaussianBlur
|
||||
result="effect1_foregroundBlur_38_26948"
|
||||
stdDeviation="8.155"
|
||||
/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 5.4 KiB |
@@ -0,0 +1,28 @@
|
||||
export function addLoginNavbar() {
|
||||
document.querySelector('head').innerHTML += `
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Pacifico&display=swap"
|
||||
rel="stylesheet" />
|
||||
<link rel="stylesheet" href="/addNavbar.css" />
|
||||
`;
|
||||
|
||||
document.querySelector('.navbar-container').innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-12 header-nav">
|
||||
<nav class="navbar">
|
||||
<a class="navbar-brand" href="/index.html">
|
||||
<img src="/asset/party_icon.jpg" width="54" height="54" class="d-inline-block align-top">
|
||||
Party Planner
|
||||
</a>
|
||||
</nav>
|
||||
<div class="login-part">
|
||||
<div class="user-login">
|
||||
<button type="button" class="btn landing-Page-login-btn" data-bs-toggle="modal" data-bs-target="#login-modal">
|
||||
<i class="bi bi-person-circle"></i>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
56
_tecky/party-planner/backend/public/functions/addNavbar.js
Normal file
56
_tecky/party-planner/backend/public/functions/addNavbar.js
Normal file
@@ -0,0 +1,56 @@
|
||||
export function addNavbar() {
|
||||
// innerHTML only works for link and img and text, not Script tag
|
||||
document.querySelector('head').innerHTML += `
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Pacifico&display=swap"
|
||||
rel="stylesheet" />
|
||||
<link rel="stylesheet" href="/addNavbar.css" />
|
||||
`;
|
||||
|
||||
document.querySelector('.navbar-container').innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-12 header-nav">
|
||||
<nav class="navbar">
|
||||
<a class="navbar-brand" href="/index.html">
|
||||
<img src="/asset/party_icon.jpg" width="54" height="54" class="d-inline-block align-top">
|
||||
<div class="navbar-logo-text">
|
||||
Party Planner
|
||||
</div>
|
||||
</a>
|
||||
</nav>
|
||||
<div class="login-part">
|
||||
<div class="user-login dropdown">
|
||||
<button type="button" class="btn landing-Page-login-btn dropdown-toggle"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-person-circle"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="/personalPage/personalPage.html">Edit Profile</a></li>
|
||||
<li><a class="dropdown-item" href="/comment/comment.html">Comments</a></li>
|
||||
<li><a class="dropdown-item logout">Log out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.querySelector('.logout').addEventListener('click', async () => {
|
||||
const res = await fetch('/login/logout', {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
const data = await res.json();
|
||||
alert(data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await res.json();
|
||||
|
||||
if (result.status) {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
alert('Unable to log out!');
|
||||
}
|
||||
});
|
||||
}
|
13
_tecky/party-planner/backend/public/functions/loadName.js
Normal file
13
_tecky/party-planner/backend/public/functions/loadName.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export async function loadName() {
|
||||
const res = await fetch(`/login/name`);
|
||||
if (res.status !== 200) {
|
||||
const data = await res.json();
|
||||
alert(data.msg);
|
||||
return;
|
||||
}
|
||||
const result = await res.json();
|
||||
if (result.status) {
|
||||
const nameHTML = document.querySelector('.user-login button');
|
||||
nameHTML.innerHTML = `<i class="bi bi-person-circle"></i>${result.user}`;
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
.invitation-container {
|
||||
height: 85vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.invitation-frame {
|
||||
width: 80%;
|
||||
height: 90%;
|
||||
background-color: #f9f9da;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.event-name-container,
|
||||
.datetime-container,
|
||||
.venue-container,
|
||||
.join-button-container {
|
||||
font-size: 20px;
|
||||
font-family: 'Calibri';
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.event-name-container,
|
||||
.join-button-container {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.venue-container,
|
||||
.datetime-container {
|
||||
margin: 20px 40px;
|
||||
}
|
||||
|
||||
.event-name-container {
|
||||
font-size: 50px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#join-event-button {
|
||||
font-size: 20px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 20px;
|
||||
margin: 18px;
|
||||
min-width: 110px;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 12px #f2d492;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
height: 50%;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
||||
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link rel="stylesheet" href="./invitation.css" />
|
||||
<title>Invitation</title>
|
||||
</head>
|
||||
|
||||
<body style="display: none">
|
||||
<div class="navbar-container container">
|
||||
<!-- NAVBAR: to be loaded with js -->
|
||||
</div>
|
||||
|
||||
<div class="invitation-container">
|
||||
<div class="invitation-frame">
|
||||
<div class="event-name-container"></div>
|
||||
<div class="content-container">
|
||||
<div class="datetime-container"></div>
|
||||
<div class="venue-container"></div>
|
||||
</div>
|
||||
<div class="join-button-container">
|
||||
<button id="join-event-button" type="submit">Join Event Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script type="module" src="./invitation.js"></script>
|
||||
</body>
|
||||
</html>
|
107
_tecky/party-planner/backend/public/invitationPage/invitation.js
Normal file
107
_tecky/party-planner/backend/public/invitationPage/invitation.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import { addNavbar } from '/functions/addNavbar.js';
|
||||
import { loadName } from '/functions/loadName.js';
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
await checkInvitationValidity();
|
||||
});
|
||||
|
||||
async function checkInvitationValidity() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const eventId = params.get('event-id');
|
||||
const token = params.get('token');
|
||||
const res = await fetch(`/events/invitation/validation/${eventId}/${token}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const result = await res.json();
|
||||
if (result.status) {
|
||||
addNavbar();
|
||||
await loadName();
|
||||
|
||||
// Load invitation page content
|
||||
document.querySelector('.event-name-container').innerHTML = `
|
||||
<div>
|
||||
🎉 ${result.eventDetail.name}
|
||||
</div>
|
||||
`;
|
||||
|
||||
let dateString = '';
|
||||
if (!result.eventDetail.start_datetime) {
|
||||
dateString += 'To Be Confirmed';
|
||||
} else {
|
||||
dateString += `
|
||||
<div class="subtitle">
|
||||
Start
|
||||
</div>
|
||||
<div>
|
||||
${new Date(result.eventDetail.start_datetime)
|
||||
.toLocaleString('en-US', { hour12: false })
|
||||
.replace(', ', ' ')
|
||||
.slice(0, -3)}
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
End
|
||||
</div>
|
||||
<div>
|
||||
${new Date(result.eventDetail.end_datetime).toLocaleString('en-US', { hour12: false }).replace(', ', ' ').slice(0, -3)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
document.querySelector('.datetime-container').innerHTML = `
|
||||
<div class="title">
|
||||
Date & Time
|
||||
</div>
|
||||
<div>
|
||||
${dateString}
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.querySelector('.venue-container').innerHTML = `
|
||||
<div class="title">
|
||||
Venue
|
||||
</div>
|
||||
<div>
|
||||
${result.eventDetail.venue ? result.eventDetail.venue : 'To Be Confirmed'}
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.style.display = 'block';
|
||||
} else {
|
||||
if (result.login) {
|
||||
alert('Invitation link is invalid or expired!');
|
||||
window.location.href = '/index.html';
|
||||
} else {
|
||||
alert('Please log in or register to join event!');
|
||||
window.location.href = `/?event-id=${eventId}&token=${token}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#join-event-button').addEventListener('click', async () => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const eventId = params.get('event-id');
|
||||
const token = params.get('token');
|
||||
const res = await fetch(`/events/invitation/participation/${eventId}/${token}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const result = await res.json();
|
||||
if (result.status) {
|
||||
alert('You have successfully joined the event!');
|
||||
window.location.href = `/eventSummary/event.html?event-id=${eventId}&is-creator=0`;
|
||||
} else {
|
||||
if (result.login) {
|
||||
if (result.isCreator) {
|
||||
alert('You are already a creator of the event, no need to join again!');
|
||||
window.location.href = `/eventSummary/event.html?event-id=${eventId}&is-creator=1`;
|
||||
} else if (result.joined) {
|
||||
alert('You have already joined the event!');
|
||||
window.location.href = `/eventSummary/event.html?event-id=${eventId}&is-creator=0`;
|
||||
} else {
|
||||
alert('Invitation link is invalid or expired!');
|
||||
window.location.href = '/index.html';
|
||||
}
|
||||
} else {
|
||||
alert('Please log in or register to join event!');
|
||||
window.location.href = `/?event-id=${eventId}&token=${token}`;
|
||||
}
|
||||
}
|
||||
});
|
302
_tecky/party-planner/backend/public/landingPage.css
Normal file
302
_tecky/party-planner/backend/public/landingPage.css
Normal file
@@ -0,0 +1,302 @@
|
||||
/* font family: */
|
||||
/* font-family: 'Lato', sans-serif;
|
||||
font-family: 'Pacifico', cursive; */
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #efefd0;
|
||||
}
|
||||
|
||||
.navbar-brand > img {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.navbar > .navbar-brand {
|
||||
font-size: 30px;
|
||||
font-family: 'Pacifico', cursive;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.navbar > .btn {
|
||||
font-size: 20px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
color: #293241;
|
||||
}
|
||||
|
||||
#logo-name {
|
||||
font-size: 60px;
|
||||
color: #293241;
|
||||
font-family: 'Pacifico', cursive;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.login-part {
|
||||
display: flex;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.user-login {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.landing-Page-login-btn {
|
||||
font-size: 20px;
|
||||
color: #495871;
|
||||
}
|
||||
|
||||
.landing-Page-login-btn > .bi {
|
||||
margin: 0px 10px 0px 2px;
|
||||
}
|
||||
|
||||
.introduction-box {
|
||||
background-color: #efefd0;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 500px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.description-box {
|
||||
background-color: #a6b7f4;
|
||||
width: 400px;
|
||||
border-radius: 20px;
|
||||
height: 220px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 30px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.description-details {
|
||||
font-size: 18px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
padding: 10px;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.buttons > button {
|
||||
font-size: 20px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 20px;
|
||||
margin: 18px;
|
||||
width: 200px;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 14px #f2d492;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
#logo-name {
|
||||
font-size: 60px;
|
||||
font-family: 'Pacifico', cursive;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.introduction-box {
|
||||
background-color: #efefd0;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 500px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.description-box {
|
||||
background-color: #a6b7f4;
|
||||
width: 90%;
|
||||
border-radius: 20px;
|
||||
height: 220px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 30px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.description-details {
|
||||
font-size: 18px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
padding: 10px;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.buttons > button {
|
||||
font-size: 20px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 20px;
|
||||
margin: 18px;
|
||||
width: 200px;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 14px #f2d492;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
|
||||
.modal-login {
|
||||
font-size: 14px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 20px;
|
||||
margin: 18px;
|
||||
width: 110px;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 12px #f2d492;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.modal-login, .modal-login:hover {
|
||||
font-size: 14px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 20px;
|
||||
margin: 18px;
|
||||
width: 110px;
|
||||
border: none;
|
||||
box-shadow: 0px 1px 12px #f2d492;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.modal-login:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.input-title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-width: 2px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#user-email {
|
||||
border-color: #495871;
|
||||
}
|
||||
|
||||
#user-password {
|
||||
border-color: #ee6c4d;
|
||||
}
|
||||
|
||||
#login-form-submit,
|
||||
#register-submit {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
left: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.form-header {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
#login-modal .input-panel {
|
||||
margin: 20px 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#register-modal .input-panel {
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.user-email .form-label {
|
||||
color: #495871;
|
||||
}
|
||||
|
||||
.user-password .form-label {
|
||||
color: #ee6c4d;
|
||||
}
|
||||
|
||||
#or-separator {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#google-separator {
|
||||
position: relative;
|
||||
}
|
163
_tecky/party-planner/backend/public/landingPage.html
Normal file
163
_tecky/party-planner/backend/public/landingPage.html
Normal file
@@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
||||
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="./landingPage.css" />
|
||||
<title>Party Planner</title>
|
||||
</head>
|
||||
|
||||
<body style="display: none">
|
||||
<div class="navbar-container container">
|
||||
<!-- NAVBAR:to be added by js -->
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="introduction-box">
|
||||
<header id="logo-name">Party Planner</header>
|
||||
<div class="description-box">
|
||||
<div class="description">Easy to use!</div>
|
||||
<div class="description-details">
|
||||
Try using the Party Planner to manage your party agenda with friends!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 buttons">
|
||||
<button type="button" class="login-button" data-bs-toggle="modal" data-bs-target="#login-modal">
|
||||
Log in
|
||||
</button>
|
||||
<button type="button" class="signup-button" data-bs-toggle="modal" data-bs-target="#register-modal">
|
||||
Sign up
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="login-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div></div>
|
||||
<h5 class="modal-title">LOG IN</h5>
|
||||
<div class="exit-modal">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group">
|
||||
<div class="input-title">Welcome back! Please enter your details.</div>
|
||||
<form>
|
||||
<div class="user-email input-panel mb-3">
|
||||
<div class="form-label">Email address</div>
|
||||
<input type="email" class="form-control" id="user-email" aria-describedby="emailHelp"
|
||||
required />
|
||||
<div id="emailHelp" class="form-text">
|
||||
We'll never share your email with anyone else.
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-password input-panel mb-3">
|
||||
<div class="form-label">Password</div>
|
||||
<input type="password" class="form-control" id="user-password" required />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="login-form-submit" type="button" class="modal-login">Log in</button>
|
||||
</div>
|
||||
<div class="modal-footer" id="google-separator">
|
||||
<span id="or-separator">or</span>
|
||||
<a href="/connect/google" type="button" class="modal-login">
|
||||
<i class="fa-brands fa-google"></i>
|
||||
Google
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="register-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div></div>
|
||||
<h5 class="modal-title">CREATE ACCOUNT</h5>
|
||||
<div class="exit-modal">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group">
|
||||
<form class="register-form">
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">First Name *</div>
|
||||
<input type="text" class="form-control" name="first_name" aria-label="first_name"
|
||||
aria-describedby="basic-addon1" required />
|
||||
</div>
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">Last Name *</div>
|
||||
<input type="text" class="form-control" name="last_name" aria-label="last_name"
|
||||
aria-describedby="basic-addon1" required />
|
||||
</div>
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">Email Address *</div>
|
||||
<input type="email" class="form-control" name="email" aria-label="email"
|
||||
aria-describedby="basic-addon1" placeholder="name@example.com" required />
|
||||
</div>
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">Phone Number *</div>
|
||||
<input type="text" class="form-control" name="phone" aria-label="phone"
|
||||
aria-describedby="basic-addon1" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required />
|
||||
<div class="form-text">
|
||||
Phone number must be in the following format: e.g. 647-111-1111
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">Create Password *</div>
|
||||
<input type="password" class="form-control" name="password" aria-label="password"
|
||||
aria-describedby="basic-addon1" minlength="8" required />
|
||||
<div class="form-text">Password must be 8 characters long</div>
|
||||
</div>
|
||||
<div class="input-panel mb-3">
|
||||
<div class="form-header">Confirm Password *</div>
|
||||
<input type="password" class="form-control" name="confirm_password"
|
||||
aria-label="confirm_password" aria-describedby="basic-addon1" minlength="8"
|
||||
required />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="register-submit" type="submit" class="btn btn-primary">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="modal-footer" id="google-separator">
|
||||
<span id="or-separator">or</span>
|
||||
<a href="/connect/google" type="button" class="modal-login">
|
||||
<i class="fa-brands fa-google"></i>
|
||||
Google
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
|
||||
crossorigin="anonymous"></script>
|
||||
<script type="module" src="./landingPage.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
116
_tecky/party-planner/backend/public/landingPage.js
Normal file
116
_tecky/party-planner/backend/public/landingPage.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import { addNavbar } from "/functions/addNavbar.js";
|
||||
import { loadName } from "/functions/loadName.js";
|
||||
import { addLoginNavbar } from "/functions/addLoginNavbar.js";
|
||||
|
||||
window.addEventListener("load", async () => {
|
||||
const res = await fetch("/login/name");
|
||||
if (res.status === 200) {
|
||||
addNavbar();
|
||||
loadName();
|
||||
} else {
|
||||
addLoginNavbar();
|
||||
}
|
||||
|
||||
document.body.style.display = "block";
|
||||
});
|
||||
|
||||
async function loginFormSubmission() {
|
||||
const userEmail = document.querySelector("#user-email").value;
|
||||
const userPassword = document.querySelector("#user-password").value;
|
||||
if (userEmail !== "" && userPassword !== "") {
|
||||
const formObj = {
|
||||
email: userEmail,
|
||||
password: userPassword,
|
||||
};
|
||||
const res = await fetch("/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(formObj),
|
||||
});
|
||||
const loginResult = await res.json();
|
||||
if (loginResult.status) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.has("event-id") && params.has("token")) {
|
||||
const eventId = params.get("event-id");
|
||||
const token = params.get("token");
|
||||
window.location.href = `/invitationPage/invitation.html?event-id=${eventId}&token=${token}`;
|
||||
} else {
|
||||
window.location.href = "/index.html";
|
||||
}
|
||||
} else {
|
||||
alert("Unable to login!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector("#login-form-submit").addEventListener("click", () => {
|
||||
loginFormSubmission();
|
||||
});
|
||||
document.querySelector("#user-password").addEventListener("keypress", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
loginFormSubmission();
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector(".register-form").addEventListener("submit", async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const form = e.target;
|
||||
|
||||
const first_name = form.first_name.value;
|
||||
const last_name = form.last_name.value;
|
||||
const email = form.email.value;
|
||||
const phone = form.phone.value;
|
||||
const password = form.password.value;
|
||||
const confirm_password = form.confirm_password.value;
|
||||
|
||||
let formObj = {
|
||||
first_name: first_name,
|
||||
last_name: last_name,
|
||||
email: email,
|
||||
phone: phone,
|
||||
password: password,
|
||||
};
|
||||
let dataPass = true;
|
||||
|
||||
// Checking data validity
|
||||
if (!(password === confirm_password)) {
|
||||
dataPass = false;
|
||||
alert("Password and confirm password do not match!");
|
||||
}
|
||||
|
||||
if (dataPass) {
|
||||
const res = await fetch("/register", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(formObj),
|
||||
});
|
||||
|
||||
const registerResult = await res.json();
|
||||
|
||||
form.reset();
|
||||
|
||||
if (registerResult.duplicate) {
|
||||
alert("Registered already!");
|
||||
} else if (registerResult.passwordNotMatch) {
|
||||
alert("Password not match!");
|
||||
} else if (!registerResult.status) {
|
||||
alert("Unable to Register, please try again!");
|
||||
} else {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
|
||||
if (params.has("event-id") && params.has("token")) {
|
||||
alert("Successfully registered! Please login now to join the event.");
|
||||
const myModal = bootstrap.Modal.getInstance(document.getElementById("register-modal"));
|
||||
myModal.hide();
|
||||
} else {
|
||||
alert("Successfully registered!");
|
||||
const myModal = bootstrap.Modal.getInstance(document.getElementById("register-modal"));
|
||||
myModal.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user