mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-20 14:34:05 +01:00
Refactor portfolio hook and page components
- Add functions to calculate total investment and get latest investment - Update graph data calculations for overall and four-year graphs - Update recent funds component to display latest investment deals - Minor code formatting and error handling improvements
This commit is contained in:
parent
22fe709ce8
commit
7356831e2e
@ -1,6 +1,38 @@
|
|||||||
import { SupabaseClient } from "@supabase/supabase-js";
|
import { SupabaseClient } from "@supabase/supabase-js";
|
||||||
import { getProjectTag, getTagName } from "@/lib/data/query";
|
import { getProjectTag, getTagName } from "@/lib/data/query";
|
||||||
|
|
||||||
|
function getTotalInvestment(deals: { deal_amount : number}[]) {
|
||||||
|
let total = 0;
|
||||||
|
for (let index = 0; index < deals.length; index++) {
|
||||||
|
total += deals[index].deal_amount;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
async function getLatestInvestment(
|
||||||
|
supabase: SupabaseClient,
|
||||||
|
deals: { project_id: number; deal_amount: number; created_time: Date }[]
|
||||||
|
) {
|
||||||
|
const llist = [];
|
||||||
|
const count = 8;
|
||||||
|
|
||||||
|
for (let i = deals.length - 1; i >= 0 && llist.length < count; --i) {
|
||||||
|
let { data: project, error } = await supabase
|
||||||
|
.from("project")
|
||||||
|
.select("project_name")
|
||||||
|
.eq("id", deals[i].project_id);
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
llist.push({
|
||||||
|
name: project?.[0]?.project_name,
|
||||||
|
amount: deals[i].deal_amount,
|
||||||
|
date: new Date(deals[i].created_time),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return llist;
|
||||||
|
}
|
||||||
|
|
||||||
async function checkForInvest(supabase: SupabaseClient, userId: string) {
|
async function checkForInvest(supabase: SupabaseClient, userId: string) {
|
||||||
let { count, error } = await supabase
|
let { count, error } = await supabase
|
||||||
.from("investment_deal")
|
.from("investment_deal")
|
||||||
@ -30,7 +62,6 @@ function countValues(arr: { value: string }[][]): Record<string, number> {
|
|||||||
return counts;
|
return counts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function getBusinessTypeName(
|
async function getBusinessTypeName(
|
||||||
supabase: SupabaseClient,
|
supabase: SupabaseClient,
|
||||||
projectId: number
|
projectId: number
|
||||||
@ -75,32 +106,38 @@ interface GraphData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function overAllGraphData(deals: Deal[]): GraphData[] {
|
function overAllGraphData(deals: Deal[]): GraphData[] {
|
||||||
return deals
|
// Initialize all months with value 0
|
||||||
? deals
|
const months = [
|
||||||
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(1))
|
"Jan",
|
||||||
.reduce((acc: GraphData[], item: Deal) => {
|
"Feb",
|
||||||
// get the first three initial letter of the month
|
"Mar",
|
||||||
const monthName = getMonthName(item.created_time.toString()).slice(
|
"Apr",
|
||||||
0,
|
"May",
|
||||||
3
|
"Jun",
|
||||||
);
|
"Jul",
|
||||||
const existingMonth = acc.find(
|
"Aug",
|
||||||
(entry: GraphData) => entry.name === monthName
|
"Sep",
|
||||||
);
|
"Oct",
|
||||||
|
"Nov",
|
||||||
|
"Dec",
|
||||||
|
];
|
||||||
|
const acc: GraphData[] = months.map((month) => ({ name: month, value: 0 }));
|
||||||
|
|
||||||
if (existingMonth) {
|
deals
|
||||||
existingMonth.value += item.deal_amount;
|
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(1))
|
||||||
}
|
.forEach((item: Deal) => {
|
||||||
// if month doesnt exist yet, create new record
|
const monthName = getMonthName(item.created_time.toString()).slice(0, 3);
|
||||||
else {
|
const monthEntry = acc.find((entry) => entry.name === monthName);
|
||||||
acc.push({ name: monthName, value: item.deal_amount });
|
|
||||||
|
if (monthEntry) {
|
||||||
|
monthEntry.value += item.deal_amount;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as GraphData[])
|
|
||||||
: [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Deal {
|
interface Deal {
|
||||||
created_time: string | number | Date;
|
created_time: string | number | Date;
|
||||||
deal_amount: any;
|
deal_amount: any;
|
||||||
@ -112,24 +149,26 @@ interface GraphData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fourYearGraphData(deals: Deal[]): GraphData[] {
|
function fourYearGraphData(deals: Deal[]): GraphData[] {
|
||||||
return deals
|
const currentYear = new Date().getFullYear();
|
||||||
|
const acc: GraphData[] = Array.from({ length: 4 }, (_, i) => ({
|
||||||
|
name: (currentYear - i).toString(),
|
||||||
|
value: 0,
|
||||||
|
})).reverse();
|
||||||
|
deals
|
||||||
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(3))
|
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(3))
|
||||||
.reduce((acc: GraphData[], item: Deal) => {
|
.forEach((item: Deal) => {
|
||||||
const year = new Date(item.created_time).getFullYear();
|
const year = new Date(item.created_time).getFullYear().toString();
|
||||||
const existingYear = acc.find(
|
const yearEntry = acc.find((entry) => entry.name === year);
|
||||||
(entry: GraphData) => entry.name === year.toString()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingYear) {
|
if (yearEntry) {
|
||||||
existingYear.value += item.deal_amount;
|
yearEntry.value += item.deal_amount;
|
||||||
} else {
|
|
||||||
acc.push({ name: year.toString(), value: item.deal_amount });
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as GraphData[]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface DayOfWeekData {
|
interface DayOfWeekData {
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
@ -238,4 +277,6 @@ export {
|
|||||||
getBusinessTypeName,
|
getBusinessTypeName,
|
||||||
countValues,
|
countValues,
|
||||||
checkForInvest,
|
checkForInvest,
|
||||||
|
getLatestInvestment,
|
||||||
|
getTotalInvestment,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import {
|
|||||||
getBusinessTypeName,
|
getBusinessTypeName,
|
||||||
countValues,
|
countValues,
|
||||||
checkForInvest,
|
checkForInvest,
|
||||||
|
getLatestInvestment,
|
||||||
|
getTotalInvestment,
|
||||||
} from "./hook";
|
} from "./hook";
|
||||||
import CountUpComponent from "@/components/countUp";
|
import CountUpComponent from "@/components/countUp";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
@ -24,6 +26,7 @@ import { RecentFunds } from "@/components/recent-funds";
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import QuestionMarkIcon from "@/components/icon/questionMark";
|
import QuestionMarkIcon from "@/components/icon/questionMark";
|
||||||
import { NoDataAlert } from "@/components/alert/noData/alert";
|
import { NoDataAlert } from "@/components/alert/noData/alert";
|
||||||
|
import { error } from "console";
|
||||||
|
|
||||||
export default async function Portfolio({
|
export default async function Portfolio({
|
||||||
params,
|
params,
|
||||||
@ -33,7 +36,6 @@ export default async function Portfolio({
|
|||||||
const supabase = createSupabaseClient();
|
const supabase = createSupabaseClient();
|
||||||
// if user hasn't invest in anything
|
// if user hasn't invest in anything
|
||||||
if (!(await checkForInvest(supabase, params.uid))) {
|
if (!(await checkForInvest(supabase, params.uid))) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<NoDataAlert />
|
<NoDataAlert />
|
||||||
@ -47,10 +49,22 @@ export default async function Portfolio({
|
|||||||
if (investorDealError) {
|
if (investorDealError) {
|
||||||
console.error(investorDealError);
|
console.error(investorDealError);
|
||||||
}
|
}
|
||||||
|
const {
|
||||||
|
data: { user },
|
||||||
|
error: userError,
|
||||||
|
} = await supabase.auth.getUser();
|
||||||
|
if (userError) {
|
||||||
|
console.error("Error while fetching user" + error);
|
||||||
|
}
|
||||||
|
const username = user ? user.user_metadata.name : "Anonymous";
|
||||||
|
// console.log(username)
|
||||||
const overAllData = deals ? overAllGraphData(deals) : [];
|
const overAllData = deals ? overAllGraphData(deals) : [];
|
||||||
const fourYearData = deals ? fourYearGraphData(deals) : [];
|
const fourYearData = deals ? fourYearGraphData(deals) : [];
|
||||||
const dayOfWeekData = deals ? dayOftheWeekData(deals) : [];
|
const dayOfWeekData = deals ? dayOftheWeekData(deals) : [];
|
||||||
const tags = deals ? await getInvestorProjectTag(supabase, deals) : [];
|
const tags = deals ? await getInvestorProjectTag(supabase, deals) : [];
|
||||||
|
const latestDeals = deals ? await getLatestInvestment(supabase, deals) : [];
|
||||||
|
const totalInvestment = deals ? getTotalInvestment(deals) : 0;
|
||||||
|
// console.log(latestDeals);
|
||||||
const tagCount = countTags(tags);
|
const tagCount = countTags(tags);
|
||||||
// console.log(investedBusinessIds);
|
// console.log(investedBusinessIds);
|
||||||
const businessType = deals
|
const businessType = deals
|
||||||
@ -80,9 +94,22 @@ export default async function Portfolio({
|
|||||||
<div>{totalInvest}</div>
|
<div>{totalInvest}</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
{/* <CountUpComponent end={100} duration={3} /> */}
|
{/* <CountUpComponent end={100} duration={3} /> */}
|
||||||
|
<div className="text-center py-4">
|
||||||
|
<h1 className="text-2xl font-semibold">
|
||||||
|
Welcome to your Portfolio, {username}!
|
||||||
|
</h1>
|
||||||
|
<p className="text-lg text-muted-foreground">
|
||||||
|
Here's an overview of your investment journey and progress.
|
||||||
|
</p>
|
||||||
|
<p className="text-xl font-medium text-green-400">
|
||||||
|
Total Investment: $
|
||||||
|
<CountUpComponent end={totalInvestment} duration={1} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flew-rows-3 gap-10 mt-5 w-full">
|
<div className="flex flew-rows-3 gap-10 mt-5 w-full">
|
||||||
<Tabs defaultValue="daily" className="space-y-4 w-full">
|
<Tabs defaultValue="daily" className="space-y-4 w-full">
|
||||||
<TabsList className="grid w-full grid-cols-3">
|
<TabsList className="grid w-96 grid-cols-3">
|
||||||
<TabsTrigger value="daily">Daily</TabsTrigger>
|
<TabsTrigger value="daily">Daily</TabsTrigger>
|
||||||
<TabsTrigger value="monthly">Monthly</TabsTrigger>
|
<TabsTrigger value="monthly">Monthly</TabsTrigger>
|
||||||
<TabsTrigger value="yearly">Yearly</TabsTrigger>
|
<TabsTrigger value="yearly">Yearly</TabsTrigger>
|
||||||
@ -246,7 +273,7 @@ export default async function Portfolio({
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="mt-5">
|
<CardContent className="mt-5">
|
||||||
<RecentFunds />
|
<RecentFunds data={latestDeals} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -39,25 +39,22 @@ const data = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
interface RecentFundsProps {
|
interface RecentFundsProps {
|
||||||
name?: string;
|
data?: { name?: string; amount?: number; avatar?: string ; date?: Date}[];
|
||||||
email?: string;
|
|
||||||
amount?: number;
|
|
||||||
avatar?: string;
|
|
||||||
}
|
}
|
||||||
export function RecentFunds(props: RecentFundsProps) {
|
export function RecentFunds(props: RecentFundsProps) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
{data.map((person, index) => (
|
{(props?.data || []).map((deal, index) => (
|
||||||
<div className="flex items-center" key={index}>
|
<div className="flex items-center" key={index}>
|
||||||
<Avatar className="h-9 w-9">
|
<Avatar className="h-9 w-9">
|
||||||
<AvatarImage src={person.avatar} alt={person.name} />
|
<AvatarImage src={deal.avatar} alt={deal.name} />
|
||||||
<AvatarFallback>{person.initials}</AvatarFallback>
|
<AvatarFallback>{(deal.name ?? "").slice(0, 3)}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="ml-4 space-y-1">
|
<div className="ml-4 space-y-1">
|
||||||
<p className="text-sm font-medium leading-none">{person.name}</p>
|
<p className="text-sm font-medium leading-none">{deal.name}</p>
|
||||||
<p className="text-sm text-muted-foreground">{person.email}</p>
|
<p className="text-xs text-muted-foreground">{deal?.date?.toLocaleDateString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto font-medium">+${person.amount}</div>
|
<div className="ml-auto font-medium">+${deal.amount}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user