Skip to content

Commit 05866fb

Browse files
committed
refactor(lint): decompose big components - repo-list
#163
1 parent b8c53c9 commit 05866fb

File tree

7 files changed

+185
-85
lines changed

7 files changed

+185
-85
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ REACT_APP_GITHUB_MAIN=https://github.com/ani-team/github-client
2020
REACT_APP_GITHUB_FEEDBACK=https://github.com/ani-team/github-client/issues/new
2121

2222
# Используется для кодогенерации, Apollo Client плагина
23-
REACT_APP_ACCESS_TOKEN=57f59e6475f92ded30f0dc78ca142a26e962cc8e
23+
REACT_APP_ACCESS_TOKEN=8709f2ca2f263a81f1de65511485c97c70f653f0

src/features/repo-list/index.tsx

Lines changed: 19 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import React from "react";
2-
import { Empty } from "antd";
3-
import { Repo, Tabs, SimplePagination, Card } from "shared/components";
4-
import { str, dom } from "shared/helpers";
52
import { useReposQuery } from "./queries.gen";
6-
import { useFilters, PAGE_SIZE, useStarring } from "./hooks";
7-
import { tabsMap } from "./params";
3+
import { useFilters, useStarring } from "./hooks";
4+
import Tabs from "./tabs";
5+
import Items from "./items";
6+
import Pagination from "./pagination";
87
import "./index.scss";
98

