import Badge from '@app/components/Common/Badge'; import Button from '@app/components/Common/Button'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import LanguageSelector from '@app/components/LanguageSelector'; import QuotaSelector from '@app/components/QuotaSelector'; import RegionSelector from '@app/components/RegionSelector'; import type { AvailableLocale } from '@app/context/LanguageContext'; import { availableLanguages } from '@app/context/LanguageContext'; import useLocale from '@app/hooks/useLocale'; import useSettings from '@app/hooks/useSettings'; import { Permission, UserType, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import Error from '@app/pages/_error'; import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline'; import type { UserSettingsGeneralResponse } from '@server/interfaces/api/userSettingsInterfaces'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import getConfig from 'next/config'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; import * as Yup from 'yup'; const messages = defineMessages({ general: 'General', generalsettings: 'General Settings', displayName: 'Display Name', email: 'Email', save: 'Save Changes', saving: 'Saving…', mediaServerUser: '{mediaServerName} User', accounttype: 'Account Type', plexuser: 'Plex User', localuser: 'Local User', role: 'Role', owner: 'Owner', admin: 'Admin', user: 'User', toastSettingsSuccess: 'Settings saved successfully!', toastSettingsFailure: 'Something went wrong while saving settings.', region: 'Discover Region', regionTip: 'Filter content by regional availability', originallanguage: 'Discover Language', originallanguageTip: 'Filter content by original language', movierequestlimit: 'Movie Request Limit', seriesrequestlimit: 'Series Request Limit', enableOverride: 'Override Global Limit', applanguage: 'Display Language', languageDefault: 'Default ({language})', discordId: 'Discord User ID', discordIdTip: 'The multi-digit ID number associated with your Discord user account', validationemailrequired: 'Email required', validationemailformat: 'Valid email required', validationDiscordId: 'You must provide a valid Discord user ID', plexwatchlistsyncmovies: 'Auto-Request Movies', plexwatchlistsyncmoviestip: 'Automatically request movies on your Plex Watchlist', plexwatchlistsyncseries: 'Auto-Request Series', plexwatchlistsyncseriestip: 'Automatically request series on your Plex Watchlist', }); const UserGeneralSettings = () => { const intl = useIntl(); const { publicRuntimeConfig } = getConfig(); const { addToast } = useToasts(); const { locale, setLocale } = useLocale(); const [movieQuotaEnabled, setMovieQuotaEnabled] = useState(false); const [tvQuotaEnabled, setTvQuotaEnabled] = useState(false); const router = useRouter(); const { user, hasPermission, revalidate: revalidateUser, } = useUser({ id: Number(router.query.userId), }); const { user: currentUser, hasPermission: currentHasPermission } = useUser(); const { currentSettings } = useSettings(); const { data, error, mutate: revalidate, } = useSWR( user ? `/api/v1/user/${user?.id}/settings/main` : null ); const UserGeneralSettingsSchema = Yup.object().shape({ email: Yup.string() .email(intl.formatMessage(messages.validationemailformat)) .required(intl.formatMessage(messages.validationemailrequired)), discordId: Yup.string() .nullable() .matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)), }); useEffect(() => { setMovieQuotaEnabled( data?.movieQuotaLimit != undefined && data?.movieQuotaDays != undefined ); setTvQuotaEnabled( data?.tvQuotaLimit != undefined && data?.tvQuotaDays != undefined ); }, [data]); if (!data && !error) { return ; } if (!data) { return ; } return ( <>

{intl.formatMessage(messages.generalsettings)}

{ try { await axios.post(`/api/v1/user/${user?.id}/settings/main`, { username: values.displayName, email: values.email, discordId: values.discordId, locale: values.locale, region: values.region, originalLanguage: values.originalLanguage, movieQuotaLimit: movieQuotaEnabled ? values.movieQuotaLimit : null, movieQuotaDays: movieQuotaEnabled ? values.movieQuotaDays : null, tvQuotaLimit: tvQuotaEnabled ? values.tvQuotaLimit : null, tvQuotaDays: tvQuotaEnabled ? values.tvQuotaDays : null, watchlistSyncMovies: values.watchlistSyncMovies, watchlistSyncTv: values.watchlistSyncTv, }); if (currentUser?.id === user?.id && setLocale) { setLocale( (values.locale ? values.locale : currentSettings.locale) as AvailableLocale ); } addToast(intl.formatMessage(messages.toastSettingsSuccess), { autoDismiss: true, appearance: 'success', }); } catch (e) { addToast(intl.formatMessage(messages.toastSettingsFailure), { autoDismiss: true, appearance: 'error', }); } finally { revalidate(); revalidateUser(); } }} > {({ errors, touched, isSubmitting, isValid, values, setFieldValue, }) => { return (
{user?.userType === UserType.PLEX ? ( {intl.formatMessage(messages.plexuser)} ) : user?.userType === UserType.LOCAL ? ( {intl.formatMessage(messages.localuser)} ) : publicRuntimeConfig.JELLYFIN_TYPE == 'emby' ? ( {intl.formatMessage(messages.mediaServerUser, { mediaServerName: 'Emby', })} ) : user?.userType === UserType.JELLYFIN ? ( {intl.formatMessage(messages.mediaServerUser, { mediaServerName: 'Jellyfin', })} ) : null}
{user?.id === 1 ? intl.formatMessage(messages.owner) : hasPermission(Permission.ADMIN) ? intl.formatMessage(messages.admin) : intl.formatMessage(messages.user)}
{errors.displayName && touched.displayName && typeof errors.displayName === 'string' && (
{errors.displayName}
)}
w === 'userEmailRequired') ? 'border-2 border-red-400 focus:border-blue-600' : '' } />
{errors.email && touched.email && (
{errors.email}
)}
{errors.discordId && touched.discordId && typeof errors.discordId === 'string' && (
{errors.discordId}
)}
{( Object.keys( availableLanguages ) as (keyof typeof availableLanguages)[] ).map((key) => ( ))}
{currentHasPermission(Permission.MANAGE_USERS) && !hasPermission(Permission.MANAGE_USERS) && ( <>
setMovieQuotaEnabled((s) => !s)} /> {intl.formatMessage(messages.enableOverride)}
setTvQuotaEnabled((s) => !s)} /> {intl.formatMessage(messages.enableOverride)}
)} {hasPermission( [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_MOVIE], { type: 'or' } ) && user?.userType === UserType.PLEX && (
{ setFieldValue( 'watchlistSyncMovies', !values.watchlistSyncMovies ); }} />
)} {hasPermission( [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_TV], { type: 'or' } ) && user?.userType === UserType.PLEX && (
{ setFieldValue( 'watchlistSyncTv', !values.watchlistSyncTv ); }} />
)}
); }}
); }; export default UserGeneralSettings;