mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-18 21:44:06 +01:00
feat: update dashboard to enhance investment data handling and display
This commit is contained in:
parent
0933f86faf
commit
804de94cbe
@ -11,16 +11,27 @@ import { getProjectByUserId } from "@/lib/data/projectQuery";
|
||||
import { Loader } from "@/components/loading/loader";
|
||||
import { getInvestmentByProjectsIds } from "@/lib/data/investmentQuery";
|
||||
import { useQuery } from "@supabase-cache-helpers/postgrest-react-query";
|
||||
import { getLatestInvestment, overAllGraphData, Deal } from "../portfolio/[uid]/query";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { overAllGraphData, Deal } from "../portfolio/[uid]/query";
|
||||
import { getUserProfile } from "@/lib/data/userQuery";
|
||||
import { Item } from "@radix-ui/react-navigation-menu";
|
||||
|
||||
export default function Dashboard() {
|
||||
let supabase = createSupabaseClient();
|
||||
const supabase = createSupabaseClient();
|
||||
const pathname = usePathname();
|
||||
const userId = useSession().session?.user.id;
|
||||
const [projects, setProjects] = useState<
|
||||
{ id: number; project_name: string; business_id: { user_id: number }[]; dataroom_id: number }[]
|
||||
>([]);
|
||||
const [latestInvestment, setLatestInvestment] = useState<
|
||||
{ projectId: number; name: any; amount: number; date: Date; logo_url: string; status: string }[]
|
||||
{
|
||||
avatarUrl: string;
|
||||
createdTime: Date;
|
||||
dealAmount: number;
|
||||
dealStatus: string;
|
||||
investorId: string;
|
||||
username: string;
|
||||
}[]
|
||||
>([]);
|
||||
const [isSuccess, setIsSuccess] = useState(false);
|
||||
const [graphType, setGraphType] = useState("line");
|
||||
@ -34,36 +45,38 @@ export default function Dashboard() {
|
||||
)
|
||||
);
|
||||
useEffect(() => {
|
||||
const fetchLatestInvestment = async () => {
|
||||
const latest = await getLatestInvestment(
|
||||
supabase,
|
||||
investmentDetail?.data?.map((deal) => {
|
||||
return {
|
||||
project_id: deal.project_id,
|
||||
deal_amount: deal.deal_amount,
|
||||
created_time: deal.created_time,
|
||||
};
|
||||
}) || []
|
||||
);
|
||||
const resolvedLatest = await Promise.all(
|
||||
latest.map(async (investment) => ({
|
||||
...investment,
|
||||
logo_url: await investment.logo_url,
|
||||
}))
|
||||
);
|
||||
setLatestInvestment(
|
||||
resolvedLatest.map((investment) => ({
|
||||
projectId: investment.projectId,
|
||||
name: investment.name,
|
||||
amount: investment.amount,
|
||||
date: investment.date,
|
||||
logo_url: investment.logo_url,
|
||||
status: investmentDetail?.data?.find((deal) => deal.project_id === investment.projectId)?.deal_status.value,
|
||||
}))
|
||||
);
|
||||
// console.table(investmentDetail);
|
||||
const setTopLatestInvestment = () => {
|
||||
if (investmentDetail?.data) {
|
||||
setLatestInvestment(
|
||||
investmentDetail.data
|
||||
.slice(0, 8)
|
||||
.map((item) => {
|
||||
// set the project according to current project id
|
||||
if (item.project_id === currentProjectId) {
|
||||
return {
|
||||
avatarUrl: item.avatar_url,
|
||||
createdTime: item.created_time,
|
||||
dealAmount: item.deal_amount,
|
||||
dealStatus: item.deal_status,
|
||||
investorId: item.investor_id,
|
||||
username: item.username,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.filter((item) => item !== undefined) as {
|
||||
avatarUrl: string;
|
||||
createdTime: Date;
|
||||
dealAmount: number;
|
||||
dealStatus: string;
|
||||
investorId: string;
|
||||
username: string;
|
||||
}[]
|
||||
);
|
||||
console.table(latestInvestment)
|
||||
}
|
||||
};
|
||||
fetchLatestInvestment();
|
||||
setTopLatestInvestment();
|
||||
}, [supabase, investmentDetail]);
|
||||
useEffect(() => {
|
||||
const fetchProjects = async () => {
|
||||
@ -88,7 +101,7 @@ export default function Dashboard() {
|
||||
// console.table(latestInvestment);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container max-w-screen-xl">
|
||||
<Loader isSuccess={isSuccess} />
|
||||
<div className="md:hidden">
|
||||
<Image
|
||||
@ -265,22 +278,18 @@ export default function Dashboard() {
|
||||
<CardTitle>Recent Funds</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<RecentFunds
|
||||
data={latestInvestment
|
||||
.map((item) => {
|
||||
if (item.projectId === currentProjectId) {
|
||||
return {
|
||||
name: item.name,
|
||||
amount: item.amount,
|
||||
avatar: item.logo_url,
|
||||
date: item.date,
|
||||
status: item.status,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.filter((item) => item !== undefined)}
|
||||
/>
|
||||
<RecentFunds
|
||||
data={latestInvestment.map((item) => {
|
||||
return {
|
||||
name: item.username,
|
||||
amount: item.dealAmount,
|
||||
avatar: item.avatarUrl,
|
||||
date: new Date(item.createdTime),
|
||||
status: item.dealStatus,
|
||||
profile_url: `/profile/${item.investorId}`,
|
||||
};
|
||||
})}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
@ -289,6 +298,6 @@ export default function Dashboard() {
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
|
||||
@ -26,7 +26,7 @@ function getTotalInvestment(deals: { deal_amount: number }[]) {
|
||||
}
|
||||
async function getLatestInvestment(
|
||||
supabase: SupabaseClient,
|
||||
deals: { project_id: number; deal_amount: number; created_time: Date }[]
|
||||
deals: { project_id: number; deal_amount: number; created_time: Date;}[]
|
||||
) {
|
||||
const llist = [];
|
||||
const count = 8;
|
||||
|
||||
@ -117,7 +117,7 @@ export default function ApplyProject() {
|
||||
confirmButtonColor: error == null ? "green" : "red",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// window.location.href = "/";
|
||||
window.location.href = "/";
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import Link from "next/link";
|
||||
|
||||
export type RecentDealData = {
|
||||
created_time: Date;
|
||||
@ -11,42 +12,122 @@ export type RecentDealData = {
|
||||
};
|
||||
|
||||
interface RecentFundsProps {
|
||||
data?: { name?: string; amount?: number; avatar?: string; date?: Date; logo_url?: string; status?: string }[];
|
||||
data?: { name?: string; amount?: number; avatar?: string; date?: Date; logo_url?: string; status?: string; profile_url?: string }[];
|
||||
}
|
||||
|
||||
export function RecentFunds(props: RecentFundsProps) {
|
||||
const content = (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
{(props?.data || []).map((deal, index) => (
|
||||
<div className="flex items-center" key={index}>
|
||||
<Avatar className="h-9 w-9">
|
||||
<AvatarImage src={deal.logo_url} alt={deal.name} />
|
||||
<AvatarFallback>{(deal.name ?? "").slice(0, 2)}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="ml-4 space-y-1">
|
||||
<p className="text-sm font-medium leading-none">{deal.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{deal?.date?.toLocaleDateString()}</p>
|
||||
{deal.status && (
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="relative flex h-3 w-3">
|
||||
<span
|
||||
className={`animate-ping absolute inline-flex h-3 w-3 rounded-full opacity-75 ${deal?.status === "In Progress" ? "bg-sky-400" : deal?.status === "Completed" ? "bg-green-400" : "bg-yellow-400"}`}
|
||||
></span>
|
||||
<span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 mt-[2px] ml-0.5 ${deal?.status === "In Progress" ? "bg-sky-500" : deal?.status === "Completed" ? "bg-green-500" : "bg-yellow-500"}`}
|
||||
></span>
|
||||
</span>
|
||||
<p
|
||||
className={`text-xs m-0 ${deal?.status === "In Progress" ? "text-sky-500" : deal?.status === "Completed" ? "text-green-500" : "text-yellow-500"}`}
|
||||
>
|
||||
{deal?.status}
|
||||
</p>
|
||||
<div key={index}>
|
||||
{deal.profile_url ? (
|
||||
<Link
|
||||
href={deal.profile_url}
|
||||
className="flex items-center w-full"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Avatar className="h-9 w-9">
|
||||
<AvatarImage src={deal.logo_url ? deal.logo_url : deal.avatar} alt={deal.name} />
|
||||
<AvatarFallback>{(deal.name ?? "").slice(0, 2)}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="ml-4 space-y-1">
|
||||
<p className="text-sm font-medium leading-none">{deal.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{deal?.date?.toLocaleDateString()}</p>
|
||||
{deal.status && (
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="relative flex h-3 w-3">
|
||||
<span
|
||||
className={`animate-ping absolute inline-flex h-3 w-3 rounded-full opacity-75 ${
|
||||
deal?.status === "In Progress"
|
||||
? "bg-sky-400"
|
||||
: deal?.status === "Completed"
|
||||
? "bg-green-400"
|
||||
: "bg-yellow-400"
|
||||
}`}
|
||||
></span>
|
||||
<span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 mt-[2px] ml-0.5 ${
|
||||
deal?.status === "In Progress"
|
||||
? "bg-sky-500"
|
||||
: deal?.status === "Completed"
|
||||
? "bg-green-500"
|
||||
: "bg-yellow-500"
|
||||
}`}
|
||||
></span>
|
||||
</span>
|
||||
<p
|
||||
className={`text-xs m-0 ${
|
||||
deal?.status === "In Progress"
|
||||
? "text-sky-500"
|
||||
: deal?.status === "Completed"
|
||||
? "text-green-500"
|
||||
: "text-yellow-500"
|
||||
}`}
|
||||
>
|
||||
{deal?.status}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+${deal.amount}</div>
|
||||
<div className="ml-auto font-medium">+${deal.amount}</div>
|
||||
</Link>
|
||||
) : (
|
||||
<div className="flex items-center w-full">
|
||||
<Avatar className="h-9 w-9">
|
||||
<AvatarImage src={deal.logo_url ? deal.logo_url : deal.avatar} alt={deal.name} />
|
||||
<AvatarFallback>{(deal.name ?? "").slice(0, 2)}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="ml-4 space-y-1">
|
||||
<p className="text-sm font-medium leading-none">{deal.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{deal?.date?.toLocaleDateString()}</p>
|
||||
{deal.status && (
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="relative flex h-3 w-3">
|
||||
<span
|
||||
className={`animate-ping absolute inline-flex h-3 w-3 rounded-full opacity-75 ${
|
||||
deal?.status === "In Progress"
|
||||
? "bg-sky-400"
|
||||
: deal?.status === "Completed"
|
||||
? "bg-green-400"
|
||||
: "bg-yellow-400"
|
||||
}`}
|
||||
></span>
|
||||
<span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 mt-[2px] ml-0.5 ${
|
||||
deal?.status === "In Progress"
|
||||
? "bg-sky-500"
|
||||
: deal?.status === "Completed"
|
||||
? "bg-green-500"
|
||||
: "bg-yellow-500"
|
||||
}`}
|
||||
></span>
|
||||
</span>
|
||||
<p
|
||||
className={`text-xs m-0 ${
|
||||
deal?.status === "In Progress"
|
||||
? "text-sky-500"
|
||||
: deal?.status === "Completed"
|
||||
? "text-green-500"
|
||||
: "text-yellow-500"
|
||||
}`}
|
||||
>
|
||||
{deal?.status}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="ml-auto font-medium">+${deal.amount}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -16,14 +16,21 @@ export const getInvestmentByProjectsIds = (client: SupabaseClient, projectIds: s
|
||||
.select(
|
||||
`
|
||||
id,
|
||||
deal_status:deal_status_id(value),
|
||||
...deal_status_id(
|
||||
deal_status:value
|
||||
),
|
||||
project_id,
|
||||
deal_amount,
|
||||
investor:users_id(email),
|
||||
created_time
|
||||
created_time,
|
||||
...profiles (
|
||||
investor_id:id,
|
||||
username,
|
||||
avatar_url
|
||||
)
|
||||
`
|
||||
)
|
||||
.in("project_id", projectIds);
|
||||
.in("project_id", projectIds)
|
||||
.order("created_time", { ascending: false });
|
||||
};
|
||||
|
||||
export const getInvestmentByUserId = (client: SupabaseClient, userId: string) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user