Commit 6d330329 authored by Max Alekseenko's avatar Max Alekseenko

update rating component

parent 9a524463
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
<path d="M16 31a15 15 0 1 1 0-30 15 15 0 0 1 0 30Zm0-28a13 13 0 1 0 0 26 13 13 0 0 0 0-26Z" fill="currentColor"/>
<path d="M13.67 22a1 1 0 0 1-.73-.32l-4.67-5a1 1 0 0 1 1.46-1.36l3.94 4.21 8.6-9.21a1 1 0 1 1 1.46 1.36l-9.33 10a1 1 0 0 1-.73.32Z" fill="currentColor"/>
</svg>
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
| "brands/solidity_scan" | "brands/solidity_scan"
| "burger" | "burger"
| "certified" | "certified"
| "check_circle"
| "check" | "check"
| "clock-light" | "clock-light"
| "clock" | "clock"
......
...@@ -20,7 +20,7 @@ interface Props extends MarketplaceAppWithSecurityReport { ...@@ -20,7 +20,7 @@ interface Props extends MarketplaceAppWithSecurityReport {
onAppClick: (event: MouseEvent, id: string) => void; onAppClick: (event: MouseEvent, id: string) => void;
className?: string; className?: string;
showContractList: (id: string, type: ContractListTypes) => void; showContractList: (id: string, type: ContractListTypes) => void;
isRatedByUser: boolean; userRating: number | undefined;
rateApp: (appId: string, recordId: string | undefined, rating: number) => void; rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
isSendingRating: boolean; isSendingRating: boolean;
isRatingLoading: boolean; isRatingLoading: boolean;
...@@ -47,7 +47,7 @@ const MarketplaceAppCard = ({ ...@@ -47,7 +47,7 @@ const MarketplaceAppCard = ({
showContractList, showContractList,
rating, rating,
ratingRecordId, ratingRecordId,
isRatedByUser, userRating,
rateApp, rateApp,
isSendingRating, isSendingRating,
isRatingLoading, isRatingLoading,
...@@ -175,7 +175,7 @@ const MarketplaceAppCard = ({ ...@@ -175,7 +175,7 @@ const MarketplaceAppCard = ({
appId={ id } appId={ id }
rating={ rating } rating={ rating }
recordId={ ratingRecordId } recordId={ ratingRecordId }
isRatedByUser={ isRatedByUser } userRating={ userRating }
rate={ rateApp } rate={ rateApp }
isSending={ isSendingRating } isSending={ isSendingRating }
isLoading={ isRatingLoading } isLoading={ isRatingLoading }
......
...@@ -17,7 +17,7 @@ const props = { ...@@ -17,7 +17,7 @@ const props = {
securityReport: securityReportsMock[0].chainsData['1'], securityReport: securityReportsMock[0].chainsData['1'],
} as MarketplaceAppWithSecurityReport, } as MarketplaceAppWithSecurityReport,
isFavorite: false, isFavorite: false,
isRatedByUser: false, userRating: undefined,
rateApp: () => {}, rateApp: () => {},
isSendingRating: false, isSendingRating: false,
isRatingLoading: false, isRatingLoading: false,
......
...@@ -23,7 +23,7 @@ type Props = { ...@@ -23,7 +23,7 @@ type Props = {
onFavoriteClick: (id: string, isFavorite: boolean, source: 'App modal') => void; onFavoriteClick: (id: string, isFavorite: boolean, source: 'App modal') => void;
data: MarketplaceAppWithSecurityReport; data: MarketplaceAppWithSecurityReport;
showContractList: (id: string, type: ContractListTypes, hasPreviousStep: boolean) => void; showContractList: (id: string, type: ContractListTypes, hasPreviousStep: boolean) => void;
isRatedByUser: boolean; userRating: number | undefined;
rateApp: (appId: string, recordId: string | undefined, rating: number) => void; rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
isSendingRating: boolean; isSendingRating: boolean;
isRatingLoading: boolean; isRatingLoading: boolean;
...@@ -36,7 +36,7 @@ const MarketplaceAppModal = ({ ...@@ -36,7 +36,7 @@ const MarketplaceAppModal = ({
onFavoriteClick, onFavoriteClick,
data, data,
showContractList: showContractListProp, showContractList: showContractListProp,
isRatedByUser, userRating,
rateApp, rateApp,
isSendingRating, isSendingRating,
isRatingLoading, isRatingLoading,
...@@ -170,7 +170,7 @@ const MarketplaceAppModal = ({ ...@@ -170,7 +170,7 @@ const MarketplaceAppModal = ({
appId={ id } appId={ id }
rating={ rating } rating={ rating }
recordId={ ratingRecordId } recordId={ ratingRecordId }
isRatedByUser={ isRatedByUser } userRating={ userRating }
rate={ rateApp } rate={ rateApp }
isSending={ isSendingRating } isSending={ isSendingRating }
isLoading={ isRatingLoading } isLoading={ isRatingLoading }
......
...@@ -91,7 +91,7 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props) ...@@ -91,7 +91,7 @@ const MarketplaceAppTopBar = ({ appId, data, isLoading, securityReport }: Props)
appId={ appId } appId={ appId }
rating={ ratings?.[appId]?.rating } rating={ ratings?.[appId]?.rating }
recordId={ ratings?.[appId]?.recordId } recordId={ ratings?.[appId]?.recordId }
isRatedByUser={ Boolean(userRatings[appId]) } userRating={ userRatings[appId] }
rate={ rateApp } rate={ rateApp }
isSending={ isSendingRating } isSending={ isSendingRating }
isLoading={ isRatingLoading } isLoading={ isRatingLoading }
......
...@@ -68,7 +68,7 @@ const MarketplaceList = ({ ...@@ -68,7 +68,7 @@ const MarketplaceList = ({
showContractList={ showContractList } showContractList={ showContractList }
rating={ app.rating } rating={ app.rating }
ratingRecordId={ app.ratingRecordId } ratingRecordId={ app.ratingRecordId }
isRatedByUser={ Boolean(userRatings[app.id]) } userRating={ userRatings[app.id] }
rateApp={ rateApp } rateApp={ rateApp }
isSendingRating={ isSendingRating } isSendingRating={ isSendingRating }
isRatingLoading={ isRatingLoading } isRatingLoading={ isRatingLoading }
......
import { Text, Flex, Spinner } from '@chakra-ui/react'; import { Text, Flex, Spinner, Button } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import IconSvg from 'ui/shared/IconSvg';
import Stars from './Stars'; import Stars from './Stars';
const ratingDescriptions = [ 'Terrible', 'Poor', 'Average', 'Very good', 'Outstanding' ]; const ratingDescriptions = [ 'Terrible', 'Poor', 'Average', 'Very good', 'Outstanding' ];
...@@ -10,32 +8,47 @@ const ratingDescriptions = [ 'Terrible', 'Poor', 'Average', 'Very good', 'Outsta ...@@ -10,32 +8,47 @@ const ratingDescriptions = [ 'Terrible', 'Poor', 'Average', 'Very good', 'Outsta
type Props = { type Props = {
appId: string; appId: string;
recordId?: string; recordId?: string;
isRatedByUser?: boolean; userRating: number | undefined;
rate: (appId: string, recordId: string | undefined, rating: number) => void; rate: (appId: string, recordId: string | undefined, rating: number) => void;
isSending?: boolean; isSending?: boolean;
}; };
const PopoverContent = ({ appId, recordId, isRatedByUser, rate, isSending }: Props) => { const PopoverContent = ({ appId, recordId, userRating, rate, isSending }: Props) => {
const [ hovered, setHovered ] = React.useState(-1); const [ hovered, setHovered ] = React.useState(-1);
const [ selected, setSelected ] = React.useState(-1);
const handleMouseOverFactory = React.useCallback((index: number) => () => { const handleMouseOverFactory = React.useCallback((index: number) => () => {
setHovered(index); setHovered(index);
}, []); }, []);
const handleSelectFactory = React.useCallback((index: number) => () => {
setSelected(index);
}, []);
const handleMouseOut = React.useCallback(() => { const handleMouseOut = React.useCallback(() => {
setHovered(-1); setHovered(-1);
}, []); }, []);
const handleRateFactory = React.useCallback((index: number) => () => { const handleRate = React.useCallback(() => {
rate(appId, recordId, index + 1); if (selected < 0) {
}, [ appId, recordId, rate ]); return;
}
rate(appId, recordId, selected + 1);
}, [ appId, recordId, selected, rate ]);
if (isRatedByUser) { if (userRating) {
return ( return (
<Flex alignItems="center"> <>
<IconSvg name="check_circle" color="green.500" boxSize={ 8 }/> <Text fontWeight="500" fontSize="xs" lineHeight="30px" variant="secondary">
<Text fontSize="md" ml={ 3 }>App is already rated</Text> App is already rated by you
</Flex> </Text>
<Flex alignItems="center" h="32px">
<Stars filledIndex={ userRating - 1 }/>
<Text fontSize="md" ml={ 2 }>
{ ratingDescriptions[ userRating - 1 ] }
</Text>
</Flex>
</>
); );
} }
...@@ -55,17 +68,20 @@ const PopoverContent = ({ appId, recordId, isRatedByUser, rate, isSending }: Pro ...@@ -55,17 +68,20 @@ const PopoverContent = ({ appId, recordId, isRatedByUser, rate, isSending }: Pro
</Text> </Text>
<Flex alignItems="center" h="32px"> <Flex alignItems="center" h="32px">
<Stars <Stars
filledIndex={ hovered } filledIndex={ hovered >= 0 ? hovered : selected }
onMouseOverFactory={ handleMouseOverFactory } onMouseOverFactory={ handleMouseOverFactory }
onMouseOut={ handleMouseOut } onMouseOut={ handleMouseOut }
onClickFactory={ handleRateFactory } onClickFactory={ handleSelectFactory }
/> />
{ hovered >= 0 && ( { (hovered >= 0 || selected >= 0) && (
<Text fontSize="md" ml={ 2 }> <Text fontSize="md" ml={ 2 }>
{ ratingDescriptions[ hovered ] } { ratingDescriptions[ hovered >= 0 ? hovered : selected ] }
</Text> </Text>
) } ) }
</Flex> </Flex>
<Button size="sm" px={ 4 } mt={ 3 } onClick={ handleRate } isDisabled={ selected < 0 }>
Rate it
</Button>
</> </>
); );
}; };
......
...@@ -11,7 +11,7 @@ type Props = { ...@@ -11,7 +11,7 @@ type Props = {
appId: string; appId: string;
rating?: number; rating?: number;
recordId?: string; recordId?: string;
isRatedByUser?: boolean; userRating: number | undefined;
rate: (appId: string, recordId: string | undefined, rating: number) => void; rate: (appId: string, recordId: string | undefined, rating: number) => void;
isSending?: boolean; isSending?: boolean;
isLoading?: boolean; isLoading?: boolean;
...@@ -20,7 +20,7 @@ type Props = { ...@@ -20,7 +20,7 @@ type Props = {
}; };
const Rating = ({ const Rating = ({
appId, rating, recordId, isRatedByUser, rate, appId, rating, recordId, userRating, rate,
isSending, isLoading, fullView, canRate, isSending, isLoading, fullView, canRate,
}: Props) => { }: Props) => {
const { isOpen, onToggle, onClose } = useDisclosure(); const { isOpen, onToggle, onClose } = useDisclosure();
...@@ -53,7 +53,7 @@ const Rating = ({ ...@@ -53,7 +53,7 @@ const Rating = ({
<Content <Content
appId={ appId } appId={ appId }
recordId={ recordId } recordId={ recordId }
isRatedByUser={ isRatedByUser } userRating={ userRating }
rate={ rate } rate={ rate }
isSending={ isSending } isSending={ isSending }
/> />
......
...@@ -10,23 +10,26 @@ type Props = { ...@@ -10,23 +10,26 @@ type Props = {
onClickFactory?: (index: number) => MouseEventHandler<HTMLDivElement>; onClickFactory?: (index: number) => MouseEventHandler<HTMLDivElement>;
}; };
const Stars = ({ filledIndex, onMouseOverFactory, onMouseOut, onClickFactory }: Props) => ( const Stars = ({ filledIndex, onMouseOverFactory, onMouseOut, onClickFactory }: Props) => {
<> const outlineStartColor = onMouseOverFactory ? 'gray.400' : 'gray.200';
{ Array(5).fill(null).map((_, index) => ( return (
<IconSvg <>
key={ index } { Array(5).fill(null).map((_, index) => (
name={ filledIndex >= index ? 'star_filled' : 'star_outline' } <IconSvg
color={ filledIndex >= index ? 'yellow.400' : 'gray.400' } key={ index }
w={ 6 } // 5 + 1 padding name={ filledIndex >= index ? 'star_filled' : 'star_outline' }
h={ 5 } color={ filledIndex >= index ? 'yellow.400' : outlineStartColor }
pr={ 1 } // use padding intead of margin so that there are no empty spaces between stars without hover effect w={ 6 } // 5 + 1 padding
cursor={ onMouseOverFactory ? 'pointer' : 'default' } h={ 5 }
onMouseOver={ onMouseOverFactory?.(index) } pr={ 1 } // use padding intead of margin so that there are no empty spaces between stars without hover effect
onMouseOut={ onMouseOut } cursor={ onMouseOverFactory ? 'pointer' : 'default' }
onClick={ onClickFactory?.(index) } onMouseOver={ onMouseOverFactory?.(index) }
/> onMouseOut={ onMouseOut }
)) } onClick={ onClickFactory?.(index) }
</> />
); )) }
</>
);
};
export default Stars; export default Stars;
...@@ -233,7 +233,7 @@ const Marketplace = () => { ...@@ -233,7 +233,7 @@ const Marketplace = () => {
onFavoriteClick={ onFavoriteClick } onFavoriteClick={ onFavoriteClick }
data={ selectedApp } data={ selectedApp }
showContractList={ showContractList } showContractList={ showContractList }
isRatedByUser={ Boolean(userRatings[selectedApp.id]) } userRating={ userRatings[selectedApp.id] }
rateApp={ rateApp } rateApp={ rateApp }
isSendingRating={ isSendingRating } isSendingRating={ isSendingRating }
isRatingLoading={ isRatingLoading } isRatingLoading={ isRatingLoading }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment