Skip to content

Commit 6266e3a

Browse files
authored
Merge pull request velopert#266 from velopert/feature/post-recommend
Show custom recommends
2 parents 1018117 + d1554ef commit 6266e3a

File tree

7 files changed

+236
-117
lines changed

7 files changed

+236
-117
lines changed

src/components/common/AdFeed.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import React, { useEffect } from 'react';
22
import styled from 'styled-components';
33
import { mediaQuery } from '../../lib/styles/media';
4+
import gtag from '../../lib/gtag';
45

5-
function AdFeed() {
6+
function AdFeed({ forPost, index }: { forPost?: boolean; index: number }) {
67
// const [isMobile, setIsMobile] = useState(false);
78

89
// useEffect(() => {
@@ -20,7 +21,14 @@ function AdFeed() {
2021
}, []);
2122

2223
return (
23-
<Block>
24+
<Block
25+
forPost={forPost}
26+
onClick={() => {
27+
if (forPost) {
28+
gtag('event', 'ads_click', { event_label: index });
29+
}
30+
}}
31+
>
2432
<ins
2533
className="adsbygoogle"
2634
style={{ display: 'block' }}
@@ -52,7 +60,7 @@ function AdFeed() {
5260
);
5361
}
5462

55-
const Block = styled.div`
63+
const Block = styled.div<{ forPost?: boolean }>`
5664
width: 20rem;
5765
margin: 1rem;
5866
min-height: 23.5625rem;

src/components/common/PostCard.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import Skeleton from './Skeleton';
1313
import { mediaQuery } from '../../lib/styles/media';
1414
import { Link } from 'react-router-dom';
1515
import usePrefetchPost from '../../lib/hooks/usePrefetchPost';
16+
import gtag from '../../lib/gtag';
1617

1718
export type PostCardProps = {
1819
post: PartialPost;
1920
forHome?: boolean;
21+
forPost?: boolean;
2022
};
2123

22-
function PostCard({ post, forHome }: PostCardProps) {
24+
function PostCard({ post, forHome, forPost }: PostCardProps) {
2325
const url = `/@${post.user.username}/${post.url_slug}`;
2426

2527
const prefetch = usePrefetchPost(post.user.username, post.url_slug);
@@ -40,6 +42,10 @@ function PostCard({ post, forHome }: PostCardProps) {
4042
onMouseEnter={onMouseEnter}
4143
onMouseLeave={onMouseLeave}
4244
forHome={!!forHome}
45+
forPost={!!forPost}
46+
onClick={() => {
47+
gtag('event', 'recommend_click');
48+
}}
4349
>
4450
{post.thumbnail && (
4551
<StyledLink to={url}>
@@ -88,9 +94,15 @@ function PostCard({ post, forHome }: PostCardProps) {
8894
);
8995
}
9096

91-
export function PostCardSkeleton({ forHome }: { forHome?: boolean }) {
97+
export function PostCardSkeleton({
98+
forHome,
99+
forPost,
100+
}: {
101+
forHome?: boolean;
102+
forPost?: boolean;
103+
}) {
92104
return (
93-
<SkeletonBlock forHome={!!forHome}>
105+
<SkeletonBlock forHome={!!forHome} forPost={!!forPost}>
94106
<div className="skeleton-thumbnail-wrapper">
95107
<Skeleton className="skeleton-thumbnail"></Skeleton>
96108
</div>
@@ -141,7 +153,7 @@ const StyledLink = styled(Link)`
141153
text-decoration: none;
142154
`;
143155

144-
const Block = styled.div<{ forHome: boolean }>`
156+
const Block = styled.div<{ forHome: boolean; forPost: boolean }>`
145157
width: 20rem;
146158
background: white;
147159
border-radius: 4px;
@@ -161,6 +173,7 @@ const Block = styled.div<{ forHome: boolean }>`
161173
162174
${(props) =>
163175
!props.forHome &&
176+
!props.forPost &&
164177
css`
165178
${mediaQuery(1440)} {
166179
width: calc(25% - 2rem);

src/components/common/PostCardGrid.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import { detectAnyAdblocker } from 'just-detect-adblock';
88
import useUser from '../../lib/hooks/useUser';
99

1010
export type PostCardGridProps = {
11-
posts: PartialPost[];
11+
posts: (PartialPost | undefined)[];
1212
loading?: boolean;
1313
forHome?: boolean;
14+
forPost?: boolean;
1415
};
1516

16-
function PostCardGrid({ posts, loading, forHome }: PostCardGridProps) {
17+
function PostCardGrid({ posts, loading, forHome, forPost }: PostCardGridProps) {
1718
const [adBlocked, setAdBlocked] = useState(false);
1819
const user = useUser();
1920

@@ -51,8 +52,15 @@ function PostCardGrid({ posts, loading, forHome }: PostCardGridProps) {
5152
<Block>
5253
{postsWithAds.map((post, i) => {
5354
if (post)
54-
return <PostCard post={post} key={post.id} forHome={forHome} />;
55-
return <AdFeed key={i} />;
55+
return (
56+
<PostCard
57+
post={post}
58+
key={post.id}
59+
forHome={forHome}
60+
forPost={forPost}
61+
/>
62+
);
63+
return <AdFeed key={i} index={i} forPost={forPost} />;
5664
})}
5765
{loading &&
5866
Array.from({ length: 8 }).map((_, i) => (

src/components/postStats/PostStats.tsx

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -61,55 +61,59 @@ function PostStats() {
6161
useEffect(() => {
6262
if (!filledStats) return;
6363

64-
promise.then(() => {
65-
const { echarts } = window;
66-
if (!chartBoxRef.current) return;
67-
if (!echarts) return;
68-
let option = {
69-
tooltip: {
70-
trigger: 'axis',
71-
},
72-
73-
xAxis: {
74-
type: 'time',
75-
boundaryGap: false,
76-
},
77-
yAxis: {
78-
type: 'value',
79-
boundaryGap: [0, '25%'],
80-
},
81-
dataZoom:
82-
filledStats.length > 30
83-
? [
84-
{
85-
type: 'inside',
86-
start: filledStats.length - 30,
87-
end: filledStats.length,
88-
},
89-
{},
90-
]
91-
: undefined,
92-
series: [
93-
{
94-
name: '조회수',
95-
type: 'line',
96-
smooth: false,
97-
data: filledStats.map((item) => [item.day, item.count]),
98-
symbol: 'none',
64+
promise
65+
.then(() => {
66+
const { echarts } = window;
67+
if (!chartBoxRef.current) return;
68+
if (!echarts) return;
69+
let option = {
70+
tooltip: {
71+
trigger: 'axis',
9972
},
100-
],
101-
grid: {
102-
top: 32,
103-
left: 32,
104-
right: 8,
105-
},
106-
};
107-
108-
const myChart =
109-
chartInstance.current ?? echarts.init(chartBoxRef.current);
110-
chartInstance.current = myChart;
111-
myChart.setOption(option);
112-
});
73+
74+
xAxis: {
75+
type: 'time',
76+
boundaryGap: false,
77+
},
78+
yAxis: {
79+
type: 'value',
80+
boundaryGap: [0, '25%'],
81+
},
82+
dataZoom:
83+
filledStats.length > 30
84+
? [
85+
{
86+
type: 'inside',
87+
start: filledStats.length - 30,
88+
end: filledStats.length,
89+
},
90+
{},
91+
]
92+
: undefined,
93+
series: [
94+
{
95+
name: '조회수',
96+
type: 'line',
97+
smooth: false,
98+
data: filledStats.map((item) => [item.day, item.count]),
99+
symbol: 'none',
100+
},
101+
],
102+
grid: {
103+
top: 32,
104+
left: 32,
105+
right: 8,
106+
},
107+
};
108+
109+
const myChart =
110+
chartInstance.current ?? echarts.init(chartBoxRef.current);
111+
chartInstance.current = myChart;
112+
myChart.setOption(option);
113+
})
114+
.catch((e) => {
115+
console.error('Failed to load echarts', e);
116+
});
113117
}, [filledStats]);
114118

115119
// handle chart responsive

src/containers/post/PostViewer.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useCallback, useRef } from 'react';
1+
import React, { useEffect, useCallback, useRef, useState } from 'react';
22
import { useDispatch } from 'react-redux';
33
import {
44
READ_POST,
@@ -61,6 +61,7 @@ const PostViewer: React.FC<PostViewerProps> = ({
6161
history,
6262
match,
6363
}) => {
64+
const [showRecommends, setShowRecommends] = useState(false);
6465
useEffect(() => {
6566
window.scrollTo(0, 0);
6667
}, [username, urlSlug]);
@@ -136,6 +137,8 @@ const PostViewer: React.FC<PostViewerProps> = ({
136137
}
137138
}, [data, prefetchPost]);
138139

140+
const postReady = !!data?.post;
141+
139142
const onScroll = useCallback(() => {
140143
const scrollTop = getScrollTop();
141144
const { scrollHeight } = document.body;
@@ -144,7 +147,10 @@ const PostViewer: React.FC<PostViewerProps> = ({
144147
if (percentage > 50) {
145148
prefetchLinkedPosts();
146149
}
147-
}, [prefetchLinkedPosts]);
150+
if (percentage > 75 && postReady) {
151+
setShowRecommends(true);
152+
}
153+
}, [prefetchLinkedPosts, postReady]);
148154

149155
useEffect(() => {
150156
if (!data) return;
@@ -372,17 +378,14 @@ const PostViewer: React.FC<PostViewerProps> = ({
372378
/>
373379
</UserProfileWrapper>
374380
<LinkedPostList linkedPosts={post.linked_posts} />
375-
<RelatedPost
376-
showAds={
377-
Date.now() - new Date(post.released_at).getTime() >
378-
1000 * 60 * 60 * 24 * 30 * 3 && userId === null
379-
}
380-
/>
381381
<PostComments
382382
count={post.comments_count}
383383
comments={post.comments}
384384
postId={post.id}
385385
/>
386+
{showRecommends && (
387+
<RelatedPost showAds={userId === null} postId={post.id} />
388+
)}
386389
</PostViewerProvider>
387390
);
388391
};

0 commit comments

Comments
 (0)