diff --git a/src/assets/data/revenueData.json b/src/assets/data/revenueData.json index 2dbe509..1b42007 100644 --- a/src/assets/data/revenueData.json +++ b/src/assets/data/revenueData.json @@ -1,4 +1,4 @@ { - "totalRevenue": 100000, + "totalRevenue": 1500000, "comparedToLastMonth": "+ 4.12 %" } \ No newline at end of file diff --git a/src/assets/data/revenueDistribution.json b/src/assets/data/revenueDistribution.json new file mode 100644 index 0000000..87eb945 --- /dev/null +++ b/src/assets/data/revenueDistribution.json @@ -0,0 +1,37 @@ +{ + "revenueDistribution": { + "totalRevenue": 1500000, + "sources": [ + { + "source": "Subscriptions", + "amount": 750000, + "percentage": 50 + }, + { + "source": "Advertisements", + "amount": 300000, + "percentage": 20 + }, + { + "source": "YouTube", + "amount": 150000, + "percentage": 10 + }, + { + "source": "Facebook", + "amount": 50000, + "percentage": 3 + }, + { + "source": "Spotify Partnerships", + "amount": 200000, + "percentage": 13 + }, + { + "source": "Affiliate Marketing", + "amount": 50000, + "percentage": 4 + } + ] + } +} \ No newline at end of file diff --git a/src/features/revenue/components/revenueDistribution.tsx b/src/features/revenue/components/revenueDistribution.tsx new file mode 100644 index 0000000..f47710b --- /dev/null +++ b/src/features/revenue/components/revenueDistribution.tsx @@ -0,0 +1,45 @@ +import { Stack } from "@mui/material"; +import { SubSection } from "../../../pages/app/components/subSection"; +import { SubSectionCard } from "../../../pages/app/components/SubSectionCard"; +import { SubSectionListCard } from "../../../pages/app/components/SubSectionListCard"; +import useRevenueData from "../../../states/revenueData/hooks/useRevenueData"; +import { RevenueSource } from "../../../states/revenueData/models/revenueSource"; + +/** + * Component to display the revenue data distribution. + */ +export default function RevenueDistribution() { + const { + isRevenueDistributionDataError, + revenueDistributionData + } = useRevenueData(); + + // Show error state + if (isRevenueDistributionDataError) { + return
Error loading revenue distribution data
; + } + + return ( + + + ({ + number: `${index + 1}`, + subtitle: `${source.amount} - ${source.percentage}%`, + title: source.source + })) || [] + } + /> + + ) } + /> + ); +} diff --git a/src/features/revenue/layout/revenueLayout.tsx b/src/features/revenue/layout/revenueLayout.tsx index ce90132..c5d34ed 100644 --- a/src/features/revenue/layout/revenueLayout.tsx +++ b/src/features/revenue/layout/revenueLayout.tsx @@ -1,12 +1,14 @@ import Stack from "@mui/material/Stack"; import RevenueDataAnalysis from "../components/revenueDataAnalysis"; import RevenueDataAnalysisChart from "../components/revenueDataAnalysisChart"; +import RevenueDistribution from "../components/revenueDistribution"; export default function RevenueLayout() { return ( + ); } diff --git a/src/pages/app/components/SubSectionListCard.tsx b/src/pages/app/components/SubSectionListCard.tsx index 9b1ef98..1eb47be 100644 --- a/src/pages/app/components/SubSectionListCard.tsx +++ b/src/pages/app/components/SubSectionListCard.tsx @@ -26,7 +26,7 @@ export interface SubSectionListCardItem { /** * image URL */ - imageUrl: string; + imageUrl?: string; } interface SubSectionListCardProps { @@ -63,11 +63,16 @@ export const SubSectionListCard: FunctionComponent = ( { addLeadingZero(contentItem.number) } - random + { + contentItem.imageUrl + && ( + random + ) + } { contentItem.title } diff --git a/src/states/revenueData/contexts/revenueDataContext.ts b/src/states/revenueData/contexts/revenueDataContext.ts index 618f0a8..cfd59b5 100644 --- a/src/states/revenueData/contexts/revenueDataContext.ts +++ b/src/states/revenueData/contexts/revenueDataContext.ts @@ -1,6 +1,7 @@ import { Context, createContext } from "react"; import { RevenueAnalyticsData } from "../models/revenueAnalyticsData"; import { RevenueData } from "../models/revenueData"; +import { RevenueDistribution } from "../models/revenueSource"; /** * Props interface for RevenueDataContext. @@ -22,6 +23,14 @@ export interface RevenueDataContextProps { * Flag indicating if an error occurred while loading the revenue analytics data. */ isRevenueAnalyticsDataError: boolean; + /** + * Revenue distribution data. + */ + revenueDistributionData: RevenueDistribution | null; + /** + * Flag indicating if an error occurred while loading the revenue distribution data. + */ + isRevenueDistributionDataError: boolean; } /** diff --git a/src/states/revenueData/models/revenueSource.ts b/src/states/revenueData/models/revenueSource.ts new file mode 100644 index 0000000..3199372 --- /dev/null +++ b/src/states/revenueData/models/revenueSource.ts @@ -0,0 +1,34 @@ +/** + * Represents a single revenue source with its amount and percentage share. + */ +export interface RevenueSource { + /** + * The name of the revenue source (e.g., Subscriptions, Advertisements, YouTube). + */ + source: string; + + /** + * The amount of revenue generated from this source. + */ + amount: number; + + /** + * The percentage contribution of this source to the total revenue. + */ + percentage: number; +} + +/** + * Represents the overall revenue distribution of Streamify. + */ +export interface RevenueDistribution { + /** + * The total revenue generated from all sources. + */ + totalRevenue: number; + + /** + * A list of different revenue sources contributing to the total revenue. + */ + sources: RevenueSource[]; +} diff --git a/src/states/revenueData/providers/revenueDataProvider.tsx b/src/states/revenueData/providers/revenueDataProvider.tsx index 7d2da0c..fed35c0 100644 --- a/src/states/revenueData/providers/revenueDataProvider.tsx +++ b/src/states/revenueData/providers/revenueDataProvider.tsx @@ -1,9 +1,11 @@ import { FunctionComponent, PropsWithChildren, ReactElement, useMemo, useState } from "react"; import revenueAnalyticsDataJson from "../../../assets/data/revenueAnalytics.json"; import revenueDataJson from "../../../assets/data/revenueData.json"; +import revenueDistributionDataJson from "../../../assets/data/revenueDistribution.json"; import RevenueDataContext from "../contexts/revenueDataContext"; import { RevenueAnalyticsData } from "../models/revenueAnalyticsData"; import { RevenueData } from "../models/revenueData"; +import { RevenueDistribution } from "../models/revenueSource"; /** * Props interface for the [RevenueDataProvider] @@ -22,9 +24,11 @@ const RevenueDataProvider: FunctionComponent = ( const { children } = props; const [ isRevenueDataError, setIsRevenueDataError ] = useState(false); - const [ RevenueData, setRevenueData ] = useState(null); + const [ revenueData, setRevenueData ] = useState(null); const [ isRevenueAnalyticsDataError, setIsRevenueAnalyticsDataError ] = useState(false); const [ revenueAnalyticsData, setRevenueAnalyticsData ] = useState(null); + const [ isRevenueDistributionDataError, setIsRevenueDistributionDataError ] = useState(false); + const [ revenueDistributionData, setRevenueDistributionData ] = useState(null); // Load the revenue data useMemo(() => { @@ -52,13 +56,28 @@ const RevenueDataProvider: FunctionComponent = ( } }, [ revenueAnalyticsDataJson ]); + // Load the revenue distribution data + useMemo(() => { + try { + if (revenueDistributionDataJson) { + setRevenueDistributionData(revenueDistributionDataJson.revenueDistribution); + setIsRevenueDistributionDataError(false); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (error) { + setIsRevenueDistributionDataError(true); + } + }, [ revenueDistributionDataJson ]); + return ( { children }