diff --git a/.changeset/irc-display-nickname.md b/.changeset/irc-display-nickname.md
new file mode 100644
index 00000000..8d38ce8e
--- /dev/null
+++ b/.changeset/irc-display-nickname.md
@@ -0,0 +1,11 @@
+---
+"fuelrats.com": minor
+---
+
+Add ability to set IRC display nickname in user profile
+
+Users can now choose which of their registered IRC nicknames appears as their primary display name. In the IRC Nicknames section of your profile:
+
+- A filled star indicates your current display nickname
+- Click the outline star next to any other nickname to set it as your new display nickname
+- Hover over the star icons for helpful tooltips
\ No newline at end of file
diff --git a/package.json b/package.json
index 42efe0bb..48a687be 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"@fingerprintjs/fingerprintjs": "^3.3.1",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
+ "@fortawesome/free-regular-svg-icons": "^7.0.1",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@fuelrats/next-adorable-avatars": "^0.4.0",
diff --git a/src/components/UserNicknamesPanel/NicknameErrorBox.js b/src/components/UserNicknamesPanel/NicknameErrorBox.js
new file mode 100644
index 00000000..2ced900f
--- /dev/null
+++ b/src/components/UserNicknamesPanel/NicknameErrorBox.js
@@ -0,0 +1,38 @@
+import { HttpStatus } from '@fuelrats/web-util/http'
+import PropTypes from 'prop-types'
+
+import ApiErrorBox from '~/components/MessageBox/ApiErrorBox'
+
+
+function getErrorText (error) {
+ switch (error.code) {
+ case HttpStatus.CONFLICT:
+ return 'Nickname already registered.'
+
+ case HttpStatus.NOT_FOUND:
+ return 'Nickname not found or no longer exists.'
+
+ case HttpStatus.UNPROCESSABLE_ENTITY:
+ return 'Nickname format is invalid.'
+
+ default:
+ return undefined
+ }
+}
+
+function NicknameErrorBox (props) {
+ const { error } = props
+
+ if (!error) {
+ return null
+ }
+
+ return ()
+}
+
+NicknameErrorBox.propTypes = {
+ error: PropTypes.object,
+}
+
+
+export default NicknameErrorBox
diff --git a/src/components/UserNicknamesPanel/UserNicknamesPanel.js b/src/components/UserNicknamesPanel/UserNicknamesPanel.js
index 4e30f188..72528764 100644
--- a/src/components/UserNicknamesPanel/UserNicknamesPanel.js
+++ b/src/components/UserNicknamesPanel/UserNicknamesPanel.js
@@ -1,19 +1,18 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { HttpStatus } from '@fuelrats/web-util/http'
-import { isError } from 'flux-standard-action'
import { useCallback, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import ConfirmActionButton from '~/components/ConfirmActionButton'
import AddNicknameForm from '~/components/Forms/AddNicknameForm/AddNicknameForm'
-import MessageBox from '~/components/MessageBox'
-import { deleteNickname } from '~/store/actions/user'
+import { deleteNickname, setDisplayNickname, getUserProfile } from '~/store/actions/user'
import {
selectUserById,
withCurrentUserId,
selectNicknamesByUserId,
} from '~/store/selectors'
+import getResponseError from '~/util/getResponseError'
+import NicknameErrorBox from './NicknameErrorBox'
import styles from './UserNicknamesPanel.module.scss'
@@ -34,28 +33,38 @@ function UserNicknamesPanel () {
const user = useSelector(withCurrentUserId(selectUserById))
const handleDeleteNickname = useCallback(async (event) => {
+ setError(null)
const response = await dispatch(deleteNickname(user, nicknames.find((nick) => {
return nick.id === event.target.name
})))
- if (isError(response)) {
- const { meta, payload } = response
- let errorMessage = 'Unknown error occurred.'
+ const responseError = getResponseError(response)
+ if (responseError) {
+ setError(responseError)
+ return responseError
+ }
- if (HttpStatus.isClientError(meta.response.status)) {
- errorMessage = payload.errors?.length ? payload.errors[0].detail : 'Client communication error'
- }
+ return true
+ }, [dispatch, nicknames, user])
- if (HttpStatus.isServerError(meta.response.status)) {
- errorMessage = 'Server communication error'
- }
+ const handleSetDisplayNickname = useCallback(async (event) => {
+ setError(null)
+ const nickname = nicknames.find((nick) => {
+ return nick.id === event.target.name
+ })
- setError(errorMessage)
- return errorMessage
+ const response = await dispatch(setDisplayNickname(nickname.id, nickname.attributes.nick))
+
+ const responseError = getResponseError(response)
+ if (responseError) {
+ setError(responseError)
+ return responseError
}
- return undefined
- }, [dispatch, nicknames, user])
+ // Refresh user profile to get updated nicknames
+ await dispatch(getUserProfile())
+ return true
+ }, [dispatch, nicknames])
const nickCount = nicknames?.length
const maxNicksReached = (nickCount >= MAX_NICKS)
@@ -72,7 +81,7 @@ function UserNicknamesPanel () {
{
error && (
-
{error}
+
)
}