189 lines · 7.1 KB
import { Link } from "@tanstack/react-router";
import { useState } from "react";
import { cn } from "~/utils/cn";
import type { ContributionDay } from "~/server/contributions";

const WEEK = 7;
const LEVELS = ["bg-kumo-base", "bg-accent-950", "bg-accent-800", "bg-accent-600", "bg-accent-400"];
const LEVEL_STEPS = [0, 1, 3, 6, 10];
const TOOLTIP_OFFSET_PX = 8;

const BREAKDOWN_LABELS = [
  { key: "commits", singular: "commit", plural: "commits" },
  { key: "pulls", singular: "pull request event", plural: "pull request events" },
  { key: "issues", singular: "issue opened", plural: "issues opened" },
  { key: "reviews", singular: "comment or review", plural: "comments and reviews" },
  { key: "other", singular: "other event", plural: "other events" },
  { key: "private", singular: "contribution in a private repository", plural: "contributions in private repositories" },
] as const;

const DATE_FORMAT = new Intl.DateTimeFormat(undefined, {
  weekday: "short",
  month: "short",
  day: "numeric",
  year: "numeric",
  timeZone: "UTC",
});

type Hover = { day: ContributionDay; left: number; top: number };

function level(count: number): string {
  let index = 0;
  for (const [step, threshold] of LEVEL_STEPS.entries()) if (count >= threshold) index = step;
  return LEVELS[index];
}

function formatDay(date: string): string {
  return DATE_FORMAT.format(new Date(`${date}T00:00:00Z`));
}

function DayCard({ hover }: { hover: Hover }) {