Feat/new UI (#153)

* wip

* feat: make forms functional

* feat: finalize pages

* chore: remove unused translations

* feat: app context

* feat: user context

* feat: finalize username login

* fix: use correct tab order in login form

* feat: add oauth logic

* chore: update readme and assets

* chore: rename docs back to assets

* feat: favicons

* feat: custom background image config option

* chore: add acknowledgements for background image

* feat: sanitize redirect URL

* feat: sanitize redirect URL on check

* chore: fix dependabot config

* refactor: bot suggestions

* fix: correctly redirect to app and check for untrusted redirects

* fix: run oauth auto redirect only when there is a redirect URI

* refactor: change select color

* fix: fix dockerfiles

* fix: fix hook rendering

* chore: remove translations cdn

* chore: formatting

* feat: validate api response against zod schema

* fix: use axios error instead of generic error in login page
This commit is contained in:
Stavros
2025-05-20 17:17:12 +03:00
committed by GitHub
parent 4d061db29a
commit 318f00993e
84 changed files with 3012 additions and 6009 deletions

View File

@@ -1,40 +1,54 @@
import { Button, PinInput } from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { z } from "zod";
import { Form, FormControl, FormField, FormItem } from "../ui/form";
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "../ui/input-otp";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { totpSchema, TotpSchema } from "@/schemas/totp-schema";
const schema = z.object({
code: z.string(),
});
type FormValues = z.infer<typeof schema>;
interface TotpFormProps {
onSubmit: (values: FormValues) => void;
isPending: boolean;
interface Props {
formId: string;
onSubmit: (code: TotpSchema) => void;
loading?: boolean;
}
export const TotpForm = (props: TotpFormProps) => {
const { onSubmit, isPending } = props;
export const TotpForm = (props: Props) => {
const { formId, onSubmit, loading } = props;
const form = useForm({
mode: "uncontrolled",
initialValues: {
code: "",
},
validate: zodResolver(schema),
const form = useForm<TotpSchema>({
resolver: zodResolver(totpSchema),
});
return (
<form onSubmit={form.onSubmit(onSubmit)}>
<PinInput
length={6}
type={"number"}
placeholder=""
{...form.getInputProps("code")}
/>
<Button type="submit" mt="xl" loading={isPending} fullWidth>
Verify
</Button>
</form>
<Form {...form}>
<form id={formId} onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="code"
render={({ field }) => (
<FormItem>
<FormControl>
<InputOTP maxLength={6} disabled={loading} {...field}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
</FormControl>
</FormItem>
)}
/>
</form>
</Form>
);
};