group posts
This commit is contained in:
@@ -1,24 +1,50 @@
|
||||
import { FC } from 'react';
|
||||
import { FC, useEffect } from 'react';
|
||||
import { cn } from '../../../lib/cn';
|
||||
import { useParams, Navigate } from 'react-router-dom';
|
||||
import { useParams, Navigate, Routes, Route } from 'react-router-dom';
|
||||
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
|
||||
import { fetchGroupById } from '../../../redux/slices/groups';
|
||||
import GroupMenu from './GroupMenu';
|
||||
import { Posts } from './posts/Posts';
|
||||
import { SearchInput } from '../../../components/input/SearchInput';
|
||||
import { Chat } from './chat/Chat';
|
||||
import { Contests } from './contests/Contests';
|
||||
|
||||
interface GroupsBlockProps {}
|
||||
|
||||
const Group: FC<GroupsBlockProps> = () => {
|
||||
const { groupId } = useParams<{ groupId: string }>();
|
||||
const groupIdNumber = Number(groupId);
|
||||
|
||||
if (!groupId || isNaN(groupIdNumber) || !groupIdNumber) {
|
||||
const groupId = Number(useParams<{ groupId: string }>().groupId);
|
||||
if (!groupId) {
|
||||
return <Navigate to="/home/groups" replace />;
|
||||
}
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const group = useAppSelector((state) => state.groups.fetchGroupById.group);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchGroupById(groupId));
|
||||
}, [groupId]);
|
||||
|
||||
console.log(group);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'border-b-[1px] border-b-liquid-lighter rounded-[10px]',
|
||||
' h-screen w-full text-liquid-white p-[20px] flex gap-[20px] flex-col',
|
||||
)}
|
||||
>
|
||||
{groupIdNumber}
|
||||
<div className="font-bold text-[40px]">{group?.name}</div>
|
||||
|
||||
<GroupMenu groupId={groupId} />
|
||||
|
||||
<Routes>
|
||||
<Route path="home" element={<Posts groupId={groupId} />} />
|
||||
<Route path="chat" element={<Chat />} />
|
||||
<Route path="contests" element={<Contests />} />
|
||||
<Route
|
||||
path="*"
|
||||
element={<Navigate to={`/group/${groupId}/home`} />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
96
src/views/home/group/GroupMenu.tsx
Normal file
96
src/views/home/group/GroupMenu.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { MessageChat, Home, Cup } from '../../../assets/icons/group';
|
||||
|
||||
import React, { FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
|
||||
import {
|
||||
setMenuActivePage,
|
||||
setMenuActiveProfilePage,
|
||||
} from '../../../redux/slices/store';
|
||||
|
||||
interface MenuItemProps {
|
||||
icon: string;
|
||||
text: string;
|
||||
href: string;
|
||||
page: string;
|
||||
profilePage: string;
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
const MenuItem: React.FC<MenuItemProps> = ({
|
||||
icon,
|
||||
text = '',
|
||||
href = '',
|
||||
active = false,
|
||||
page = '',
|
||||
profilePage = '',
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
return (
|
||||
<Link
|
||||
to={href}
|
||||
className={`
|
||||
flex items-center gap-3 p-[16px] rounded-[10px] h-[40px] text-[18px] font-bold
|
||||
transition-all duration-300 text-liquid-white
|
||||
active:scale-95 hover:bg-liquid-lighter hover:ring-[1px] hover:ring-liquid-light hover:ring-inset
|
||||
${active && 'bg-liquid-lighter '}
|
||||
`}
|
||||
onClick={() => {
|
||||
dispatch(setMenuActivePage(page));
|
||||
dispatch(setMenuActiveProfilePage(profilePage));
|
||||
}}
|
||||
>
|
||||
<img src={icon} />
|
||||
<span>{text}</span>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
interface GroupMenuProps {
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
const GroupMenu: FC<GroupMenuProps> = ({ groupId }) => {
|
||||
const menuItems = [
|
||||
{
|
||||
text: 'Главная',
|
||||
href: `/group/${groupId}/home`,
|
||||
icon: Home,
|
||||
page: 'group',
|
||||
profilePage: 'home',
|
||||
},
|
||||
{
|
||||
text: 'Чат',
|
||||
href: `/group/${groupId}/chat`,
|
||||
icon: MessageChat,
|
||||
page: 'group',
|
||||
profilePage: 'chat',
|
||||
},
|
||||
{
|
||||
text: 'Контесты',
|
||||
href: `/group/${groupId}/contests`,
|
||||
icon: Cup,
|
||||
page: 'group',
|
||||
profilePage: 'contests',
|
||||
},
|
||||
];
|
||||
|
||||
const activeGroupPage = useAppSelector(
|
||||
(state) => state.store.menu.activeGroupPage,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-full relative flex gap-[10px]">
|
||||
{menuItems.map((v, i) => (
|
||||
<MenuItem
|
||||
{...v}
|
||||
key={i}
|
||||
active={activeGroupPage == v.profilePage}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GroupMenu;
|
||||
12
src/views/home/group/chat/Chat.tsx
Normal file
12
src/views/home/group/chat/Chat.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useAppDispatch } from '../../../../redux/hooks';
|
||||
import { setMenuActiveGroupPage } from '../../../../redux/slices/store';
|
||||
|
||||
export const Chat = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMenuActiveGroupPage('chat'));
|
||||
}, []);
|
||||
return <></>;
|
||||
};
|
||||
12
src/views/home/group/contests/Contests.tsx
Normal file
12
src/views/home/group/contests/Contests.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useAppDispatch } from '../../../../redux/hooks';
|
||||
import { setMenuActiveGroupPage } from '../../../../redux/slices/store';
|
||||
|
||||
export const Contests = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMenuActiveGroupPage('contests'));
|
||||
}, []);
|
||||
return <></>;
|
||||
};
|
||||
0
src/views/home/group/posts/PostItem.tsx
Normal file
0
src/views/home/group/posts/PostItem.tsx
Normal file
83
src/views/home/group/posts/Posts.tsx
Normal file
83
src/views/home/group/posts/Posts.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import { FC, useEffect } from 'react';
|
||||
|
||||
import { useAppSelector, useAppDispatch } from '../../../../redux/hooks';
|
||||
import { fetchGroupPosts } from '../../../../redux/slices/groupfeed';
|
||||
import { SearchInput } from '../../../../components/input/SearchInput';
|
||||
import { setMenuActiveGroupPage } from '../../../../redux/slices/store';
|
||||
|
||||
interface PostsProps {
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
export const Posts: FC<PostsProps> = ({ groupId }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { pages, status } = useAppSelector(
|
||||
(state) => state.groupfeed.fetchPosts,
|
||||
);
|
||||
|
||||
// Загружаем только первую страницу
|
||||
useEffect(() => {
|
||||
dispatch(fetchGroupPosts({ groupId, page: 0, pageSize: 20 }));
|
||||
}, [groupId]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setMenuActiveGroupPage('home'));
|
||||
}, []);
|
||||
|
||||
const page0 = pages[0];
|
||||
|
||||
return (
|
||||
<div className="h-full overflow-y-scroll thin-dark-scrollbar">
|
||||
<div className="h-[40px] mb-[20px]">
|
||||
<SearchInput
|
||||
onChange={(v) => {}}
|
||||
placeholder="Поиск сообщений"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{status === 'loading' && <div>Загрузка...</div>}
|
||||
{status === 'failed' && <div>Ошибка загрузки постов</div>}
|
||||
|
||||
{status == 'successful' &&
|
||||
page0?.items &&
|
||||
page0.items.length > 0 ? (
|
||||
<div className="space-y-4">
|
||||
{page0.items.map((post) => (
|
||||
<div
|
||||
key={post.id}
|
||||
className="border border-gray-700 rounded p-3"
|
||||
>
|
||||
<div>
|
||||
<b>ID:</b> {post.id}
|
||||
</div>
|
||||
<div>
|
||||
<b>Название:</b> {post.name}
|
||||
</div>
|
||||
<div>
|
||||
<b>Содержимое:</b> {post.content}
|
||||
</div>
|
||||
<div>
|
||||
<b>Автор:</b> {post.authorUsername}
|
||||
</div>
|
||||
<div>
|
||||
<b>Автор ID:</b> {post.authorId}
|
||||
</div>
|
||||
<div>
|
||||
<b>Group ID:</b> {post.groupId}
|
||||
</div>
|
||||
<div>
|
||||
<b>Создан:</b> {post.createdAt}
|
||||
</div>
|
||||
<div>
|
||||
<b>Обновлён:</b> {post.updatedAt}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : status === 'successful' ? (
|
||||
<div>Постов пока нет</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user