@@ -2,7 +2,7 @@ import 'dayjs/plugin/relativeTime';
22
33import dayjs from 'dayjs' ;
44import styled from 'styled-components' ;
5- import React , { forwardRef } from 'react' ;
5+ import React , { forwardRef , useCallback } from 'react' ;
66import {
77 Button ,
88 IconDeckArrow ,
@@ -11,23 +11,23 @@ import {
1111 Skeleton ,
1212 Text ,
1313} from '@box/shared/ui' ;
14- import type { Card , User } from '@box/shared/api' ;
14+ import type { Card } from '@box/shared/api' ;
1515import { Editor , useExtendedEditor } from '@cardbox/editor' ;
1616import type { EditorValue } from '@cardbox/editor' ;
1717import { HighlightText } from '@box/entities/search' ;
1818import { Link } from 'react-router-dom' ;
1919import { breakpoints } from '@box/shared/lib/breakpoints' ;
20+ import { cardModel } from '@box/entities/card' ;
2021import { navigationModel } from '@box/entities/navigation' ;
22+ import { paths } from '@box/pages/paths' ;
2123import { theme } from '@box/shared/lib/theme' ;
22- import { useEvent } from 'effector-react' ;
24+ import { useEvent , useStoreMap } from 'effector-react/scope ' ;
2325import { useMouseSelection } from '@box/shared/lib/use-mouse-selection' ;
2426
2527type CardSize = 'small' | 'large' ;
2628
2729interface CardPreviewProps {
2830 card : Card ;
29- isCardInFavorite ?: boolean ;
30- href ?: string ;
3131 loading ?: boolean ;
3232 /**
3333 * @remark May be in future - make sense to split independent components - CardItem, CardDetails
@@ -38,13 +38,25 @@ interface CardPreviewProps {
3838
3939export const CardPreview = ( {
4040 card,
41- isCardInFavorite = false ,
42- href,
4341 loading = false ,
4442 size = 'small' ,
4543} : CardPreviewProps ) => {
44+ const href = paths . cardView ( card . id ) ;
45+ const isCardInFavorites = useStoreMap ( {
46+ store : cardModel . $favoritesCards ,
47+ keys : [ card . id ] ,
48+ fn : ( list , [ id ] ) => list . some ( ( card ) => card . id === id ) ,
49+ } ) ;
50+
51+ const addToFavorites = useEvent ( cardModel . favoritesAdd ) ;
52+ const removeFromFavorites = useEvent ( cardModel . favoritesRemove ) ;
4653 const historyPush = useEvent ( navigationModel . historyPush ) ;
4754
55+ const toggleFavorites = useCallback ( ( ) => {
56+ if ( isCardInFavorites ) removeFromFavorites ( card . id ) ;
57+ else addToFavorites ( card . id ) ;
58+ } , [ addToFavorites , removeFromFavorites , card . id , isCardInFavorites ] ) ;
59+
4860 const { handleMouseDown, handleMouseUp, buttonRef } = useMouseSelection (
4961 ( inNewTab = false ) => {
5062 if ( ! href ) return ;
@@ -66,13 +78,18 @@ export const CardPreview = ({
6678 aria-label = "Open card"
6779 >
6880 < ContentBlock >
69- < Content card = { card } href = { href } size = { size } />
81+ < Content card = { card } size = { size } />
7082
7183 < OverHelm />
7284 </ ContentBlock >
7385
7486 { size === 'small' && < Meta card = { card } /> }
75- < AddButton ref = { buttonRef } isCardToDeckAdded = { isCardInFavorite } />
87+ < SaveCardButton
88+ ref = { buttonRef }
89+ onClick = { toggleFavorites }
90+ isCardInFavorites = { isCardInFavorites }
91+ card = { card }
92+ />
7693 </ PaperContainerStyled >
7794 ) ;
7895} ;
@@ -120,9 +137,10 @@ const PaperContainerStyled = styled(PaperContainer)<{
120137 }
121138` ;
122139
123- type ContentProps = { card : Card } & Pick < CardPreviewProps , 'href' | ' size'> ;
140+ type ContentProps = { card : Card } & Pick < CardPreviewProps , 'size' > ;
124141
125- const Content = ( { card, size, href } : ContentProps ) => {
142+ const Content = ( { card, size } : ContentProps ) => {
143+ const href = paths . cardView ( card . id ) ;
126144 const editor = useExtendedEditor ( ) ;
127145 return (
128146 < ContentStyled >
@@ -200,35 +218,41 @@ const ContentStyled = styled.div`
200218 overflow: hidden;
201219` ;
202220
203- const AddButton = forwardRef < HTMLButtonElement , { isCardToDeckAdded : boolean } > (
204- ( { isCardToDeckAdded } , ref ) => {
205- const handleClick : React . MouseEventHandler = ( e ) => {
206- e . stopPropagation ( ) ;
207- } ;
208-
209- if ( isCardToDeckAdded ) {
210- return (
211- < CardButton
212- ref = { ref }
213- onClick = { handleClick }
214- variant = "outlined"
215- theme = "primary"
216- icon = { < IconDeckCheck title = "Remove card from my deck" /> }
217- />
218- ) ;
219- }
221+ const SaveCardButton = forwardRef <
222+ HTMLButtonElement ,
223+ {
224+ isCardInFavorites : boolean ;
225+ card : Card ;
226+ onClick : ( id : string ) => void ;
227+ }
228+ > ( ( { isCardInFavorites, card, onClick } , ref ) => {
229+ const handleClick : React . MouseEventHandler = ( e ) => {
230+ e . stopPropagation ( ) ;
231+ onClick ( card . id ) ;
232+ } ;
220233
234+ if ( isCardInFavorites ) {
221235 return (
222236 < CardButton
223237 ref = { ref }
224238 onClick = { handleClick }
225239 variant = "outlined"
226- theme = "secondary "
227- icon = { < IconDeckArrow title = "Add card to my deck" /> }
240+ theme = "primary "
241+ icon = { < IconDeckCheck title = "Remove card from my deck" /> }
228242 />
229243 ) ;
230- } ,
231- ) ;
244+ }
245+
246+ return (
247+ < CardButton
248+ ref = { ref }
249+ onClick = { handleClick }
250+ variant = "outlined"
251+ theme = "secondary"
252+ icon = { < IconDeckArrow title = "Add card to my deck" /> }
253+ />
254+ ) ;
255+ } ) ;
232256
233257const ContentBlock = styled . div `
234258 display: flex;
0 commit comments