diff --git a/server.py b/server.py index f25f2b0..001182f 100644 --- a/server.py +++ b/server.py @@ -12,6 +12,7 @@ import requests import dotenv import csv from io import StringIO +from datetime import date, datetime dotenv.load_dotenv() @@ -86,6 +87,69 @@ SCHEDULE_DATA = load_schedule_data() app = Flask(__name__) +def parse_schedule_date(raw_date: str) -> date | None: + """Parse a schedule date string using common formats.""" + if not raw_date: + return None + + cleaned = raw_date.strip() + + # Try ISO date first. + try: + return date.fromisoformat(cleaned) + except ValueError: + pass + + formats = [ + "%d/%m/%Y", + "%m/%d/%Y", + "%d/%m/%y", + "%m/%d/%y", + "%d-%m-%Y", + "%m-%d-%Y", + "%d %b %Y", + "%d %B %Y", + "%b %d, %Y", + "%B %d, %Y", + "%a %d %b %Y", + "%A %d %B %Y", + ] + + for fmt in formats: + try: + return datetime.strptime(cleaned, fmt).date() + except ValueError: + continue + + month_day_formats = [ + "%B %d", + "%b %d", + "%B %d,", + "%b %d,", + ] + + current_year = date.today().year + for fmt in month_day_formats: + try: + # Add current year to the end of the string for parsing + date_str_with_year = f"{cleaned} {current_year}" + return datetime.strptime(date_str_with_year, fmt + " %Y").date() + except ValueError: + continue + + return None + + +def find_upcoming_week_index(schedule: list[dict]) -> int | None: + """Return the index of the next schedule item that is today or later.""" + today = date.today() + for index, item in enumerate(schedule): + parsed_date = parse_schedule_date(item.get("date", "")) + if parsed_date and parsed_date >= today: + return index + return None + + def find(name, path): for root, dirs, files in os.walk(path): if name in files: @@ -140,7 +204,12 @@ def wellknown(path): # region Main routes @app.route("/") def index(): - return render_template("schedule.html", schedule=SCHEDULE_DATA) + upcoming_week_index = find_upcoming_week_index(SCHEDULE_DATA) + return render_template( + "schedule.html", + schedule=SCHEDULE_DATA, + upcoming_week_index=upcoming_week_index, + ) @app.route("/") @@ -196,4 +265,4 @@ def not_found(e): # endregion if __name__ == "__main__": - app.run(debug=True, port=5000, host="0.0.0.0") + app.run(debug=True, port=5000, host="127.0.0.1") diff --git a/templates/assets/css/schedule.css b/templates/assets/css/schedule.css index 86c093a..2ce8c93 100644 --- a/templates/assets/css/schedule.css +++ b/templates/assets/css/schedule.css @@ -16,6 +16,9 @@ --empty-leader-color: #666; --select-bg: rgba(50, 50, 50, 0.8); --select-border: #666; + --upcoming-accent: #7dd3fc; + --upcoming-row-bg: rgba(125, 211, 252, 0.14); + --upcoming-glow: rgba(125, 211, 252, 0.28); } [data-theme="pink"] { @@ -34,6 +37,9 @@ --empty-leader-color: #996677; --select-bg: rgba(80, 40, 60, 0.8); --select-border: #a55577; + --upcoming-accent: #f9a8d4; + --upcoming-row-bg: rgba(249, 168, 212, 0.16); + --upcoming-glow: rgba(249, 168, 212, 0.32); } body { @@ -207,6 +213,36 @@ h1 { background-color: var(--special-event-hover); } +.upcoming-week { + background: linear-gradient(90deg, var(--upcoming-row-bg) 0%, transparent 72%); + box-shadow: inset 4px 0 0 var(--upcoming-accent), inset 0 0 0 1px var(--upcoming-glow); +} + +.upcoming-week:hover { + background: linear-gradient(90deg, var(--upcoming-row-bg) 0%, var(--row-hover-bg) 72%); +} + +.upcoming-date { + position: relative; + padding-left: 12px; + font-weight: 700; +} + +.upcoming-date::before { + content: none; +} + +.upcoming-date::after { + content: "next up"; + display: block; + margin-top: 2px; + font-size: 10px; + line-height: 1; + letter-spacing: 1.2px; + text-transform: uppercase; + color: var(--upcoming-accent); +} + .date-cell { font-weight: 600; color: var(--date-color); @@ -329,6 +365,15 @@ h1 { font-size: 13px; font-weight: 700; } + + .upcoming-date { + padding-left: 8px; + } + + .upcoming-date::after { + font-size: 9px; + letter-spacing: 1px; + } .leader-cell { width: 30%; @@ -378,6 +423,11 @@ h1 { .date-cell { width: 30%; font-size: 14px; + padding-left: 10px !important; + } + + .upcoming-date::after { + display: none; } .topic-cell { diff --git a/templates/schedule.html b/templates/schedule.html index 3c50c1f..3e4c0f6 100644 --- a/templates/schedule.html +++ b/templates/schedule.html @@ -43,8 +43,8 @@ {% for item in schedule %} - - {{ item.date }} + + {{ item.date }} {% if item.leaders %}{% if item.leaders|length > 1 %}{{ item.leaders[:-1]|join(', ') }} & {{ item.leaders[-1] }}{% else %}{{ item.leaders[0] }}{% endif %}{% endif %} {{ item.topic }}