mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-20 14:34:05 +01:00
fix: can't access portfolio page
This commit is contained in:
parent
00c6b847e7
commit
a440110098
@ -1,7 +1,7 @@
|
|||||||
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/tagQuery";
|
||||||
|
|
||||||
function getTotalInvestment(deals: { deal_amount : number}[]) {
|
function getTotalInvestment(deals: { deal_amount: number }[]) {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
for (let index = 0; index < deals.length; index++) {
|
for (let index = 0; index < deals.length; index++) {
|
||||||
total += deals[index].deal_amount;
|
total += deals[index].deal_amount;
|
||||||
@ -16,10 +16,7 @@ async function getLatestInvestment(
|
|||||||
const count = 8;
|
const count = 8;
|
||||||
|
|
||||||
for (let i = deals.length - 1; i >= 0 && llist.length < count; --i) {
|
for (let i = deals.length - 1; i >= 0 && llist.length < count; --i) {
|
||||||
let { data: project, error } = await supabase
|
let { data: project, error } = await supabase.from("project").select("project_name").eq("id", deals[i].project_id);
|
||||||
.from("project")
|
|
||||||
.select("project_name")
|
|
||||||
.eq("id", deals[i].project_id);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
@ -62,15 +59,9 @@ function countValues(arr: { value: string }[][]): Record<string, number> {
|
|||||||
return counts;
|
return counts;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getBusinessTypeName(
|
async function getBusinessTypeName(supabase: SupabaseClient, projectId: number) {
|
||||||
supabase: SupabaseClient,
|
|
||||||
projectId: number
|
|
||||||
) {
|
|
||||||
// step 1: get business id from project id
|
// step 1: get business id from project id
|
||||||
let { data: project, error: projectError } = await supabase
|
let { data: project, error: projectError } = await supabase.from("project").select("business_id").eq("id", projectId);
|
||||||
.from("project")
|
|
||||||
.select("business_id")
|
|
||||||
.eq("id", projectId);
|
|
||||||
if (projectError) {
|
if (projectError) {
|
||||||
console.error(projectError);
|
console.error(projectError);
|
||||||
}
|
}
|
||||||
@ -107,20 +98,7 @@ interface GraphData {
|
|||||||
|
|
||||||
function overAllGraphData(deals: Deal[]): GraphData[] {
|
function overAllGraphData(deals: Deal[]): GraphData[] {
|
||||||
// Initialize all months with value 0
|
// Initialize all months with value 0
|
||||||
const months = [
|
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||||
"Jan",
|
|
||||||
"Feb",
|
|
||||||
"Mar",
|
|
||||||
"Apr",
|
|
||||||
"May",
|
|
||||||
"Jun",
|
|
||||||
"Jul",
|
|
||||||
"Aug",
|
|
||||||
"Sep",
|
|
||||||
"Oct",
|
|
||||||
"Nov",
|
|
||||||
"Dec",
|
|
||||||
];
|
|
||||||
const acc: GraphData[] = months.map((month) => ({ name: month, value: 0 }));
|
const acc: GraphData[] = months.map((month) => ({ name: month, value: 0 }));
|
||||||
|
|
||||||
deals
|
deals
|
||||||
@ -137,7 +115,6 @@ function overAllGraphData(deals: Deal[]): GraphData[] {
|
|||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Deal {
|
interface Deal {
|
||||||
created_time: string | number | Date;
|
created_time: string | number | Date;
|
||||||
deal_amount: any;
|
deal_amount: any;
|
||||||
@ -168,7 +145,6 @@ function fourYearGraphData(deals: Deal[]): GraphData[] {
|
|||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface DayOfWeekData {
|
interface DayOfWeekData {
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
@ -191,24 +167,16 @@ function dayOftheWeekData(deals: Deal[]): DayOfWeekData[] {
|
|||||||
});
|
});
|
||||||
return dayOfWeekData;
|
return dayOfWeekData;
|
||||||
}
|
}
|
||||||
async function getInvestorProjectTag(
|
async function getInvestorProjectTag(supabase: SupabaseClient, deals: number | { project_id: number }[]) {
|
||||||
supabase: SupabaseClient,
|
|
||||||
deals: number | { project_id: number }[]
|
|
||||||
) {
|
|
||||||
// get unique project id from deals
|
// get unique project id from deals
|
||||||
const uniqueProjectIds: number[] = Array.isArray(deals)
|
const uniqueProjectIds: number[] = Array.isArray(deals)
|
||||||
? Array.from(
|
? Array.from(new Set(deals.map((deal: { project_id: number }) => deal.project_id)))
|
||||||
new Set(deals.map((deal: { project_id: number }) => deal.project_id))
|
|
||||||
)
|
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const tagIds = (
|
const tagIds = (
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
uniqueProjectIds.map(async (projectId: number) => {
|
uniqueProjectIds.map(async (projectId: number) => {
|
||||||
const { data: tagIdsArray, error: tagError } = await getProjectTag(
|
const { data: tagIdsArray, error: tagError } = await getProjectTag(supabase, projectId);
|
||||||
supabase,
|
|
||||||
projectId
|
|
||||||
);
|
|
||||||
if (tagError) {
|
if (tagError) {
|
||||||
console.error(tagError);
|
console.error(tagError);
|
||||||
return [];
|
return [];
|
||||||
@ -223,10 +191,7 @@ async function getInvestorProjectTag(
|
|||||||
tagIds
|
tagIds
|
||||||
.filter((tagId) => tagId !== null)
|
.filter((tagId) => tagId !== null)
|
||||||
.map(async (id: number) => {
|
.map(async (id: number) => {
|
||||||
const { data: tagName, error: nameError } = await getTagName(
|
const { data: tagName, error: nameError } = await getTagName(supabase, id);
|
||||||
supabase,
|
|
||||||
id
|
|
||||||
);
|
|
||||||
if (nameError) {
|
if (nameError) {
|
||||||
console.error(nameError);
|
console.error(nameError);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -1,39 +1,24 @@
|
|||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||||
|
|
||||||
export type RecentDealData = {
|
|
||||||
created_time: Date;
|
|
||||||
deal_amount: number;
|
|
||||||
investor_id: string;
|
|
||||||
username: string;
|
|
||||||
avatar_url?: string;
|
|
||||||
// email: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface RecentFundsProps {
|
interface RecentFundsProps {
|
||||||
recentDealData: RecentDealData[];
|
data?: { name?: string; amount?: number; avatar?: string; date?: Date }[];
|
||||||
}
|
}
|
||||||
|
export function RecentFunds(props: RecentFundsProps) {
|
||||||
export function RecentFunds({ recentDealData }: RecentFundsProps) {
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
{recentDealData?.length > 0 ? (
|
{(props?.data || []).map((deal, index) => (
|
||||||
recentDealData.map((data) => (
|
<div className="flex items-center" key={index}>
|
||||||
<div className="flex items-center" key={data.investor_id}>
|
|
||||||
<Avatar className="h-9 w-9">
|
<Avatar className="h-9 w-9">
|
||||||
<AvatarImage src={data.avatar_url} alt={data.username} />
|
<AvatarImage src={deal.avatar} alt={deal.name} />
|
||||||
{/* #TODO make this not quick fix */}
|
<AvatarFallback>{(deal.name ?? "").slice(0, 2)}</AvatarFallback>
|
||||||
<AvatarFallback>{data.username ? data.username[0] : ""}</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">{data.username}</p>
|
<p className="text-sm font-medium leading-none">{deal.name}</p>
|
||||||
{/* <p className="text-sm text-muted-foreground">{data.email}</p> */}
|
<p className="text-xs text-muted-foreground">{deal?.date?.toLocaleDateString()}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto font-medium">+${data.deal_amount}</div>
|
<div className="ml-auto font-medium">+${deal.amount}</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))}
|
||||||
) : (
|
|
||||||
<p>No recent deals available.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,22 +2,68 @@
|
|||||||
|
|
||||||
import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis, LineChart, Line, Tooltip } from "recharts";
|
import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis, LineChart, Line, Tooltip } from "recharts";
|
||||||
|
|
||||||
|
// const data = [
|
||||||
|
// {
|
||||||
|
// name: "Jan",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Feb",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Mar",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Apr",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "May",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Jun",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Jul",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Aug",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Sep",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Oct",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Nov",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: "Dec",
|
||||||
|
// total: Math.floor(Math.random() * 5000) + 1000,
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
interface OverViewProps {
|
interface OverViewProps {
|
||||||
graphType: string;
|
graphType: string;
|
||||||
graphData: Record<string, number>; // Object with month-year as keys and sum as value
|
data: { name: string; value: number }[];
|
||||||
|
graphHeight?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Overview(props: OverViewProps) {
|
export function Overview(props: OverViewProps) {
|
||||||
// Transform the grouped data into the format for the chart
|
|
||||||
const chartData = Object.entries(props.graphData).map(([monthYear, totalArray]) => ({
|
|
||||||
name: monthYear,
|
|
||||||
total: totalArray, // Get the total amount for the month
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResponsiveContainer width="100%" height={350}>
|
<ResponsiveContainer width="100%" height={props.graphHeight || 350}>
|
||||||
{props.graphType === "line" ? (
|
{props.graphType === "line" ? (
|
||||||
<LineChart data={chartData}>
|
<LineChart data={props.data}>
|
||||||
<XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} />
|
<XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} />
|
||||||
<YAxis
|
<YAxis
|
||||||
stroke="#888888"
|
stroke="#888888"
|
||||||
@ -26,10 +72,18 @@ export function Overview(props: OverViewProps) {
|
|||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickFormatter={(value) => `$${value}`}
|
tickFormatter={(value) => `$${value}`}
|
||||||
/>
|
/>
|
||||||
<Line dataKey="total" fill="currentColor" className="fill-primary" />
|
<Tooltip
|
||||||
|
formatter={(value) => `$${value}`}
|
||||||
|
contentStyle={{
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
borderRadius: "5px",
|
||||||
|
color: "#000",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Line dataKey="value" fill="currentColor" className="fill-primary" />
|
||||||
</LineChart>
|
</LineChart>
|
||||||
) : (
|
) : (
|
||||||
<BarChart data={chartData}>
|
<BarChart data={props.data}>
|
||||||
<XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} />
|
<XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} />
|
||||||
<YAxis
|
<YAxis
|
||||||
stroke="#888888"
|
stroke="#888888"
|
||||||
@ -38,7 +92,15 @@ export function Overview(props: OverViewProps) {
|
|||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickFormatter={(value) => `$${value}`}
|
tickFormatter={(value) => `$${value}`}
|
||||||
/>
|
/>
|
||||||
<Bar dataKey="total" fill="currentColor" className="fill-primary" />
|
<Tooltip
|
||||||
|
formatter={(value) => `$${value}`}
|
||||||
|
contentStyle={{
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
borderRadius: "5px",
|
||||||
|
color: "#000",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Bar dataKey="value" fill="currentColor" className="fill-primary" radius={[15, 15, 0, 0]} />
|
||||||
</BarChart>
|
</BarChart>
|
||||||
)}
|
)}
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
|
|||||||
@ -3,3 +3,11 @@ import { SupabaseClient } from "@supabase/supabase-js";
|
|||||||
export const getTagsByProjectIds = (client: SupabaseClient, projectIds: string[]) => {
|
export const getTagsByProjectIds = (client: SupabaseClient, projectIds: string[]) => {
|
||||||
return client.from("project_tag").select(`item_id, ...tag (tag_value:value)`).in("item_id", projectIds);
|
return client.from("project_tag").select(`item_id, ...tag (tag_value:value)`).in("item_id", projectIds);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getProjectTag(client: SupabaseClient, projectId: number) {
|
||||||
|
return client.from("project_tag").select("tag_id").in("item_id", [projectId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTagName(client: SupabaseClient, tagId: number) {
|
||||||
|
return client.from("tag").select("value").in("id", [tagId]);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user