Skip to content

Instantly share code, notes, and snippets.

@yunseop-kim
Created April 2, 2020 01:39
Show Gist options
  • Save yunseop-kim/cbf5e01eac4a82bbd3688442936e094f to your computer and use it in GitHub Desktop.
Save yunseop-kim/cbf5e01eac4a82bbd3688442936e094f to your computer and use it in GitHub Desktop.
codegen
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import Page from 'components/Page';
import useSearch from 'hooks/useSearch';
import LanguageMenu from 'components/LanguageMenu';
import { Table, Checkbox, Button } from 'antd';
import {
useBlogsLazyQuery,
OrderType,
OrderByDirectionType,
Tag,
useCreateBlogMutation,
useToggleBlogStatusMutation,
BlogsQuery,
BlogsQueryVariables,
BlogsDocument,
BlogStatusType,
useToggleBlogTransStatusMutation,
BlogTransStatusType,
} from 'graphql/generated';
import useLanguage from 'hooks/useLanguage';
import useSelectFilter from 'hooks/useSelectFilter';
import RadioFilter from 'components/RadioFilter';
import Search from 'antd/lib/input/Search';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from 'store';
import useRadioFilter from 'hooks/useRadioFilter';
import { saveFilters } from 'store/blog';
import SelectFilter from 'components/SelectFilter';
import { AutoCompleteTags } from './AutoCompleteTags';
import { Link } from 'react-router-dom';
import notificationOfBaseOption from 'utils/notificationOfBaseOption';
const Container = styled.div``;
const FilterSection = styled.section`
display: flex;
align-items: center;
margin-bottom: 0.5rem;
`;
const RecommendFilter = SelectFilter;
const PublicFilter = SelectFilter;
const columns = [
{
title: '#',
dataIndex: 'code',
},
{
title: '제목',
dataIndex: 'title',
},
{
title: '조회수',
dataIndex: 'viewCount',
},
{
title: '공유',
dataIndex: 'likeCount',
},
{
title: '추천',
dataIndex: 'isRecommend',
},
{
title: '번역공개',
dataIndex: 'isTranslationPublish',
},
{
title: '전체공개',
dataIndex: 'isPublish',
},
{
title: '작성일',
dataIndex: 'createdAt',
},
];
interface DataSource {
key: number;
code: number;
title: JSX.Element;
viewCount: number;
likeCount: number;
isRecommend: JSX.Element;
isTranslationPublish: JSX.Element;
isPublish: JSX.Element;
createdAt: string;
}
export default function Blogs(): JSX.Element {
const { language } = useLanguage();
const { isPublish, searchQuery: storedSearchQuery, isRecommend, order, tags: storedTags } = useSelector(
(state: RootState) => state.blog.filters,
);
const { onChangeFilters, selectedFilter } = useRadioFilter<OrderType>(order);
const [page, setPage] = useState<number>(1);
const { query, searchQuery, onChange: onChangeQuery, onSearch } = useSearch(storedSearchQuery);
const { filterStatus: recommend, onChange: onChangeRecommend, onClick: onClickRecommend } = useSelectFilter(
isRecommend,
);
const { filterStatus: publish, onChange: onChangePublish, onClick: onClickPublish } = useSelectFilter(
isPublish,
);
const [tags, setTags] = useState<Tag[]>(storedTags?.length > 0 && storedTags);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
saveFilters({
isPublish: publish,
isRecommend: recommend,
searchQuery,
order: selectedFilter,
tags,
}),
);
}, [dispatch, publish, recommend, searchQuery, selectedFilter, tags]);
const [getBlogList, { loading, data, refetch }] = useBlogsLazyQuery({
variables: {
input: {
page,
limit: 10,
order: {
field: order,
direction: OrderByDirectionType.Desc,
},
filter: {
title: searchQuery || undefined,
isPublish,
isRecommend,
language,
tags: tags?.length > 0 ? tags.map(tag => tag.code) : undefined,
// excludeTags: [6119],
},
},
language,
},
});
const [createBlog] = useCreateBlogMutation({
variables: {
language,
},
...notificationOfBaseOption('블로그가 생성되었습니다.', '오류가 발생했습니다.', refetch),
});
const [toggleBlogStatus] = useToggleBlogStatusMutation({
update: (proxy, { data }) => {
const oldData = proxy.readQuery<BlogsQuery, BlogsQueryVariables>({
query: BlogsDocument,
variables: {
input: {
page,
limit: 10,
order: {
field: order,
direction: OrderByDirectionType.Desc,
},
filter: {
title: searchQuery || undefined,
isPublish,
isRecommend,
language,
tags: tags?.length > 0 ? tags.map(tag => tag.code) : undefined,
// excludeTags: [6119],
},
},
language,
},
});
proxy.writeQuery<BlogsQuery, BlogsQueryVariables>({
query: BlogsDocument,
variables: {
input: {
page,
limit: 10,
order: {
field: order,
direction: OrderByDirectionType.Desc,
},
filter: {
title: searchQuery || undefined,
isPublish,
isRecommend,
language,
tags: tags?.length > 0 ? tags.map(tag => tag.code) : undefined,
// excludeTags: [6119],
},
},
language,
},
data: {
...oldData,
blogs: {
...oldData.blogs,
edges: [
...oldData.blogs.edges.filter(blog => blog.code !== data.toggleBlogStatus.code),
oldData.blogs.edges.find(blog => blog.code === data.toggleBlogStatus.code),
].sort((a, b) => b.code - a.code),
},
},
});
},
...notificationOfBaseOption(),
});
const [toggleBlogTransStatus] = useToggleBlogTransStatusMutation({
update: (proxy, { data }) => {
const oldData = proxy.readQuery<BlogsQuery, BlogsQueryVariables>({
query: BlogsDocument,
variables: {
input: {
page,
limit: 10,
order: {
field: order,
direction: OrderByDirectionType.Desc,
},
filter: {
title: searchQuery || undefined,
isPublish,
isRecommend,
language,
tags: tags?.length > 0 ? tags.map(tag => tag.code) : undefined,
// excludeTags: [6119],
},
},
language,
},
});
const blog = oldData.blogs.edges.find(blog => blog.code === data.toggleBlogTransStatus.blogCode);
proxy.writeQuery<BlogsQuery, BlogsQueryVariables>({
query: BlogsDocument,
variables: {
input: {
page,
limit: 10,
order: {
field: order,
direction: OrderByDirectionType.Desc,
},
filter: {
title: searchQuery || undefined,
isPublish,
isRecommend,
language,
tags: tags?.length > 0 ? tags.map(tag => tag.code) : undefined,
// excludeTags: [6119],
},
},
language,
},
data: {
...oldData,
blogs: {
...oldData.blogs,
edges: [
...oldData.blogs.edges.filter(blog => blog.code !== data.toggleBlogTransStatus.blogCode),
{
...blog,
translations: [...blog.translations.filter(t => t.language !== language), data.toggleBlogTransStatus],
},
].sort((a, b) => b.code - a.code),
},
},
});
},
...notificationOfBaseOption(),
});
const onChangePage = (page: number): void => {
setPage(page);
};
const onChangeTags = (selectedTag: Tag, selectedTags: Tag[]): void => {
setTags([...selectedTags]);
};
const dataSource: DataSource[] = data?.blogs?.edges?.map(
(blog, index): DataSource => ({
key: index,
code: blog?.code,
title: <Link to={`/blog/${blog.code}`}>{blog.translations[0]?.title}</Link>,
viewCount: blog?.viewCount,
likeCount: blog?.likeCount,
isRecommend: (
<Checkbox
checked={blog?.isRecommend}
onChange={e => {
toggleBlogStatus({
variables: {
input: {
code: blog?.code,
statusType: BlogStatusType.Recommend,
},
},
});
}}
/>
),
isTranslationPublish: (
<Checkbox
checked={blog?.translations.find(t => t.language === language)?.isPublish}
onChange={e => {
toggleBlogTransStatus({
variables: {
input: {
code: blog?.translations.find(t => t.language === language)?.code,
statusType: BlogTransStatusType.Publish,
},
},
});
}}
/>
),
isPublish: (
<Checkbox
checked={blog?.isPublish}
onChange={e => {
toggleBlogStatus({
variables: {
input: {
code: blog?.code,
statusType: BlogStatusType.Publish,
},
},
});
}}
/>
),
createdAt: blog?.translations[0]?.createdAt,
}),
);
useEffect(() => {
getBlogList();
}, [getBlogList, searchQuery, isRecommend, language, page]);
return (
<Page>
<LanguageMenu />
<Container>
<FilterSection>
<RecommendFilter
applyLabel="추천"
notApplyLabel="비추천"
FilterStatus={recommend}
onChangeFilter={onChangeRecommend}
onClick={onClickRecommend}
style={{ marginRight: '1rem' }}
/>
<PublicFilter
applyLabel="공개"
notApplyLabel="비공개"
FilterStatus={publish}
onChangeFilter={onChangePublish}
onClick={onClickPublish}
style={{ marginRight: '1rem' }}
/>
<RadioFilter<OrderType>
onChangeFilters={onChangeFilters}
selectedFilter={selectedFilter}
options={[
{ value: OrderType.CreatedAt, text: '최신순' },
{ value: OrderType.LikeCount, text: '인기순' },
]}
/>
<Search
value={query}
onChange={onChangeQuery}
placeholder="검색어 입력..."
onSearch={onSearch}
style={{ width: '15rem' }}
/>
<Button onClick={() => createBlog()}>생성</Button>
</FilterSection>
<AutoCompleteTags initialTags={tags} onChange={onChangeTags} />
<Table
loading={loading}
columns={columns}
dataSource={dataSource}
pagination={{
current: page,
total: data?.blogs?.totalCount,
pageSize: 20,
showQuickJumper: true,
onChange: (page: number): void => onChangePage(page),
}}
size="small"
/>
</Container>
</Page>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment