mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-09 04:02:40 -05:00
* Add types * Delete stuff * wip * findAllBetweenTwoTimestamps refactor * wip * wip * wip * wip * wip * wip * wip * Fixes * wip * wip * Fix InfoPopover button styling * wip * wip * wip * Merge branch 'rewrite' into new-calendar * wip * wip * wip * wip * Rename myform -> sendouform * wip * wip * wip * wip * wip * wip * wip * wip * wip * rename * fix test
76 lines
1.9 KiB
TypeScript
76 lines
1.9 KiB
TypeScript
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { useFetcher } from "@remix-run/react";
|
|
import * as React from "react";
|
|
import { type DefaultValues, FormProvider, useForm } from "react-hook-form";
|
|
import { useTranslation } from "react-i18next";
|
|
import type { z } from "zod";
|
|
import { logger } from "~/utils/logger";
|
|
import type { ActionError } from "~/utils/remix.server";
|
|
import { LinkButton } from "../Button";
|
|
import { SubmitButton } from "../SubmitButton";
|
|
|
|
export function SendouForm<T extends z.ZodTypeAny>({
|
|
schema,
|
|
defaultValues,
|
|
heading,
|
|
children,
|
|
cancelLink,
|
|
}: {
|
|
schema: T;
|
|
defaultValues?: DefaultValues<z.infer<T>>;
|
|
heading?: string;
|
|
children: React.ReactNode;
|
|
cancelLink?: string;
|
|
}) {
|
|
const { t } = useTranslation(["common"]);
|
|
const fetcher = useFetcher<any>();
|
|
const methods = useForm({
|
|
resolver: zodResolver(schema),
|
|
defaultValues,
|
|
});
|
|
|
|
if (methods.formState.isSubmitted && methods.formState.errors) {
|
|
logger.error(methods.formState.errors);
|
|
}
|
|
|
|
React.useEffect(() => {
|
|
if (!fetcher.data?.isError) return;
|
|
|
|
const error = fetcher.data as ActionError;
|
|
|
|
methods.setError(error.field as any, {
|
|
message: error.msg,
|
|
});
|
|
}, [fetcher.data, methods.setError]);
|
|
|
|
const onSubmit = React.useCallback(
|
|
methods.handleSubmit((values) =>
|
|
fetcher.submit(values, { method: "post", encType: "application/json" }),
|
|
),
|
|
[],
|
|
);
|
|
|
|
return (
|
|
<FormProvider {...methods}>
|
|
<fetcher.Form className="stack md-plus items-start" onSubmit={onSubmit}>
|
|
{heading ? <h1 className="text-lg">{heading}</h1> : null}
|
|
{children}
|
|
<div className="stack horizontal lg justify-between mt-6 w-full">
|
|
<SubmitButton state={fetcher.state}>
|
|
{t("common:actions.submit")}
|
|
</SubmitButton>
|
|
{cancelLink ? (
|
|
<LinkButton
|
|
variant="minimal-destructive"
|
|
to={cancelLink}
|
|
size="tiny"
|
|
>
|
|
{t("common:actions.cancel")}
|
|
</LinkButton>
|
|
) : null}
|
|
</div>
|
|
</fetcher.Form>
|
|
</FormProvider>
|
|
);
|
|
}
|