Initial Commit v0.0.1

This commit is contained in:
TropiiDev 2025-04-21 22:38:47 -04:00
parent 71db1a0b67
commit cb7d17a47e
9 changed files with 703 additions and 0 deletions

139
assets/css/defaults.css Normal file
View File

@ -0,0 +1,139 @@
/* vars & default settings */
:root {
--bg-black: #131200;
--white: #E3E4DB;
--silver: #CDCDCD;
--maroon-pink: #7C6C77;
--gray: #646E78;
--font-family: 'Arial', sans-serif;
}
body {
margin: 0;
padding: 0;
font-family: var(--font-family);
background-color: var(--bg-black);
color: var(--silver);
}
.signed-in {
display: none;
}
/* nav */
.nav-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
border-bottom: 2px solid var(--gray);
backdrop-filter: blur(8px);
position: sticky;
top: 0;
z-index: 1000;
}
.nav {
display: flex;
gap: 2rem;
align-items: center;
width: 100%;
}
.nav a {
color: var(--white);
text-decoration: none;
font-size: 1rem;
transition: color 0.2s ease-in-out;
position: relative;
}
.nav a:hover {
color: var(--silver);
}
.nav a::after {
content: '';
position: absolute;
width: 0;
height: 2px;
bottom: -4px;
left: 0;
background-color: var(--white);
transition: width 0.2s ease-in-out;
}
.nav a:hover::after {
width: 100%;
}
.nav-home {
font-size: 1.25rem !important;
font-weight: 600;
margin-right: auto;
}
.nav-signin,
.nav-register,
.nav-user {
padding: 0.5rem 1rem;
border-radius: 4px;
}
.nav-register {
background-color: var(--white);
color: var(--bg-black) !important;
}
.nav-register:hover {
opacity: 0.9;
}
/* tooltips */
.tooltip {
position: relative;
padding: 0.75rem 1rem;
border-radius: 4px;
font-size: 0.9rem;
opacity: 0;
margin-bottom: 1rem;
transform: translateY(-5px);
transition: all 0.3s ease;
backdrop-filter: blur(8px);
text-align: center;
box-sizing: border-box;
}
.tooltip.visible {
opacity: 1;
transform: translateY(0);
display: block !important;
}
.tooltip.info {
background-color: rgba(100, 110, 120, 0.2);
border: 1px solid var(--gray);
color: var(--silver);
}
.tooltip.error {
background-color: rgba(220, 53, 69, 0.2);
border: 1px solid #dc3545;
color: #ff8c94;
}
.tooltip.success {
background-color: rgba(40, 167, 69, 0.2);
border: 1px solid #28a745;
color: #98fb98;
}
/* Position variants */
.tooltip.top {
bottom: calc(100% + 10px);
}
.tooltip.bottom {
top: calc(100% + 10px);
}

101
assets/css/main.css Normal file
View File

@ -0,0 +1,101 @@
/* hero */
.hero-section {
min-height: calc(100vh - 74px); /* Subtract navbar height */
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.main-screen {
text-align: center;
padding: 2rem;
}
.center-screen {
margin-bottom: 3rem;
}
.hero-title {
font-size: 3.5rem;
color: var(--white);
margin-bottom: 1rem;
}
.hero-subtext {
font-size: 1.2rem;
color: var(--maroon-pink);
font-weight: normal;
margin: 0;
}
.hero-buttons {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 2rem;
}
.hero-buttons a {
padding: 0.75rem 1.5rem;
border-radius: 4px;
text-decoration: none;
transition: all 0.2s ease-in-out;
}
.hero-register {
background-color: var(--white);
color: var(--bg-black);
}
.hero-signin, .hero-about {
border: 2px solid var(--white);
color: var(--white);
}
.hero-buttons a:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
/* Scroll indicator animation */
.scroll-indicator {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
opacity: 0.8;
animation: fadeInOut 2s ease-in-out infinite;
}
.scroll-text {
color: var(--silver);
font-size: 0.9rem;
}
.scroll-arrow {
width: 20px;
height: 20px;
border: solid var(--silver);
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
@keyframes fadeInOut {
0% {
opacity: 0.3;
transform: translateX(-50%) translateY(-10px);
}
50% {
opacity: 0.8;
transform: translateX(-50%) translateY(0);
}
100% {
opacity: 0.3;
transform: translateX(-50%) translateY(-10px);
}
}

94
assets/css/register.css Normal file
View File

@ -0,0 +1,94 @@
/* register */
.register-section {
min-height: calc(100vh - 74px);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.main-screen {
background-color: rgba(100, 110, 120, 0.1);
backdrop-filter: blur(8px);
border-radius: 12px;
padding: 2.5rem;
width: 100%;
max-width: 460px;
}
.register-text {
text-align: center;
margin-bottom: 2.5rem;
}
.register-title {
color: var(--white);
font-size: 2rem;
margin: 0 0 0.5rem 0;
}
.register-subtext {
color: var(--maroon-pink);
font-weight: normal;
margin: 0;
}
.register-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.register-form label {
color: var(--silver);
font-size: 0.9rem;
margin-bottom: -0.5rem;
}
.register-form input {
background-color: rgba(255, 255, 255, 0.05);
border: 1px solid var(--gray);
border-radius: 4px;
padding: 0.75rem;
color: var(--white);
font-size: 1rem;
transition: border-color 0.2s ease;
}
.register-form input:focus {
outline: none;
border-color: var(--white);
}
.register-form input::placeholder {
color: var(--maroon-pink);
opacity: 0.7;
}
#register-submit-btn {
margin-top: 1rem;
background-color: var(--white);
color: var(--bg-black);
border: none;
border-radius: 4px;
padding: 0.75rem;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s ease;
}
#register-submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
/* Responsive design */
@media (max-width: 480px) {
.main-screen {
padding: 1.5rem;
}
.register-title {
font-size: 1.75rem;
}
}

94
assets/css/sign-in.css Normal file
View File

@ -0,0 +1,94 @@
/* sign-in */
.sign-in-section {
min-height: calc(100vh - 74px);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.main-screen {
background-color: rgba(100, 110, 120, 0.1);
backdrop-filter: blur(8px);
border-radius: 12px;
padding: 2.5rem;
width: 100%;
max-width: 460px;
}
.sign-in-text {
text-align: center;
margin-bottom: 2.5rem;
}
.sign-in-title {
color: var(--white);
font-size: 2rem;
margin: 0 0 0.5rem 0;
}
.sign-in-subtext {
color: var(--maroon-pink);
font-weight: normal;
margin: 0;
}
.sign-in-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.sign-in-form label {
color: var(--silver);
font-size: 0.9rem;
margin-bottom: -0.5rem;
}
.sign-in-form input {
background-color: rgba(255, 255, 255, 0.05);
border: 1px solid var(--gray);
border-radius: 4px;
padding: 0.75rem;
color: var(--white);
font-size: 1rem;
transition: border-color 0.2s ease;
}
.sign-in-form input:focus {
outline: none;
border-color: var(--white);
}
.sign-in-form input::placeholder {
color: var(--maroon-pink);
opacity: 0.7;
}
#sign-in-submit-btn {
margin-top: 1rem;
background-color: var(--white);
color: var(--bg-black);
border: none;
border-radius: 4px;
padding: 0.75rem;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s ease;
}
#sign-in-submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
/* Responsive design */
@media (max-width: 480px) {
.main-screen {
padding: 1.5rem;
}
.sign-in-title {
font-size: 1.75rem;
}
}

113
assets/js/sign-in.js Normal file
View File

@ -0,0 +1,113 @@
const url = "https://task-api.fstropii.com";
const localhostUrl = "http://localhost:8000";
const signInBtn = document.getElementById("sign-in-submit-btn");
const tooltip = document.getElementById('tooltip');
signInBtn.addEventListener("click", function(e) {
e.preventDefault();
const username = document.querySelector('.sign-in-username-input').value;
const password = document.querySelector('.sign-in-password-input').value;
// validate the username and password. will return a promise
const signedInPromise = signIn(username, password);
signedInPromise.then((res) => res.json()).then((json) => validateUser(json))
});
const setTooltip = (type, message) => {
tooltip.classList.add(type);
tooltip.classList.add('visible');
tooltip.innerText = message
tooltip.style.display = "block";
}
const removeTooltip = () => {
tooltip.classList.remove('visible');
tooltip.style.display = "none";
}
const signIn = async (username, password) => {
const res = fetch(`${url}/user/login`, {
method: "POST",
body: JSON.stringify({
username: username,
password: password
}),
headers: {
"Content-type": "application/json"
}
});
return res;
};
const validateUser = async (parsedJson) => {
if (parsedJson.detail == "Login successful") {
setTooltip("success", "Login successful");
// get user token. will return a promise
const tokenPromise = getUserToken();
tokenPromise.then((res) => res.json()).then((json => {
const token = json.access_token;
const type = json.token_type;
const expiresInDays = json.expires_days;
// save a cookie
const cookieText = `token=${token},type=${type},expires_days=${expiresInDays}`;
setCookie(token, type, expiresInDays);
}));
} else if (parsedJson.detail == "Invalid password") {
setTooltip("error", "Invalid password");
} else if (parsedJson.detail == "User not found") {
setTooltip("error", "User not found");
}
}
const getUserToken = async () => {
const form = document.getElementById("sign-in-form");
const formData = new FormData(form);
const res = fetch(`${url}/token`, {
method: "POST",
body: formData,
});
return res;
}
const setCookie = (token, type, expires_days) => {
const d = new Date();
d.setTime(d.getTime() + (expires_days*24*60*60*1000))
let expires = `expires=${d.toUTCString()}`;
document.cookie = `token=${token},type=${type},${expires}`;
}
const getCookie = (returnType) => {
let decodedCookie = decodeURIComponent(document.cookie);
if (decodedCookie == "") {
return;
}
let ca = decodedCookie.split(',');
const token = ca[0].split("token=")[1];
const type = ca[1].split("type=")[1];
const expiresDay = ca[2].split("expires=")[1];
const expiresDate = ca[3]
const expires = `${expiresDay}${expiresDate}`
if (returnType == "token") {
return token;
} else if (returnType == "type") {
return type
} else if (returnType == "expires") {
return expires;
}
return null;
}
const token = getCookie("token");
if (token != undefined) {
window.location.href = '/';
}

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/assets/css/defaults.css" />
<link rel="stylesheet" href="/assets/css/register.css" />
<title>Task Manager</title>
</head>
<body>
<section class="nav-section">
<nav class="nav">
<a class="nav-home" href="/">Task</a>
<a class="nav-signin" href="/assets/pages/sign-in.html">Sign In</a>
</nav>
</section>
<section class="register-section">
<div class="main-screen">
<div class="register-text">
<h1 class="register-title">Create an account!</h1>
<h4 class="register-subtext">Staying organzied has never been so easy.</h4>
</div>
<div class="register-form-div">
<form class="register-form">
<label for="name" class="register-label-name">Name</label>
<input id="name" type="text" class="register-name-input" placeholder="John Doe" />
<label for="username" class="register-label-username">Username</label>
<input id="username" type="text" class="register-username-input" placeholder="johndoe23" />
<label for="email" class="register-label-email">Email</label>
<input id="email" type="text" class="register-email-input" placeholder="johndoe23@gmail.com" />
<label for="password" class="register-label-empassword">Password</label>
<input id="password" type="password" class="register-email-password" />
<label for="email" class="register-label-password">Verify Password</label>
<input id="email" type="password" class="register-email-password" />
<button type="submit" id="register-submit-btn">Register!</button>
</form>
</div>
</div>
</section>
</body>
</html>

39
assets/pages/sign-in.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/assets/css/defaults.css" />
<link rel="stylesheet" href="/assets/css/sign-in.css" />
<title>Task Manager</title>
</head>
<body>
<section class="nav-section">
<nav class="nav">
<a class="nav-home" href="/">Task</a>
<a class="nav-register signed-out" href="/assets/pages/register.html">Register</a>
</nav>
</section>
<section class="sign-in-section">
<div class="main-screen">
<div class="sign-in-text">
<h1 class="sign-in-title">Welcome back!</h1>
<h4 class="sign-in-subtext">Ready to get started?</h4>
</div>
<div class="sign-in-form-div">
<div id='tooltip' class="tooltip" style="display: none;"></div>
<form id="sign-in-form" class="sign-in-form">
<label for="username" class="sign-in-label-username">Username</label>
<input name="username" id="username" type="text" class="sign-in-username-input" placeholder="johndoe23" />
<label for="password" class="sign-in-label-empassword">Password</label>
<input name="password" id="password" type="password" class="sign-in-password-input" />
<button type="submit" id="sign-in-submit-btn">Sign in!</button>
</form>
</div>
</div>
</section>
<script src="/assets/js/sign-in.js"></script>
</body>
</html>

40
assets/pages/user.html Normal file
View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/assets/css/styles.css" />
<title>Task Manager</title>
</head>
<body>
<section class="nav-section">
<nav class="nav">
<a class="nav-home" href="/">Task</a>
<a class="nav-signin signed-out" href="/sign-in.html">Sign In</a>
<a class="nav-register signed-out" href="/register.html">Register</a>
<a class="nav-user signed-in" href="/user.html">Profile</a>
</nav>
</section>
<section class="hero-section">
<div class="main-screen">
<div class="center-screen">
<h1 class="hero-title">Welcome to your task manager!</h1>
<h4 class="hero-subtext">Keep yourself organized and stay productive.</h4>
</div>
<!-- If user is registered, show register/login & about. Else, give the user the option to their profile-->
<div class="hero-buttons">
<a class="signed-out hero-signin" href="/sign-in.html">Sign In</a>
<a class="signed-out hero-register" href="/register.html">Register</a>
<a class="signed-in hero-profile" href="user.html">Profile</a>
<a class="hero-about" href="#about">About us!</a>
</div>
</div>
<div class="scroll-indicator">
<span class="scroll-text">Scroll to explore</span>
<div class="scroll-arrow"></div>
</div>
</div>
</section>
</body>
</html>

41
index.html Normal file
View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/assets/css/defaults.css" />
<link rel="stylesheet" href="/assets/css/main.css" />
<title>Task Manager</title>
</head>
<body>
<section class="nav-section">
<nav class="nav">
<a class="nav-home" href="/">Task</a>
<a class="nav-signin signed-out" href="/assets/pages/sign-in.html">Sign In</a>
<a class="nav-register signed-out" href="/assets/pages/register.html">Register</a>
<a class="nav-user signed-in" href="/assets/pages/user.html">Profile</a>
</nav>
</section>
<section class="hero-section">
<div class="main-screen">
<div class="center-screen">
<h1 class="hero-title">Welcome to your task manager!</h1>
<h4 class="hero-subtext">Keep yourself organized and stay productive.</h4>
</div>
<!-- If user is registered, show register/login & about. Else, give the user the option to their profile-->
<div class="hero-buttons">
<a class="signed-out hero-signin" href="/assets/pages/sign-in.html">Sign In</a>
<a class="signed-out hero-register" href="/assets/pages/register.html">Register</a>
<a class="signed-in hero-profile" href="/assets/pages/user.html">Profile</a>
<a class="hero-about" href="#about">About us!</a>
</div>
</div>
<div class="scroll-indicator">
<span class="scroll-text">Scroll to explore</span>
<div class="scroll-arrow"></div>
</div>
</div>
</section>
</body>
</html>