Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

feat: фильтрация проектов и кнопки Откликнуться #55

Merged
merged 5 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/providers/router/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export const normalRoutes = [
path: PATHS.project,
view: { base: <ProjectPage /> },
},
{
path: PATHS.searchProject,
view: { base: <ProjectPage /> },
},
{
path: PATHS.addProject,
view: { base: <AddProjectPage /> },
Expand Down
12 changes: 10 additions & 2 deletions src/pages/projects/ui/AddProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Tab,
TabPanels,
TabPanel,
useToast,
} from '@chakra-ui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
Expand All @@ -22,6 +23,7 @@ import { useApi } from '~/shared/hooks';
import { GoBack } from '~/shared/ui/GoBack';

export const AddProjectPage = () => {
const toast = useToast();
const queryClient = useQueryClient();
const navigate = useNavigate();
const { projectsApi } = useApi();
Expand All @@ -42,8 +44,14 @@ export const AddProjectPage = () => {
queryClient.invalidateQueries(['getAllProjects']);
navigate(-1);
},
onError: () => {
alert('there was an error');
onError: (e: Error) => {
toast({
title: 'Ошибка создания проекта',
description: e.message,
status: 'error',
duration: 9000,
isClosable: true,
});
},
});

Expand Down
32 changes: 19 additions & 13 deletions src/pages/projects/ui/ProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ export const ProjectPage = () => {
onSuccess: (data) => {
setOwnerID(data.owner_id);
},
staleTime: 50000,
});

const { data: userData, isLoading: userIsLoading } = useQuery({
queryKey: ['ownerID', ownerID],
queryFn: () => userApi.getUser(ownerID),
enabled: !!ownerID,
staleTime: 50000,
});

const { data: myData, isLoading: meIsLoading } = useQuery({
queryKey: ['myID', ownerID],
queryFn: () => userApi.getMe(),
enabled: !!ownerID,
});

return (
Expand Down Expand Up @@ -139,17 +143,19 @@ export const ProjectPage = () => {
</CardBody>
</ChakraCard>
<Flex bg="bg" position="sticky" bottom="4.6rem" p={0} py={3} mt="auto">
<Button
type="button"
onClick={() => {
// handleTabsChange(1);
}}
fontSize="sm"
fontWeight="600"
w="full"
>
Откликнуться
</Button>
{!meIsLoading && myData?.id !== data?.owner_id && (
<Button
type="button"
onClick={() => {
// handleTabsChange(1);
}}
fontSize="sm"
fontWeight="600"
w="full"
>
Откликнуться
</Button>
)}
</Flex>
</>
)}
Expand Down
113 changes: 85 additions & 28 deletions src/pages/projects/ui/ProjectsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-floating-promises */
import { Flex, SimpleGrid, Heading, Container, Box, Skeleton } from '@chakra-ui/react';
import { useInfiniteQuery } from '@tanstack/react-query';
import {
Flex,
SimpleGrid,
Heading,
Container,
Box,
Skeleton,
Image,
Text,
Button,
} from '@chakra-ui/react';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import React, { useEffect, useRef } from 'react';
import { Link, generatePath } from 'react-router-dom';
import { Link, generatePath, useNavigate } from 'react-router-dom';

import { ProjectCard } from '~/widgets/project-card';

Expand All @@ -16,9 +26,12 @@ import { useApi } from '~/shared/hooks';
import { PATHS } from '~/shared/lib/router';
import { STag } from '~/shared/ui/STag';

import NotAuth from './NotAuth.svg';

