my eye

author Angelo Gladding

name Calendar

published 2025-08-15T22:11:06.712200-07:00

type entry

updated 2026-10-23T00:28:40.614068-07:00

url /calendar, /2025/08/16/mh

visibility public

Content

$def with ()

$code:
    events = web.tx.db.select(
        "resources",
        what="""
            json_extract(resource, '$."in-reply-to"[0].name[0]') AS name,
            json_extract(resource, '$."in-reply-to"[0].url[0]') AS url,
            COALESCE(
                json_extract(resource, '$."in-reply-to"[0].start[0].datetime'),
                json_extract(resource, '$."in-reply-to"[0].start[0]')
            ) AS start,
            COALESCE(
                json_extract(resource, '$."in-reply-to"[0].end[0].datetime'),
                json_extract(resource, '$."in-reply-to"[0].end[0]')
            ) AS end
        """,
        where="""
            json_extract(resource, '$.rsvp[0]') = 'yes'
            AND julianday(json_extract(resource, '$.published[0].datetime'))
                >= julianday('now', '-1 month')
            AND substr(start, 1, 10)
                >= date('now', 'start of month', '-1 month')
            AND substr(start, 1, 10)
                < date('now', 'start of month', '+3 months')
        """,
        order="start"
    )

    events_by_day = collections.defaultdict(list)
    for event in events:
        events_by_day[str(event["start"])[:10]].append(event)

    days = web.tx.db.select(
        """(
            WITH RECURSIVE
            offsets(n) AS (VALUES (-1), (0), (1), (2)),
            numbers(n) AS (
                SELECT 0
                UNION ALL
                SELECT n + 1 FROM numbers WHERE n < 41
            ),
            months(month) AS (
                SELECT date('now', 'start of month', printf('%+d months', n))
                FROM offsets
            )
            SELECT
                substr(month, 1, 7) AS month,
                date(
                    month,
                    printf('-%d days', strftime('%w', month)),
                    printf('+%d days', numbers.n)
                ) AS day
            FROM months CROSS JOIN numbers
        ) AS grid""",
        what="month, day",
        order="month, day"
    )

    grids = collections.defaultdict(list)
    for day in days:
        grids[day["month"]].append(day["day"])

    month_names = (
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
    )

<div class="rsvp-calendars">
    $for month in sorted(grids):
        <section>
            <h2>$(month_names[int(month[5:7]) - 1]) $(month[:4])</h2>
            <table class="rsvp-calendar">
                <thead>
                    <tr>
                        $for weekday in ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"):
                            <th scope="col">$weekday</th>
                    </tr>
                </thead>
                <tbody>
                    $for week_start in range(0, 42, 7):
                        $if grids[month][week_start][:7] == month or grids[month][week_start + 6][:7] == month:
                            <tr>
                                $for day in grids[month][week_start:week_start + 7]:
                                    $if day[:7] == month:
                                        <td>
                                            <time datetime="$day">$(int(day[8:10]))</time>
                                            $for event in events_by_day.get(day, []):
                                                <a class="calendar-event" href="$(event['url'])">
                                                    <time datetime="$(event['start'])">
                                                        $(str(event["start"])[11:16])
                                                    </time>
                                                    <span>$(event["name"])</span>
                                                </a>
                                        </td>
                                    $else:
                                        <td class="calendar-padding"></td>
                            </tr>
                </tbody>
            </table>
        </section>
</div>

<style>
.rsvp-calendars {
    display: grid;
    gap: 2rem;
}

.rsvp-calendar {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
}

.rsvp-calendar th,
.rsvp-calendar td {
    border: 1px solid #8886;
    padding: .4rem;
}

.rsvp-calendar th {
    font-size: .8rem;
}

.rsvp-calendar td {
    height: 6rem;
    vertical-align: top;
}

.rsvp-calendar .calendar-padding {
    border: 0;
    background: transparent;
}

.calendar-event {
    display: block;
    margin-top: .4rem;
    padding: .35rem;
    border-radius: .25rem;
    background: #8882;
    font-size: .8rem;
    overflow-wrap: anywhere;
}

.calendar-event time,
.calendar-event span {
    display: block;
}
</style>