mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-09 04:02:40 -05:00
* Set up tables * Initial * Frontend for finalize tournament * Enter summaries to DB * Handle changes on tournament page after tournament is finalized * Fix streams tab text not centered * Add translations * Results on user page * Highlight logic for tournament results * Leaderboard page initial * Team leaderboard * CSS tweaks * Add unit tests * Add some i18n * Add leaderboards page meta * Support tournaments of size 2 * Add E2E test * Add missing group by
72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
import { useFetcher } from "@remix-run/react";
|
|
import React from "react";
|
|
import invariant from "tiny-invariant";
|
|
import { useTranslation } from "~/hooks/useTranslation";
|
|
import { Button, type ButtonProps } from "./Button";
|
|
import { Dialog } from "./Dialog";
|
|
import { SubmitButton } from "./SubmitButton";
|
|
|
|
export function FormWithConfirm({
|
|
fields,
|
|
children,
|
|
dialogHeading,
|
|
deleteButtonText,
|
|
action,
|
|
submitButtonTestId = "submit-button",
|
|
submitButtonVariant = "destructive",
|
|
}: {
|
|
fields?: [name: string, value: string | number][];
|
|
children: React.ReactNode;
|
|
dialogHeading: string;
|
|
deleteButtonText?: string;
|
|
action?: string;
|
|
submitButtonTestId?: string;
|
|
submitButtonVariant?: ButtonProps["variant"];
|
|
}) {
|
|
const fetcher = useFetcher();
|
|
const { t } = useTranslation(["common"]);
|
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
const formRef = React.useRef<HTMLFormElement>(null);
|
|
const id = React.useId();
|
|
|
|
const openDialog = () => setDialogOpen(true);
|
|
const closeDialog = () => setDialogOpen(false);
|
|
|
|
invariant(React.isValidElement(children));
|
|
|
|
return (
|
|
<>
|
|
<fetcher.Form
|
|
id={id}
|
|
className="hidden"
|
|
ref={formRef}
|
|
method="post"
|
|
action={action}
|
|
>
|
|
{fields?.map(([name, value]) => (
|
|
<input type="hidden" key={name} name={name} value={value} />
|
|
))}
|
|
</fetcher.Form>
|
|
<Dialog isOpen={dialogOpen} close={closeDialog} className="text-center">
|
|
<div className="stack md">
|
|
<h2 className="text-sm">{dialogHeading}</h2>
|
|
<div className="stack horizontal md justify-center">
|
|
<SubmitButton
|
|
form={id}
|
|
variant={submitButtonVariant}
|
|
testId={dialogOpen ? "confirm-button" : submitButtonTestId}
|
|
>
|
|
{deleteButtonText ?? t("common:actions.delete")}
|
|
</SubmitButton>
|
|
<Button onClick={closeDialog}>{t("common:actions.cancel")}</Button>
|
|
</div>
|
|
</div>
|
|
</Dialog>
|
|
{React.cloneElement(children, {
|
|
// @ts-expect-error broke with @types/react upgrade. TODO: figure out narrower type than React.ReactNode
|
|
onClick: openDialog,
|
|
})}
|
|
</>
|
|
);
|
|
}
|