refactor: python to go
This commit is contained in:
136
templates/base.html
Normal file
136
templates/base.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, viewport-fit=cover"
|
||||
/>
|
||||
<title>{{block "title" .}}RideAware{{end}}</title>
|
||||
|
||||
<!-- Icons/Fonts -->
|
||||
<link
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/css/styles.css"
|
||||
/>
|
||||
|
||||
<!-- Favicons -->
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/static/assets/32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="alternate icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/static/assets/32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/static/assets/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="manifest"
|
||||
href="/static/assets/site.webmanifest"
|
||||
/>
|
||||
<meta name="theme-color" content="#0f172a" />
|
||||
|
||||
{{block "extra_head" .}}{{end}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="nav-container">
|
||||
<a
|
||||
href="/"
|
||||
class="logo"
|
||||
aria-label="RideAware home"
|
||||
>
|
||||
<img
|
||||
src="/static/assets/logo.png"
|
||||
alt="RideAware"
|
||||
class="logo-img"
|
||||
width="140"
|
||||
height="28"
|
||||
decoding="async"
|
||||
fetchpriority="high"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<button
|
||||
class="nav-toggle"
|
||||
id="nav-toggle"
|
||||
aria-label="Toggle navigation"
|
||||
aria-controls="primary-nav"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="bar"></span>
|
||||
<span class="bar"></span>
|
||||
<span class="bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{{block "content" .}}{{end}}
|
||||
|
||||
<footer class="footer">
|
||||
<p>© 2025 RideAware. All rights reserved.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Core JS -->
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
{{block "extra_scripts" .}}
|
||||
<script>
|
||||
(function () {
|
||||
const btn = document.getElementById("nav-toggle");
|
||||
const menu = document.getElementById("primary-nav");
|
||||
if (!btn || !menu) return;
|
||||
|
||||
function closeMenu() {
|
||||
btn.classList.remove("active");
|
||||
btn.setAttribute("aria-expanded", "false");
|
||||
menu.classList.remove("open");
|
||||
}
|
||||
|
||||
btn.addEventListener("click", () => {
|
||||
const open = btn.classList.toggle("active");
|
||||
btn.setAttribute("aria-expanded", String(open));
|
||||
menu.classList.toggle("open", open);
|
||||
});
|
||||
|
||||
menu.addEventListener("click", (e) => {
|
||||
if (e.target.tagName === "A") closeMenu();
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") closeMenu();
|
||||
});
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!menu.contains(e.target) && !btn.contains(e.target)) {
|
||||
closeMenu();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +1,343 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Thanks for Subscribing!</title>
|
||||
<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"
|
||||
/>
|
||||
<title>Welcome to RideAware!</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
html,
|
||||
body {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
height: 100% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
* {
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
table,
|
||||
td {
|
||||
mso-table-lspace: 0pt !important;
|
||||
mso-table-rspace: 0pt !important;
|
||||
}
|
||||
img {
|
||||
-ms-interpolation-mode: bicubic;
|
||||
border: 0;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
.bg {
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.header {
|
||||
background: #1e4e9c;
|
||||
background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
|
||||
padding: 40px 24px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
.logo-text {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-weight: 800;
|
||||
font-size: 24px;
|
||||
line-height: 1.2;
|
||||
color: #ffffff;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
.logo-accent {
|
||||
color: #00d4ff;
|
||||
}
|
||||
.header-title {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
margin: 6px 0 6px 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
.subtitle {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
color: rgba(255, 255, 255, 0.92);
|
||||
margin: 0;
|
||||
}
|
||||
.content {
|
||||
padding: 32px 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.main-message {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
color: #1a1a1a;
|
||||
font-weight: 600;
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
.description {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
.features-wrap {
|
||||
padding: 0 24px 24px 24px;
|
||||
}
|
||||
.features {
|
||||
border: 1px solid rgba(30, 78, 156, 0.12);
|
||||
border-radius: 12px;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
}
|
||||
.features-title {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
color: #1e4e9c;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 12px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.feature-item {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(2, 6, 23, 0.05);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.feature-title {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
.feature-desc {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin: 0;
|
||||
}
|
||||
.cta {
|
||||
padding: 8px 24px 32px 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.cta-btn {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
display: inline-block;
|
||||
background: #1e4e9c;
|
||||
background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
padding: 14px 28px;
|
||||
border-radius: 999px;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
.social {
|
||||
background-color: #f8fafc;
|
||||
padding: 20px 24px;
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
margin: 0 24px 24px 24px;
|
||||
}
|
||||
.social-title {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 10px 0;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.social-link {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
text-decoration: none;
|
||||
color: #ffffff !important;
|
||||
border-radius: 50%;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
margin: 0 6px;
|
||||
background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
|
||||
}
|
||||
.footer {
|
||||
background: #1a1a1a;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
padding: 24px;
|
||||
}
|
||||
.footer p {
|
||||
margin: 6px 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
.unsubscribe {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.12);
|
||||
margin-top: 14px;
|
||||
padding-top: 14px;
|
||||
}
|
||||
.unsubscribe a {
|
||||
color: #9ca3af !important;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
}
|
||||
.unsubscribe a:hover {
|
||||
color: #00d4ff !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
.header {
|
||||
padding: 32px 18px !important;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
.content {
|
||||
padding: 24px 18px !important;
|
||||
}
|
||||
a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
.features {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>Thanks for subscribing to RideAware newsletter!</h2>
|
||||
<p>We're excited to share our journey with you.</p>
|
||||
<p>If you ever wish to unsubscribe, please click <a href="{{ unsubscribe_link }}">here</a>.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body class="bg">
|
||||
<center role="article" aria-roledescription="email">
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table role="presentation" class="container" width="600" cellspacing="0" cellpadding="0" border="0">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="header">
|
||||
<div class="logo-text">Ride<span class="logo-accent">Aware</span></div>
|
||||
<div style="font-size: 36px; line-height: 1; margin-bottom: 10px;" aria-hidden="true">🎉</div>
|
||||
<div class="header-title">Welcome Aboard!</div>
|
||||
<div class="subtitle">You're now part of the RideAware community</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body -->
|
||||
<tr>
|
||||
<td class="content">
|
||||
<p class="main-message">Thanks for subscribing to the RideAware newsletter!</p>
|
||||
<p class="description">
|
||||
We're thrilled to have you with us. Expect training tips, performance insights,
|
||||
product news, and community highlights—delivered straight to your inbox.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Features -->
|
||||
<tr>
|
||||
<td class="features-wrap">
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="features">
|
||||
<tr>
|
||||
<td align="center" style="padding-bottom: 10px;">
|
||||
<div class="features-title">What to expect from us</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
|
||||
<tr>
|
||||
<td class="feature-item">
|
||||
<div class="feature-title">Training Tips</div>
|
||||
<div class="feature-desc">Actionable advice to improve your performance.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-item">
|
||||
<div class="feature-title">Performance Insights</div>
|
||||
<div class="feature-desc">Data-driven analysis for smarter rides.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-item">
|
||||
<div class="feature-title">Feature Updates</div>
|
||||
<div class="feature-desc">Be first to know about new releases.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="feature-item" style="margin-bottom: 0;">
|
||||
<div class="feature-title">Community Stories</div>
|
||||
<div class="feature-desc">Inspiring journeys from fellow cyclists.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- CTA -->
|
||||
<tr>
|
||||
<td class="cta" align="center">
|
||||
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color:#1a1a1a; font-size:15px; margin: 0 0 12px 0;">
|
||||
Ready to start your journey with RideAware?
|
||||
</p>
|
||||
<a href="https://rideaware.org" target="_blank" class="cta-btn">Explore RideAware →</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Social -->
|
||||
<tr>
|
||||
<td>
|
||||
<div class="social">
|
||||
<div class="social-title">Stay Connected</div>
|
||||
<a href="https://twitter.com" class="social-link" title="Twitter" aria-label="Twitter">T</a>
|
||||
<a href="https://facebook.com" class="social-link" title="Facebook" aria-label="Facebook">f</a>
|
||||
<a href="https://instagram.com" class="social-link" title="Instagram" aria-label="Instagram">IG</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="footer">
|
||||
<p><strong>RideAware Team</strong></p>
|
||||
<p>Empowering cyclists, one ride at a time</p>
|
||||
<div class="unsubscribe">
|
||||
<p style="margin: 0;">
|
||||
<a href="{{.UnsubscribeLink}}">Unsubscribe</a>
|
||||
|
|
||||
<a href="mailto:support@rideaware.com">Contact Support</a>
|
||||
</p>
|
||||
<p style="font-size: 12px; color: #9ca3af;">
|
||||
© 2025 RideAware. All rights reserved.
|
||||
</p>
|
||||
<p style="font-size: 11px; color: #9ca3af;">
|
||||
You received this email because you subscribed to RideAware updates.
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,95 +1,214 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>RideAware</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/">
|
||||
<span>Ride</span><span style="color: #1e4e9c;">Aware</span>
|
||||
</a>
|
||||
<a href="/newsletters">Newsletters</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<section class="hero-section-1">
|
||||
<div class="hero-content">
|
||||
<div class="hero-text">
|
||||
<img src="{{ url_for('static', filename='assets/RideAwareLogo.svg') }}" alt="RideAware Logo">
|
||||
{{define "title"}}RideAware - Smart Cycling Training Platform{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<!-- Hero Section -->
|
||||
<section class="hero">
|
||||
<div class="hero-container">
|
||||
<div class="hero-content">
|
||||
<h1>Elevate Your Cycling Journey</h1>
|
||||
<p class="subtitle">
|
||||
The ultimate smart training platform for cyclists who demand
|
||||
excellence in every ride.
|
||||
</p>
|
||||
|
||||
<div class="cta-section">
|
||||
<h3>Coming soon!</h3>
|
||||
<p>Join us while waiting for launch</p>
|
||||
|
||||
<div class="email-form">
|
||||
<input
|
||||
type="email"
|
||||
class="email-input"
|
||||
id="email-input"
|
||||
placeholder="Enter your email address"
|
||||
required
|
||||
/>
|
||||
<button class="notify-btn" id="notify-button">Notify Me</button>
|
||||
</div>
|
||||
</section>
|
||||
<section class="hero-section-2">
|
||||
<h2>Get notified when we’re launching</h2>
|
||||
<p>Sign up to receive updates and special offers as we prepare to launch.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subscription">
|
||||
<input id="email-input" type="email" placeholder="Enter your email" required />
|
||||
<button id="notify-button">Notify Me</button>
|
||||
<div class="hero-visual">
|
||||
<div class="phone-mockup">
|
||||
<div class="screen">
|
||||
<div class="app-interface">
|
||||
<div class="app-brand">
|
||||
<img
|
||||
src="/static/assets/32x32.png"
|
||||
alt="RideAware icon"
|
||||
class="app-brand-icon"
|
||||
width="32"
|
||||
height="32"
|
||||
decoding="async"
|
||||
/>
|
||||
<div class="app-logo">RideAware</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">24.5</div>
|
||||
<div class="stat-label">KM/H AVG</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">45</div>
|
||||
<div class="stat-label">MINUTES</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">285</div>
|
||||
<div class="stat-label">CALORIES</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">18.2</div>
|
||||
<div class="stat-label">DISTANCE</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features Section -->
|
||||
{{if .IsHome}}
|
||||
<section class="features" id="features">
|
||||
<div class="section-header">
|
||||
<h2>Powerful Features for Every Cyclist</h2>
|
||||
<p>
|
||||
From beginners to professionals, RideAware provides comprehensive
|
||||
tools to optimize your training and performance.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<section class="hero-section-3">
|
||||
<h2 class="hero-sec2-header">Features</h2>
|
||||
<div class="feature-cards">
|
||||
<div class="feature-card">
|
||||
<h3>Workout Planning</h3>
|
||||
<ul>
|
||||
<li><b>Customizable Training Plans:</b> Allow users to create customized training plans based on their goals and fitness level.</li>
|
||||
<li><b>Workout Scheduling:</b> Provide a feature to schedule workouts and set reminders.</li>
|
||||
<li><b>Goal Setting:</b> Allow users to set and track their fitness goals.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>Workout Tracking</h3>
|
||||
<ul>
|
||||
<li><b>Workout Logging:</b> Allow users to log their workouts, including exercises, sets, reps, and weight.</li>
|
||||
<li><b>Data Analysis:</b> Provide tools to analyze user data, including charts, graphs, and statistics.</li>
|
||||
<li><b>Progress Tracking:</b> Allow users to track their progress over time.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>Training and Coaching</h3>
|
||||
<ul>
|
||||
<li><b>Coaching and Guidance:</b> Provide coaching and guidance to help users achieve their fitness goals.</li>
|
||||
<li><b>Virtual Training Rides:</b> Offer immersive virtual training rides to boost users' cycling performance.</li>
|
||||
<li><b>Structured Workouts:</b> Offer structured workouts to help users improve their fitness and performance.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>Nutrition and Recovery</h3>
|
||||
<ul>
|
||||
<li><b>Nutrition Planning:</b> Provide tools to help users plan and track their nutrition.</li>
|
||||
<li><b>Recovery Planning:</b> Offer resources and tools to help users plan and track their recovery.</li>
|
||||
<li><b>Injury Prevention and Management:</b> Provide resources and tools to help users prevent and manage injuries.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>Social and Community</h3>
|
||||
<ul>
|
||||
<li><b>Social Sharing:</b> Allow users to share their workouts and progress on social media.</li>
|
||||
<li><b>Community Forum:</b> Create a community forum where users can connect with each other and share their experiences.</li>
|
||||
<li><b>Leaderboards:</b> Provide leaderboards to encourage competition and motivation.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>Integration and Data</h3>
|
||||
<ul>
|
||||
<li><b>Integration with Wearable Devices:</b> Integrate with wearable devices to track user activity and health metrics.</li>
|
||||
<li><b>Integration with Music Services:</b> Integrate with music services to provide a more engaging workout experience.</li>
|
||||
<li><b>Data Import/Export:</b> Allow users to import and export their data to other platforms.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="features-container">
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="normal-footer">
|
||||
Copyright © 2025 RideAware. All rights reserved.
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
<h3>Smart Training Plans</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>AI-Powered Planning:</strong> Customized training plans
|
||||
based on your goals and fitness level
|
||||
</li>
|
||||
<li>
|
||||
<strong>Adaptive Scheduling:</strong> Smart workout scheduling
|
||||
with automated reminders
|
||||
</li>
|
||||
<li>
|
||||
<strong>Goal Tracking:</strong> Set and monitor your cycling
|
||||
objectives in real-time
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</div>
|
||||
<h3>Advanced Analytics</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>Detailed Logging:</strong> Track exercises, sets, reps,
|
||||
and performance metrics
|
||||
</li>
|
||||
<li>
|
||||
<strong>Data Visualization:</strong> Interactive charts, graphs,
|
||||
and progress statistics
|
||||
</li>
|
||||
<li>
|
||||
<strong>Progress Insights:</strong> Monitor your improvement
|
||||
over time with AI analysis
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-bicycle"></i>
|
||||
</div>
|
||||
<h3>Virtual Training</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>Expert Coaching:</strong> Professional guidance to
|
||||
achieve your cycling goals
|
||||
</li>
|
||||
<li>
|
||||
<strong>Immersive Rides:</strong> Virtual training experiences
|
||||
to boost performance
|
||||
</li>
|
||||
<li>
|
||||
<strong>Structured Workouts:</strong> Designed programs for
|
||||
fitness and performance gains
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-heart"></i>
|
||||
</div>
|
||||
<h3>Health & Recovery</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>Nutrition Tracking:</strong> Plan and monitor your
|
||||
dietary intake for optimal performance
|
||||
</li>
|
||||
<li>
|
||||
<strong>Recovery Optimization:</strong> Tools and resources for
|
||||
effective rest and recovery
|
||||
</li>
|
||||
<li>
|
||||
<strong>Injury Prevention:</strong> Proactive measures to
|
||||
prevent and manage injuries
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-users"></i>
|
||||
</div>
|
||||
<h3>Community & Social</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>Social Sharing:</strong> Share achievements and progress
|
||||
on social platforms
|
||||
</li>
|
||||
<li>
|
||||
<strong>Active Community:</strong> Connect with fellow cyclists
|
||||
and share experiences
|
||||
</li>
|
||||
<li>
|
||||
<strong>Competitive Leaderboards:</strong> Challenge yourself
|
||||
against the community
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
</div>
|
||||
<h3>Smart Integration</h3>
|
||||
<ul class="feature-list">
|
||||
<li>
|
||||
<strong>Wearable Sync:</strong> Connect with fitness trackers
|
||||
and smart devices
|
||||
</li>
|
||||
<li>
|
||||
<strong>Music Integration:</strong> Seamlessly sync with your
|
||||
favorite music services
|
||||
</li>
|
||||
<li>
|
||||
<strong>Data Portability:</strong> Easy import/export to other
|
||||
cycling platforms
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,32 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>RideAware - Newsletter Detail</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/">
|
||||
<span>Ride</span><span style="color: #1e4e9c;">Aware</span>
|
||||
</a>
|
||||
<a href="/newsletters">Newsletters</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<a href="/newsletters" class="back-link">← Back to Newsletters</a>
|
||||
<h1>{{ newsletter.subject }}</h1>
|
||||
<div class="newsletter-content">
|
||||
{{ newsletter.body | safe }}
|
||||
{{define "title"}}RideAware - {{.Subject}}{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="article-wrap">
|
||||
<aside class="article-aside">
|
||||
<a href="/newsletters" class="back-link">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
Back to Newsletters
|
||||
</a>
|
||||
|
||||
<div class="article-meta">
|
||||
<h2 class="article-title">
|
||||
{{.Subject}}
|
||||
</h2>
|
||||
|
||||
<div class="meta-row">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>{{.SentAt.Format "January 2, 2006 at 3:04 PM"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="normal-footer">
|
||||
<p>© 2025 RideAware. All rights reserved.</p>
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<nav class="toc">
|
||||
<div class="toc-title">On this page</div>
|
||||
<ol id="toc-list"></ol>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<main class="article-main">
|
||||
<header class="article-hero">
|
||||
<div class="newsletter-icon">
|
||||
<i class="fas fa-envelope-open-text"></i>
|
||||
</div>
|
||||
<h1>{{.Subject}}</h1>
|
||||
</header>
|
||||
|
||||
<article class="newsletter-content" id="article">
|
||||
{{.Body}}
|
||||
</article>
|
||||
|
||||
<div class="newsletter-actions">
|
||||
<a href="/newsletters" class="action-btn primary">
|
||||
<i class="fas fa-list"></i>
|
||||
View All Newsletters
|
||||
</a>
|
||||
<button onclick="window.print()" class="action-btn secondary">
|
||||
<i class="fas fa-print"></i>
|
||||
Print
|
||||
</button>
|
||||
<button onclick="shareNewsletter()" class="action-btn secondary">
|
||||
<i class="fas fa-share-alt"></i>
|
||||
Share
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extra_scripts"}}
|
||||
<script>
|
||||
function shareNewsletter() {
|
||||
if (navigator.share) {
|
||||
navigator
|
||||
.share({ title: document.title, url: location.href })
|
||||
.catch(() => {});
|
||||
} else {
|
||||
navigator.clipboard.writeText(location.href);
|
||||
alert('Link copied to clipboard!');
|
||||
}
|
||||
}
|
||||
|
||||
// Build TOC from h2/h3 inside the article
|
||||
(function buildTOC() {
|
||||
const article = document.getElementById('article');
|
||||
if (!article) return;
|
||||
|
||||
const headings = article.querySelectorAll('h2, h3');
|
||||
const list = document.getElementById('toc-list');
|
||||
if (!headings.length || !list) return;
|
||||
|
||||
headings.forEach((h, idx) => {
|
||||
const id = h.id || `h-${idx}`;
|
||||
h.id = id;
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.className = h.tagName === 'H2' ? 'toc-h2' : 'toc-h3';
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = `#${id}`;
|
||||
a.textContent = h.textContent;
|
||||
|
||||
li.appendChild(a);
|
||||
list.appendChild(li);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
@@ -1,40 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>RideAware - Newsletters</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
{{define "title"}}RideAware - Newsletters{{end}}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/">
|
||||
<span>Ride</span><span style="color: #1e4e9c;">Aware</span>
|
||||
</a>
|
||||
<a href="/newsletters" class="active">Newsletters</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="newsletter-main">
|
||||
<h1>RideAware Newsletters</h1>
|
||||
{% if newsletters %}
|
||||
{% for nl in newsletters %}
|
||||
<div class="newsletter">
|
||||
<h2>
|
||||
<a href="/newsletter/{{ nl['id'] }}">{{ nl['subject'] }}</a>
|
||||
</h2>
|
||||
<p class="newsletter-time">Sent on: {{ nl['sent_at'] }}</p>
|
||||
<a href="/newsletter/{{ nl['id'] }}" class="read-more">Read More</a>
|
||||
{{define "content"}}
|
||||
<section class="page-header">
|
||||
<div class="page-header-content">
|
||||
<div class="header-icon">
|
||||
<i class="fas fa-newspaper"></i>
|
||||
</div>
|
||||
<h1>RideAware Newsletters</h1>
|
||||
<p>
|
||||
Stay updated with the latest cycling tips, training insights, and
|
||||
product updates from our team.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<main class="main-content">
|
||||
{{if .}}
|
||||
<div class="newsletters-grid">
|
||||
{{range .}}
|
||||
<article class="newsletter-card">
|
||||
<div class="newsletter-header">
|
||||
<div class="newsletter-icon">
|
||||
<i class="fas fa-envelope-open-text"></i>
|
||||
</div>
|
||||
<div class="newsletter-info">
|
||||
<h2>
|
||||
<a href="/newsletter/{{.ID}}">
|
||||
{{.Subject}}
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="newsletter-date">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>Sent on: {{.SentAt.Format "2006-01-02 15:04:05"}}</span>
|
||||
</div>
|
||||
|
||||
<div class="newsletter-excerpt">
|
||||
Get the latest updates on cycling training, performance tips,
|
||||
and RideAware features in this newsletter edition.
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="/newsletter/{{.ID}}"
|
||||
class="read-more-btn"
|
||||
>
|
||||
Read Full Newsletter
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</article>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<i class="fas fa-inbox"></i>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>No newsletters to display yet.</p>
|
||||
{% endif %}
|
||||
<h3>No Newsletters Yet</h3>
|
||||
<p>
|
||||
We're working on some amazing content for you. Subscribe to be the
|
||||
first to know when we publish our newsletters!
|
||||
</p>
|
||||
<a href="/" class="subscribe-prompt">
|
||||
<i class="fas fa-bell"></i>
|
||||
Subscribe for Updates
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
<footer class="fixed-footer">
|
||||
<p>© 2025 RideAware. All rights reserved.</p>
|
||||
</footer>
|
||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user