feat: add guilds and channels CRUD (#14)

This commit is contained in:
Divlo
2022-03-05 18:22:30 +01:00
committed by GitHub
parent 9f56a10305
commit 780788d682
50 changed files with 6459 additions and 9039 deletions

View File

@ -1,9 +1,11 @@
import { createContext, useContext, useEffect } from 'react'
import { useRouter } from 'next/router'
import { NextPage, usePagination } from 'hooks/usePagination'
import { useAuthentication } from 'tools/authentication'
import { Channel } from 'models/Channel'
import { Channel, ChannelWithDefaultChannelId } from 'models/Channel'
import { GuildsChannelsPath } from 'components/Application'
import { handleSocketData, SocketData } from 'tools/handleSocketData'
export interface Channels {
channels: Channel[]
@ -20,19 +22,38 @@ export interface ChannelsProviderProps {
export const ChannelsProvider: React.FC<ChannelsProviderProps> = (props) => {
const { path, children } = props
const router = useRouter()
const { authentication } = useAuthentication()
const {
items: channels,
hasMore,
nextPage,
resetPagination
resetPagination,
setItems
} = usePagination<Channel>({
api: authentication.api,
url: `/guilds/${path.guildId}/channels`
})
useEffect(() => {
authentication.socket.on(
'channels',
async (data: SocketData<ChannelWithDefaultChannelId>) => {
handleSocketData({ data, setItems })
if (data.action === 'delete') {
await router.push(
`/application/${path.guildId}/${data.item.defaultChannelId}`
)
}
}
)
return () => {
authentication.socket.off('channels')
}
}, [authentication.socket, path.guildId, router, setItems])
useEffect(() => {
resetPagination()
nextPage()

View File

@ -1,48 +1,92 @@
import { createContext, useContext, useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { Guild } from 'models/Guild'
import { GuildWithDefaultChannelId } from 'models/Guild'
import { Member } from 'models/Member'
import { GuildsChannelsPath } from 'components/Application'
import { useAuthentication } from 'tools/authentication'
import { SocketData } from 'tools/handleSocketData'
export interface GuildMember {
guild: Guild
guild: GuildWithDefaultChannelId
member: Member
}
export interface GuildMemberResult extends GuildMember {
setGuildMember: React.Dispatch<React.SetStateAction<GuildMember>>
}
export interface GuildMemberProps {
guildMember: GuildMember
path: GuildsChannelsPath
path: {
guildId: number
}
}
const defaultGuildMemberContext = {} as any
const GuildMemberContext = createContext<GuildMember>(defaultGuildMemberContext)
const GuildMemberContext = createContext<GuildMemberResult>(
defaultGuildMemberContext
)
export const GuildMemberProvider: React.FC<GuildMemberProps> = (props) => {
const { path, children } = props
const router = useRouter()
const [guildMember, setGuildMember] = useState(props.guildMember)
const { authentication } = useAuthentication()
useEffect(() => {
const fetchGuildMember = async (): Promise<void> => {
const { data } = await authentication.api.get(
`/guilds/${props.path.guildId}`
)
const { data } = await authentication.api.get(`/guilds/${path.guildId}`)
setGuildMember(data)
}
fetchGuildMember().catch((error) => {
console.error(error)
})
}, [props.path, authentication.api])
}, [path, authentication.api])
useEffect(() => {
authentication.socket.on(
'guilds',
async (data: SocketData<GuildWithDefaultChannelId>) => {
if (data.item.id === path.guildId) {
switch (data.action) {
case 'delete':
await router.push('/application')
break
case 'update':
setGuildMember((oldGuildMember) => {
return {
...oldGuildMember,
guild: {
...oldGuildMember.guild,
...data.item
}
}
})
break
}
}
}
)
return () => {
authentication.socket.off('guilds')
}
}, [authentication.socket, path.guildId, router])
return (
<GuildMemberContext.Provider value={guildMember}>
{props.children}
<GuildMemberContext.Provider
value={{
...guildMember,
setGuildMember
}}
>
{children}
</GuildMemberContext.Provider>
)
}
export const useGuildMember = (): GuildMember => {
export const useGuildMember = (): GuildMemberResult => {
const guildMember = useContext(GuildMemberContext)
if (guildMember === defaultGuildMemberContext) {
throw new Error('useGuildMember must be used within GuildMemberProvider')

View File

@ -3,6 +3,7 @@ import { createContext, useContext, useEffect } from 'react'
import { NextPage, usePagination } from 'hooks/usePagination'
import { useAuthentication } from 'tools/authentication'
import { GuildWithDefaultChannelId } from 'models/Guild'
import { handleSocketData, SocketData } from 'tools/handleSocketData'
export interface Guilds {
guilds: GuildWithDefaultChannelId[]
@ -22,12 +23,26 @@ export const GuildsProvider: React.FC = (props) => {
items: guilds,
hasMore,
nextPage,
resetPagination
resetPagination,
setItems
} = usePagination<GuildWithDefaultChannelId>({
api: authentication.api,
url: '/guilds'
})
useEffect(() => {
authentication.socket.on(
'guilds',
(data: SocketData<GuildWithDefaultChannelId>) => {
handleSocketData({ data, setItems })
}
)
return () => {
authentication.socket.off('guilds')
}
}, [authentication.socket, setItems])
useEffect(() => {
resetPagination()
nextPage()

View File

@ -4,6 +4,8 @@ import { NextPage, usePagination } from 'hooks/usePagination'
import { useAuthentication } from 'tools/authentication'
import { MemberWithPublicUser } from 'models/Member'
import { GuildsChannelsPath } from 'components/Application'
import { handleSocketData, SocketData } from 'tools/handleSocketData'
import { User } from 'models/User'
export interface Members {
members: MemberWithPublicUser[]
@ -27,12 +29,45 @@ export const MembersProviders: React.FC<MembersProviderProps> = (props) => {
items: members,
hasMore,
nextPage,
resetPagination
resetPagination,
setItems
} = usePagination<MemberWithPublicUser>({
api: authentication.api,
url: `/guilds/${path.guildId}/members`
})
useEffect(() => {
authentication.socket.on(
'members',
(data: SocketData<MemberWithPublicUser>) => {
handleSocketData({ data, setItems })
}
)
authentication.socket.on('users', (data: SocketData<User>) => {
setItems((oldItems) => {
const newItems = [...oldItems]
switch (data.action) {
case 'update': {
for (const member of newItems) {
if (member.user.id === data.item.id) {
member.user = data.item
break
}
}
break
}
}
return newItems
})
})
return () => {
authentication.socket.off('members')
authentication.socket.off('users')
}
}, [authentication.socket, setItems])
useEffect(() => {
resetPagination()
nextPage()