2022-01-01 20:42:25 +01:00
|
|
|
import { useState, useEffect } from 'react'
|
2021-10-24 06:09:43 +02:00
|
|
|
import Image from 'next/image'
|
2022-01-01 20:42:25 +01:00
|
|
|
import { PlusIcon, MenuIcon, UsersIcon, XIcon } from '@heroicons/react/solid'
|
2022-08-28 18:26:56 +02:00
|
|
|
import classNames from 'clsx'
|
2021-10-24 06:09:43 +02:00
|
|
|
import { useMediaQuery } from 'react-responsive'
|
|
|
|
import { useSwipeable } from 'react-swipeable'
|
|
|
|
|
2022-08-31 21:44:33 +02:00
|
|
|
import type { DirectionSidebar } from './Sidebar'
|
|
|
|
import { Sidebar } from './Sidebar'
|
2022-01-07 21:21:38 +01:00
|
|
|
import { IconButton } from '../design/IconButton'
|
|
|
|
import { IconLink } from '../design/IconLink'
|
2021-10-24 06:09:43 +02:00
|
|
|
import { Guilds } from './Guilds/Guilds'
|
|
|
|
import { Divider } from '../design/Divider'
|
|
|
|
import { Members } from './Members'
|
2022-01-07 21:21:38 +01:00
|
|
|
import { useAuthentication } from '../../tools/authentication'
|
2021-10-24 06:09:43 +02:00
|
|
|
|
2022-03-05 18:22:30 +01:00
|
|
|
export interface ChannelsPath {
|
2021-10-24 06:09:43 +02:00
|
|
|
channelId: number
|
|
|
|
}
|
2022-03-05 18:22:30 +01:00
|
|
|
export interface GuildsPath {
|
|
|
|
guildId: number
|
|
|
|
}
|
|
|
|
export interface GuildsChannelsPath extends GuildsPath, ChannelsPath {}
|
|
|
|
|
|
|
|
const isGuildsChannelsPath = (path: any): path is GuildsChannelsPath => {
|
|
|
|
return path.guildId !== undefined && path.channelId !== undefined
|
|
|
|
}
|
2021-10-24 06:09:43 +02:00
|
|
|
|
2022-01-01 20:42:25 +01:00
|
|
|
export type ApplicationPath =
|
|
|
|
| '/application'
|
|
|
|
| '/application/guilds/join'
|
|
|
|
| '/application/guilds/create'
|
|
|
|
| `/application/users/${number}`
|
2022-02-19 23:20:33 +01:00
|
|
|
| `/application/users/settings`
|
2022-01-01 20:42:25 +01:00
|
|
|
| GuildsChannelsPath
|
2022-03-05 18:22:30 +01:00
|
|
|
| GuildsPath
|
2022-01-01 20:42:25 +01:00
|
|
|
|
2021-10-24 06:09:43 +02:00
|
|
|
export interface ApplicationProps {
|
2022-01-01 20:42:25 +01:00
|
|
|
path: ApplicationPath
|
|
|
|
guildLeftSidebar?: React.ReactNode
|
|
|
|
title: string
|
2021-10-24 06:09:43 +02:00
|
|
|
}
|
|
|
|
|
2022-05-12 20:35:46 +02:00
|
|
|
export const Application: React.FC<
|
|
|
|
React.PropsWithChildren<ApplicationProps>
|
|
|
|
> = (props) => {
|
2022-01-01 20:42:25 +01:00
|
|
|
const { children, path, guildLeftSidebar, title } = props
|
2021-10-24 06:09:43 +02:00
|
|
|
|
|
|
|
const { user } = useAuthentication()
|
|
|
|
|
|
|
|
const [mounted, setMounted] = useState(false)
|
|
|
|
|
|
|
|
const isMobile = useMediaQuery({
|
|
|
|
query: '(max-width: 900px)'
|
|
|
|
})
|
|
|
|
|
2022-03-21 16:12:22 +01:00
|
|
|
const [visibleSidebars, setVisibleSidebars] = useState({
|
|
|
|
left: !isMobile,
|
|
|
|
right: false
|
|
|
|
})
|
|
|
|
|
2021-10-24 06:09:43 +02:00
|
|
|
const handleToggleSidebars = (direction: DirectionSidebar): void => {
|
|
|
|
if (!isMobile) {
|
|
|
|
if (direction === 'left') {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
left: !visibleSidebars.left
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (direction === 'right') {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
right: !visibleSidebars.right
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (direction === 'right' && visibleSidebars.left) {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
left: false,
|
|
|
|
right: true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (direction === 'left' && visibleSidebars.right) {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
left: true,
|
|
|
|
right: false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (direction === 'left' && !visibleSidebars.right) {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
left: !visibleSidebars.left
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (direction === 'right' && !visibleSidebars.left) {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
right: !visibleSidebars.right
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 21:42:11 +01:00
|
|
|
const handleCloseSidebars = (): void => {
|
|
|
|
if (isMobile && (visibleSidebars.left || visibleSidebars.right)) {
|
|
|
|
return setVisibleSidebars({
|
|
|
|
left: false,
|
|
|
|
right: false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-24 06:09:43 +02:00
|
|
|
const swipeableHandlers = useSwipeable({
|
|
|
|
trackMouse: false,
|
|
|
|
trackTouch: true,
|
2022-05-12 20:35:46 +02:00
|
|
|
preventScrollOnSwipe: true,
|
2021-10-24 06:09:43 +02:00
|
|
|
onSwipedRight: () => {
|
|
|
|
if (visibleSidebars.right) {
|
|
|
|
return setVisibleSidebars({ ...visibleSidebars, right: false })
|
|
|
|
}
|
|
|
|
setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
left: true
|
|
|
|
})
|
|
|
|
},
|
|
|
|
onSwipedLeft: () => {
|
2022-04-09 11:10:34 +02:00
|
|
|
if (isGuildsChannelsPath(path)) {
|
|
|
|
if (visibleSidebars.left) {
|
|
|
|
return setVisibleSidebars({ ...visibleSidebars, left: false })
|
|
|
|
}
|
|
|
|
setVisibleSidebars({
|
|
|
|
...visibleSidebars,
|
|
|
|
right: true
|
|
|
|
})
|
2021-10-24 06:09:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
setMounted(true)
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
if (!mounted) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2022-02-19 23:20:33 +01:00
|
|
|
<header className='z-50 flex h-16 items-center justify-between bg-gray-200 px-2 py-3 shadow-lg dark:bg-gray-800'>
|
2021-10-24 06:09:43 +02:00
|
|
|
<IconButton
|
2022-02-19 23:20:33 +01:00
|
|
|
className='h-10 w-10 p-2'
|
2022-08-31 21:44:33 +02:00
|
|
|
onClick={() => {
|
|
|
|
return handleToggleSidebars('left')
|
|
|
|
}}
|
2021-10-24 06:09:43 +02:00
|
|
|
>
|
|
|
|
{!visibleSidebars.left ? <MenuIcon /> : <XIcon />}
|
|
|
|
</IconButton>
|
2022-01-01 20:42:25 +01:00
|
|
|
<div
|
|
|
|
data-cy='application-title'
|
2022-02-19 23:20:33 +01:00
|
|
|
className='text-md font-semibold text-green-800 dark:text-green-400'
|
2022-01-01 20:42:25 +01:00
|
|
|
>
|
2021-10-24 06:09:43 +02:00
|
|
|
{title}
|
|
|
|
</div>
|
|
|
|
<div className='flex space-x-2'>
|
|
|
|
{title.startsWith('#') && (
|
|
|
|
<IconButton
|
2022-01-01 20:42:25 +01:00
|
|
|
data-cy='icon-button-right-sidebar-members'
|
2022-02-19 23:20:33 +01:00
|
|
|
className='h-10 w-10 p-2'
|
2022-08-31 21:44:33 +02:00
|
|
|
onClick={() => {
|
|
|
|
return handleToggleSidebars('right')
|
|
|
|
}}
|
2021-10-24 06:09:43 +02:00
|
|
|
>
|
|
|
|
{!visibleSidebars.right ? <UsersIcon /> : <XIcon />}
|
|
|
|
</IconButton>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
|
|
|
|
<main
|
2022-02-19 23:20:33 +01:00
|
|
|
className='h-full-without-header relative flex overflow-hidden'
|
2021-10-24 06:09:43 +02:00
|
|
|
{...swipeableHandlers}
|
|
|
|
>
|
|
|
|
<Sidebar
|
|
|
|
direction='left'
|
|
|
|
visible={visibleSidebars.left}
|
|
|
|
isMobile={isMobile}
|
|
|
|
>
|
2022-02-19 23:20:33 +01:00
|
|
|
<div className='top-0 left-0 z-50 flex min-w-[92px] flex-col space-y-4 border-r-2 border-gray-500 bg-gray-200 py-2 dark:border-white/20 dark:bg-gray-800'>
|
2021-10-24 06:09:43 +02:00
|
|
|
<IconLink
|
2022-02-19 23:20:33 +01:00
|
|
|
href={`/application/users/settings`}
|
|
|
|
selected={path === `/application/users/settings`}
|
2021-10-24 06:09:43 +02:00
|
|
|
title='Settings'
|
|
|
|
>
|
|
|
|
<Image
|
2022-04-07 16:54:05 +02:00
|
|
|
quality={100}
|
2021-10-24 06:09:43 +02:00
|
|
|
className='rounded-full'
|
2021-10-26 16:38:55 +02:00
|
|
|
src={
|
|
|
|
user.logo == null
|
|
|
|
? '/images/data/user-default.png'
|
2022-04-08 20:59:04 +02:00
|
|
|
: user.logo
|
2021-10-26 16:38:55 +02:00
|
|
|
}
|
2022-01-01 20:42:25 +01:00
|
|
|
alt={"Users's profil picture"}
|
|
|
|
draggable={false}
|
2021-10-24 06:09:43 +02:00
|
|
|
width={48}
|
|
|
|
height={48}
|
|
|
|
/>
|
|
|
|
</IconLink>
|
|
|
|
<IconLink
|
|
|
|
href='/application'
|
|
|
|
selected={path === '/application'}
|
|
|
|
title='Join or create a Guild'
|
|
|
|
>
|
2022-02-19 23:20:33 +01:00
|
|
|
<PlusIcon className='h-12 w-12 text-green-800 dark:text-green-400' />
|
2021-10-24 06:09:43 +02:00
|
|
|
</IconLink>
|
|
|
|
<Divider />
|
|
|
|
<Guilds path={path} />
|
|
|
|
</div>
|
2022-01-01 20:42:25 +01:00
|
|
|
{guildLeftSidebar}
|
2021-10-24 06:09:43 +02:00
|
|
|
</Sidebar>
|
|
|
|
|
|
|
|
<div
|
2021-11-13 21:50:34 +01:00
|
|
|
id='application-page-content'
|
2022-03-21 21:42:11 +01:00
|
|
|
onClick={handleCloseSidebars}
|
2021-10-24 06:09:43 +02:00
|
|
|
className={classNames(
|
2022-04-09 13:48:48 +02:00
|
|
|
'h-full-without-header relative top-0 z-0 flex w-full flex-1 flex-col overflow-y-auto transition',
|
2021-10-24 06:09:43 +02:00
|
|
|
{
|
|
|
|
'absolute opacity-20':
|
|
|
|
isMobile && (visibleSidebars.left || visibleSidebars.right)
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
|
2022-03-05 18:22:30 +01:00
|
|
|
{isGuildsChannelsPath(path) && (
|
2022-01-01 20:42:25 +01:00
|
|
|
<Sidebar
|
|
|
|
direction='right'
|
|
|
|
visible={visibleSidebars.right}
|
|
|
|
isMobile={isMobile}
|
|
|
|
>
|
|
|
|
<Members />
|
|
|
|
</Sidebar>
|
|
|
|
)}
|
2021-10-24 06:09:43 +02:00
|
|
|
</main>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|