Skip to content

Commit

Permalink
Add social oracle info (#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
hellno authored Aug 26, 2024
1 parent 3640fdf commit 1ca5219
Show file tree
Hide file tree
Showing 32 changed files with 376 additions and 108 deletions.
2 changes: 1 addition & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const nextConfig = {
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=3600',
value: 'public, max-age=43200, s-maxage=43200, stale-while-revalidate=43200',
},
],
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.0.7",
"@radix-ui/react-tooltip": "^1.1.2",
"@radix-ui/themes": "^2.0.3",
"@rainbow-me/rainbowkit": "^2.0.0-beta.1",
"@sentry/nextjs": "^8",
Expand Down
31 changes: 26 additions & 5 deletions pages/analytics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Button } from '@/components/ui/button';
import { ChartBarIcon } from '@heroicons/react/20/solid';
import Link from 'next/link';
import ClickToCopyText from '@/common/components/ClickToCopyText';
import { Interval } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { IntervalFilter } from '@/common/components/IntervalFilter';
import DynamicChartCard from '@/common/components/Analytics/DynamicChartCard';
import { addDays, formatDistanceToNow, isBefore } from 'date-fns';
Expand All @@ -25,9 +25,12 @@ import CastsCard from '@/common/components/Analytics/CastsCard';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import TopFollowers from '@/common/components/Analytics/TopFollowers';
import { UTCDate } from '@date-fns/utc';
import { getPlanLimitsForPlan } from '@/config/planLimits';
import { isPaidUser } from '@/stores/useUserStore';
import UpgradeFreePlanCard from '@/common/components/UpgradeFreePlanCard';

type FidToAnalyticsData = Record<string, AnalyticsData>;
const intervals = [Interval.d7, Interval.d30];
const intervals = [Interval.d7, Interval.d30, Interval.d90];

