Skip to content

Commit

Permalink
fix: profile post frontend (#1953)
Browse files Browse the repository at this point in the history
* fix

* format fix

* format fix
  • Loading branch information
RiXelanya authored Aug 27, 2024
1 parent f83e21f commit 218d9c9
Show file tree
Hide file tree
Showing 10 changed files with 420 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/components/PostCreate/MobilePostCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export const MobilePostCreate: React.FC<MobilePostCreateProps> = props => {
page,
);

setUserExperiences([...userExperiences , ...experiences]);
setUserExperiences([...userExperiences, ...experiences]);
if (experiences.length !== 0)
setSelectedTimeline(experiences[0].experience);

Expand Down
2 changes: 1 addition & 1 deletion src/components/PostCreate/MobilePostImport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const MobilePostImport: React.FC<MobilePostImportProps> = props => {
page,
);

setUserExperiences([...userExperiences,...experiences]);
setUserExperiences([...userExperiences, ...experiences]);
if (experiences.length !== 0)
setSelectedTimeline(experiences[0].experience);

Expand Down
2 changes: 1 addition & 1 deletion src/components/PostCreate/PostCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ export const PostCreate: React.FC<PostCreateProps> = props => {
page,
);

setUserExperiences([...userExperiences,...experiences]);
setUserExperiences([...userExperiences, ...experiences]);

if (meta.currentPage < meta.totalPageCount) setPage(page + 1);
};
Expand Down
137 changes: 137 additions & 0 deletions src/components/PostList/ProfilePostList.container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { PencilIcon } from '@heroicons/react/outline';

import React, { useEffect, useState } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';

import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';

import { IconButton, SvgIcon, useMediaQuery } from '@material-ui/core';
import Grid from '@material-ui/core/Grid';

import { Skeleton as PostSkeleton } from '../PostDetail';
import { EmptyResult } from '../Search/EmptyResult';
import { EmptyContentEnum } from '../Search/EmptyResult.interfaces';
import { Loading } from '../atoms/Loading';
import { useStyles } from './PostList.styles';
import { useProfileFilter } from './hooks/use-profile-filter.hook';
import { useTimelineFilter } from './hooks/use-timeline-filter.hook';

import { PostDetailContainer } from 'components/PostDetail/PostDetail.container';
import ShowIf from 'components/common/show-if.component';
import { ParsedUrlQuery } from 'querystring';
import { useBlockList } from 'src/hooks/use-blocked-list.hook';
import { TimelineFilterFields } from 'src/interfaces/timeline';
import { TimelineType } from 'src/interfaces/timeline';
import { User } from 'src/interfaces/user';
import theme from 'src/themes/default';

const PostCreateContainer = dynamic(
() => import('../PostCreate/PostCreate.container'),
{
ssr: false,
},
);

type ProfilePostsListContainerProps = {
query?: ParsedUrlQuery;
filters?: TimelineFilterFields;
user?: User;
userId?: string;
};

