Refactor Portfolio component and add data aggregation hooks

This commit is contained in:
THIS ONE IS A LITTLE BIT TRICKY KRUB 2024-10-30 14:52:20 +07:00
parent 62e20c282a
commit 16a171db3c
3 changed files with 133 additions and 90 deletions

View File

@ -0,0 +1,106 @@
// only use deal that were made at most year ago
interface Deal {
created_time: string | number | Date;
deal_amount: any;
}
interface GraphData {
name: string;
value: number;
}
function overAllGraphData(deals: Deal[]): GraphData[] {
return deals
? deals
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(1))
.reduce((acc: GraphData[], item: Deal) => {
// get the first three initial letter of the month
const monthName = getMonthName(item.created_time.toString()).slice(
0,
3
);
const existingMonth = acc.find(
(entry: GraphData) => entry.name === monthName
);
if (existingMonth) {
existingMonth.value += item.deal_amount;
}
// if month doesnt exist yet, create new record
else {
acc.push({ name: monthName, value: item.deal_amount });
}
return acc;
}, [] as GraphData[])
: [];
}
interface Deal {
created_time: string | number | Date;
deal_amount: any;
}
interface GraphData {
name: string;
value: number;
}
function fourYearGraphData(deals: Deal[]): GraphData[] {
return deals
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(3))
.reduce((acc: GraphData[], item: Deal) => {
const year = new Date(item.created_time).getFullYear();
const existingYear = acc.find(
(entry: GraphData) => entry.name === year.toString()
);
if (existingYear) {
existingYear.value += item.deal_amount;
} else {
acc.push({ name: year.toString(), value: item.deal_amount });
}
return acc;
}, [] as GraphData[]);
}
interface DayOfWeekData {
name: string;
value: number;
}
function dayOftheWeekData(deals: Deal[]): DayOfWeekData[] {
const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const dayOfWeekData: DayOfWeekData[] = daysOfWeek.map((day) => ({
name: day,
value: 0,
}));
deals
.filter((item: Deal) => new Date(item.created_time) >= yearAgo(1))
.forEach((item: Deal) => {
const day = getDayAbbreviation(item.created_time);
const dayEntry = dayOfWeekData.find((entry) => entry.name === day);
if (dayEntry) {
dayEntry.value += item.deal_amount;
}
});
return dayOfWeekData;
}
const getDayAbbreviation = (dateString: string | number | Date) => {
const date = new Date(dateString);
return date.toLocaleString("default", { weekday: "short" });
};
const yearAgo = (num: number) => {
const newDate = new Date();
newDate.setFullYear(newDate.getFullYear() - num);
return newDate;
};
const getMonthName = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleString("default", { month: "long", year: "numeric" });
};
export { overAllGraphData, fourYearGraphData, dayOftheWeekData };

View File

@ -2,6 +2,7 @@ import { Overview } from "@/components/ui/overview";
import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
import { getInvestorDeal, getProjectTag, getTagName } from "@/lib/data/query";
import PieChart from "@/components/pieChart";
import { overAllGraphData, fourYearGraphData, dayOftheWeekData } from "./hook";
export default async function Portfolio({
params,
@ -9,12 +10,13 @@ export default async function Portfolio({
params: { uid: string };
}) {
const supabase = createSupabaseClient();
const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const dayOfWeekData = daysOfWeek.map((day) => ({ name: day, value: 0 }));
const { data: deals, error: investorDealError } = await getInvestorDeal(
supabase,
params.uid
);
const overAllData = deals ? overAllGraphData(deals) : [];
const fourYearData = deals ? fourYearGraphData(deals) : [];
const dayOfWeekData = deals ? dayOftheWeekData(deals) : [];
const projectTag = async () => {
// get unique project id from deals
@ -81,80 +83,6 @@ export default async function Portfolio({
console.error(investorDealError);
}
const yearAgo = (num: number) => {
const newDate = new Date();
newDate.setFullYear(newDate.getFullYear() - num);
return newDate;
};
const getMonthName = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleString("default", { month: "long", year: "numeric" });
};
// only use deal that were made at most year ago
const overAllGraphData = deals
? deals
.filter((item) => new Date(item.created_time) >= yearAgo(1))
.reduce(
(acc, item) => {
const monthName = getMonthName(item.created_time).slice(0, 3);
const existingMonth = acc.find(
(entry: { name: string }) => entry.name === monthName
);
if (existingMonth) {
existingMonth.value += item.deal_amount;
} else {
acc.push({ name: monthName, value: item.deal_amount });
}
return acc;
},
[] as { name: string; value: number }[]
)
: [];
const threeYearGraphData = deals
? deals
.filter((item) => new Date(item.created_time) >= yearAgo(3))
.reduce(
(acc, item) => {
const year = new Date(item.created_time).getFullYear();
const existingYear = acc.find(
(entry: { name: string }) => entry.name === year.toString()
);
if (existingYear) {
existingYear.value += item.deal_amount;
} else {
acc.push({ name: year.toString(), value: item.deal_amount });
}
return acc;
},
[] as { name: string; value: number }[]
)
: [];
const getDayAbbreviation = (dateString: string | number | Date) => {
const date = new Date(dateString);
return date.toLocaleString("default", { weekday: "short" });
};
let totalInvest = 0;
if (deals) {
deals
.filter((item) => new Date(item.created_time) >= yearAgo(1))
.forEach((item) => {
const day = getDayAbbreviation(item.created_time);
const dayEntry = dayOfWeekData.find((entry) => entry.name === day);
if (dayEntry) {
dayEntry.value += item.deal_amount;
}
});
totalInvest = deals.reduce((acc, item) => acc + item.deal_amount, 0);
}
return (
<div>
{/* {JSON.stringify(params.uid)} */}
@ -169,19 +97,21 @@ export default async function Portfolio({
<div>{totalInvest}</div>
</div> */}
<div className="flex w-full gap-10">
<Overview graphType="line" data={overAllGraphData}></Overview>
<Overview graphType="bar" data={threeYearGraphData}></Overview>
<Overview graphType="line" data={overAllData}></Overview>
<Overview graphType="bar" data={fourYearData}></Overview>
<Overview graphType="bar" data={dayOfWeekData}></Overview>
</div>
<PieChart
data={tagCount.map(
(item: { name: string; count: number }) => item.count
)}
labels={tagCount.map(
(item: { name: string; count: number }) => item.name
)}
header="Total"
/>
<div className="w-96">
<PieChart
data={tagCount.map(
(item: { name: string; count: number }) => item.count
)}
labels={tagCount.map(
(item: { name: string; count: number }) => item.name
)}
header="Total"
/>
</div>
</div>
);
}

View File

@ -24,11 +24,18 @@ const PieChart = (props: PieChartProps) => {
},
],
};
const options = {
plugins: {
legend: {
position: "bottom" as const,
},
},
};
return (
<div style={{ width: "50%", margin: "auto" }}>
<Pie data={chartData} />
</div>
<>
<Pie data={chartData} options={options} />
</>
);
};