109
type Props = {
@@ -15,6 +14,7 @@ type Props = {
1514
/**
1615
* @feature Список репозиториев пользователя
1716
* FIXME: rename to UserRepoList? (coz - user as dep)
17+
* FIXME: simplify inner components
1818
*/
1919
const RepoList = ({ username }: Props) => {
2020
const { handleTabClick, handlePaginationClick, config } = useFilters();
@@ -23,60 +23,23 @@ const RepoList = ({ username }: Props) => {
2323
});
2424
// TODO: transmit id and viewerHasStarred of nodes to handler func
2525
const starring = useStarring(variables);
26-
const { pageInfo, totalCount = 0, nodes } = data?.user?.repositories || {};
27-
const length = nodes?.length;
26+
const { repositories } = data?.user || {};
2827

2928
return (
3029
<div className="repo-list">
31-
<Tabs className="repo-list__tabs">
32-
{Object.keys(tabsMap).map((type) => (
33-
<Tabs.Item
34-
key={type}
35-
name={str.capitalize(type)}
36-
className="repo-list__tab"
37-
active={config.tab === type}
38-
onClick={() => handleTabClick(type)}
39-
label={config.tab === type && !loading ? String(totalCount) : undefined}
40-
/>
41-
))}
42-
</Tabs>
43-
44-
<div className="repo-list__items mt-6">
45-
{/* NOTE: А то все {PAGE_SIZE} плейсхолдеров слишком много */}
46-
{loading && <Card.SkeletonGroup amount={10} />}
47-
{length !== 0 ? (
48-
data?.user?.repositories.nodes?.map((node) => (
49-
<Repo
50-
onStarring={() => starring.handle(node?.id, node?.viewerHasStarred)}
51-
key={node?.id}
52-
data={node}
53-
loading={starring.debouncedLoadingId === node?.id}
54-
/>
55-
))
56-
) : (
57-
<Empty
58-
className="repo-list__placeholder"
59-
description={<h2>{username} doesn’t have any repositories yet.</h2>}
60-
/>
61-
)}
62-
</div>
63-
<div className="repo-list__pagination my-6">
64-
{totalCount > PAGE_SIZE && pageInfo && (
65-
<SimplePagination
66-
onPrev={() => {
67-
handlePaginationClick({ before: pageInfo.startCursor });
68-
dom.scrollToTop();
69-
}}
70-
onNext={() => {
71-
handlePaginationClick({ after: pageInfo.endCursor });
72-
dom.scrollToTop();
73-
}}
74-
hasNextPage={pageInfo.hasNextPage}
75-
hasPrevPage={pageInfo.hasPreviousPage}
76-
center
77-
/>
78-
)}
79-
</div>
30+
<Tabs
31+
handleTabClick={handleTabClick}
32+
config={config}
33+
loading={loading}
34+
totalCount={repositories?.totalCount}
35+
/>
36+
<Items
37+
loading={loading}
38+
nodes={repositories?.nodes}
39+
starring={starring}
40+
username={username}
41+
/>
42+
<Pagination handlePaginationClick={handlePaginationClick} {...repositories} />
8043
</div>
8144
);
8245
};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from "react";
2+
import { Empty } from "antd";
3+
import { Repo, Card } from "shared/components";
4+
import { RepositoriesDetailsFragment } from "../queries.gen";
5+
import { useStarring } from "../hooks";
6+
7+
type Props = {
8+
/** Флаг загрузки */
9+
loading: boolean;
10+
/** Список элементов-репозиториев */
11+
nodes: RepositoriesDetailsFragment["nodes"];
12+
/** Мутации по star/unstarring */
13+
starring: ReturnType<typeof useStarring>;
14+
/** Логин owner-а */
15+
username: string;
16+
};
17+
18+
/**
19+
* Список репозиториев
20+
*/
21+
const RepoListItems = (props: Props) => {
22+
const { loading, nodes, starring, username } = props;
23+
const length = nodes?.length;
24+
25+
return (
26+
<div className="repo-list__items mt-6">
27+
{/* NOTE: А то все {PAGE_SIZE} плейсхолдеров слишком много */}
28+
{loading && <Card.SkeletonGroup amount={10} />}
29+
{length !== 0 ? (
30+
nodes?.map((node) => (
31+
<Repo
32+
onStarring={() => starring.handle(node?.id, node?.viewerHasStarred)}
33+
key={node?.id}
34+
data={node}
35+
loading={starring.debouncedLoadingId === node?.id}
36+
/>
37+
))
38+
) : (
39+
<Empty
40+
className="repo-list__placeholder"
41+
description={<h2>{username} doesn’t have any repositories yet.</h2>}
42+
/>
43+
)}
44+
</div>
45+
);
46+
};
47+
48+
export default RepoListItems;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from "react";
2+
import { SimplePagination } from "shared/components";
3+
import { dom } from "shared/helpers";
4+
import { RepositoriesDetailsFragment } from "../queries.gen";
5+
import { useFilters, PAGE_SIZE } from "../hooks";
6+
7+
type Props = Partial<RepositoriesDetailsFragment> & {
8+
/** Обработчик пагинации */
9+
handlePaginationClick: ReturnType<typeof useFilters>["handlePaginationClick"];
10+
};
11+
12+
/**
13+
* Пагинация списка репозиториев
14+
*/
15+
const RepoListPagination = (props: Props) => {
16+
const { pageInfo, totalCount = 0, handlePaginationClick } = props;
17+
18+
return (
19+
<div className="repo-list__pagination my-6">
20+
{totalCount > PAGE_SIZE && pageInfo && (
21+
<SimplePagination
22+
onPrev={() => {
23+
handlePaginationClick({ before: pageInfo.startCursor });
24+
dom.scrollToTop();
25+
}}
26+
onNext={() => {
27+
handlePaginationClick({ after: pageInfo.endCursor });
28+
dom.scrollToTop();
29+
}}
30+
hasNextPage={pageInfo.hasNextPage}
31+
hasPrevPage={pageInfo.hasPreviousPage}
32+
center
33+
/>
34+
)}
35+
</div>
36+
);
37+
};
38+
39+
export default RepoListPagination;

src/features/repo-list/queries.gen.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as Types from '../../models.gen';
33

44
import { gql } from '@apollo/client';
55
import * as Apollo from '@apollo/client';
6+
export type RepositoriesDetailsFragment = { readonly totalCount: number, readonly pageInfo: { readonly endCursor?: Types.Maybe<string>, readonly startCursor?: Types.Maybe<string>, readonly hasNextPage: boolean, readonly hasPreviousPage: boolean }, readonly nodes?: Types.Maybe<ReadonlyArray<Types.Maybe<{ readonly id: string, readonly name: string, readonly updatedAt: any, readonly viewerHasStarred: boolean, readonly primaryLanguage?: Types.Maybe<{ readonly color?: Types.Maybe<string>, readonly name: string }>, readonly owner: { readonly login: string } | { readonly login: string } }>>> };
7+
68
export type ReposQueryVariables = Types.Exact<{
79
login: Types.Scalars['String'];
810
ownerAffiliations?: Types.Maybe<ReadonlyArray<Types.Maybe<Types.RepositoryAffiliation>>>;
@@ -13,7 +15,7 @@ export type ReposQueryVariables = Types.Exact<{
1315
}>;
1416

1517

16-
export type ReposQuery = { readonly user?: Types.Maybe<{ readonly id: string, readonly repositories: { readonly totalCount: number, readonly pageInfo: { readonly endCursor?: Types.Maybe<string>, readonly startCursor?: Types.Maybe<string>, readonly hasNextPage: boolean, readonly hasPreviousPage: boolean }, readonly nodes?: Types.Maybe<ReadonlyArray<Types.Maybe<{ readonly id: string, readonly name: string, readonly updatedAt: any, readonly viewerHasStarred: boolean, readonly primaryLanguage?: Types.Maybe<{ readonly color?: Types.Maybe<string>, readonly name: string }>, readonly owner: { readonly login: string } | { readonly login: string } }>>> } }> };
18+
export type ReposQuery = { readonly user?: Types.Maybe<{ readonly id: string, readonly repositories: RepositoriesDetailsFragment }> };
1719

1820
export type AddStarMutationVariables = Types.Exact<{
1921
starrableId: Types.Scalars['ID'];
@@ -29,36 +31,40 @@ export type RemoveStarMutationVariables = Types.Exact<{
2931

3032
export type RemoveStarMutation = { readonly removeStar?: Types.Maybe<{ readonly starrable?: Types.Maybe<{ readonly id: string } | { readonly id: string } | { readonly id: string }> }> };
3133

32-
34+
export const RepositoriesDetailsFragmentDoc = gql`
35+
fragment RepositoriesDetails on RepositoryConnection {
36+
pageInfo {
37+
endCursor
38+
startCursor
39+
hasNextPage
40+
hasPreviousPage
41+
}
42+
totalCount
43+
nodes {
44+
id
45+
name
46+
primaryLanguage {
47+
color
48+
name
49+
}
50+
owner {
51+
login
52+
}
53+
updatedAt
54+
viewerHasStarred
55+
}
56+
}
57+
`;
3358
export const ReposDocument = gql`
3459
query Repos($login: String!, $ownerAffiliations: [RepositoryAffiliation], $after: String, $before: String, $first: Int, $last: Int) {
3560
user(login: $login) {
3661
id
3762
repositories(ownerAffiliations: $ownerAffiliations, orderBy: {field: PUSHED_AT, direction: DESC}, after: $after, before: $before, first: $first, last: $last) {
38-
pageInfo {
39-
endCursor
40-
startCursor
41-
hasNextPage
42-
hasPreviousPage
43-
}
44-
totalCount
45-
nodes {
46-
id
47-
name
48-
primaryLanguage {
49-
color
50-
name
51-
}
52-
owner {
53-
login
54-
}
55-
updatedAt
56-
viewerHasStarred
57-
}
63+
...RepositoriesDetails
5864
}
5965
}
6066
}
61-
`;
67+
${RepositoriesDetailsFragmentDoc}`;
6268

6369
/**
6470
* __useReposQuery__

src/features/repo-list/queries.gql

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
query Repos ($login: String!, $ownerAffiliations: [RepositoryAffiliation], $after: String, $before: String, $first: Int, $last: Int) {
2-
user(login: $login) {
3-
id
4-
repositories(ownerAffiliations: $ownerAffiliations, orderBy: {field: PUSHED_AT, direction: DESC}, after: $after, before: $before, first: $first, last: $last) {
5-
pageInfo {
1+
fragment RepositoriesDetails on RepositoryConnection {
2+
pageInfo {
63
endCursor
74
startCursor
85
hasNextPage
@@ -22,6 +19,13 @@ query Repos ($login: String!, $ownerAffiliations: [RepositoryAffiliation], $afte
2219
updatedAt
2320
viewerHasStarred
2421
}
22+
}
23+
24+
query Repos ($login: String!, $ownerAffiliations: [RepositoryAffiliation], $after: String, $before: String, $first: Int, $last: Int) {
25+
user(login: $login) {
26+
id
27+
repositories(ownerAffiliations: $ownerAffiliations, orderBy: {field: PUSHED_AT, direction: DESC}, after: $after, before: $before, first: $first, last: $last) {
28+
...RepositoriesDetails
2529
}
2630
}
2731
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from "react";
2+
import { Tabs } from "shared/components";
3+
import { str } from "shared/helpers";
4+
import { useFilters } from "../hooks";
5+
import { tabsMap } from "../params";
6+
7+
type Props = {
8+
/** Фильтры */
9+
config: ReturnType<typeof useFilters>["config"];
10+
/** Обработчик смены вкладки */
11+
handleTabClick: ReturnType<typeof useFilters>["handleTabClick"];
12+
/** Флаг загрузки */
13+
loading: boolean;
14+
/** Общее кол-во элементов */
15+
totalCount?: number;
16+
};
17+
18+
/**
19+
* Вкладки списка репозиториев
20+
*/
21+
const RepoListTabs = (props: Props) => {
22+
const { config, handleTabClick, loading, totalCount } = props;
23+
24+
return (
25+
<Tabs className="repo-list__tabs">
26+
{Object.keys(tabsMap).map((type) => (
27+
<Tabs.Item
28+
key={type}
29+
name={str.capitalize(type)}
30+
className="repo-list__tab"
31+
active={config.tab === type}
32+
onClick={() => handleTabClick(type)}
33+
label={config.tab === type && !loading ? String(totalCount || 0) : undefined}
34+
/>
35+
))}
36+
</Tabs>
37+
);
38+
};
39+
40+
export default RepoListTabs;

0 commit comments

Comments
 (0)