diff --git a/components/Application/Channels/Channel/Channel.stories.tsx b/components/Application/Channels/Channel/Channel.stories.tsx new file mode 100644 index 0000000..8c3fd2f --- /dev/null +++ b/components/Application/Channels/Channel/Channel.stories.tsx @@ -0,0 +1,16 @@ +import { Meta, Story } from '@storybook/react' +import { channelExample } from 'cypress/fixtures/channels/channel' + +import { Channel as Component, ChannelProps } from './Channel' + +const Stories: Meta = { + title: 'Channel', + component: Component +} + +export default Stories + +export const Channel: Story = (arguments_) => { + return +} +Channel.args = { path: { channelId: 1, guildId: 1 }, channel: channelExample } diff --git a/components/Application/Channels/Channel/Channel.test.tsx b/components/Application/Channels/Channel/Channel.test.tsx new file mode 100644 index 0000000..092bbe2 --- /dev/null +++ b/components/Application/Channels/Channel/Channel.test.tsx @@ -0,0 +1,13 @@ +import { render } from '@testing-library/react' +import { channelExample } from 'cypress/fixtures/channels/channel' + +import { Channel } from './Channel' + +describe('', () => { + it('should render successfully', () => { + const { baseElement } = render( + + ) + expect(baseElement).toBeTruthy() + }) +}) diff --git a/components/Application/Channels/Channel/Channel.tsx b/components/Application/Channels/Channel/Channel.tsx new file mode 100644 index 0000000..63e8daf --- /dev/null +++ b/components/Application/Channels/Channel/Channel.tsx @@ -0,0 +1,32 @@ +import classNames from 'classnames' +import Link from 'next/link' + +import { GuildsChannelsPath } from '../../Application' +import { Channel as ChannelType } from '../../../../models/Channel' + +export interface ChannelProps { + path: GuildsChannelsPath + channel: ChannelType +} + +export const Channel: React.FC = (props) => { + const { channel, path } = props + + return ( + + + # {channel.name} + + + ) +} diff --git a/components/Application/Channels/Channel/index.ts b/components/Application/Channels/Channel/index.ts new file mode 100644 index 0000000..8d34a7c --- /dev/null +++ b/components/Application/Channels/Channel/index.ts @@ -0,0 +1 @@ +export * from './Channel' diff --git a/components/Application/Channels/Channels.stories.tsx b/components/Application/Channels/Channels.stories.tsx deleted file mode 100644 index 5f53bd2..0000000 --- a/components/Application/Channels/Channels.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Meta, Story } from '@storybook/react' - -import { Channels as Component, ChannelsProps } from './' - -const Stories: Meta = { - title: 'Channels', - component: Component -} - -export default Stories - -export const Channels: Story = (arguments_) => ( - -) -Channels.args = { path: { channelId: 1, guildId: 2 } } diff --git a/components/Application/Channels/Channels.test.tsx b/components/Application/Channels/Channels.test.tsx deleted file mode 100644 index 0b15616..0000000 --- a/components/Application/Channels/Channels.test.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { render } from '@testing-library/react' - -import { Channels } from './' - -describe('', () => { - it('should render successfully', () => { - const { baseElement } = render( - - ) - expect(baseElement).toBeTruthy() - }) -}) diff --git a/components/Application/Channels/Channels.tsx b/components/Application/Channels/Channels.tsx index 55066ce..2056175 100644 --- a/components/Application/Channels/Channels.tsx +++ b/components/Application/Channels/Channels.tsx @@ -1,7 +1,9 @@ -import Link from 'next/link' -import classNames from 'classnames' +import InfiniteScroll from 'react-infinite-scroll-component' import { GuildsChannelsPath } from '../Application' +import { Loader } from 'components/design/Loader' +import { Channel } from './Channel' +import { useChannels } from 'contexts/Channels' export interface ChannelsProps { path: GuildsChannelsPath @@ -10,27 +12,19 @@ export interface ChannelsProps { export const Channels: React.FC = (props) => { const { path } = props + const { channels, hasMore, nextPage } = useChannels() + return ( - + ) } diff --git a/components/Application/GuildLeftSidebar/GuildLeftSidebar.tsx b/components/Application/GuildLeftSidebar/GuildLeftSidebar.tsx index 5cf9826..0d0c2d3 100644 --- a/components/Application/GuildLeftSidebar/GuildLeftSidebar.tsx +++ b/components/Application/GuildLeftSidebar/GuildLeftSidebar.tsx @@ -21,7 +21,7 @@ export const GuildLeftSidebar: React.FC = (props) => {

{guild.name}

-
+
diff --git a/components/Application/Guilds/Guilds.tsx b/components/Application/Guilds/Guilds.tsx index 2ba0a59..ce30e87 100644 --- a/components/Application/Guilds/Guilds.tsx +++ b/components/Application/Guilds/Guilds.tsx @@ -1,44 +1,31 @@ -import { useEffect } from 'react' import InfiniteScroll from 'react-infinite-scroll-component' -import { useAuthentication } from 'utils/authentication' -import { GuildWithDefaultChannelId } from 'models/Guild' import { Loader } from 'components/design/Loader' import { ApplicationProps } from '../Application' import { Guild } from './Guild' -import { usePagination } from 'hooks/usePagination' +import { useGuilds } from 'contexts/Guilds' export interface GuildsProps extends ApplicationProps {} export const Guilds: React.FC = (props) => { const { path } = props - const { authentication } = useAuthentication() - const { items, hasMore, nextPage } = usePagination( - { - api: authentication.api, - url: '/guilds' - } - ) - - useEffect(() => { - nextPage() - }, [nextPage]) + const { guilds, hasMore, nextPage } = useGuilds() return (
} > - {items.map((guild) => { + {guilds.map((guild) => { return ( (defaultChannelsContext) + +export interface ChannelsProviderProps { + path: GuildsChannelsPath +} + +export const ChannelsProvider: React.FC = (props) => { + const { path, children } = props + + const { authentication } = useAuthentication() + + const { + items: channels, + hasMore, + nextPage, + resetPagination + } = usePagination({ + api: authentication.api, + url: `/guilds/${path.guildId}/channels` + }) + + useEffect(() => { + resetPagination() + nextPage() + }, [nextPage, resetPagination]) + + return ( + + {children} + + ) +} + +export const useChannels = (): Channels => { + const channels = useContext(ChannelsContext) + if (channels === defaultChannelsContext) { + throw new Error('useChannels must be used within ChannelsProvider') + } + return channels +} diff --git a/contexts/GuildMember.tsx b/contexts/GuildMember.tsx index ecb0d75..fdd2848 100644 --- a/contexts/GuildMember.tsx +++ b/contexts/GuildMember.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext } from 'react' +import { createContext, useContext, useState } from 'react' import { Guild } from 'models/Guild' import { Member } from 'models/Member' @@ -16,8 +16,10 @@ const defaultGuildMemberContext = {} as any const GuildMemberContext = createContext(defaultGuildMemberContext) export const GuildMemberProvider: React.FC = (props) => { + const [guildMember] = useState(props.guildMember) + return ( - + {props.children} ) diff --git a/contexts/Guilds.tsx b/contexts/Guilds.tsx new file mode 100644 index 0000000..3359ca7 --- /dev/null +++ b/contexts/Guilds.tsx @@ -0,0 +1,49 @@ +import { createContext, useContext, useEffect } from 'react' + +import { NextPage, usePagination } from 'hooks/usePagination' +import { useAuthentication } from 'utils/authentication' +import { GuildWithDefaultChannelId } from 'models/Guild' + +export interface Guilds { + guilds: GuildWithDefaultChannelId[] + hasMore: boolean + nextPage: NextPage +} + +const defaultGuildsContext = {} as any +const GuildsContext = createContext(defaultGuildsContext) + +export const GuildsProvider: React.FC = (props) => { + const { children } = props + + const { authentication } = useAuthentication() + + const { + items: guilds, + hasMore, + nextPage, + resetPagination + } = usePagination({ + api: authentication.api, + url: '/guilds' + }) + + useEffect(() => { + resetPagination() + nextPage() + }, [nextPage, resetPagination]) + + return ( + + {children} + + ) +} + +export const useGuilds = (): Guilds => { + const guilds = useContext(GuildsContext) + if (guilds === defaultGuildsContext) { + throw new Error('useGuilds must be used within GuildsProvider') + } + return guilds +} diff --git a/hooks/usePagination.ts b/hooks/usePagination.ts index ea9c178..7640a5d 100644 --- a/hooks/usePagination.ts +++ b/hooks/usePagination.ts @@ -1,5 +1,6 @@ import { useState, useRef, useCallback } from 'react' import { AxiosInstance } from 'axios' + import { FetchState } from './useFetchState' export interface Query { diff --git a/models/Channel.ts b/models/Channel.ts index 4246744..b30c555 100644 --- a/models/Channel.ts +++ b/models/Channel.ts @@ -1,9 +1,7 @@ -import { Type } from '@sinclair/typebox' +import { Type, Static } from '@sinclair/typebox' import { date, id } from './utils' -export const types = [Type.Literal('text')] - export const channelSchema = { id, name: Type.String({ minLength: 1, maxLength: 20 }), @@ -11,3 +9,5 @@ export const channelSchema = { updatedAt: date.updatedAt, guildId: id } +const channelObjectSchema = Type.Object(channelSchema) +export type Channel = Static diff --git a/pages/application/[guildId]/[channelId].tsx b/pages/application/[guildId]/[channelId].tsx index dac48b5..d9486a6 100644 --- a/pages/application/[guildId]/[channelId].tsx +++ b/pages/application/[guildId]/[channelId].tsx @@ -10,6 +10,8 @@ import { } from 'utils/authentication' import { GuildMember, GuildMemberProvider } from 'contexts/GuildMember' import { GuildLeftSidebar } from 'components/Application/GuildLeftSidebar' +import { ChannelsProvider } from 'contexts/Channels' +import { GuildsProvider } from 'contexts/Guilds' export interface ChannelPageProps extends PagePropsWithAuthentication { channelId: number @@ -20,27 +22,26 @@ export interface ChannelPageProps extends PagePropsWithAuthentication { const ChannelPage: NextPage = (props) => { const { channelId, guildId, authentication, guildMember } = props + const path = { + channelId, + guildId + } + return ( - - - - } - > - - - + + + + + } + > + + + + + ) } diff --git a/pages/application/guilds/create.tsx b/pages/application/guilds/create.tsx index e03e3e6..80b0618 100644 --- a/pages/application/guilds/create.tsx +++ b/pages/application/guilds/create.tsx @@ -8,14 +8,17 @@ import { PagePropsWithAuthentication } from 'utils/authentication' import { CreateGuild } from 'components/Application/CreateGuild' +import { GuildsProvider } from 'contexts/Guilds' const CreateGuildPage: NextPage = (props) => { return ( - - - - + + + + + + ) } diff --git a/pages/application/guilds/join.tsx b/pages/application/guilds/join.tsx index 671a249..fc7b322 100644 --- a/pages/application/guilds/join.tsx +++ b/pages/application/guilds/join.tsx @@ -8,14 +8,17 @@ import { PagePropsWithAuthentication } from 'utils/authentication' import { JoinGuildsPublic } from 'components/Application/JoinGuildsPublic' +import { GuildsProvider } from 'contexts/Guilds' const JoinGuildPage: NextPage = (props) => { return ( - - - - + + + + + + ) } diff --git a/pages/application/index.tsx b/pages/application/index.tsx index 9066394..498da9c 100644 --- a/pages/application/index.tsx +++ b/pages/application/index.tsx @@ -8,14 +8,17 @@ import { AuthenticationProvider, PagePropsWithAuthentication } from 'utils/authentication' +import { GuildsProvider } from 'contexts/Guilds' const ApplicationPage: NextPage = (props) => { return ( - - - - + + + + + + ) } diff --git a/pages/application/users/[userId].tsx b/pages/application/users/[userId].tsx index 82e90eb..53efffb 100644 --- a/pages/application/users/[userId].tsx +++ b/pages/application/users/[userId].tsx @@ -8,14 +8,17 @@ import { PagePropsWithAuthentication } from 'utils/authentication' import { UserProfile } from 'components/Application/UserProfile' +import { GuildsProvider } from 'contexts/Guilds' const UserProfilePage: NextPage = (props) => { return ( - - - - + + + + + + ) }