Customizable fonts
This commit is contained in:
@@ -12,6 +12,7 @@ import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import FontPicker from 'react-fontpicker-ts';
|
||||
import { cardClasses, switchClasses, textClasses, textInputClasses } from 'styles';
|
||||
import type { PersonalData } from 'types';
|
||||
|
||||
@@ -20,25 +21,44 @@ const PersonalizationSettings = () => {
|
||||
const { data: personalData, isFetching: personalDataIsFetching } = useQueryAPI({
|
||||
endpoint: endpoint,
|
||||
});
|
||||
const [personal, setPersonal] = useState<PersonalData>(personalData?.[0] || {});
|
||||
const personal: PersonalData = personalData?.[0] || {};
|
||||
const [wolEnabled, setWolEnabled] = useState<boolean>(personal?.enableWol === 1);
|
||||
const [guacamoleEnabled, setGuacamoleEnabled] = useState<boolean>(
|
||||
personal?.enableGuacamole === 1,
|
||||
);
|
||||
const [defaultFont, setDefaultFont] = useState<string>(personal?.defaultFont);
|
||||
const [update, setUpdate] = useState<any>({});
|
||||
const [debounced] = useDebouncedValue(update, 1000);
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(debounced).length) {
|
||||
setPersonal(update);
|
||||
mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced });
|
||||
setUpdate({});
|
||||
}
|
||||
}, [debounced]);
|
||||
|
||||
useEffect(() => {
|
||||
if (update !== personal && Object.keys(update).length) {
|
||||
setPersonal(update);
|
||||
if (Object.keys(personal).length > 0) {
|
||||
setWolEnabled(personal.enableWol === 1);
|
||||
setGuacamoleEnabled(personal.enableGuacamole === 1);
|
||||
setDefaultFont(personal.defaultFont);
|
||||
}
|
||||
}, [update]);
|
||||
}, [personal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
Object.keys(personal).length > 0 &&
|
||||
defaultFont &&
|
||||
defaultFont !== personal.defaultFont
|
||||
) {
|
||||
setUpdate({
|
||||
...personal,
|
||||
defaultFont: defaultFont,
|
||||
});
|
||||
}
|
||||
}, [defaultFont]);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<SettingsHeader
|
||||
@@ -76,163 +96,229 @@ const PersonalizationSettings = () => {
|
||||
}}
|
||||
/>
|
||||
<Grid w={'75%'}>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card className={cardClasses.settingsItem} classNames={cardClasses} pt={0}>
|
||||
<TextInput
|
||||
label={'First Name'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.firstName}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
firstName: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card className={cardClasses.settingsItem} classNames={cardClasses} pt={0}>
|
||||
<TextInput
|
||||
label={'Last Name'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.lastName}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
lastName: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card className={cardClasses.settingsItem} classNames={cardClasses} pt={0}>
|
||||
<TextInput
|
||||
label={'Email'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.email}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
email: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={12}>
|
||||
<Card className={cardClasses.settingsItem} classNames={cardClasses} pt={0}>
|
||||
<TextInput
|
||||
label={'Physical Address'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.physicalAddress}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
physicalAddress: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
{Object.keys(personal).length > 0 && (
|
||||
<>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
pt={0}
|
||||
>
|
||||
<TextInput
|
||||
label={'First Name'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.firstName}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
firstName: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
pt={0}
|
||||
>
|
||||
<TextInput
|
||||
label={'Last Name'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.lastName}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
lastName: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={isMobile ? 12 : 4}>
|
||||
<Card
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
pt={0}
|
||||
>
|
||||
<TextInput
|
||||
label={'Email'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.email}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
email: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={12}>
|
||||
<Card
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
pt={0}
|
||||
>
|
||||
<TextInput
|
||||
label={'Nickname'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.nickname || ''}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
nickname: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={12}>
|
||||
<Card
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
pt={0}
|
||||
>
|
||||
<TextInput
|
||||
label={'Physical Address'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.physicalAddress}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
physicalAddress: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridCol span={12}>
|
||||
<Card
|
||||
w={'100%'}
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
style={{ overflow: 'visible' }}
|
||||
>
|
||||
<Stack w={'100%'} px={16}>
|
||||
<Text
|
||||
top={-12}
|
||||
className={textClasses.currentTheme}
|
||||
classNames={textClasses}
|
||||
>
|
||||
Extras
|
||||
</Text>
|
||||
<Text>Font Select</Text>
|
||||
{defaultFont && (
|
||||
<FontPicker
|
||||
autoLoad
|
||||
defaultValue={defaultFont || 'Jost'}
|
||||
value={(font: string) => setDefaultFont(font)}
|
||||
/>
|
||||
)}
|
||||
<Switch
|
||||
label={'Enable Wake on LAN'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={wolEnabled}
|
||||
onChange={(event) => {
|
||||
setWolEnabled(!wolEnabled);
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableWol: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
label={'Enable Guacamole Clients'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={guacamoleEnabled}
|
||||
onChange={(event) => {
|
||||
setGuacamoleEnabled(!guacamoleEnabled);
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableGuacamole: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
{personal?.enableGuacamole === 1 && (
|
||||
<TextInput
|
||||
label={'Guacamole Host'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.guacamoleHost}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
guacamoleHost: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: {
|
||||
boxShadow: '2px 2px var(--mantine-color-border-0)',
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
</GridCol>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<Card
|
||||
w={'75%'}
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
style={{ overflow: 'visible' }}
|
||||
>
|
||||
<Stack w={'100%'} px={16}>
|
||||
<Text top={-12} className={textClasses.currentTheme} classNames={textClasses}>
|
||||
Extras
|
||||
</Text>
|
||||
<Switch
|
||||
label={'Enable Wake on LAN'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={personal?.enableWol === 1}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableWol: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
label={'Enable Guacamole Clients'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={personal?.enableGuacamole === 1}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableGuacamole: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
{personal?.enableGuacamole === 1 && (
|
||||
<TextInput
|
||||
label={'Guacamole Host'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.guacamoleHost}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
guacamoleHost: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user