function timeUntilNextUTCHour(hour: number): string {
const now = new Date();
Expand All @@ -54,6 +57,14 @@ export default function AnalyticsPage() {
const [fidToAnalytics, setAnalyticsData] = useState<FidToAnalyticsData>({});
const selectedAccountInApp = useAccountStore((state) => state.accounts[state.selectedAccountIdx]);
const { accounts } = useAccountStore();
const isCustomer = isPaidUser();

const disabledIntervals = useMemo(() => {
if (isCustomer) return [];

const enabeldIntervals = getPlanLimitsForPlan('openSource').analyticsEnabledInterval;
return intervals.filter((i) => !enabeldIntervals.includes(i));
}, [isCustomer]);

const defaultProfiles = useMemo(() => {
return accounts.filter((account) => account.status === 'active').map((a) => a.user) as User[];
Expand Down Expand Up @@ -161,7 +172,12 @@ export default function AnalyticsPage() {
size="sm"
text={`https://app.herocast.xyz/analytics?fid=${fid}`}
/>
<IntervalFilter intervals={intervals} defaultInterval={Interval.d7} updateInterval={setInterval} />
<IntervalFilter
intervals={intervals}
defaultInterval={Interval.d7}
updateInterval={setInterval}
disabledIntervals={disabledIntervals}
/>
</div>
{analyticsData?.updatedAt && (
<div className="text-sm text-foreground/70">Next update {timeUntilNextUTCHour(4)}</div>
Expand Down Expand Up @@ -192,7 +208,7 @@ export default function AnalyticsPage() {
align: 'start',
loop: true,
}}
className="mr-12 lg:mx-0"
className="mr-12"
>
<CarouselContent className="">
<CarouselItem className="md:basis-1/2 lg:basis-1/3">
Expand All @@ -210,13 +226,18 @@ export default function AnalyticsPage() {
<ReactionsCard data={analyticsData.reactions} isLoading={isLoading} interval={interval} />
)}
</CarouselItem>
{!isCustomer && (
<CarouselItem className="md:basis-1/2 lg:basis-1/3 -mt-2 mb-2 mx-auto text-center">
<UpgradeFreePlanCard limitKey="analyticsEnabledInterval" />
</CarouselItem>
)}
<CarouselItem className="md:basis-1/2 lg:basis-1/3">
{analyticsData?.casts && (
<CastsCard data={analyticsData.casts} isLoading={isLoading} interval={interval} />
)}
</CarouselItem>
</CarouselContent>
<CarouselNext className="lg:hidden" />
<CarouselNext />
</Carousel>
<div className="mt-8">
<DynamicChartCard analyticsData={analyticsData} isLoading={isLoading} interval={interval} />
Expand Down
8 changes: 5 additions & 3 deletions pages/api/additionalProfileInfo.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { getAirstackSocialInfoForFid } from '@/common/helpers/airstack';
import { getIcebreakerSocialInfoForFid } from '@/common/helpers/icebreaker';
import { getCoordinapeInfoForAddresses } from '@/common/helpers/coordinapeAttestations';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'GET') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
const { fid } = req.query;
const { fid, addresses } = req.query;

if (!fid || typeof fid !== 'string') {
return res.status(400).json({ message: 'Invalid FID provided' });
}

try {
const [airstackSocialInfo, icebreakerSocialInfo] = await Promise.all([
const [airstackSocialInfo, icebreakerSocialInfo, coordinapeAttestations] = await Promise.all([
getAirstackSocialInfoForFid(fid),
getIcebreakerSocialInfoForFid(fid),
addresses ? getCoordinapeInfoForAddresses(addresses.toString()) : {},
]);
res.status(200).json({ airstackSocialInfo, icebreakerSocialInfo });
res.status(200).json({ airstackSocialInfo, icebreakerSocialInfo, coordinapeAttestations });
} catch (error) {
console.error('Error fetching additional profile info:', error);
res.status(500).json({ message: 'Internal Server Error' });
Expand Down
3 changes: 2 additions & 1 deletion pages/feeds/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import { AccountStatusType } from '@/common/constants/accounts';
import { createClient } from '@/common/helpers/supabase/component';
import includes from 'lodash.includes';
import { useListStore } from '@/stores/useListStore';
import { getCastsFromSearch, Interval, SearchFilters } from '@/common/helpers/search';
import { getCastsFromSearch, SearchFilters } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';

type Feed = {
casts: CastWithInteractions[];
Expand Down
4 changes: 2 additions & 2 deletions pages/post/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ChannelType } from '@/common/constants/channels';
import { UUID } from 'crypto';
import { usePathname, useSearchParams } from 'next/navigation';
import UpgradeFreePlanCard from '@/common/components/UpgradeFreePlanCard';
import { getPlanLimitsForUser } from '@/config/planLimits';
import { getPlanLimitsForPlan } from '@/config/planLimits';

enum DraftListTab {
writing = 'writing',
Expand Down Expand Up @@ -351,7 +351,7 @@ export default function NewPost() {
};

const renderFreePlanCard = () => {
const scheduledCastLimit = getPlanLimitsForUser('openSource').maxScheduledCasts;
const scheduledCastLimit = getPlanLimitsForPlan('openSource').maxScheduledCasts;
if (scheduledCastsCount < scheduledCastLimit) return null;

return <UpgradeFreePlanCard limitKey="maxScheduledCasts" />;
Expand Down
1 change: 1 addition & 0 deletions pages/profile/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const ProfilePage = () => {
isSelected={selectedFeedIdx === idx}
onSelect={() => onSelectCast(idx)}
showAdminActions={selectedAccount?.status === 'active' && profile?.fid === viewerFid}
recastedByFid={item.author.fid !== profile?.fid && profile?.fid}
/>
</li>
);
Expand Down
8 changes: 2 additions & 6 deletions pages/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ import { map, uniq, debounce } from 'lodash';
import SkeletonCastRow from '@/common/components/SkeletonCastRow';
import { Switch } from '@/components/ui/switch';
import { IntervalFilter } from '@/common/components/IntervalFilter';
import {
getFromFidFromSearchTerm,
getMentionFidFromSearchTerm,
Interval,
SearchResponse,
} from '@/common/helpers/search';
import { getFromFidFromSearchTerm, getMentionFidFromSearchTerm, SearchResponse } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { AdjustmentsHorizontalIcon } from '@heroicons/react/24/solid';
import { cn } from '@/lib/utils';
import { usePostHog } from 'posthog-js/react';
Expand Down
2 changes: 1 addition & 1 deletion pages/upgrade/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const plans = [
},
features: [
'2 Keyword Feeds',
'15 Scheduled Casts',
'Unlimited Scheduled Casts',
'2 Keyword Alerts',
'Analytics (1 month)',
'Onchain user insights',
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/Analytics/AnalyticsGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useMemo } from 'react';
import { format, subDays } from 'date-fns';
import { Interval } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from 'recharts';
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';
import { Skeleton } from '@/components/ui/skeleton';
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/Analytics/CastsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import React from 'react';
import AnalyticsGraph from './AnalyticsGraph';
import { CombinedActivityData } from '@/common/types/types';
import { Interval } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { formatLargeNumber } from '@/common/helpers/text';
import { startOfDay, subDays } from 'date-fns';
import { fillMissingDaysBetweenDates } from '@/common/helpers/analytics';
Expand Down
46 changes: 31 additions & 15 deletions src/common/components/Analytics/DynamicChartCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useMemo } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { AnalyticsData } from '@/common/types/types';
import { AnalyticsData, Interval } from '@/common/types/types';
import { format, subDays } from 'date-fns';
import { Interval } from '@/common/helpers/search';
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis } from 'recharts';
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';
import { cn } from '@/lib/utils';
Expand All @@ -15,10 +14,17 @@ import { roundToNextDigit } from '@/common/helpers/math';
type DynamicChartCardProps = {
interval: Interval;
analyticsData: AnalyticsData;
isLoading: boolean;
};

function DataPickerDropdown({ values, defaultValue, updateValue }) {
function DataPickerDropdown({
values,
defaultValue,
updateValue,
}: {
values: string[];
defaultValue: string;
updateValue: (value: string) => void;
}) {
const [open, setOpen] = React.useState(false);
const [value, setValue] = React.useState<Interval | undefined>(defaultValue);

Expand Down Expand Up @@ -72,7 +78,7 @@ const normalizeTimestampToDate = (timestamp: string) => {
return new Date(timestamp).toISOString().split('T')[0];
};

const getAggregatedDataForKey = (analyticsData: AnalyticsData, dataKey: string, startDate: Date) => {
const getAggregatedDataForKey = (analyticsData: AnalyticsData, dataKey: keyof AnalyticsData, startDate: Date) => {
const activityData = analyticsData[dataKey];
if (!activityData || !activityData?.aggregated) return [];

Expand All @@ -83,7 +89,7 @@ const getAggregatedDataForKey = (analyticsData: AnalyticsData, dataKey: string,
return res.filter((item) => new Date(item.date) >= startDate);
};

const mergeData = (data1, data2, startDate: Date, dataKeys: string[]) => {
const mergeData = (data1: any[], data2: any[], startDate: Date, dataKeys: string[]) => {
const dataMap = new Map();
data1.forEach((item) => {
dataMap.set(item.date, { ...dataMap.get(item.date), ...item });
Expand Down Expand Up @@ -111,11 +117,14 @@ const mergeData = (data1, data2, startDate: Date, dataKeys: string[]) => {
return result;
};

const DynamicChartCard = ({ interval, analyticsData, isLoading }: DynamicChartCardProps) => {
const DynamicChartCard = ({ interval, analyticsData }: DynamicChartCardProps) => {
const [dataKey1, setDataKey1] = React.useState(values[0]);
const [dataKey2, setDataKey2] = React.useState(values[1]);
const chartConfig = React.useMemo(
() => Object.fromEntries(values.map((value) => [value, { label: value }])),
() =>
Object.fromEntries(
values.map((value, idx) => [value, { label: value, color: `hsl(var(--chart-dynamic-${idx + 1}))` }])
),
[values]
);

Expand Down Expand Up @@ -178,13 +187,20 @@ const DynamicChartCard = ({ interval, analyticsData, isLoading }: DynamicChartCa
<ChartTooltip
content={
<ChartTooltipContent
labelFormatter={(value) => {
return new Date(value).toLocaleDateString('en-US', {
day: 'numeric',
month: 'long',
year: 'numeric',
});
}}
labelFormatter={(value) => format(value, 'PP')}
formatter={(value, name, item, index) => (
<>
<div
className="h-2.5 w-2.5 shrink-0 rounded-[2px] bg-[--color-bg]"
style={
{
'--color-bg': `var(--color-${name})`,
} as React.CSSProperties
}
/>
{chartConfig[name as keyof typeof chartConfig]?.label || name}
</>
)}
/>
}
cursor={false}
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/Analytics/NewFollowersCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import React, { useMemo } from 'react';
import AnalyticsGraph from './AnalyticsGraph';
import { CombinedActivityData } from '@/common/types/types';
import { Interval } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { formatLargeNumber } from '@/common/helpers/text';
import { subDays } from 'date-fns';
import { fillMissingDaysBetweenDates } from '@/common/helpers/analytics';
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/Analytics/ReactionsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import AnalyticsGraph from './AnalyticsGraph';
import { Interval } from '@/common/helpers/search';
import { Interval } from '@/common/types/types';
import { CombinedActivityData } from '@/common/types/types';
import { formatLargeNumber } from '@/common/helpers/text';
import { subDays } from 'date-fns';
Expand Down
Loading

0 comments on commit 1ca5219

Please sign in to comment.