export const ProjectsPage = () => {
const targetRef = useRef(null);
const { projectsApi } = useApi();
const { projectsApi, userApi } = useApi();
const navigate = useNavigate();
const dummyAvatars = [
{ firstName: 'Alex', lastName: 'Gordon', img: 'https://bit.ly/ryan-florence' },
{ firstName: 'Игорь', lastName: 'Крутой', img: 'https://bit.ly/sage-adebayo' },
Expand All @@ -31,10 +44,15 @@ export const ProjectsPage = () => {
const { data, isLoading, fetchNextPage, isFetchingNextPage } = useInfiniteQuery({
queryKey: ['getAllProjects'],
queryFn: ({ pageParam = 1 }) => projectsApi.getAllProjects(pageParam),
getNextPageParam: (lastPage) => lastPage.page + 1,
// getNextPageParam: (lastPage) => lastPage.page + 1,
staleTime: 5000,
});

const { data: myData, isLoading: meIsLoading } = useQuery({
queryKey: ['myID'],
queryFn: () => userApi.getMe(),
});

useEffect(() => {
const options = {
root: null,
Expand Down Expand Up @@ -67,38 +85,77 @@ export const ProjectsPage = () => {
</Flex>
</Flex>

{isLoading || !data ? (
{isLoading || meIsLoading || !data ? (
<>
<Skeleton height="200px" borderRadius="2xl" mb={3} />
<Skeleton height="200px" borderRadius="2xl" mb={3} />
<Skeleton height="200px" borderRadius="2xl" mb={3} />
</>
) : (
<SimpleGrid gap={4}>
{data.pages.map((group, i) => (
<React.Fragment key={i}>
{group.data.map((project) => {
return (
<Link
key={project.id}
to={generatePath(PATHS.project, { id: project.id })}
{data.pages.map((group, i) => {
const filteredProject = group.data.filter(
({ owner_id }) => owner_id === myData?.id,
);
return (
<>
{filteredProject.length === 0 ? (
<Flex
bg="white"
my={6}
borderRadius="2xl"
p={5}
direction="column"
alignItems="center"
gap={5}
>
<ProjectCard
status={project.status}
title={project.name}
date={project.deadline}
description={project.description}
<Image src={NotAuth} />
<Text fontSize="md" fontWeight="medium" mt={1}>
Нет проектов
</Text>
<Text color="gray.700" textAlign="center">
Здесь будут отображаться все ваши проекты в качестве участника и
организатора
</Text>
<Button
type="button"
onClick={() => {
navigate(PATHS.addProject);
}}
fontSize="sm"
fontWeight="600"
w="full"
>
<Flex justifyContent="space-between" alignItems="center">
<STag mainTags={['Организатор']} />
<AvatarsGroup avatars={dummyAvatars} />
</Flex>
</ProjectCard>
</Link>
);
})}
</React.Fragment>
))}
Создать свой проект
</Button>
</Flex>
) : (
<React.Fragment key={i}>
{filteredProject.map((project) => {
return (
<Link
key={project.id}
to={generatePath(PATHS.project, { id: project.id })}
>
<ProjectCard
status={project.status}
title={project.name}
date={project.deadline}
description={project.description}
>
<Flex justifyContent="space-between" alignItems="center">
<STag mainTags={['Организатор']} />
<AvatarsGroup avatars={dummyAvatars} />
</Flex>
</ProjectCard>
</Link>
);
})}
</React.Fragment>
)}
</>
);
})}
{isFetchingNextPage && (
<>
<Skeleton height="200px" borderRadius="2xl" mb={3} />
Expand Down
2 changes: 1 addition & 1 deletion src/pages/search/ui/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const SearchPage = () => {
return (
<Link
key={project.id}
to={generatePath(PATHS.project, { id: project.id })}
to={generatePath(PATHS.searchProject, { id: project.id })}
>
<ProjectCard
status={project.status}
Expand Down
26 changes: 22 additions & 4 deletions src/shared/api/clients/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ export class ProjectsApiClient extends BaseApiClient {
};
const { deadline, status, ...rest } = data;
let formatDate;
if (deadline) formatDate = new Date(deadline).toLocaleDateString('ru');
return { ...rest, deadline: formatDate ?? '', status: statusAdapter[status] };
if (deadline)
formatDate = new Date(deadline).toLocaleDateString('ru', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
return {
...rest,
deadline: `с ${formatDate}`.slice(0, -3),
status: statusAdapter[status],
};
}

async getAllProjects(page: number) {
Expand All @@ -49,8 +58,17 @@ export class ProjectsApiClient extends BaseApiClient {
};
const { deadline, status, ...rest } = project;
let formatDate;
if (deadline) formatDate = new Date(deadline).toLocaleDateString('ru');
return { ...rest, deadline: formatDate ?? '', status: statusAdapter[status] };
if (deadline)
formatDate = new Date(deadline).toLocaleDateString('ru', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
return {
...rest,
deadline: `с ${formatDate}`.slice(0, -3),
status: statusAdapter[status],
};
});
return { ...others, data: newData };
}
Expand Down
1 change: 1 addition & 0 deletions src/shared/lib/router/paths.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const PATHS = {
root: '/',
search: '/search',
searchProject: '/search/:id',
projects: '/projects',
project: '/projects/:id',
addProject: '/add-project',
Expand Down
Loading