bucketlist added

This commit is contained in:
esef committed 2026-07-20 22:42:55 +03:00
1 parent 97841f3f24
commit 650211e8ab
7 files changed
+240 -15

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
# Repository Guidelines
## Project Structure & Module Organization
```
website/
├── index.html # Single-page entry point — all 5 tabs live here
├── gallery-container.html # Static gallery image tags (50 images)
├── _redirects # Netlify SPA rewrite rule (/* → /index.html)
├── js/
│ ├── tabs.js # Client-side routing, tab switching, background video swap
│ ├── comments.js # Steam-style comment wall (Firestore: comments + stats)
│ ├── yuukabot.js # Live bot dashboard (Firestore: sysinfo/server)
│ ├── calendar.js # Event calendar (Firestore: calendar_events)
│ └── gallery.js # Lightbox + dynamic thumbnail loader
├── style/
│ ├── styles.css # Global layout, nav bar, base typography
│ ├── comments.css # Steam-profile comment UI
│ ├── yuukabot.css # Dashboard glassmorphism cards + grid
│ ├── calendar.css # Calendar grid, popups, sidebar
│ ├── gallery.css # Gallery grid + lightbox
│ └── ahmet.css # Bucketlist tab button
├── gallery/ # 50 full-quality images + thumbnails/ subdirectory
├── textures/ # Background MP4 videos + clickable character PNG
├── sounds/ # Click SFX (yuuka_click.mp3)
├── generate_thumbnails.py # Pillow script: resizes gallery/ images → thumbnails/
└── firebase.txt # Firestore security rules (reference only)
```
- **No frameworks, no build step, no package manager.** Every file is served directly.
- Assets are organised by type (images in `gallery/`, videos/PNGs in `textures/`).
- Firebase config is duplicated per JS file, each guarding `firebase.initializeApp()` with `if (!firebase.apps.length)` to avoid collisions.
## Build, Test, and Development Commands
This is a static site with **no build system**. Run locally with any HTTP server:
```sh
# Python 3 (recommended)
python -m http.server 8080
# Node.js alternative
npx serve .
```
- `_redirects` handles SPA routing on Netlify; for local dev, navigate to `/index.html` directly.
- `generate_thumbnails.py` regenerates gallery thumbnails: `python generate_thumbnails.py`. Requires `Pillow`.
There are **no automated tests** in this project.
## Coding Style & Naming Conventions
- **HTML:** Semantic elements where practical. Tab contents use `<section id="…" class="tab-content">`. IDs are kebab-case.
- **CSS:** Each tab has its own stylesheet under `style/`. Class names follow BEM-lite (`cal-day`, `dash-card`). CSS variables define layout knobs (`--dash-columns`, `--dash-gap`).
- **JavaScript:** Vanilla ES6+, no transpilation. Functions are `camelCase`, DOM-referencing IDs match kebab-case HTML IDs. Each script is self-contained with a `DOMContentLoaded` guard. Firebase config is repeated per-file (same values) — keep this pattern.
- **Whitespace:** 4-space indentation in JS/CSS, 2-space in HTML. No trailing semicolons are required but consistency within each file is expected.
- No linters or formatters are configured.
## Commit & Pull Request Guidelines
Commit history follows an informal style:
```
<verb> <short description>
```
Examples from the repo: `calendar added`, `fix upcoming filter`, `css polish bs`, `tab specific routing added`.
- Use lowercase, imperative mood.
- Keep messages short (under 72 characters).
- Group related changes into a single commit where possible.
- PRs should include a brief description of what changed and why; screenshots are appreciated for visual/UI changes.
## Security & Configuration
- **Firebase API keys** are public by design (they identify the project, not authenticate). Do not commit service-account credentials or `.env` files.
- `firebase.txt` is in `.gitignore` — keep the live rules reference there, not hardcoded in source.
- All Firestore writes are guarded by security rules (see `firebase.txt`): only `comments` and `stats/global_clicks` accept public writes; everything else is read-only.
## Adding a New Feature
1. Add the new `<section class="tab-content" id="…">` in `index.html`.
2. Add a `<button id="…-btn">` to the nav bar (`#top-line`).
3. Add the tab name to the `valid` array in `js/tabs.js`.
4. Create a dedicated stylesheet in `style/` and JS module in `js/` if needed.
5. Link both in `index.html` `<head>` (CSS) and before `</body>` (JS).
6. If the feature reads/writes Firestore, add the matching security rules to `firebase.txt`.
+9 -4
View File
@@ -8,6 +8,7 @@
<link rel="stylesheet" href="style/comments.css">
<link rel="stylesheet" href="style/yuukabot.css">
<link rel="stylesheet" href="style/calendar.css">
<link rel="stylesheet" href="style/bucketlist.css">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<title>Esef</title>
</head>
@@ -19,14 +20,14 @@
<video muted loop playsinline preload="none" id="calendar-background-video" style="display:none">
<source src="textures/calendar_background.mp4" type="video/mp4">
</video>
<video muted loop playsinline preload="none" id="czscores-background-video" style="display:none">
<video muted loop playsinline preload="none" id="bucketlist-background-video" style="display:none">
<source src="textures/cz_background.mp4" type="video/mp4">
</video>
<div id="top-line">
<a href="index.html" id="home-btn"></a>
<button id="about-btn">About This Website</button>
<button id="gallery-btn">Gallery</button>
<button id="czscores-btn">Cz Scores</button>
<button id="bucketlist-btn">Bucketlist</button>
<button id="yuukabot-btn">Bot Status</button>
<button id="calendar-btn">Calendar</button>
</div>
@@ -116,8 +117,11 @@
<div id="gallery-container" class="gallery-grid"></div>
</section>
<section id="czscores" class="tab-content">
<div id="czscores-container">
<section id="bucketlist" class="tab-content">
<div class="bl-panel">
<div class="bl-list" id="bl-list">
<p class="bl-empty">Loading...</p>
</div>
</div>
</section>
@@ -221,6 +225,7 @@
<script src="js/comments.js"></script>
<script src="js/yuukabot.js"></script>
<script src="js/calendar.js"></script>
<script src="js/bucketlist.js"></script>
<!-- Lightbox -->
<div id="lightbox" class="lightbox">
+60
View File
@@ -0,0 +1,60 @@
// Bucketlist tab — real-time Firestore list
const BL_FB_CONFIG = {
apiKey: "AIzaSyDuSjEGEKx5FnWYnQq8f_owbpYRBRrl5x0",
authDomain: "esef-514bf.firebaseapp.com",
projectId: "esef-514bf",
storageBucket: "esef-514bf.firebasestorage.app",
messagingSenderId: "353969651290",
appId: "1:353969651290:web:41e3aaf8e54c743702a263"
};
document.addEventListener("DOMContentLoaded", () => {
const tab = document.getElementById("bucketlist");
if (!tab) return;
if (!firebase.apps.length) firebase.initializeApp(BL_FB_CONFIG);
const db = firebase.firestore();
const listEl = document.getElementById("bl-list");
if (!listEl) return;
db.collection("bucketlist_items").onSnapshot(snap => {
const items = [];
snap.forEach(doc => {
const d = doc.data();
items.push({
id: doc.id,
title: d.title || "",
description: d.description || "",
date: d.date || "",
utc: d.utc || "",
done: d.done || false
});
});
items.sort((a, b) => (a.utc || "").localeCompare(b.utc || ""));
render(items);
}, () => {
if (listEl) listEl.innerHTML = '<p class="bl-empty">Could not load.</p>';
});
function render(items) {
if (items.length === 0) {
listEl.innerHTML = '<p class="bl-empty">Nothing here yet.</p>';
return;
}
listEl.innerHTML = items.map(item =>
'<div class="bl-item' + (item.done ? ' bl-done' : '') + '">' +
'<div class="bl-title">' + esc(item.title) + '</div>' +
(item.date ? '<div class="bl-date">' + esc(item.date) + '</div>' : '') +
(item.description ? '<div class="bl-desc">' + esc(item.description) + '</div>' : '') +
'</div>'
).join("");
}
function esc(s) {
if (!s) return "";
return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;")
.replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;");
}
});
+6 -6
View File
@@ -3,14 +3,14 @@ document.addEventListener('DOMContentLoaded', () => {
const tabs = document.querySelectorAll('.tab-content');
const mainVideo = document.getElementById('background-video');
const calVideo = document.getElementById('calendar-background-video');
const czVideo = document.getElementById('czscores-background-video');
const bucketlistVideo = document.getElementById('bucketlist-background-video');
// ── Map URL path → tab id ──────────────────────────────
function pathToTab(path) {
const slug = path.replace(/^\/+|\/+$/g, '') || 'about';
const valid = ['about', 'gallery', 'czscores', 'yuukabot', 'calendar'];
const valid = ['about', 'gallery', 'bucketlist', 'yuukabot', 'calendar'];
// backward compat: old /ahmet links
if (slug === 'ahmet') return 'czscores';
if (slug === 'ahmet') return 'bucketlist';
return valid.includes(slug) ? slug : 'about';
}
@@ -24,12 +24,12 @@ document.addEventListener('DOMContentLoaded', () => {
// map tab id → its dedicated video element (null = use main)
const tabVideos = {
calendar: calVideo,
czscores: czVideo
bucketlist: bucketlistVideo
};
function setBgForTab(tabId) {
// Hide + pause ALL videos first
[mainVideo, calVideo, czVideo].forEach(v => {
[mainVideo, calVideo, bucketlistVideo].forEach(v => {
if (v) { v.style.display = 'none'; v.pause(); }
});
@@ -46,7 +46,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Top-bar theme toggle
if (topLine) {
topLine.classList.toggle('cal-theme', tabId === 'calendar');
topLine.classList.toggle('czscores-theme', tabId === 'czscores');
topLine.classList.toggle('bucketlist-theme', tabId === 'bucketlist');
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
/* Cz Scores tab */
/* Bucketlist tab */
#czscores-btn {
#bucketlist-btn {
background-color: aliceblue;
color: #153dee;
border: none;
+73
View File
@@ -0,0 +1,73 @@
/* Bucketlist tab — baked-in left panel, internal scroll only */
/* ── Lock section to viewport so body never scrolls ────────── */
#bucketlist.tab-content {
padding: 0;
height: 100vh;
overflow: hidden;
}
/* ── Panel (framed, no extra space) ────────────────────────── */
.bl-panel {
width: 420px;
height: calc(100vh - 210px);
margin: 125px 0 85px 48px;
background: rgba(35, 35, 41, 0.6);
border: 1px solid rgba(181, 177, 198, 0.18);
border-radius: 10px;
padding: 0;
color: #F4F2F5;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* ── Scrollable list (fills the frame exactly) ────────────── */
.bl-list {
display: flex;
flex-direction: column;
gap: 8px;
overflow-y: auto;
flex: 1;
padding: 14px 16px;
}
/* ── Item card ────────────────────────────────────────────── */
.bl-item {
padding: 14px 18px;
background: rgba(35, 35, 41, 0.75);
border: 1px solid rgba(181, 177, 198, 0.08);
border-radius: 8px;
transition: border-color 0.2s, box-shadow 0.2s;
flex-shrink: 0;
}
.bl-item:hover {
border-color: rgba(184, 68, 87, 0.3);
box-shadow: 0 3px 16px rgba(184, 68, 87, 0.08);
}
.bl-item .bl-title {
color: #F4F2F5;
font-size: 0.95rem;
font-weight: 500;
margin-bottom: 2px;
}
.bl-item .bl-date {
color: rgba(244, 242, 245, 0.45);
font-size: 0.7rem;
margin-bottom: 6px;
}
.bl-item .bl-desc {
color: rgba(244, 242, 245, 0.55);
font-size: 0.78rem;
line-height: 1.5;
}
/* ── Empty state ─────────────────────────────────────────── */
.bl-empty {
text-align: center;
color: rgba(244, 242, 245, 0.3);
padding: 60px 0;
font-family: Arial, sans-serif;
font-size: 0.82rem;
}
+3 -3
View File
@@ -18,7 +18,7 @@ html, body {
}
#background-video,
#calendar-background-video,
#czscores-background-video {
#bucketlist-background-video {
position: fixed;
right: 0%;
left: 0%;
@@ -76,8 +76,8 @@ html, body {
transition: border-color 0.4s ease, color 0.4s ease;
}
/* ── Cz Scores-themed top bar buttons ─────────────────── */
#top-line.czscores-theme button {
/* ── Bucketlist-themed top bar buttons ─────────────────── */
#top-line.bucketlist-theme button {
border-bottom-color: #B5B1C6;
border-left-color: #B5B1C6;
border-right-color: #B5B1C6;