mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
refactor(settings-modal): align avatar settings UI with crypto wallets
Refactor avatar settings to match crypto wallets UI structure and styling. Use flexbox layout for consistent spacing, align input widths, use ErrorDisplay component for errors, and add delete avatar functionality with translations.
This commit is contained in:
@@ -26,61 +26,94 @@
|
||||
}
|
||||
|
||||
.avatarSettingsForm {
|
||||
padding: 10px 0 15px 10px;
|
||||
padding: 5px 0 15px 10px;
|
||||
}
|
||||
|
||||
.avatarSettingsForm input {
|
||||
width: 200px;
|
||||
.settingField {
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.settingField input {
|
||||
flex: 0 1 200px;
|
||||
min-width: 0;
|
||||
max-width: 200px;
|
||||
padding: 2px;
|
||||
margin-left: 5px;
|
||||
box-shadow: var(--box-shadow-input);
|
||||
}
|
||||
|
||||
.avatarSettingInput input {
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
.settingField[class*='step']::before {
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
.avatarSettingInput a {
|
||||
color: var(--link-primary);
|
||||
.settingField.step1::before {
|
||||
content: '1.\00a0';
|
||||
}
|
||||
|
||||
.avatarSettingInput a {
|
||||
.settingField.step2::before {
|
||||
content: '2.\00a0';
|
||||
}
|
||||
|
||||
.settingField.step3::before {
|
||||
content: '3.\00a0';
|
||||
}
|
||||
|
||||
.settingField.step4::before {
|
||||
content: '4.\00a0';
|
||||
}
|
||||
|
||||
.settingField a {
|
||||
color: var(--post-link-text-color);
|
||||
text-decoration: var(--post-content-link-text-decoration);
|
||||
}
|
||||
|
||||
.avatarSettingInput a:hover {
|
||||
.settingField a:hover {
|
||||
color: var(--post-link-text-color-hover);
|
||||
text-decoration: var(--post-content-link-text-decoration-hover);
|
||||
}
|
||||
|
||||
.settingTitle {
|
||||
font-style: italic;
|
||||
text-transform: lowercase;
|
||||
font-style: inherit;
|
||||
text-transform: none;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.copyMessage {
|
||||
padding-bottom: 10px;
|
||||
.timestampfield {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.pasteSignature span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pasteSignature button {
|
||||
.buttons {
|
||||
margin-top: 10px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.save {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.state {
|
||||
text-transform: lowercase;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
max-width: 300px;
|
||||
color: var(--post-mobile-abbr-text-color);
|
||||
}
|
||||
|
||||
.copyMessage a {
|
||||
color: var(--text-primary);
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.copyMessage a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.deleteAvatarContainer {
|
||||
margin-top: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.removeAvatar {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { setAccount, useAccount, useAuthorAvatar } from '@plebbit/plebbit-react-
|
||||
import styles from './avatar-settings.module.css';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import LoadingEllipsis from '../../loading-ellipsis';
|
||||
import ErrorDisplay from '../../error-display/error-display';
|
||||
import _ from 'lodash';
|
||||
|
||||
const AvatarPreview = ({ avatar }: any) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -31,7 +33,7 @@ const AvatarPreview = ({ avatar }: any) => {
|
||||
</div>
|
||||
{state !== 'succeeded' && account?.author?.avatar && (
|
||||
<div className={styles.state}>
|
||||
{!error && stateText} {error && error?.message}
|
||||
{!error && stateText} {error && <ErrorDisplay error={error} />}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
@@ -111,15 +113,26 @@ const AvatarSettings = () => {
|
||||
return alert(t('missing_signature'));
|
||||
}
|
||||
setAccount({ ...account, author: { ...account?.author, avatar } });
|
||||
alert(`saved`);
|
||||
alert(t('saved'));
|
||||
};
|
||||
|
||||
const _removeAvatar = () => {
|
||||
if (window.confirm(t('delete_confirm', { value: 'avatar', interpolation: { escapeValue: false } }))) {
|
||||
setAccount({ ...account, author: { ...account?.author, avatar: undefined } });
|
||||
setChainTicker(undefined);
|
||||
setTokenAddress(undefined);
|
||||
setTokenId(undefined);
|
||||
setTimestamp(undefined);
|
||||
setSignature(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.avatarSettings}>
|
||||
<AvatarPreview avatar={avatar} />
|
||||
<div className={styles.avatarSettingsForm}>
|
||||
<div className={styles.avatarSettingInput}>
|
||||
<span className={styles.settingTitle}>{t('chain_ticker')}</span>
|
||||
<div className={`${styles.settingField} ${styles.step1}`}>
|
||||
<span className={styles.settingTitle}>{_.capitalize(t('chain_ticker'))}: </span>
|
||||
<input
|
||||
type='text'
|
||||
placeholder='eth/sol/avax'
|
||||
@@ -130,7 +143,7 @@ const AvatarSettings = () => {
|
||||
onChange={(e) => setChainTicker(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.avatarSettingInput}>
|
||||
<div className={`${styles.settingField} ${styles.step2}`}>
|
||||
<span className={styles.settingTitle}>
|
||||
<Trans
|
||||
i18nKey='token_address_whitelist'
|
||||
@@ -146,6 +159,7 @@ const AvatarSettings = () => {
|
||||
),
|
||||
}}
|
||||
/>
|
||||
:{' '}
|
||||
</span>
|
||||
<input
|
||||
type='text'
|
||||
@@ -157,43 +171,33 @@ const AvatarSettings = () => {
|
||||
onChange={(e) => setTokenAddress(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.avatarSettingInput}>
|
||||
<span className={styles.settingTitle}>{t('token_id')}</span>
|
||||
<input
|
||||
type='text'
|
||||
placeholder='Token ID'
|
||||
autoCorrect='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
defaultValue={account?.author?.avatar?.id}
|
||||
onChange={(e) => setTokenId(e.target.value)}
|
||||
/>
|
||||
<div className={`${styles.settingField} ${styles.step3}`}>
|
||||
<span className={styles.settingTitle}>
|
||||
<Trans
|
||||
i18nKey='copy_message_etherscan'
|
||||
values={{ copy: hasCopied ? t('copied') : t('copy') }}
|
||||
components={{
|
||||
1: <button key='copy-message-button' onClick={copyMessageToSign} />,
|
||||
// eslint-disable-next-line
|
||||
2: <a key='etherscan-link' href='https://etherscan.io/verifiedSignatures' target='_blank' rel='noopener noreferrer' />,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.copyMessage}>
|
||||
<Trans
|
||||
i18nKey='copy_message_etherscan'
|
||||
values={{ copy: hasCopied ? t('copied') : t('copy') }}
|
||||
components={{
|
||||
1: <button key='copy-message-button' onClick={copyMessageToSign} />,
|
||||
// eslint-disable-next-line
|
||||
2: <a key='etherscan-link' href='https://etherscan.io/verifiedSignatures' target='_blank' rel='noopener noreferrer' />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.avatarSettingInput}>
|
||||
<span className={styles.settingTitle}>{t('timestamp')}</span>
|
||||
<div className={styles.settingField}>
|
||||
<span className={`${styles.settingTitle} ${styles.timestampfield}`}>{_.capitalize(t('timestamp'))}: </span>
|
||||
<input
|
||||
type='text'
|
||||
placeholder='Timestamp'
|
||||
autoCorrect='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
value={timestamp}
|
||||
value={timestamp || ''}
|
||||
onChange={(e) => setTimestamp(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.pasteSignature}>
|
||||
<span className={styles.settingTitle}>{t('paste_signature')}</span>
|
||||
<div className={`${styles.settingField} ${styles.step4}`}>
|
||||
<span className={styles.settingTitle}>{_.capitalize(t('paste_signature'))}: </span>
|
||||
<input
|
||||
type='text'
|
||||
placeholder='0x...'
|
||||
@@ -203,7 +207,16 @@ const AvatarSettings = () => {
|
||||
defaultValue={account?.author?.avatar?.signature?.signature}
|
||||
onChange={(e) => setSignature(e.target.value)}
|
||||
/>
|
||||
<button onClick={save}>{t('save')}</button>
|
||||
</div>
|
||||
<div className={styles.buttons}>
|
||||
<button className={styles.save} onClick={save}>
|
||||
{t('save_changes')}
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles.deleteAvatarContainer}>
|
||||
<button className={styles.removeAvatar} onClick={_removeAvatar}>
|
||||
{t('delete_avatar')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+9
-2
@@ -52,9 +52,16 @@
|
||||
content: '5. ';
|
||||
}
|
||||
|
||||
.walletField input {
|
||||
width: 200px;
|
||||
.walletField {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.settingField input {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
padding: 2px;
|
||||
margin-left: 5px;
|
||||
box-shadow: var(--box-shadow-input);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user