Presupuestador_web/client/src/app/settings/edit.tsx

286 lines
9.6 KiB
TypeScript

import { ErrorOverlay, FormTextAreaField, LoadingOverlay } from "@/components";
import {
Alert,
AlertDescription,
AlertTitle,
Button,
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
Form,
} from "@/ui";
import { t } from "i18next";
import { AlertCircleIcon } from "lucide-react";
import { useMemo, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { Trans } from "react-i18next";
import { useUnsavedChangesNotifier } from "@/lib/hooks";
import { cn } from "@/lib/utils";
import { IUpdateProfile_Request_DTO } from "@shared/contexts";
import { toast } from "react-toastify";
import { useSettings } from "./hooks";
type SettingsDataForm = IUpdateProfile_Request_DTO;
export const SettingsEditor = () => {
const [activeSection, setActiveSection] = useState("profile");
const { useOne, useUpdate } = useSettings();
const { data, status, error: queryError } = useOne();
const defaultValues = useMemo(
() => ({
contact_information: "",
default_payment_method: "",
default_notes: "",
default_legal_terms: "",
default_quote_validity: "",
}),
[]
);
const { mutate } = useUpdate();
const form = useForm<SettingsDataForm>({
mode: "onBlur",
values: data?.dealer,
defaultValues,
//defaultValues: _defaultValues,
/*resolver: joiResolver(
Joi.object({
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
password: Joi.string().min(4).alphanum().required(),
}),
{
messages: SpanishJoiMessages,
}
),*/
});
const { formState, reset, getValues, handleSubmit } = form;
const { isSubmitting, isDirty } = formState;
useUnsavedChangesNotifier({
isDirty,
});
const onSubmit: SubmitHandler<SettingsDataForm> = async (data) => {
mutate(data, {
onError: (error) => {
console.debug(error);
toast.error(error.message);
//alert(error.message);
},
//onSettled: () => {},
onSuccess: () => {
reset(getValues());
toast("Ajustes guardados");
},
});
};
if (isSubmitting) {
return <LoadingOverlay title='Guardando ajustes' />;
}
if (status === "error") {
return <ErrorOverlay errorMessage={queryError.message} />;
}
if (status !== "success") {
return <LoadingOverlay />;
}
return (
<>
<div className='grid w-full max-w-6xl gap-2 mx-auto'>
<h1 className='text-2xl font-semibold md:text-3xl'>
<Trans i18nKey='settings.edit.title' />
</h1>
</div>
<Form {...form}>
<form onSubmit={handleSubmit(onSubmit)}>
<div className='mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]'>
{form.formState.errors.root?.message && (
<Alert variant='destructive'>
<AlertCircleIcon className='w-4 h-4' />
<AlertTitle>
<Trans i18nKey='common.error' />
</AlertTitle>
<AlertDescription>{form.formState.errors.root?.message}</AlertDescription>
</Alert>
)}
<nav className='grid gap-4 text-sm text-muted-foreground'>
<a
onClick={() => setActiveSection("profile")}
className={
activeSection === "profile" ? "font-semibold text-primary" : "cursor-pointer"
}
>
<Trans i18nKey='settings.edit.tabs.profile' />
</a>
<a
onClick={() => setActiveSection("quotes")}
className={
activeSection === "quotes" ? "font-semibold text-primary" : "cursor-pointer "
}
>
<Trans i18nKey='settings.edit.tabs.quotes' />
</a>
<a
onClick={() => setActiveSection("legal")}
className={
activeSection === "legal" ? "font-semibold text-primary" : "cursor-pointer "
}
>
<Trans i18nKey='settings.edit.tabs.legal' />
</a>
</nav>
<div className={cn("grid gap-6", activeSection === "profile" ? "visible" : "hidden")}>
<Card>
<CardHeader>
<CardTitle>
<Trans i18nKey='settings.form_fields.contact_information.label' />
</CardTitle>
<CardDescription>
<Trans i18nKey='settings.form_fields.contact_information.desc' />
</CardDescription>
</CardHeader>
<CardContent>
<FormTextAreaField
autoSize
placeholder={t("settings.form_fields.contact_information.placeholder")}
{...form.register("contact_information", {
required: true,
})}
errors={form.formState.errors}
/>
</CardContent>
<CardFooter className='px-6 py-4 border-t'>
<Button>
<Trans i18nKey='common.save' />
</Button>
</CardFooter>
</Card>
</div>
<div className={cn("grid gap-6", activeSection === "quotes" ? "visible" : "hidden")}>
<Card>
<CardHeader>
<CardTitle>
<Trans i18nKey='settings.form_fields.default_payment_method.label' />
</CardTitle>
<CardDescription>
<Trans i18nKey='settings.form_fields.default_payment_method.desc' />
</CardDescription>
</CardHeader>
<CardContent>
<FormTextAreaField
autoSize
placeholder={t("settings.form_fields.default_payment_method.placeholder")}
{...form.register("default_payment_method", {
required: true,
})}
errors={form.formState.errors}
/>
</CardContent>
<CardFooter className='px-6 py-4 border-t'>
<Button>
<Trans i18nKey='common.save' />
</Button>
</CardFooter>
</Card>
<Card>
<CardHeader>
<CardTitle>
<Trans i18nKey='settings.form_fields.default_quote_validity.label' />
</CardTitle>
<CardDescription>
<Trans i18nKey='settings.form_fields.default_quote_validity.desc' />
</CardDescription>
</CardHeader>
<CardContent>
<FormTextAreaField
autoSize
placeholder={t("settings.form_fields.default_quote_validity.placeholder")}
{...form.register("default_quote_validity", {
required: true,
})}
errors={form.formState.errors}
/>
</CardContent>
<CardFooter className='px-6 py-4 border-t'>
<Button>
<Trans i18nKey='common.save' />
</Button>
</CardFooter>
</Card>
<Card>
<CardHeader>
<CardTitle>
<Trans i18nKey='settings.form_fields.default_notes.label' />
</CardTitle>
<CardDescription>
<Trans i18nKey='settings.form_fields.default_notes.desc' />
</CardDescription>
</CardHeader>
<CardContent>
<FormTextAreaField
autoSize
placeholder={t("settings.form_fields.default_notes.placeholder")}
{...form.register("default_notes", {
required: true,
})}
errors={form.formState.errors}
/>
</CardContent>
<CardFooter className='px-6 py-4 border-t'>
<Button>
<Trans i18nKey='common.save' />
</Button>
</CardFooter>
</Card>
</div>
<div className={cn("grid gap-6", activeSection === "legal" ? "visible" : "hidden")}>
<Card>
<CardHeader>
<CardTitle>
<Trans i18nKey='settings.form_fields.default_legal_terms.label' />
</CardTitle>
<CardDescription>
<Trans i18nKey='settings.form_fields.default_legal_terms.desc' />
</CardDescription>
</CardHeader>
<CardContent>
<FormTextAreaField
autoSize
placeholder={t("settings.form_fields.default_legal_terms.placeholder")}
{...form.register("default_legal_terms", {
required: true,
})}
errors={form.formState.errors}
/>
</CardContent>
<CardFooter className='px-6 py-4 border-t'>
<Button>
<Trans i18nKey='common.save' />
</Button>
</CardFooter>
</Card>
</div>
</div>
</form>
</Form>
</>
);
};