2022-11-24 21:37:43 +00:00
|
|
|
import { PageWrap } from '../../_shared/PageWrap'
|
2022-12-01 08:37:04 +00:00
|
|
|
import { t } from '../../../utils/intl'
|
2022-11-24 21:37:43 +00:00
|
|
|
import { Icon } from '../../_shared/Icon'
|
2022-11-28 22:14:19 +00:00
|
|
|
import ProfileSettingsNavigation from '../../Discours/ProfileSettingsNavigation'
|
2023-02-10 01:19:20 +00:00
|
|
|
import { For, createSignal, Show, onMount } from 'solid-js'
|
2022-12-01 08:37:04 +00:00
|
|
|
import { clsx } from 'clsx'
|
|
|
|
import styles from './Settings.module.scss'
|
2022-12-01 17:16:14 +00:00
|
|
|
import { useProfileForm } from '../../../context/profile'
|
2022-12-07 08:37:40 +00:00
|
|
|
import validateUrl from '../../../utils/validateUrl'
|
2023-01-31 12:14:46 +00:00
|
|
|
import { createFileUploader, UploadFile } from '@solid-primitives/upload'
|
2023-02-09 17:53:11 +00:00
|
|
|
import { Loading } from '../../Loading'
|
|
|
|
import { useSession } from '../../../context/session'
|
|
|
|
import Button from '../../_shared/Button'
|
2023-02-09 22:39:52 +00:00
|
|
|
import { useSnackbar } from '../../../context/snackbar'
|
2022-11-24 21:37:43 +00:00
|
|
|
|
2023-02-10 01:19:20 +00:00
|
|
|
const handleFileUpload = async (uploadFile: UploadFile) => {
|
|
|
|
const formData = new FormData()
|
|
|
|
formData.append('file', uploadFile.file, uploadFile.name)
|
|
|
|
const response = await fetch('/api/upload', {
|
|
|
|
method: 'POST',
|
|
|
|
body: formData
|
|
|
|
})
|
|
|
|
return response.json()
|
|
|
|
}
|
|
|
|
|
2023-02-09 17:53:11 +00:00
|
|
|
export const ProfileSettingsPage = () => {
|
|
|
|
const [addLinkForm, setAddLinkForm] = createSignal(false)
|
|
|
|
const [incorrectUrl, setIncorrectUrl] = createSignal(false)
|
|
|
|
const [isSubmitting, setIsSubmitting] = createSignal(false)
|
|
|
|
const [isUserpicUpdating, setIsUserpicUpdating] = createSignal(false)
|
2023-02-09 22:39:52 +00:00
|
|
|
|
|
|
|
const {
|
|
|
|
actions: { showSnackbar }
|
|
|
|
} = useSnackbar()
|
|
|
|
|
2023-02-09 17:53:11 +00:00
|
|
|
const {
|
|
|
|
actions: { loadSession }
|
|
|
|
} = useSession()
|
2022-12-07 08:53:41 +00:00
|
|
|
const { form, updateFormField, submit, slugError } = useProfileForm()
|
2023-02-09 17:53:11 +00:00
|
|
|
|
2023-01-26 05:30:39 +00:00
|
|
|
const handleChangeSocial = (value: string) => {
|
2022-12-07 08:37:40 +00:00
|
|
|
if (validateUrl(value)) {
|
|
|
|
updateFormField('links', value)
|
|
|
|
setAddLinkForm(false)
|
|
|
|
} else {
|
|
|
|
setIncorrectUrl(true)
|
|
|
|
}
|
2022-12-01 17:16:14 +00:00
|
|
|
}
|
2023-02-09 22:39:52 +00:00
|
|
|
|
2023-02-09 17:53:11 +00:00
|
|
|
const handleSubmit = async (event: Event) => {
|
2022-12-01 17:16:14 +00:00
|
|
|
event.preventDefault()
|
2023-02-09 17:53:11 +00:00
|
|
|
setIsSubmitting(true)
|
2023-02-09 22:39:52 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
await submit(form)
|
2023-02-10 22:10:16 +00:00
|
|
|
showSnackbar({ body: `<Icon name="success-sign"/> ${t('Profile successfully saved')}` })
|
2023-02-09 22:39:52 +00:00
|
|
|
} catch {
|
|
|
|
showSnackbar({ type: 'error', body: t('Error') })
|
|
|
|
}
|
|
|
|
|
|
|
|
loadSession()
|
2023-02-09 17:53:11 +00:00
|
|
|
setIsSubmitting(false)
|
2022-12-01 17:16:14 +00:00
|
|
|
}
|
2023-01-31 12:14:46 +00:00
|
|
|
|
|
|
|
const { selectFiles } = createFileUploader({ multiple: false, accept: 'image/*' })
|
|
|
|
|
2023-02-09 22:56:00 +00:00
|
|
|
const handleAvatarClick = async () => {
|
2023-01-31 12:14:46 +00:00
|
|
|
await selectFiles(async ([uploadFile]) => {
|
|
|
|
try {
|
2023-02-09 17:53:11 +00:00
|
|
|
setIsUserpicUpdating(true)
|
2023-01-31 12:14:46 +00:00
|
|
|
const fileUrl = await handleFileUpload(uploadFile)
|
|
|
|
updateFormField('userpic', fileUrl)
|
2023-02-09 17:53:11 +00:00
|
|
|
setIsUserpicUpdating(false)
|
2023-01-31 12:14:46 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.error('[upload avatar] error', error)
|
|
|
|
}
|
|
|
|
})
|
2022-12-02 06:12:50 +00:00
|
|
|
}
|
2023-01-28 00:31:46 +00:00
|
|
|
|
2023-02-11 11:33:32 +00:00
|
|
|
const [hostname, setHostname] = createSignal<string | null>(null)
|
2022-12-04 09:46:13 +00:00
|
|
|
onMount(() => setHostname(window?.location.host))
|
2022-12-02 06:12:50 +00:00
|
|
|
|
2022-11-24 21:37:43 +00:00
|
|
|
return (
|
|
|
|
<PageWrap>
|
2022-12-01 17:16:14 +00:00
|
|
|
<Show when={form}>
|
2022-12-01 08:37:04 +00:00
|
|
|
<div class="wide-container">
|
|
|
|
<div class="shift-content">
|
|
|
|
<div class="left-col">
|
|
|
|
<div class={clsx('left-navigation', styles.leftNavigation)}>
|
|
|
|
<ProfileSettingsNavigation />
|
|
|
|
</div>
|
2022-11-28 22:14:19 +00:00
|
|
|
</div>
|
2022-12-01 08:37:04 +00:00
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-10 col-lg-9 col-xl-8">
|
|
|
|
<h1>{t('Profile settings')}</h1>
|
|
|
|
<p class="description">{t('Here you can customize your profile the way you want.')}</p>
|
2023-02-09 17:53:11 +00:00
|
|
|
<form onSubmit={handleSubmit} enctype="multipart/form-data">
|
2022-12-01 08:37:04 +00:00
|
|
|
<h4>{t('Userpic')}</h4>
|
|
|
|
<div class="pretty-form__item">
|
|
|
|
<div class={styles.avatarContainer}>
|
2023-02-09 17:53:11 +00:00
|
|
|
<Show when={!isUserpicUpdating()} fallback={<Loading />}>
|
2023-02-09 22:56:00 +00:00
|
|
|
<img
|
|
|
|
class={styles.avatar}
|
|
|
|
src={form.userpic}
|
|
|
|
alt={form.name}
|
|
|
|
onClick={handleAvatarClick}
|
|
|
|
/>
|
2023-02-09 17:53:11 +00:00
|
|
|
</Show>
|
2022-12-01 08:37:04 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<h4>{t('Name')}</h4>
|
|
|
|
<p class="description">
|
|
|
|
{t(
|
|
|
|
'Your name will appear on your profile page and as your signature in publications, comments and responses.'
|
|
|
|
)}
|
|
|
|
</p>
|
|
|
|
<div class="pretty-form__item">
|
2022-11-24 21:37:43 +00:00
|
|
|
<input
|
2022-12-01 08:37:04 +00:00
|
|
|
type="text"
|
|
|
|
name="username"
|
|
|
|
id="username"
|
2022-12-01 17:16:14 +00:00
|
|
|
placeholder={t('Name')}
|
|
|
|
onChange={(event) => updateFormField('name', event.currentTarget.value)}
|
|
|
|
value={form.name}
|
2022-11-24 21:37:43 +00:00
|
|
|
/>
|
2022-12-02 06:40:26 +00:00
|
|
|
<label for="username">{t('Name')}</label>
|
2022-11-24 21:37:43 +00:00
|
|
|
</div>
|
|
|
|
|
2022-12-02 06:40:26 +00:00
|
|
|
<h4>{t('Address on Discourse')}</h4>
|
|
|
|
<div class="pretty-form__item">
|
|
|
|
<div class={styles.discoursName}>
|
2022-12-04 09:46:13 +00:00
|
|
|
<label for="user-address">https://{hostname()}/author/</label>
|
2022-12-02 06:40:26 +00:00
|
|
|
<div class={styles.discoursNameField}>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
name="user-address"
|
|
|
|
id="user-address"
|
|
|
|
onChange={(event) => updateFormField('slug', event.currentTarget.value)}
|
|
|
|
value={form.slug}
|
|
|
|
class="nolabel"
|
|
|
|
/>
|
2022-12-07 08:53:41 +00:00
|
|
|
<p class="form-message form-message--error">{t(`${slugError()}`)}</p>
|
2022-12-02 06:40:26 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<h4>{t('Introduce')}</h4>
|
|
|
|
<div class="pretty-form__item">
|
|
|
|
<textarea name="presentation" id="presentation" placeholder={t('Introduce')}>
|
|
|
|
{form.bio}
|
|
|
|
</textarea>
|
|
|
|
<label for="presentation">{t('Introduce')}</label>
|
|
|
|
</div>
|
2022-11-24 21:37:43 +00:00
|
|
|
|
2022-12-09 06:09:21 +00:00
|
|
|
<h4>{t('About myself')}</h4>
|
|
|
|
<div class="pretty-form__item">
|
|
|
|
<textarea
|
|
|
|
name="about"
|
|
|
|
id="about"
|
|
|
|
placeholder={t('About myself')}
|
|
|
|
value={form.about}
|
|
|
|
onChange={(event) => updateFormField('about', event.currentTarget.value)}
|
|
|
|
/>
|
|
|
|
<label for="about">{t('About myself')}</label>
|
|
|
|
</div>
|
2022-12-06 03:41:49 +00:00
|
|
|
|
2022-12-09 06:09:21 +00:00
|
|
|
{/*Нет реализации полей на бэке*/}
|
2022-12-01 17:16:14 +00:00
|
|
|
{/*<h4>{t('How can I help/skills')}</h4>*/}
|
|
|
|
{/*<div class="pretty-form__item">*/}
|
|
|
|
{/* <input type="text" name="skills" id="skills" />*/}
|
|
|
|
{/*</div>*/}
|
|
|
|
{/*<h4>{t('Where')}</h4>*/}
|
|
|
|
{/*<div class="pretty-form__item">*/}
|
|
|
|
{/* <input type="text" name="location" id="location" placeholder="Откуда" />*/}
|
|
|
|
{/* <label for="location">{t('Where')}</label>*/}
|
|
|
|
{/*</div>*/}
|
2022-12-01 08:37:04 +00:00
|
|
|
|
2022-12-01 17:16:14 +00:00
|
|
|
{/*<h4>{t('Date of Birth')}</h4>*/}
|
|
|
|
{/*<div class="pretty-form__item">*/}
|
|
|
|
{/* <input*/}
|
|
|
|
{/* type="date"*/}
|
|
|
|
{/* name="birthdate"*/}
|
|
|
|
{/* id="birthdate"*/}
|
|
|
|
{/* placeholder="Дата рождения"*/}
|
|
|
|
{/* class="nolabel"*/}
|
|
|
|
{/* />*/}
|
|
|
|
{/*</div>*/}
|
2022-12-01 08:37:04 +00:00
|
|
|
|
|
|
|
<div class={clsx(styles.multipleControls, 'pretty-form__item')}>
|
|
|
|
<div class={styles.multipleControlsHeader}>
|
|
|
|
<h4>{t('Social networks')}</h4>
|
2022-12-01 17:16:14 +00:00
|
|
|
<button type="button" class="button" onClick={() => setAddLinkForm(!addLinkForm())}>
|
|
|
|
+
|
|
|
|
</button>
|
2022-12-01 08:37:04 +00:00
|
|
|
</div>
|
2022-12-01 17:16:14 +00:00
|
|
|
<Show when={addLinkForm()}>
|
|
|
|
<div class={styles.multipleControlsItem}>
|
|
|
|
<input
|
|
|
|
autofocus={true}
|
|
|
|
type="text"
|
|
|
|
name="link"
|
|
|
|
class="nolabel"
|
|
|
|
onChange={(event) => handleChangeSocial(event.currentTarget.value)}
|
|
|
|
/>
|
|
|
|
</div>
|
2022-12-07 08:37:40 +00:00
|
|
|
<Show when={incorrectUrl()}>
|
|
|
|
<p class="form-message form-message--error">{t('It does not look like url')}</p>
|
|
|
|
</Show>
|
2022-12-01 17:16:14 +00:00
|
|
|
</Show>
|
|
|
|
<For each={form.links}>
|
2022-12-01 08:37:04 +00:00
|
|
|
{(link) => (
|
|
|
|
<div class={styles.multipleControlsItem}>
|
2022-12-01 17:16:14 +00:00
|
|
|
<input type="text" value={link} readonly={true} name="link" class="nolabel" />
|
|
|
|
<button type="button" onClick={() => updateFormField('links', link, true)}>
|
2022-12-01 08:37:04 +00:00
|
|
|
<Icon name="remove" class={styles.icon} />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
2022-11-24 21:37:43 +00:00
|
|
|
</div>
|
2022-12-01 08:37:04 +00:00
|
|
|
<br />
|
2023-02-09 17:53:11 +00:00
|
|
|
<Button type="submit" size="L" value={t('Save settings')} loading={isSubmitting()} />
|
2022-12-01 08:37:04 +00:00
|
|
|
</form>
|
|
|
|
</div>
|
2022-11-24 21:37:43 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-12-01 08:37:04 +00:00
|
|
|
</Show>
|
2022-11-24 21:37:43 +00:00
|
|
|
</PageWrap>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// for lazy loading
|
|
|
|
export default ProfileSettingsPage
|