export const ProfilePostsListContainer: React.FC<ProfilePostsListContainerProps> =
props => {
const { query, filters, user, userId } = props;
const styles = useStyles();
const { posts, loading, empty, hasMore, filterTimeline, nextPage, clear } =
useProfileFilter(filters, userId);
const { loadAll: loadAllBlockedUser } = useBlockList(user);

const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

const router = useRouter();
const [createPostOpened, setCreatePostOpened] = useState(false);

const handleOpenCreatePost = () => {
setCreatePostOpened(true);
};

const handleCloseCreatePost = () => {
setCreatePostOpened(false);
if (query.type && query.type === TimelineType.ALL) {
router.push('/', undefined, { shallow: true });
}
};

useEffect(() => {
clear();
if (!user) filterTimeline({ ...query, timelineType: TimelineType.ALL });
filterTimeline(query);

loadAllBlockedUser();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [query]);

const loadNextPage = () => {
nextPage();
};

if (loading)
return (
<Grid container justifyContent="center">
<PostSkeleton />
<PostSkeleton />
</Grid>
);

if (empty)
return (
<EmptyResult
emptyContent={
(query.type && query.type === TimelineType.EXPERIENCE) ||
(!query.type && user)
? EmptyContentEnum.DISCOVER
: EmptyContentEnum.POST
}
/>
);

return (
<div className={styles.root}>
<PostCreateContainer
open={createPostOpened}
onClose={handleCloseCreatePost}
/>

<ShowIf condition={!isMobile}>
<div className={styles.button}>
<IconButton
onClick={handleOpenCreatePost}
className={styles.iconbutton}>
<SvgIcon
className={styles.fill}
component={PencilIcon}
viewBox="0 0 28 28"
/>
</IconButton>
</div>
</ShowIf>

<InfiniteScroll
dataLength={posts.length}
hasMore={hasMore}
next={loadNextPage}
loader={<Loading />}>
{posts.map(post => (
<PostDetailContainer
key={`post-${post.id}`}
user={user}
post={post}
metric={post.metric}
/>
))}
</InfiniteScroll>
</div>
);
};
210 changes: 210 additions & 0 deletions src/components/PostList/hooks/use-profile-filter.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { useCallback } from 'react';
import { useSelector, useDispatch, shallowEqual } from 'react-redux';

import { ParsedUrlQuery } from 'querystring';
import { Post } from 'src/interfaces/post';
import {
TimelineType,
TimelineOrderType,
PostOriginType,
TimelineFilterFields,
} from 'src/interfaces/timeline';
import { User } from 'src/interfaces/user';
import { SortType } from 'src/lib/api/interfaces/pagination-params.interface';
import { RootState } from 'src/reducers';
import { loadProfile, clearTimeline } from 'src/reducers/timeline/actions';

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useProfileFilter = (
filters?: TimelineFilterFields,
userId?: string,
) => {
const dispatch = useDispatch();

const filterFields = useSelector<RootState, TimelineFilterFields>(
state => state.timelineState.filters.fields,
shallowEqual,
);
const people = useSelector<RootState, User>(
state => state.profileState.detail,
shallowEqual,
);
const anonymous = useSelector<RootState, boolean>(
state => state.userState.anonymous,
shallowEqual,
);
const { posts, empty, loading, hasMore } = useSelector<
RootState,
{ posts: Post[]; empty: boolean; loading: boolean; hasMore: boolean }
>(
state => ({
posts: filters?.owner
? state.timelineState.posts.filter(
posts => posts.createdBy === filters?.owner,
)
: state.timelineState.posts,
empty:
state.timelineState.meta.totalItemCount === 0 &&
!state.timelineState.loading,
loading:
state.timelineState.meta.totalItemCount === 0 &&
state.timelineState.loading,
hasMore:
state.timelineState.meta.totalPageCount >
state.timelineState.meta.currentPage,
}),
shallowEqual,
);
const currentPage = useSelector<RootState, number>(
state => state.timelineState.meta.currentPage,
shallowEqual,
);
const originType: PostOriginType = filterFields?.platform
? filterFields.platform.includes.length === 1 &&
filterFields.platform.includes('myriad')
? 'myriad'
: 'imported'
: 'all';

const filterTimeline = useCallback(
async (query?: ParsedUrlQuery) => {
console.log('HAHAHA');
let timelineType = TimelineType.PROFILE;
let timelineOrder = TimelineOrderType.LATEST;
let tags: string[] = [];
let search: string;

if (query?.tag) {
tags = Array.isArray(query.tag) ? query.tag : [query.tag];
}

if (query?.order) {
const order = Array.isArray(query.order) ? query.order[0] : query.order;

if (
Object.values(TimelineOrderType).includes(order as TimelineOrderType)
) {
timelineOrder = order as TimelineOrderType;
}
}

if (query?.q) {
search = query.q as string;
}

const newFilterFields: TimelineFilterFields = {
...filterFields,
...filters,
tags,
};

if (anonymous) {
// TODO: anonymous user should only see trending posts
}

dispatch(
loadProfile(
1,
userId,
{
fields: newFilterFields,
order: timelineOrder,
query: search,
},
timelineType,
),
);
},
[filterFields],
);

const filterByOrigin = useCallback(
(origin: PostOriginType) => {
const timelineOrder = TimelineOrderType.LATEST;

if (!people || !filters) return;

switch (origin) {
case 'myriad':
filterFields.platform = ['myriad'];
filterFields.owner = people.id;
break;
case 'imported':
filterFields.platform = ['facebook', 'reddit', 'twitter'];
filterFields.owner = people.id;
break;

default:
filterFields.owner = people.id;
filterFields.platform = undefined;
break;
}

const newFilterFields: TimelineFilterFields = {
...filterFields,
...filters,
};

dispatch(
loadProfile(
1,
userId,
{
fields: newFilterFields,
order: timelineOrder,
},
TimelineType.ALL,
),
);
},
[filterFields],
);

const sortTimeline = useCallback(
(sort: SortType) => {
const newFilterFields: TimelineFilterFields = {
...filterFields,
...filters,
};
const timelineOrder = TimelineOrderType.LATEST;

dispatch(
loadProfile(
1,
userId,
{
fields: newFilterFields,
order: timelineOrder,
sort,
},
TimelineType.ALL,
),
);
},
[filterFields, filters],
);

const nextPage = useCallback(() => {
const page = currentPage + 1;

dispatch(loadProfile(page, userId));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPage]);

const clear = useCallback(() => {
dispatch(clearTimeline());
}, []);

return {
empty,
loading,
hasMore,
posts,
originType,
filterTimeline,
filterByOrigin,
sortTimeline,
nextPage,
clear,
};
};
1 change: 1 addition & 0 deletions src/components/PostList/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './PostList.container';
export * from './ProfilePostList.container';
Loading

0 comments on commit 218d9c9

Please sign in to comment.