169 lines · 6.3 KB
import { createFileRoute, Link } from "@tanstack/react-router";
import { useState } from "react";
import { z } from "zod";
import { deleteMilestone, listMilestones, saveMilestone } from "~/fns/milestones";
import { useAction } from "~/hooks/use-action";
import { ProgressBar } from "~/components/ProgressBar";
import { EmptyState } from "~/ui/EmptyState";
import { Panel } from "~/ui/Panel";
import { Button, buttonClass } from "~/ui/Button";
import { TextAreaField, TextField } from "~/ui/Field";
import { ErrorBanner } from "~/ui/Callout";
import { cn } from "~/utils/cn";

export const Route = createFileRoute("/$owner/$repo/milestones/")({
  validateSearch: z.object({ state: z.enum(["open", "closed"]).optional() }),
  loaderDeps: ({ search }) => search,
  loader: ({ params, deps }) =>
    listMilestones({ data: { owner: params.owner, repo: params.repo, state: deps.state ?? "open" } }),
  component: MilestonesPage,
});

function dueDate(value: FormDataEntryValue | null): number | null {
  const text = String(value ?? "");
  return text ? new Date(`${text}T00:00:00Z`).getTime() : null;
}

function NewMilestone({ owner, repo, onClose }: { owner: string; repo: string; onClose: () => void }) {
  const save = useAction(saveMilestone);
  return (
    <Panel title="New milestone">
      <form
        className="space-y-3 p-4"
        onSubmit={async (event) => {
          event.preventDefault();
          const form = new FormData(event.currentTarget);
          const ok = await save.run({
            data: {
              owner,
              repo,
              id: null,