Files
Homarr/src/pages/user/preferences.tsx

149 lines
4.4 KiB
TypeScript
Raw Normal View History

import { Button, Group, Select, Stack, Text, Title } from '@mantine/core';
import { createFormContext } from '@mantine/form';
import type { InferGetServerSidePropsType } from 'next';
import { GetServerSidePropsContext } from 'next';
import { forwardRef } from 'react';
import { z } from 'zod';
import { AccessibilitySettings } from '~/components/Settings/Customization/Accessibility/AccessibilitySettings';
2023-07-30 15:33:43 +02:00
import { MainLayout } from '~/components/layout/admin/main-admin.layout';
2023-07-30 16:30:48 +02:00
import { CommonHeader } from '~/components/layout/common-header';
import { languages } from '~/tools/language';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { RouterOutputs, api } from '~/utils/api';
import { useI18nZodResolver } from '~/utils/i18n-zod-resolver';
import { updateSettingsValidationSchema } from '~/validations/user';
const PreferencesPage = ({ locale }: InferGetServerSidePropsType<typeof getServerSideProps>) => {
const { data } = api.user.getWithSettings.useQuery();
2023-07-29 14:49:44 +02:00
2023-07-30 15:33:43 +02:00
return (
<MainLayout>
2023-07-30 16:30:48 +02:00
<CommonHeader>
2023-07-30 15:33:43 +02:00
<title>Preferences Homarr</title>
2023-07-30 16:30:48 +02:00
</CommonHeader>
<Title mb="xl">Preferences</Title>
{data && <SettingsComponent settings={data.settings} />}
2023-07-30 15:33:43 +02:00
</MainLayout>
);
};
2023-07-29 14:49:44 +02:00
export const [FormProvider, useFormContext, useForm] =
createFormContext<z.infer<typeof updateSettingsValidationSchema>>();
const SettingsComponent = ({
settings,
}: {
settings: RouterOutputs['user']['getWithSettings']['settings'];
}) => {
const languagesData = languages.map((language) => ({
image: 'https://img.icons8.com/clouds/256/000000/futurama-bender.png',
label: language.originalName,
description: language.translatedName,
value: language.shortName,
country: language.country,
}));
const { i18nZodResolver } = useI18nZodResolver();
const form = useForm({
initialValues: {
disablePingPulse: settings.disablePingPulse,
replaceDotsWithIcons: settings.replacePingWithIcons,
language: settings.language,
},
validate: i18nZodResolver(updateSettingsValidationSchema),
validateInputOnBlur: true,
validateInputOnChange: true,
});
const { mutate } = api.user.updateSettings.useMutation();
const handleSubmit = () => {
mutate(form.values);
};
return (
<FormProvider form={form}>
<form onSubmit={form.onSubmit(handleSubmit)}>
<Stack spacing={5}>
<Title order={2} size="lg">
Localization
</Title>
<Select
label="Language"
itemComponent={SelectItem}
data={languagesData}
searchable
maxDropdownHeight={400}
filter={(value, item) =>
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
item.description.toLowerCase().includes(value.toLowerCase().trim())
}
defaultValue={settings.language}
withAsterisk
mb="xs"
{...form.getInputProps('language')}
/>
<Select
label="First day of the week"
data={[
{ value: 'monday', label: 'Monday' },
{ value: 'sunday', label: 'Sunday' },
{ value: 'saturday', label: 'Saturday' },
]}
/>
<Title order={2} size="lg" mt="lg" mb="md">
Accessibility
</Title>
<AccessibilitySettings />
<Button type="submit" fullWidth mt="md">
Save
</Button>
</Stack>
</form>
</FormProvider>
);
};
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
image: string;
label: string;
description: string;
country: string;
}
const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
({ image, label, description, country, ...others }: ItemProps, ref) => (
<div ref={ref} {...others}>
<Group noWrap>
<span className={`fi fi-${country?.toLowerCase()}`}></span>
<div>
<Text size="sm">{label}</Text>
<Text size="xs" opacity={0.65}>
{description}
</Text>
</div>
</Group>
</div>
)
);
export async function getServerSideProps({ req, res, locale }: GetServerSidePropsContext) {
const translations = await getServerSideTranslations([], locale, undefined, undefined);
return {
props: {
...translations,
locale: locale,
},
};
}
2023-07-30 15:33:43 +02:00
export default PreferencesPage;