Commit 8f5c41a4 authored by Max Alekseenko's avatar Max Alekseenko

add check if specific address can rate

parent a630b361
......@@ -53,6 +53,7 @@ NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6u
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
NEXT_PUBLIC_MARKETPLACE_FEATURED_APP=gearbox-protocol
NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=app4iqrpmtJ5NrbjP
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'uniswap'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}]
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG={'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}
......
......@@ -24,6 +24,7 @@ interface Props extends MarketplaceAppWithSecurityReport {
rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
}
const MarketplaceAppCard = ({
......@@ -50,6 +51,7 @@ const MarketplaceAppCard = ({
rateApp,
isSendingRating,
isRatingLoading,
canRate,
}: Props) => {
const isMobile = useIsMobile();
const categoriesLabel = categories.join(', ');
......@@ -177,7 +179,7 @@ const MarketplaceAppCard = ({
rate={ rateApp }
isSending={ isSendingRating }
isLoading={ isRatingLoading }
canRate={ Math.random() > 0.5 }
canRate={ canRate }
/>
<IconButton
aria-label="Mark as favorite"
......
......@@ -27,6 +27,7 @@ type Props = {
rateApp: (appId: string, recordId: string | undefined, rating: number) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
}
const MarketplaceAppModal = ({
......@@ -39,6 +40,7 @@ const MarketplaceAppModal = ({
rateApp,
isSendingRating,
isRatingLoading,
canRate,
}: Props) => {
const {
id,
......@@ -172,7 +174,7 @@ const MarketplaceAppModal = ({
isSending={ isSendingRating }
isLoading={ isRatingLoading }
fullView
canRate={ Math.random() > 0.5 }
canRate={ canRate }
/>
</Box>
......
......@@ -22,11 +22,12 @@ type Props = {
rateApp: (appId: string, recordId: string, rating: number) => void;
isSendingRating: boolean;
isRatingLoading: boolean;
canRate: boolean | undefined;
}
const MarketplaceList = ({
apps, showAppInfo, favoriteApps, onFavoriteClick, isLoading, selectedCategoryId,
onAppClick, showContractList, userRatings, rateApp, isSendingRating, isRatingLoading,
onAppClick, showContractList, userRatings, rateApp, isSendingRating, isRatingLoading, canRate,
}: Props) => {
const handleInfoClick = useCallback((id: string) => {
mixpanel.logEvent(mixpanel.EventTypes.PAGE_WIDGET, { Type: 'More button', Info: id, Source: 'Discovery view' });
......@@ -71,6 +72,7 @@ const MarketplaceList = ({
rateApp={ rateApp }
isSendingRating={ isSendingRating }
isRatingLoading={ isRatingLoading }
canRate={ canRate }
/>
)) }
</Grid>
......
......@@ -14,7 +14,7 @@ type Props = {
isSending?: boolean;
isLoading?: boolean;
fullView?: boolean;
canRate: boolean;
canRate: boolean | undefined;
};
const Rating = ({
......
import { Button, chakra, useColorModeValue, Tooltip } from '@chakra-ui/react';
import React from 'react';
import { useAccount } from 'wagmi';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import IconSvg from 'ui/shared/IconSvg';
......@@ -10,11 +9,11 @@ type Props = {
fullView?: boolean;
isActive: boolean;
onClick: () => void;
canRate: boolean;
canRate: boolean | undefined;
};
const getTooltipText = (isWalletConnected: boolean, canRate: boolean) => {
if (!isWalletConnected) {
const getTooltipText = (canRate: boolean | undefined) => {
if (canRate === undefined) {
return <>You need a connected wallet to leave your rating.<br/>Link your wallet to Blockscout first</>;
}
if (!canRate) {
......@@ -29,11 +28,10 @@ const TriggerButton = (
) => {
const textColor = useColorModeValue('blackAlpha.800', 'whiteAlpha.800');
const onFocusCapture = usePreventFocusAfterModalClosing();
const { address } = useAccount();
return (
<Tooltip
label={ getTooltipText(Boolean(address), canRate) }
label={ getTooltipText(canRate) }
openDelay={ 100 }
textAlign="center"
>
......@@ -43,7 +41,7 @@ const TriggerButton = (
variant="outline"
border={ 0 }
p={ 0 }
onClick={ canRate && Boolean(address) ? onClick : undefined }
onClick={ canRate ? onClick : undefined }
fontSize={ fullView ? 'md' : 'sm' }
fontWeight={ fullView ? '400' : '500' }
lineHeight="21px"
......
......@@ -5,6 +5,8 @@ import { useAccount } from 'wagmi';
import type { UserRatings, AppRatings } from 'types/client/marketplace';
import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import { ADDRESS_COUNTERS } from 'stubs/address';
const feature = config.features.marketplace;
const base = (feature.isEnabled && feature.rating) ?
......@@ -14,10 +16,21 @@ const base = (feature.isEnabled && feature.rating) ?
export default function useRatings() {
const { address } = useAccount();
const addressCountersQuery = useApiQuery<'address_counters', { status: number }>('address_counters', {
pathParams: { hash: address },
queryOptions: {
enabled: Boolean(address),
placeholderData: ADDRESS_COUNTERS,
refetchOnMount: false,
},
});
const [ ratings, setRatings ] = useState<AppRatings>({});
const [ userRatings, setUserRatings ] = useState<UserRatings>({});
const [ isLoading, setIsLoading ] = useState<boolean>(false);
const [ isRatingLoading, setIsRatingLoading ] = useState<boolean>(false);
const [ isUserRatingLoading, setIsUserRatingLoading ] = useState<boolean>(false);
const [ isSending, setIsSending ] = useState<boolean>(false);
const [ canRate, setCanRate ] = useState<boolean | undefined>(undefined);
const fetchRatings = useCallback(async() => {
if (!base) {
......@@ -37,15 +50,16 @@ export default function useRatings() {
useEffect(() => {
async function fetch() {
setIsLoading(true);
setIsRatingLoading(true);
await fetchRatings();
setIsLoading(false);
setIsRatingLoading(false);
}
fetch();
}, [ fetchRatings ]);
useEffect(() => {
async function fetchUserRatings() {
setIsUserRatingLoading(true);
let userRatings = {} as UserRatings;
if (address && base) {
const data = await base('users_ratings').select({
......@@ -62,10 +76,17 @@ export default function useRatings() {
}, {});
}
setUserRatings(userRatings);
setIsUserRatingLoading(false);
}
fetchUserRatings();
}, [ address ]);
useEffect(() => {
const { isPlaceholderData, data } = addressCountersQuery;
const canRate = address && !isPlaceholderData && Number(data?.transactions_count) >= 10;
setCanRate(canRate);
}, [ address, addressCountersQuery ]);
const rateApp = useCallback(async(appId: string, recordId: string | undefined, rating: number) => {
if (!address || !base || !recordId) {
return;
......@@ -92,6 +113,8 @@ export default function useRatings() {
userRatings,
rateApp,
isSendingRating: isSending,
isRatingLoading: isLoading,
isRatingLoading,
isUserRatingLoading,
canRate,
};
}
......@@ -87,7 +87,7 @@ export default function useMarketplace() {
const {
isPlaceholderData, isError, error, data, displayedApps, setSorting,
userRatings, rateApp, isSendingRating, isRatingLoading,
userRatings, rateApp, isSendingRating, isRatingLoading, canRate,
} = useMarketplaceApps(debouncedFilterQuery, selectedCategoryId, favoriteApps, isFavoriteAppsLoaded);
const {
isPlaceholderData: isCategoriesPlaceholderData, data: categories,
......@@ -156,6 +156,7 @@ export default function useMarketplace() {
rateApp,
isSendingRating,
isRatingLoading,
canRate,
}), [
selectedCategoryId,
categories,
......@@ -183,5 +184,6 @@ export default function useMarketplace() {
rateApp,
isSendingRating,
isRatingLoading,
canRate,
]);
}
......@@ -61,7 +61,7 @@ export default function useMarketplaceApps(
const apiFetch = useApiFetch();
const { data: securityReports, isPlaceholderData: isSecurityReportsPlaceholderData } = useSecurityReports();
const { ratings, userRatings, rateApp, isSendingRating, isRatingLoading } = useRatings();
const { ratings, userRatings, rateApp, isSendingRating, isRatingLoading, canRate } = useRatings();
// Set the value only 1 time to avoid unnecessary useQuery calls and re-rendering of all applications
const [ snapshotFavoriteApps, setSnapshotFavoriteApps ] = React.useState<Array<string> | undefined>();
......@@ -124,6 +124,7 @@ export default function useMarketplaceApps(
rateApp,
isSendingRating,
isRatingLoading,
canRate,
}), [
data,
displayedApps,
......@@ -136,5 +137,6 @@ export default function useMarketplaceApps(
rateApp,
isSendingRating,
isRatingLoading,
canRate,
]);
}
......@@ -73,6 +73,7 @@ const Marketplace = () => {
rateApp,
isSendingRating,
isRatingLoading,
canRate,
} = useMarketplace();
const isMobile = useIsMobile();
......@@ -221,6 +222,7 @@ const Marketplace = () => {
rateApp={ rateApp }
isSendingRating={ isSendingRating }
isRatingLoading={ isRatingLoading }
canRate={ canRate }
/>
{ (selectedApp && isAppInfoModalOpen) && (
......@@ -234,6 +236,7 @@ const Marketplace = () => {
rateApp={ rateApp }
isSendingRating={ isSendingRating }
isRatingLoading={ isRatingLoading }
canRate={ canRate }
/>
) }
......
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