feat: improve landing page and login

This commit is contained in:
2025-12-03 16:42:52 -03:00
parent ae7d5aa5b5
commit 63312b1bc0
6 changed files with 535 additions and 77 deletions
+335 -9
View File
@@ -19,6 +19,13 @@
min-height: 50px;
}
.logo h1 {
margin: 0;
font-size: 2rem;
font-weight: 700;
letter-spacing: -0.5px;
}
.logo h2 {
margin: 0;
font-size: 1.3rem;
@@ -30,20 +37,108 @@
align-items: center;
}
.auth-form {
background: rgba(40, 40, 40, 0.9);
backdrop-filter: blur(10px);
border-radius: 6px;
padding: 25px;
min-width: 300px;
.auth-buttons {
display: flex;
align-items: center;
gap: 12px;
}
.auth-buttons .header-btn.primary {
background: linear-gradient(135deg, #6B8DD6 0%, #5A7BC6 100%);
border: 1px solid rgba(107, 141, 214, 0.6);
}
.auth-buttons .header-btn.primary:hover {
box-shadow: 0 4px 15px rgba(107, 141, 214, 0.4);
}
/* Authentication Modal */
.auth-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
backdrop-filter: blur(8px);
animation: fadeIn 0.3s ease-out;
}
.auth-modal-content {
background: rgba(40, 40, 40, 0.95);
backdrop-filter: blur(20px);
border-radius: 12px;
padding: 40px;
max-width: 450px;
width: 90%;
border: 1px solid rgba(100, 100, 100, 0.3);
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
position: relative;
animation: slideUp 0.3s ease-out;
}
.close-modal-btn {
position: absolute;
top: 15px;
right: 15px;
background: transparent;
border: none;
color: rgba(255, 255, 255, 0.6);
font-size: 2rem;
cursor: pointer;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
transition: all 0.2s ease;
line-height: 1;
}
.close-modal-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: white;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.auth-form {
background: transparent;
border-radius: 0;
padding: 0;
min-width: auto;
border: none;
}
.auth-form h3 {
margin: 0 0 20px 0;
margin: 0 0 25px 0;
text-align: center;
font-size: 1.3rem;
font-weight: 500;
font-size: 1.6rem;
font-weight: 600;
color: white;
}
.auth-form .form-group {
@@ -308,6 +403,10 @@
order: 1;
}
.logo h1 {
font-size: 1.4rem;
}
.logo h2 {
font-size: 1.1rem;
}
@@ -318,6 +417,16 @@
justify-content: center;
}
.auth-buttons {
order: 2;
gap: 8px;
}
.auth-buttons .header-btn {
font-size: 0.85rem;
padding: 8px 14px;
}
.user-info {
order: 2;
position: relative;
@@ -356,6 +465,163 @@
}
}
/* Landing Page Styles */
.landing-page {
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);
min-height: calc(100vh - 80px);
padding: 60px 20px;
}
.landing-container {
max-width: 1200px;
margin: 0 auto;
}
.landing-hero {
text-align: center;
margin-bottom: 60px;
animation: fadeInUp 0.8s ease-out;
}
.landing-title {
font-size: 3rem;
font-weight: 700;
color: white;
margin: 0 0 20px 0;
line-height: 1.2;
background: linear-gradient(135deg, #6B8DD6 0%, #9B7BC6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.landing-subtitle {
font-size: 1.3rem;
color: rgba(255, 255, 255, 0.85);
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
.landing-features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
margin-bottom: 60px;
animation: fadeInUp 0.8s ease-out 0.2s backwards;
}
.feature-card {
background: rgba(40, 40, 40, 0.6);
backdrop-filter: blur(10px);
border: 1px solid rgba(100, 100, 100, 0.3);
border-radius: 12px;
padding: 30px;
text-align: center;
transition: all 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
border-color: rgba(107, 141, 214, 0.5);
box-shadow: 0 8px 30px rgba(107, 141, 214, 0.2);
}
.feature-icon {
font-size: 3rem;
margin-bottom: 15px;
display: block;
}
.feature-card h3 {
color: white;
font-size: 1.3rem;
margin: 0 0 12px 0;
font-weight: 600;
}
.feature-card p {
color: rgba(255, 255, 255, 0.75);
font-size: 1rem;
line-height: 1.5;
margin: 0;
}
.landing-cta {
text-align: center;
background: rgba(74, 93, 138, 0.4);
backdrop-filter: blur(10px);
border: 1px solid rgba(100, 100, 100, 0.3);
border-radius: 12px;
padding: 50px 30px;
animation: fadeInUp 0.8s ease-out 0.4s backwards;
}
.landing-cta h2 {
color: white;
font-size: 2rem;
margin: 0 0 15px 0;
font-weight: 600;
}
.landing-cta p {
color: rgba(255, 255, 255, 0.85);
font-size: 1.1rem;
margin: 0 0 30px 0;
}
.cta-buttons {
display: flex;
gap: 15px;
justify-content: center;
flex-wrap: wrap;
}
.cta-btn {
padding: 15px 40px;
border-radius: 8px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
border: none;
min-width: 220px;
}
.cta-btn.primary {
background: linear-gradient(135deg, #6B8DD6 0%, #5A7BC6 100%);
color: white;
box-shadow: 0 4px 15px rgba(107, 141, 214, 0.4);
}
.cta-btn.primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 25px rgba(107, 141, 214, 0.5);
}
.cta-btn.secondary {
background: rgba(40, 40, 40, 0.8);
color: white;
border: 1px solid rgba(107, 141, 214, 0.5);
}
.cta-btn.secondary:hover {
background: rgba(60, 60, 60, 0.9);
border-color: rgba(107, 141, 214, 0.8);
transform: translateY(-2px);
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* For very small screens */
@media (max-width: 480px) {
.auth-container {
@@ -376,7 +642,67 @@
right: -10px;
}
.logo h1 {
font-size: 1.3rem;
}
.logo h2 {
font-size: 1rem;
}
.auth-buttons {
gap: 8px;
}
.auth-buttons .header-btn {
padding: 6px 10px;
font-size: 0.8rem;
min-width: auto;
}
.auth-modal-content {
padding: 30px 20px;
}
}
/* Landing Page Responsive */
@media (max-width: 768px) {
.landing-page {
padding: 40px 15px;
}
.landing-title {
font-size: 2rem;
}
.landing-subtitle {
font-size: 1.1rem;
}
.landing-features {
grid-template-columns: 1fr;
gap: 20px;
}
.feature-card {
padding: 25px;
}
.landing-cta {
padding: 35px 20px;
}
.landing-cta h2 {
font-size: 1.5rem;
}
.cta-buttons {
flex-direction: column;
align-items: center;
}
.cta-btn {
width: 100%;
max-width: 300px;
}
}
+108 -41
View File
@@ -30,49 +30,13 @@
<header class="auth-header">
<div class="auth-container">
<div class="logo">
<h2>🍎 Food Tracker</h2>
<h1>🍎 Food Tracker</h1>
</div>
<!-- Authentication Forms -->
<div id="auth-section" class="auth-section">
<!-- Login Form -->
<div id="login-form" class="auth-form">
<h3>Login</h3>
<form id="loginForm">
<div class="form-group">
<input type="email" id="loginEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="loginPassword" placeholder="Password" required>
</div>
<button type="submit" class="auth-btn">Login</button>
<p class="auth-switch">
Don't have an account?
<a href="#" id="showRegister">Register here</a>
</p>
</form>
</div>
<!-- Register Form -->
<div id="register-form" class="auth-form hidden">
<h3>Register</h3>
<form id="registerForm">
<div class="form-group">
<input type="text" id="registerName" placeholder="Name" required>
</div>
<div class="form-group">
<input type="email" id="registerEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="registerPassword" placeholder="Password" required minlength="8">
</div>
<button type="submit" class="auth-btn">Register</button>
<p class="auth-switch">
Already have an account?
<a href="#" id="showLogin">Login here</a>
</p>
</form>
</div>
<!-- Authentication Buttons (shown when not logged in) -->
<div id="auth-buttons" class="auth-buttons">
<button id="open-login-btn" class="header-btn">Login</button>
<button id="open-register-btn" class="header-btn primary">Get Started</button>
</div>
<!-- User Info (shown when logged in) -->
@@ -99,6 +63,109 @@
</div>
</header>
<!-- Authentication Modal -->
<div id="auth-modal" class="auth-modal hidden">
<div class="auth-modal-content">
<button id="close-auth-modal" class="close-modal-btn">×</button>
<!-- Login Form -->
<div id="login-form" class="auth-form">
<h3>Welcome Back</h3>
<form id="loginForm">
<div class="form-group">
<input type="email" id="loginEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="loginPassword" placeholder="Password" required>
</div>
<button type="submit" class="auth-btn">Login</button>
<p class="auth-switch">
Don't have an account?
<a href="#" id="showRegister">Register here</a>
</p>
</form>
</div>
<!-- Register Form -->
<div id="register-form" class="auth-form hidden">
<h3>Create Your Account</h3>
<form id="registerForm">
<div class="form-group">
<input type="text" id="registerName" placeholder="Name" required>
</div>
<div class="form-group">
<input type="email" id="registerEmail" placeholder="Email" required>
</div>
<div class="form-group">
<input type="password" id="registerPassword" placeholder="Password" required minlength="8">
</div>
<button type="submit" class="auth-btn">Register</button>
<p class="auth-switch">
Already have an account?
<a href="#" id="showLogin">Login here</a>
</p>
</form>
</div>
</div>
</div>
<!-- Landing Page Content (shown when not logged in) -->
<section id="landing-page" class="landing-page hidden">
<div class="landing-container">
<div class="landing-hero">
<h1 class="landing-title">Track Your Nutrition, Transform Your Health</h1>
<p class="landing-subtitle">Take control of your diet with our comprehensive calorie and nutrition tracker. Perfect for anyone who wants to maintain a balanced diet and achieve their health goals.</p>
</div>
<div class="landing-features">
<div class="feature-card">
<div class="feature-icon">📊</div>
<h3>Detailed Tracking</h3>
<p>Monitor calories, protein, fat, carbs, and fiber for every meal. Get a complete picture of your daily nutrition.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🎯</div>
<h3>Set Goals</h3>
<p>Define your daily macros targets and track your progress. Stay motivated and on track with your health journey.</p>
</div>
<div class="feature-card">
<div class="feature-icon">📅</div>
<h3>Calendar View</h3>
<p>Visualize your nutrition history with an intuitive calendar. See patterns and maintain consistency over time.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🥗</div>
<h3>Alkaline Balance</h3>
<p>Track your alkaline food intake to maintain a healthy pH balance and support overall wellness.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔍</div>
<h3>Smart Search</h3>
<p>Quickly find and log foods from our comprehensive database. Make tracking effortless and accurate.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔗</div>
<h3>Share Progress</h3>
<p>Share your daily food log with friends, trainers, or nutritionists. Get support and accountability.</p>
</div>
</div>
<div class="landing-cta">
<h2>Ready to Start Your Health Journey?</h2>
<p>Join today and take the first step towards a healthier, more balanced lifestyle.</p>
<div class="cta-buttons">
<button id="cta-register-btn" class="cta-btn primary">Get Started Free</button>
<button id="cta-login-btn" class="cta-btn secondary">Already Have an Account?</button>
</div>
</div>
</div>
</section>
<!-- Loading Overlay -->
<div id="loading-overlay" class="loading-overlay hidden">
<div class="loading-spinner"></div>
+8 -8
View File
@@ -9,12 +9,12 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"appwrite": "^21.3.0",
"appwrite": "^21.5.0",
"sweetalert": "^2.1.2"
},
"devDependencies": {
"typescript": "^5.9.3",
"vite": "^7.1.12"
"vite": "^7.2.6"
}
},
"node_modules/@esbuild/aix-ppc64": {
@@ -747,9 +747,9 @@
"license": "MIT"
},
"node_modules/appwrite": {
"version": "21.3.0",
"resolved": "https://registry.npmjs.org/appwrite/-/appwrite-21.3.0.tgz",
"integrity": "sha512-b3apD2fiQ7g+2damLZ0Lk9SdCJb32wXKq1ijB7blAl0uItqMx0I34E0RVaC5aER5VTCXHFAlHRjZ1GQypdNt1A==",
"version": "21.5.0",
"resolved": "https://registry.npmjs.org/appwrite/-/appwrite-21.5.0.tgz",
"integrity": "sha512-643bMRZVYXMluXvSXbdaLAi9qqTJLWbVGguKH4vH6IdKHur6gGIirhCOqAEt33pV4TOFJ55VBu8c/+Ft1ke2SA==",
"license": "BSD-3-Clause"
},
"node_modules/es6-object-assign": {
@@ -999,9 +999,9 @@
}
},
"node_modules/vite": {
"version": "7.1.12",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz",
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
"version": "7.2.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
"integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+2 -2
View File
@@ -13,10 +13,10 @@
"description": "",
"devDependencies": {
"typescript": "^5.9.3",
"vite": "^7.1.12"
"vite": "^7.2.6"
},
"dependencies": {
"appwrite": "^21.3.0",
"appwrite": "^21.5.0",
"sweetalert": "^2.1.2"
}
}
+36 -1
View File
@@ -1,9 +1,24 @@
import { getDivById } from "./DomUtils";
export function showAuthForms() {
getDivById('auth-section').classList.remove('hidden');
getDivById('auth-buttons').classList.remove('hidden');
getDivById('user-info').classList.add('hidden');
getDivById('app-content').classList.add('hidden');
getDivById('landing-page').classList.remove('hidden');
}
export function hideAuthForms() {
getDivById('auth-buttons').classList.add('hidden');
getDivById('auth-modal').classList.add('hidden');
getDivById('landing-page').classList.add('hidden');
}
export function openAuthModal() {
getDivById('auth-modal').classList.remove('hidden');
}
export function closeAuthModal() {
getDivById('auth-modal').classList.add('hidden');
}
export function toggleAuthForms() {
@@ -16,3 +31,23 @@ export function toggleAuthForms() {
const resetForm = document.getElementById('registerForm') as HTMLFormElement;
resetForm.reset();
}
export function showRegisterForm() {
document.getElementById('login-form')?.classList.add('hidden');
document.getElementById('register-form')?.classList.remove('hidden');
const resetForm = document.getElementById('registerForm') as HTMLFormElement;
resetForm.reset();
openAuthModal();
}
export function showLoginForm() {
document.getElementById('login-form')?.classList.remove('hidden');
document.getElementById('register-form')?.classList.add('hidden');
const logForm = document.getElementById('loginForm') as HTMLFormElement;
logForm.reset();
openAuthModal();
}
+33 -3
View File
@@ -4,7 +4,7 @@ import { DailyTotalCalories, FoodItem, FoodStorage } from './types.js';
import { AppwriteAuth, AppwriteDB } from './appwrite.js';
import swal from 'sweetalert';
import { closeMobileMenu, delay, getCleanName, getIcon, handleMobileCalendarClick, hideLoading, hideSearchResults, navigateResultsKeyboard, QUICK_DELAY, scrollToCalendarView, showLoading, toggleCardHandler, toggleMobileMenu } from './Utils.ts';
import { showAuthForms, toggleAuthForms } from './auth.ts';
import { showAuthForms, toggleAuthForms, showRegisterForm, showLoginForm, hideAuthForms, closeAuthModal } from './auth.ts';
import { appState } from "./state";
// App state
@@ -67,6 +67,7 @@ async function handleRegister(e: SubmitEvent) {
await AppwriteAuth.login(email, password);
currentUser = await AppwriteAuth.getCurrentUser();
closeAuthModal();
await showMainApp();
selectDate(selectedDate);
@@ -92,6 +93,7 @@ async function handleLogin(e: SubmitEvent) {
await AppwriteAuth.login(email, password);
currentUser = await AppwriteAuth.getCurrentUser();
closeAuthModal();
await showMainApp();
selectDate(selectedDate);
@@ -245,7 +247,7 @@ async function handleMobileSettingsClick() {
}
async function showMainApp() {
getDivById('auth-section').classList.add('hidden');
hideAuthForms();
getDivById('user-info').classList.remove('hidden');
getDivById('app-content').classList.remove('hidden');
@@ -423,6 +425,34 @@ const setupEventListeners = () => {
document.getElementById('close-share-modal')?.addEventListener('click', closeShareModal);
document.getElementById('copy-share-link')?.addEventListener('click', copyShareLink);
// Landing page CTA button event listeners
document.getElementById('cta-register-btn')?.addEventListener('click', () => {
showRegisterForm();
});
document.getElementById('cta-login-btn')?.addEventListener('click', () => {
showLoginForm();
});
// Header auth button event listeners
document.getElementById('open-login-btn')?.addEventListener('click', () => {
showLoginForm();
});
document.getElementById('open-register-btn')?.addEventListener('click', () => {
showRegisterForm();
});
// Close auth modal
document.getElementById('close-auth-modal')?.addEventListener('click', () => {
closeAuthModal();
});
// Close modal when clicking outside
document.getElementById('auth-modal')?.addEventListener('click', (e) => {
if (e.target === document.getElementById('auth-modal')) {
closeAuthModal();
}
});
// Search functionality
getInputById('foodSearchInput').addEventListener('input', function(e: Event) {
const target = e.target as HTMLInputElement;
@@ -1442,7 +1472,7 @@ async function checkSharedView() {
});
// Hide auth section and show app content
getDivById('auth-section').classList.add('hidden');
getDivById('auth-buttons').classList.add('hidden');
getDivById('user-info').classList.add('hidden');
getDivById('app-content').classList.remove('hidden');