Skip to content

Commit e2ab8c3

Browse files
authored
Likes for community search (codesandbox#5620)
* locally managed likes * managed like as well
1 parent 3745720 commit e2ab8c3

File tree

4 files changed

+79
-22
lines changed

4 files changed

+79
-22
lines changed

packages/app/src/app/overmind/namespaces/dashboard/actions.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,3 +1852,18 @@ export const unlikeSandbox = async (
18521852
effects.notificationToast.error('There was a problem removing your like');
18531853
}
18541854
};
1855+
1856+
export const likeCommunitySandbox = async (
1857+
{ actions, effects }: Context,
1858+
id: string
1859+
) => {
1860+
try {
1861+
// we don't have optimistic updates because the shape of
1862+
// a liked sandbox is not the same as a community sandbox
1863+
// so we refetch liked sandboxes from the api
1864+
await effects.api.likeSandbox(id);
1865+
actions.dashboard.getLikedSandboxes();
1866+
} catch (e) {
1867+
effects.notificationToast.error('There was a problem liking the sandbox');
1868+
}
1869+
};

packages/app/src/app/pages/Dashboard/Components/CommunitySandbox/CommunitySandboxCard.tsx

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import React from 'react';
2-
import { Stack, Text, Icon, IconButton, Avatar } from '@codesandbox/components';
2+
import {
3+
Stack,
4+
Text,
5+
Icon,
6+
IconButton,
7+
Avatar,
8+
Button,
9+
} from '@codesandbox/components';
310
import { formatNumber } from '@codesandbox/components/lib/components/Stats';
411
import css from '@styled-system/css';
512
import { AnonymousAvatar } from './AnonymousAvatar';
@@ -47,25 +54,35 @@ const SandboxTitle: React.FC<SandboxTitleProps> = React.memo(
4754

4855
type StatsProps = Pick<
4956
CommunitySandboxItemComponentProps,
50-
'forkCount' | 'likeCount' | 'liked'
57+
'forkCount' | 'likeCount' | 'liked' | 'onLikeToggle'
5158
>;
52-
const Stats: React.FC<StatsProps> = React.memo(
53-
({ forkCount, likeCount, liked }) => (
54-
<Stack as={Text} variant="muted" align="center" gap={2}>
55-
<Stack align="center" gap={1}>
56-
<Icon name="fork" size={14} />
57-
<Text size={3}>{formatNumber(forkCount)}</Text>
58-
</Stack>
59-
<Stack align="center" gap={1}>
60-
<Icon
61-
name="heart"
62-
size={14}
63-
css={css({ color: liked ? 'reds.300' : 'inherit' })}
64-
/>
65-
<Text size={3}>{formatNumber(likeCount)}</Text>
66-
</Stack>
59+
const Stats: React.FC<StatsProps> = ({
60+
forkCount,
61+
likeCount,
62+
liked,
63+
onLikeToggle,
64+
}) => (
65+
<Stack as={Text} variant="muted" align="center" gap={2}>
66+
<Stack align="center" gap={1}>
67+
<Icon name="fork" size={14} />
68+
<Text size={3}>{formatNumber(forkCount)}</Text>
6769
</Stack>
68-
)
70+
<Stack
71+
as={Button}
72+
variant="link"
73+
gap={1}
74+
autoWidth
75+
paddingX={0}
76+
onClick={onLikeToggle}
77+
>
78+
<Icon
79+
name="heart"
80+
size={14}
81+
css={css({ color: liked ? 'reds.300' : 'inherit' })}
82+
/>
83+
<Text size={3}>{formatNumber(likeCount)}</Text>
84+
</Stack>
85+
</Stack>
6986
);
7087

7188
type AuthorProps = Pick<CommunitySandboxItemComponentProps, 'author'>;
@@ -98,6 +115,7 @@ export const SandboxCard = ({
98115
onClick,
99116
onDoubleClick,
100117
onContextMenu,
118+
onLikeToggle,
101119
...props
102120
}: CommunitySandboxItemComponentProps) => {
103121
const [stoppedScrolling, setStoppedScrolling] = React.useState(false);
@@ -151,7 +169,12 @@ export const SandboxCard = ({
151169
marginRight={3}
152170
>
153171
<Author author={author} />
154-
<Stats likeCount={likeCount} forkCount={forkCount} liked={liked} />
172+
<Stats
173+
likeCount={likeCount}
174+
forkCount={forkCount}
175+
liked={liked}
176+
onLikeToggle={onLikeToggle}
177+
/>
155178
</Stack>
156179
</Stack>
157180
</Stack>

packages/app/src/app/pages/Dashboard/Components/CommunitySandbox/index.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { useHistory } from 'react-router-dom';
33

4-
import { useAppState } from 'app/overmind';
4+
import { useAppState, useActions } from 'app/overmind';
55
import { sandboxUrl } from '@codesandbox/common/lib/utils/url-generator';
66
import track from '@codesandbox/common/lib/utils/analytics';
77
import { SandboxCard } from './CommunitySandboxCard';
@@ -22,6 +22,9 @@ export const CommunitySandbox = ({
2222
const {
2323
dashboard: { viewMode },
2424
} = useAppState();
25+
const {
26+
dashboard: { likeCommunitySandbox, unlikeSandbox },
27+
} = useActions();
2528

2629
const { sandbox } = item;
2730
const title = sandbox.title || sandbox.alias || sandbox.id;
@@ -73,14 +76,28 @@ export const CommunitySandbox = ({
7376
track('Dashboard - Community Search sandbox opened');
7477
};
7578

79+
const [managedLikeCount, setLikeCount] = React.useState(likeCount);
80+
const [managedLiked, setLiked] = React.useState(liked);
81+
const onLikeToggle = () => {
82+
if (managedLiked) {
83+
unlikeSandbox(sandbox.id);
84+
setLiked(false);
85+
setLikeCount(managedLikeCount - 1);
86+
} else {
87+
likeCommunitySandbox(sandbox.id);
88+
setLiked(true);
89+
setLikeCount(managedLikeCount + 1);
90+
}
91+
};
92+
7693
const sandboxProps = {
7794
title,
7895
TemplateIcon,
7996
screenshotUrl,
8097
forkCount,
81-
likeCount,
8298
author,
83-
liked,
99+
likeCount: managedLikeCount,
100+
liked: managedLiked,
84101
};
85102

86103
const interactionProps = {
@@ -94,6 +111,7 @@ export const CommunitySandbox = ({
94111
onDoubleClick,
95112
onContextMenu,
96113
'data-selection-id': sandbox.id,
114+
onLikeToggle,
97115
};
98116

99117
const Component = viewMode === 'list' ? SandboxListItem : SandboxCard;

packages/app/src/app/pages/Dashboard/Components/CommunitySandbox/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ export type CommunitySandboxItemComponentProps = Pick<
1515
onClick: (evt: React.MouseEvent) => void;
1616
onDoubleClick: (evt: React.MouseEvent) => void;
1717
onContextMenu: (evt: React.MouseEvent) => void;
18+
onLikeToggle: (evt: React.MouseEvent) => void;
1819
};

0 commit comments

Comments
 (0)