refactor: update Next.js, React.js and Node.js (#815)

* refactor: update Next.js and React.js

* refactor: update Next.js images

* refactor: update ESLint rules and fix warnings/errors

* fix: remove old intl polyfill

* fix: add proper size to next/image components

* fix: adjust full-size for next/image components

* fix: temporary allow all domains for image optimization

* build: fixes an issue where dev env could lead to javascript heap out of memory

* fix: resolve webpack cache issue with country-flag-icons

* refactor: switch compiler from Babel to SWC

* fix: resize logo in sidebar

* fix: break word on long path to avoid text overflow

* chore: added sharp for production image optimisation

* fix: change extract script for i18n to a custom script

* fix: resolve GitHub CodeQL alert

* chore: temporarily remove builds for ARMv7

* fix: resize avatar images

* refactor: update Node.js to v20

* fix: resolve various UI issues

* build: migrate yarn to pnpm and restrict engine to node@^20.0.0

* ci: specify the pnpm version to use in workflow actions

* ci: fix typo in pnpm action-setup for cypress workflow

* test(cypress): use pnpm instead of yarn

* style: ran prettier on pnpm-lock

* ci(cypress): setup nodejs v20 in cypress workflow

* ci: pnpm cache to reduce install time

* ci: use sh shell to get pnpm store directory

* build(dockerfile): migrate to pnpm from yarn in docker builds

* build(dockerfile): copy the proper pnpm lockfile

* build: install pnpm for all platforms

* build(dockerfile): remove unnecessary `&&` on apk installation steps

* build: migrate pnpm 8 to 9

* build(dockerfile): add node-gyp back in

* build(dockerfile): install node-gyp through npm

* build(dockerfile): ignore scripts to not run husky install when devdependencies are pruned

* build: migrate to pnpm from yarn

* chore: remove a section that is no longer relevant

---------

Co-authored-by: fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
This commit is contained in:
Gauthier
2024-06-23 23:43:54 +02:00
committed by GitHub
parent 4fddf89084
commit 989af67c0a
172 changed files with 28147 additions and 15483 deletions

View File

@@ -1,11 +1,13 @@
import Button from '@app/components/Common/Button';
import type { User } from '@app/hooks/useUser';
import { Permission, useUser } from '@app/hooks/useUser';
import defineMessages from '@app/utils/defineMessages';
import { CogIcon, UserIcon } from '@heroicons/react/24/solid';
import Image from 'next/image';
import Link from 'next/link';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
const messages = defineMessages({
const messages = defineMessages('components.UserProfile.ProfileHeader', {
settings: 'Edit Settings',
profile: 'View Profile',
joindate: 'Joined {joindate}',
@@ -40,10 +42,12 @@ const ProfileHeader = ({ user, isSettingsPage }: ProfileHeaderProps) => {
<div className="flex items-end justify-items-end space-x-5">
<div className="flex-shrink-0">
<div className="relative">
<img
<Image
className="h-24 w-24 rounded-full bg-gray-600 object-cover ring-1 ring-gray-700"
src={user.avatar}
alt=""
width={96}
height={96}
/>
<span
className="absolute inset-0 rounded-full shadow-inner"
@@ -57,10 +61,9 @@ const ProfileHeader = ({ user, isSettingsPage }: ProfileHeaderProps) => {
href={
user.id === loggedInUser?.id ? '/profile' : `/users/${user.id}`
}
className="text-overseerr text-lg font-bold hover:to-purple-200 sm:text-2xl"
>
<a className="text-overseerr text-lg font-bold hover:to-purple-200 sm:text-2xl">
{user.displayName}
</a>
{user.displayName}
</Link>
{user.email && user.displayName.toLowerCase() !== user.email && (
<span className="text-sm text-gray-400 sm:ml-2 sm:text-lg">
@@ -88,6 +91,7 @@ const ProfileHeader = ({ user, isSettingsPage }: ProfileHeaderProps) => {
: `/users/${user.id}/settings`
}
passHref
legacyBehavior
>
<Button as="a">
<CogIcon />
@@ -101,6 +105,7 @@ const ProfileHeader = ({ user, isSettingsPage }: ProfileHeaderProps) => {
loggedInUser?.id === user.id ? `/profile` : `/users/${user.id}`
}
passHref
legacyBehavior
>
<Button as="a">
<UserIcon />

View File

@@ -12,6 +12,7 @@ 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 defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { UserSettingsGeneralResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
@@ -19,50 +20,53 @@ 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 { 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 <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> 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 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
plexwatchlistsyncseries: 'Auto-Request Series',
plexwatchlistsyncseriestip:
'Automatically request series on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserGeneralSettings',
{
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 <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> 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 <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
plexwatchlistsyncseries: 'Auto-Request Series',
plexwatchlistsyncseriestip:
'Automatically request series on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
}
);
const UserGeneralSettings = () => {
const intl = useIntl();

View File

@@ -3,24 +3,28 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
discordsettingssaved: 'Discord notification settings saved successfully!',
discordsettingsfailed: 'Discord notification settings failed to save.',
discordId: 'User ID',
discordIdTip:
'The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your user account',
validationDiscordId: 'You must provide a valid user ID',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
discordsettingssaved: 'Discord notification settings saved successfully!',
discordsettingsfailed: 'Discord notification settings failed to save.',
discordId: 'User ID',
discordIdTip:
'The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your user account',
validationDiscordId: 'You must provide a valid user ID',
}
);
const UserNotificationsDiscord = () => {
const intl = useIntl();

View File

@@ -8,24 +8,28 @@ import { OpenPgpLink } from '@app/components/Settings/Notifications/Notification
import SettingsBadge from '@app/components/Settings/SettingsBadge';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
emailsettingssaved: 'Email notification settings saved successfully!',
emailsettingsfailed: 'Email notification settings failed to save.',
pgpPublicKey: 'PGP Public Key',
pgpPublicKeyTip:
'Encrypt email messages using <OpenPgpLink>OpenPGP</OpenPgpLink>',
validationPgpPublicKey: 'You must provide a valid PGP public key',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
emailsettingssaved: 'Email notification settings saved successfully!',
emailsettingsfailed: 'Email notification settings failed to save.',
pgpPublicKey: 'PGP Public Key',
pgpPublicKeyTip:
'Encrypt email messages using <OpenPgpLink>OpenPGP</OpenPgpLink>',
validationPgpPublicKey: 'You must provide a valid PGP public key',
}
);
const UserEmailSettings = () => {
const intl = useIntl();

View File

@@ -4,24 +4,29 @@ import SensitiveInput from '@app/components/Common/SensitiveInput';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
pushbulletsettingssaved:
'Pushbullet notification settings saved successfully!',
pushbulletsettingsfailed: 'Pushbullet notification settings failed to save.',
pushbulletAccessToken: 'Access Token',
pushbulletAccessTokenTip:
'Create a token from your <PushbulletSettingsLink>Account Settings</PushbulletSettingsLink>',
validationPushbulletAccessToken: 'You must provide an access token',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
pushbulletsettingssaved:
'Pushbullet notification settings saved successfully!',
pushbulletsettingsfailed:
'Pushbullet notification settings failed to save.',
pushbulletAccessToken: 'Access Token',
pushbulletAccessTokenTip:
'Create a token from your <PushbulletSettingsLink>Account Settings</PushbulletSettingsLink>',
validationPushbulletAccessToken: 'You must provide an access token',
}
);
const UserPushbulletSettings = () => {
const intl = useIntl();

View File

@@ -4,31 +4,35 @@ import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import useSettings from '@app/hooks/useSettings';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import type { PushoverSound } from '@server/api/pushover';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
pushoverApplicationToken: 'Application API Token',
pushoverApplicationTokenTip:
'<ApplicationRegistrationLink>Register an application</ApplicationRegistrationLink> for use with {applicationTitle}',
pushoverUserKey: 'User or Group Key',
pushoverUserKeyTip:
'Your 30-character <UsersGroupsLink>user or group identifier</UsersGroupsLink>',
sound: 'Notification Sound',
deviceDefault: 'Device Default',
validationPushoverApplicationToken:
'You must provide a valid application token',
validationPushoverUserKey: 'You must provide a valid user or group key',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
pushoverApplicationToken: 'Application API Token',
pushoverApplicationTokenTip:
'<ApplicationRegistrationLink>Register an application</ApplicationRegistrationLink> for use with {applicationTitle}',
pushoverUserKey: 'User or Group Key',
pushoverUserKeyTip:
'Your 30-character <UsersGroupsLink>user or group identifier</UsersGroupsLink>',
sound: 'Notification Sound',
deviceDefault: 'Device Default',
validationPushoverApplicationToken:
'You must provide a valid application token',
validationPushoverUserKey: 'You must provide a valid user or group key',
}
);
const UserPushoverSettings = () => {
const intl = useIntl();

View File

@@ -3,26 +3,30 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
telegramChatId: 'Chat ID',
telegramChatIdTipLong:
'<TelegramBotLink>Start a chat</TelegramBotLink>, add <GetIdBotLink>@get_id_bot</GetIdBotLink>, and issue the <code>/my_id</code> command',
sendSilently: 'Send Silently',
sendSilentlyDescription: 'Send notifications with no sound',
validationTelegramChatId: 'You must provide a valid chat ID',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
telegramChatId: 'Chat ID',
telegramChatIdTipLong:
'<TelegramBotLink>Start a chat</TelegramBotLink>, add <GetIdBotLink>@get_id_bot</GetIdBotLink>, and issue the <code>/my_id</code> command',
sendSilently: 'Send Silently',
sendSilentlyDescription: 'Send notifications with no sound',
validationTelegramChatId: 'You must provide a valid chat ID',
}
);
const UserTelegramSettings = () => {
const intl = useIntl();

View File

@@ -5,19 +5,23 @@ import NotificationTypeSelector, {
} from '@app/components/NotificationTypeSelector';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import axios from 'axios';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR, { mutate } from 'swr';
const messages = defineMessages({
webpushsettingssaved: 'Web push notification settings saved successfully!',
webpushsettingsfailed: 'Web push notification settings failed to save.',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
webpushsettingssaved: 'Web push notification settings saved successfully!',
webpushsettingsfailed: 'Web push notification settings failed to save.',
}
);
const UserWebPushSettings = () => {
const intl = useIntl();

View File

@@ -9,18 +9,22 @@ import SettingsTabs from '@app/components/Common/SettingsTabs';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { CloudIcon, EnvelopeIcon } from '@heroicons/react/24/solid';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const messages = defineMessages({
notifications: 'Notifications',
notificationsettings: 'Notification Settings',
email: 'Email',
webpush: 'Web Push',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserNotificationSettings',
{
notifications: 'Notifications',
notificationsettings: 'Notification Settings',
email: 'Email',
webpush: 'Web Push',
}
);
type UserNotificationSettingsProps = {
children: React.ReactNode;

View File

@@ -6,37 +6,41 @@ import SensitiveInput from '@app/components/Common/SensitiveInput';
import { Permission, useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
password: 'Password',
currentpassword: 'Current Password',
newpassword: 'New Password',
confirmpassword: 'Confirm Password',
toastSettingsSuccess: 'Password saved successfully!',
toastSettingsFailure: 'Something went wrong while saving the password.',
toastSettingsFailureVerifyCurrent:
'Something went wrong while saving the password. Was your current password entered correctly?',
validationCurrentPassword: 'You must provide your current password',
validationNewPassword: 'You must provide a new password',
validationNewPasswordLength:
'Password is too short; should be a minimum of 8 characters',
validationConfirmPassword: 'You must confirm the new password',
validationConfirmPasswordSame: 'Passwords must match',
noPasswordSet:
'This user account currently does not have a password set. Configure a password below to enable this account to sign in as a "local user."',
noPasswordSetOwnAccount:
'Your account currently does not have a password set. Configure a password below to enable sign-in as a "local user" using your email address.',
nopermissionDescription:
"You do not have permission to modify this user's password.",
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserPasswordChange',
{
password: 'Password',
currentpassword: 'Current Password',
newpassword: 'New Password',
confirmpassword: 'Confirm Password',
toastSettingsSuccess: 'Password saved successfully!',
toastSettingsFailure: 'Something went wrong while saving the password.',
toastSettingsFailureVerifyCurrent:
'Something went wrong while saving the password. Was your current password entered correctly?',
validationCurrentPassword: 'You must provide your current password',
validationNewPassword: 'You must provide a new password',
validationNewPasswordLength:
'Password is too short; should be a minimum of 8 characters',
validationConfirmPassword: 'You must confirm the new password',
validationConfirmPasswordSame: 'Passwords must match',
noPasswordSet:
'This user account currently does not have a password set. Configure a password below to enable this account to sign in as a "local user."',
noPasswordSetOwnAccount:
'Your account currently does not have a password set. Configure a password below to enable sign-in as a "local user" using your email address.',
nopermissionDescription:
"You do not have permission to modify this user's password.",
}
);
const UserPasswordChange = () => {
const intl = useIntl();

View File

@@ -6,20 +6,24 @@ import PermissionEdit from '@app/components/PermissionEdit';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
const messages = defineMessages({
toastSettingsSuccess: 'Permissions saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
permissions: 'Permissions',
unauthorizedDescription: 'You cannot modify your own permissions.',
});
const messages = defineMessages(
'components.UserProfile.UserSettings.UserPermissions',
{
toastSettingsSuccess: 'Permissions saved successfully!',
toastSettingsFailure: 'Something went wrong while saving settings.',
permissions: 'Permissions',
unauthorizedDescription: 'You cannot modify your own permissions.',
}
);
const UserPermissions = () => {
const intl = useIntl();

View File

@@ -8,13 +8,14 @@ import useSettings from '@app/hooks/useSettings';
import { useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
import { hasPermission, Permission } from '@server/lib/permissions';
import { useRouter } from 'next/router';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.UserProfile.UserSettings', {
menuGeneralSettings: 'General',
menuChangePass: 'Password',
menuNotifications: 'Notifications',

View File

@@ -8,6 +8,7 @@ import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
import ProfileHeader from '@app/components/UserProfile/ProfileHeader';
import { Permission, UserType, useUser } from '@app/hooks/useUser';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { ArrowRightCircleIcon } from '@heroicons/react/24/outline';
import type { WatchlistResponse } from '@server/interfaces/api/discoverInterfaces';
import type {
@@ -20,10 +21,10 @@ import type { TvDetails } from '@server/models/Tv';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useCallback, useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.UserProfile', {
recentrequests: 'Recent Requests',
limit: '{remaining} of {limit}',
requestsperdays: '{limit} remaining',
@@ -164,7 +165,7 @@ const UserProfile = () => {
: `/users/${user?.id}/requests?filter=all`
}
>
<a>{intl.formatNumber(user.requestCount)}</a>
{intl.formatNumber(user.requestCount)}
</Link>
</dd>
</div>
@@ -296,11 +297,10 @@ const UserProfile = () => {
? '/profile/requests?filter=all'
: `/users/${user?.id}/requests?filter=all`
}
className="slider-title"
>
<a className="slider-title">
<span>{intl.formatMessage(messages.recentrequests)}</span>
<ArrowRightCircleIcon />
</a>
<span>{intl.formatMessage(messages.recentrequests)}</span>
<ArrowRightCircleIcon />
</Link>
</div>
<Slider
@@ -336,11 +336,10 @@ const UserProfile = () => {
? '/profile/watchlist'
: `/users/${user.id}/watchlist`
}
className="slider-title"
>
<a className="slider-title">
<span>{watchlistSliderTitle}</span>
<ArrowRightCircleIcon />
</a>
<span>{watchlistSliderTitle}</span>
<ArrowRightCircleIcon />
</Link>
</div>
<Slider