From bd664d23be9492f19a02ff94aa5063f494f5f592 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Tue, 7 Jul 2026 12:05:44 +0800 Subject: [PATCH] feat(ui): add landing page with random public postcards for unauthenticated visitors --- app/locales/en.json | 4 +++ app/locales/zh.json | 4 +++ app/routers/web.py | 46 +++++++++++++++++++++++-- app/templates/base.html | 2 +- app/templates/index.html | 74 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 app/templates/index.html diff --git a/app/locales/en.json b/app/locales/en.json index 8d9e088..53daf3e 100644 --- a/app/locales/en.json +++ b/app/locales/en.json @@ -3,6 +3,10 @@ "name": "English" }, "brand": "📮 Mailova", + "index.title": "Mailova", + "index.subtitle": "Postcards from around the world", + "index.go_login": "Login", + "index.empty": "No public postcards yet", "nav.profiles": "Profiles", "nav.settings": "Settings", "nav.invites": "Invites", diff --git a/app/locales/zh.json b/app/locales/zh.json index 40e515e..12e7447 100644 --- a/app/locales/zh.json +++ b/app/locales/zh.json @@ -3,6 +3,10 @@ "name": "中文" }, "brand": "📮 星笺", + "index.title": "星笺", + "index.subtitle": "来自世界各地的明信片", + "index.go_login": "登录", + "index.empty": "暂无公开明信片", "nav.profiles": "Profile", "nav.settings": "设置", "nav.invites": "邀请码管理", diff --git a/app/routers/web.py b/app/routers/web.py index 2b3a355..4669837 100644 --- a/app/routers/web.py +++ b/app/routers/web.py @@ -1,5 +1,6 @@ from datetime import datetime, timezone, timedelta from pathlib import Path +from random import shuffle from uuid import uuid4 from fastapi import APIRouter, Depends, File, Form, Query, Request, UploadFile @@ -17,12 +18,11 @@ from app.auth import ( ) from app.config import SECRET_KEY, SESSION_COOKIE_NAME, UPLOAD_DIR from app.database import get_db -from datetime import datetime from random import choice from string import ascii_letters, digits from app.models import InviteCode, Postcard, Profile, User -from app.i18n import t as _t +from app.i18n import t as _t, get_languages as _get_languages router = APIRouter(tags=["web"]) templates = Jinja2Templates(directory=str(Path(__file__).resolve().parent.parent / "templates")) @@ -109,6 +109,48 @@ def _redirect(url: str) -> RedirectResponse: return RedirectResponse(url, status_code=303) +# ---------- Root / Index ---------- + +@router.get("/", response_class=HTMLResponse) +def index_page(request: Request, db: Session = Depends(get_db)): + user = redirect_if_not_logged_in(request, db) + if user: + return _redirect("/dashboard") + + # Collect all public postcards from all users with showcase enabled + all_postcards: list[Postcard] = [] + users = db.query(User).filter(User.showcase_mode.isnot(None)).all() + for u in users: + profiles = db.query(Profile).filter( + Profile.user_id == u.id, Profile.showcase_enabled == True + ).all() + for p in profiles: + cards = db.query(Postcard).filter( + Postcard.profile_id == p.id, Postcard.showcase_hidden == False + ).all() + for c in cards: + visible = True + if c.status in ("sent", "delivered") and p.showcase_visible not in ("sent", "both"): + visible = False + if c.status == "received" and p.showcase_visible not in ("received", "both"): + visible = False + if visible: + all_postcards.append(c) + + shuffle(all_postcards) + + lang = request.query_params.get("lang") + avail = _get_languages() + if not lang or lang not in avail: + lang = request.cookies.get("showcase_lang") + if not lang or lang not in avail: + lang = "zh" + + return templates.TemplateResponse("index.html", { + "request": request, "postcards": all_postcards, "lang": lang, + }) + + # ---------- Auth ---------- @router.get("/login", response_class=HTMLResponse) diff --git a/app/templates/base.html b/app/templates/base.html index 61204ae..dd18dee 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -9,7 +9,7 @@ {% block nav %}