1.1.1Updated a month ago
import { Handlers, PageProps } from "$fresh/server.ts";
import { Package } from "$classes/package.ts";

import moment from "npm:moment";
import { Postgres } from "https://viapak.xyz/@db/pg/mod.ts";

export const handler: Handlers<NamespacePageProps> = {
  async GET(_req, ctx) {
    const { rows: tag_results } = await Postgres.query<NamespacePageProps['tag_results'][0]>(`
      SELECT
        DISTINCT(tag) as tag,
        COUNT(DISTINCT id) AS count,
        MAX(
          to_timestamp((event->>'timestamp')::bigint / 1000)
        )::timestamptz + interval '2 hours' as latest_timestamp
      FROM
        ${Package.table} t
        CROSS JOIN LATERAL jsonb_array_elements(t.events) AS event
        CROSS JOIN LATERAL jsonb_array_elements_text(tags) AS tag
      GROUP BY 1
      ORDER BY count DESC, latest_timestamp DESC
    `);

    return ctx.render({ tag_results });
  }
}

interface NamespacePageProps {
  tag_results: {
    tag: string
    count: number
    latest_timestamp: Date
  }[]
}

export default function NamespacePage({ data: { tag_results } }: PageProps<NamespacePageProps>) {
  return (
    <div>
      <div class="container mx-auto">
        <ul class="list bg-base-100 rounded-box shadow-md w-full">
          <li class="p-4 pb-2 text-xs opacity-60 tracking-wide">Namespaces</li>

          { tag_results.map(({ tag, latest_timestamp, count }) => (
            <a href={`tags/${tag}`}>
              <li class="list-row">
                <div class="list-col-grow">
                  <div>
                    <span class="badge badge-primary badge-soft">
                      {tag}
                    </span>
                  </div>
                  <div class="text-xs uppercase font-semibold opacity-60">{moment(latest_timestamp).fromNow()}</div>
                </div>
                <button type="button" class="btn btn-ghost">
                  { count } Packages
                  {/* <svg class="size-[1.2em]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"></path></g></svg> */}
                </button>
              </li>
            </a>
          )) }
        </ul>
      </div>
    </div>
  );
}