import { createContext, useContext, useEffect, useState } from 'react' import { useRouter } from 'next/router' import type { GuildWithDefaultChannelId } from '../models/Guild' import type { Member } from '../models/Member' import { useAuthentication } from '../tools/authentication' import type { SocketData } from '../tools/handleSocketData' export interface GuildMember { guild: GuildWithDefaultChannelId member: Member } export interface GuildMemberResult extends GuildMember {} export interface GuildMemberProps { guildMember: GuildMember path: { guildId: number } } const defaultGuildMemberContext = {} as any const GuildMemberContext = createContext( defaultGuildMemberContext ) export const GuildMemberProvider: React.FC< React.PropsWithChildren > = (props) => { const { path, children } = props const router = useRouter() const [guildMember, setGuildMember] = useState(props.guildMember) const { authentication } = useAuthentication() useEffect(() => { const fetchGuildMember = async (): Promise => { const { data } = await authentication.api.get(`/guilds/${path.guildId}`) setGuildMember(data) } fetchGuildMember().catch((error) => { console.error(error) }) }, [path, authentication.api]) useEffect(() => { authentication?.socket?.on( 'guilds', async (data: SocketData) => { 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 ( {children} ) } export const useGuildMember = (): GuildMemberResult => { const guildMember = useContext(GuildMemberContext) if (guildMember === defaultGuildMemberContext) { throw new Error( '`useGuildMember` must be used within `GuildMemberProvider`' ) } return guildMember }