Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
25261b54ef | |||
0028974c3b | |||
4141f1eeab | |||
5ef8f18060 | |||
8bb4ef8b54 | |||
32f2edd7fc | |||
4799acbc29 | |||
0d6aa0a78f |
@ -18,7 +18,7 @@
|
||||
|
||||
Thream's website to stay close with your friends and communities.
|
||||
|
||||
It uses [Thream/api](https://github.com/Thream/api) [v1.0.0](https://github.com/Thream/api/releases/tag/v1.0.0).
|
||||
It uses [Thream/api](https://github.com/Thream/api) [v1.0.1](https://github.com/Thream/api/releases/tag/v1.0.1).
|
||||
|
||||
## ⚙️ Getting Started
|
||||
|
||||
|
@ -121,13 +121,15 @@ export const Application: React.FC<ApplicationProps> = (props) => {
|
||||
})
|
||||
},
|
||||
onSwipedLeft: () => {
|
||||
if (visibleSidebars.left) {
|
||||
return setVisibleSidebars({ ...visibleSidebars, left: false })
|
||||
if (isGuildsChannelsPath(path)) {
|
||||
if (visibleSidebars.left) {
|
||||
return setVisibleSidebars({ ...visibleSidebars, left: false })
|
||||
}
|
||||
setVisibleSidebars({
|
||||
...visibleSidebars,
|
||||
right: true
|
||||
})
|
||||
}
|
||||
setVisibleSidebars({
|
||||
...visibleSidebars,
|
||||
right: true
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { useRouter } from 'next/router'
|
||||
import { useState } from 'react'
|
||||
import { Form } from 'react-component-form'
|
||||
import useTranslation from 'next-translate/useTranslation'
|
||||
import axios from 'axios'
|
||||
|
||||
import { HandleSubmitCallback, useForm } from '../../../hooks/useForm'
|
||||
import { FormState } from '../../design/FormState'
|
||||
@ -81,7 +82,11 @@ export const ChannelSettings: React.FC<ChannelSettingsProps> = (props) => {
|
||||
await router.push(`/application/${guild.id}/${data.defaultChannelId}`)
|
||||
} catch (error) {
|
||||
setFetchState('error')
|
||||
setMessageTranslationKey('errors:server-error')
|
||||
if (axios.isAxiosError(error) && error.response?.status === 400) {
|
||||
setMessageTranslationKey('application:delete-channel-only-one')
|
||||
} else {
|
||||
setMessageTranslationKey('errors:server-error')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,84 +16,94 @@ export const UserProfile: React.FC<UserProfileProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className='relative flex h-full flex-col items-center justify-center'>
|
||||
<div className='transition'>
|
||||
<div className='max-w-[1000px] px-12'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex w-max items-center'>
|
||||
<div className='relative flex items-center justify-center overflow-hidden rounded-full shadow-lg transition-all'>
|
||||
<Image
|
||||
quality={100}
|
||||
className='rounded-full'
|
||||
src={
|
||||
user.logo != null
|
||||
? user.logo
|
||||
: '/images/data/user-default.png'
|
||||
}
|
||||
alt='Profil Picture'
|
||||
draggable='false'
|
||||
height={125}
|
||||
width={125}
|
||||
/>
|
||||
</div>
|
||||
<div className='ml-10 flex flex-col'>
|
||||
<div className='mb-2 flex items-center'>
|
||||
<p
|
||||
className='space text-dark text-3xl font-bold tracking-wide dark:text-white'
|
||||
data-cy='user-name'
|
||||
>
|
||||
{user.name}
|
||||
</p>
|
||||
<p
|
||||
className='ml-8 select-none text-sm tracking-widest text-white opacity-40'
|
||||
data-cy='user-createdAt'
|
||||
>
|
||||
{date.format(new Date(user.createdAt), 'DD/MM/YYYY')}
|
||||
</p>
|
||||
<>
|
||||
<div className='relative flex h-full flex-col items-center justify-center'>
|
||||
<div className='transition'>
|
||||
<div className='max-w-[1000px] px-12'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex w-max flex-col items-center gap-7 md:flex-row'>
|
||||
<div className='relative flex items-center justify-center overflow-hidden rounded-full shadow-lg transition-all'>
|
||||
<Image
|
||||
quality={100}
|
||||
className='rounded-full'
|
||||
src={
|
||||
user.logo != null
|
||||
? user.logo
|
||||
: '/images/data/user-default.png'
|
||||
}
|
||||
alt='Profil Picture'
|
||||
draggable='false'
|
||||
height={125}
|
||||
width={125}
|
||||
/>
|
||||
</div>
|
||||
<div className='my-2 text-left'>
|
||||
{user.email != null && (
|
||||
<p className='font-bold'>
|
||||
Email:{' '}
|
||||
<a
|
||||
href={`mailto:${user.email}`}
|
||||
target='_blank'
|
||||
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-1px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
|
||||
rel='noreferrer'
|
||||
data-cy='user-email'
|
||||
>
|
||||
{user.email}
|
||||
</a>
|
||||
<div className='ml-10 flex flex-col'>
|
||||
<div className='mb-2 flex items-center'>
|
||||
<p
|
||||
className='space text-dark text-3xl font-bold tracking-wide dark:text-white'
|
||||
data-cy='user-name'
|
||||
>
|
||||
{user.name}
|
||||
</p>
|
||||
)}
|
||||
{user.website != null && (
|
||||
<p className='font-bold'>
|
||||
{t('application:website')}:{' '}
|
||||
<a
|
||||
href={user.website}
|
||||
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-2px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
|
||||
>
|
||||
{user.website}
|
||||
</a>
|
||||
<p
|
||||
className='ml-8 select-none text-sm tracking-widest text-white opacity-40'
|
||||
data-cy='user-createdAt'
|
||||
>
|
||||
{date.format(new Date(user.createdAt), 'DD/MM/YYYY')}
|
||||
</p>
|
||||
)}
|
||||
{user.status != null && (
|
||||
<p className='flex font-bold'>
|
||||
{t('application:status')}:{' '}
|
||||
<span className='ml-2 font-normal tracking-wide'>
|
||||
{user.status}
|
||||
</span>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className='my-2 text-left'>
|
||||
{user.email != null && (
|
||||
<p className='font-bold'>
|
||||
Email:{' '}
|
||||
<a
|
||||
href={`mailto:${user.email}`}
|
||||
target='_blank'
|
||||
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-1px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
|
||||
rel='noreferrer'
|
||||
data-cy='user-email'
|
||||
>
|
||||
{user.email}
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
{user.website != null && (
|
||||
<p className='font-bold'>
|
||||
{t('application:website')}:{' '}
|
||||
<a
|
||||
href={user.website}
|
||||
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-2px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
|
||||
>
|
||||
{user.website}
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
{user.status != null && (
|
||||
<p className='flex font-bold'>
|
||||
{t('application:status')}:{' '}
|
||||
<span className='ml-2 font-normal tracking-wide'>
|
||||
{user.status}
|
||||
</span>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-7'>
|
||||
{user.biography != null && <p>{user.biography}</p>}
|
||||
{user.biography != null && (
|
||||
<div className='mt-7 text-center'>
|
||||
<p>{user.biography}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx global>{`
|
||||
#application-page-content {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -84,7 +84,10 @@ export const UserSettings: React.FC = () => {
|
||||
return {
|
||||
...oldUser,
|
||||
...userCurrentData,
|
||||
settings: userCurrentSettings.settings
|
||||
settings: {
|
||||
...oldUser.settings,
|
||||
...userCurrentSettings.settings
|
||||
}
|
||||
}
|
||||
})
|
||||
return {
|
||||
|
@ -2,8 +2,12 @@
|
||||
"website": "Website",
|
||||
"create": "Create",
|
||||
"status": "Status",
|
||||
"create-a-channel": "Create a channel",
|
||||
"delete-channel-only-one": "The guild should have at least one channel. You can't delete the only channel of the guild.",
|
||||
"create-a-guild": "Create a Guild",
|
||||
"create-a-guild-description": "Create your own guild and manage everything.",
|
||||
"user-settings": "User settings",
|
||||
"guild-settings": "Guild settings",
|
||||
"join-a-guild": "Join a Guild",
|
||||
"join-the-guild": "Join the guild",
|
||||
"join-a-guild-description": "Talk, collaborate, share and have fun with your friends by joining an already existing guild!",
|
||||
|
@ -2,8 +2,12 @@
|
||||
"website": "Site web",
|
||||
"create": "Créer",
|
||||
"status": "Statut",
|
||||
"create-a-channel": "Créer un channel",
|
||||
"delete-channel-only-one": "La guilde doit avoir au moins un channel. Vous ne pouvez pas supprimer le seul channel de la guilde.",
|
||||
"create-a-guild": "Créer une Guilde",
|
||||
"create-a-guild-description": "Créez votre propre guilde et gérez tout.",
|
||||
"user-settings": "Paramètres utilisateur",
|
||||
"guild-settings": "Paramètres de la guilde",
|
||||
"join-a-guild": "Rejoindre une Guilde",
|
||||
"join-the-guild": "Rejoindre la guilde",
|
||||
"join-a-guild-description": "Discutez, collaborez, partagez et amusez-vous avec vos amis en rejoignant une guilde déjà existante!",
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@thream/website",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@thream/website",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fontsource/montserrat": "4.5.7",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@thream/website",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -43,7 +43,7 @@ const ChannelPage: NextPage<ChannelPageProps> = (props) => {
|
||||
<MembersProviders path={path}>
|
||||
<ChannelsProvider path={path}>
|
||||
<MessagesProvider path={path}>
|
||||
<Head title='Thream | Application' />
|
||||
<Head title={`Thream | ${selectedChannel.name}`} />
|
||||
<Application
|
||||
path={path}
|
||||
guildLeftSidebar={<GuildLeftSidebar path={path} />}
|
||||
|
@ -40,7 +40,7 @@ const ChannelSettingsPage: NextPage<ChannelSettingsPageProps> = (props) => {
|
||||
<GuildMemberProvider guildMember={guildMember} path={path}>
|
||||
<MembersProviders path={path}>
|
||||
<ChannelsProvider path={path}>
|
||||
<Head title='Thream | Application' />
|
||||
<Head title={`Thream | ${selectedChannel.name}`} />
|
||||
<Application
|
||||
path={path}
|
||||
guildLeftSidebar={<GuildLeftSidebar path={path} />}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { NextPage } from 'next'
|
||||
import useTranslation from 'next-translate/useTranslation'
|
||||
|
||||
import { Head } from '../../../../components/Head'
|
||||
import { Application } from '../../../../components/Application'
|
||||
@ -21,6 +22,7 @@ export interface CreateChannelPageProps extends PagePropsWithAuthentication {
|
||||
|
||||
const CreateChannelPage: NextPage<CreateChannelPageProps> = (props) => {
|
||||
const { guildId, authentication, guildMember } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const path = { guildId }
|
||||
|
||||
@ -29,10 +31,10 @@ const CreateChannelPage: NextPage<CreateChannelPageProps> = (props) => {
|
||||
<GuildsProvider>
|
||||
<GuildMemberProvider guildMember={guildMember} path={path}>
|
||||
<Head
|
||||
title={`Thream | Crée un channel`}
|
||||
description={'Crée un nouveau channel'}
|
||||
title={`Thream | ${t('application:create-a-channel')}`}
|
||||
description={t('application:create-a-channel')}
|
||||
/>
|
||||
<Application path={path} title={'Crée un channel'}>
|
||||
<Application path={path} title={t('application:create-a-channel')}>
|
||||
<CreateChannel />
|
||||
</Application>
|
||||
</GuildMemberProvider>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { NextPage } from 'next'
|
||||
import useTranslation from 'next-translate/useTranslation'
|
||||
|
||||
import { Head } from '../../../components/Head'
|
||||
import { Application } from '../../../components/Application'
|
||||
@ -18,6 +19,7 @@ export interface GuildSettingsPageProps extends PagePropsWithAuthentication {
|
||||
|
||||
const GuildSettingsPage: NextPage<GuildSettingsPageProps> = (props) => {
|
||||
const { guildId, authentication, guildMember } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const path = { guildId }
|
||||
|
||||
@ -25,8 +27,8 @@ const GuildSettingsPage: NextPage<GuildSettingsPageProps> = (props) => {
|
||||
<AuthenticationProvider authentication={authentication}>
|
||||
<GuildsProvider>
|
||||
<GuildMemberProvider guildMember={guildMember} path={path}>
|
||||
<Head title='Thream | Guild settings' />
|
||||
<Application path={path} title='Guild settings'>
|
||||
<Head title={`Thream | ${t('application:guild-settings')}`} />
|
||||
<Application path={path} title={t('application:guild-settings')}>
|
||||
<GuildSettings />
|
||||
</Application>
|
||||
</GuildMemberProvider>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { NextPage } from 'next'
|
||||
import useTranslation from 'next-translate/useTranslation'
|
||||
|
||||
import { Head } from '../../../components/Head'
|
||||
import { Application } from '../../../components/Application'
|
||||
@ -11,11 +12,16 @@ import { UserSettings } from '../../../components/Application/UserSettings'
|
||||
import { GuildsProvider } from '../../../contexts/Guilds'
|
||||
|
||||
const UserSettingsPage: NextPage<PagePropsWithAuthentication> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<AuthenticationProvider authentication={props.authentication}>
|
||||
<GuildsProvider>
|
||||
<Head title='Thream | Settings' />
|
||||
<Application path={`/application/users/settings`} title='Settings'>
|
||||
<Head title={`Thream | ${t('application:user-settings')}`} />
|
||||
<Application
|
||||
path='/application/users/settings'
|
||||
title={t('application:user-settings')}
|
||||
>
|
||||
<UserSettings />
|
||||
</Application>
|
||||
</GuildsProvider>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export const API_VERSION = '1.0.0'
|
||||
export const API_VERSION = '1.0.1'
|
||||
|
||||
export const API_DEFAULT_PORT = 8080
|
||||
|
||||
|
@ -5,7 +5,6 @@ import useTranslation from 'next-translate/useTranslation'
|
||||
|
||||
import { Authentication, PagePropsWithAuthentication } from '.'
|
||||
import { UserCurrent } from '../../models/User'
|
||||
import { Language, Theme } from '../../models/UserSettings'
|
||||
|
||||
export interface AuthenticationValue {
|
||||
authentication: Authentication
|
||||
@ -41,14 +40,13 @@ export const AuthenticationProvider: React.FC<PagePropsWithAuthentication> = (
|
||||
useEffect(() => {
|
||||
authentication.api
|
||||
.put('/users/current/settings', { theme, language: lang })
|
||||
.then(() => {
|
||||
.then(({ data: userCurrentSettings }) => {
|
||||
setUser((oldUser) => {
|
||||
return {
|
||||
...oldUser,
|
||||
settings: {
|
||||
...oldUser.settings,
|
||||
theme: theme as Theme,
|
||||
language: lang as Language
|
||||
...userCurrentSettings.settings
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Reference in New Issue
Block a user