connect recent funded people to database

This commit is contained in:
Naytitorn Chaovirachot 2024-10-21 14:52:54 +07:00
parent 0150b4840b
commit f65fc2a696
5 changed files with 80 additions and 59 deletions

View File

@ -7,14 +7,17 @@ export type Deal = {
investor_id: string; investor_id: string;
}; };
// Sort the dealList by created_time in descending order
export function byCreatedTimeDesc(a: Deal, b: Deal) {
return new Date(b.created_time).getTime() - new Date(a.created_time).getTime();
}
export async function getDealList() { export async function getDealList() {
const supabase = createSupabaseClient(); const supabase = createSupabaseClient();
const { data: dealData, error } = await supabase const { data: dealData, error } = await supabase
.from('business') .from('business')
.select(` .select(`
id,
project ( project (
id,
investment_deal ( investment_deal (
deal_amount, deal_amount,
created_time, created_time,
@ -25,7 +28,6 @@ export async function getDealList() {
.eq('user_id', await getCurrentUserID()) .eq('user_id', await getCurrentUserID())
.single(); .single();
// Handle errors and no data cases
if (error) { if (error) {
alert(JSON.stringify(error)); alert(JSON.stringify(error));
console.error('Error fetching deal list:', error); console.error('Error fetching deal list:', error);
@ -37,22 +39,51 @@ export async function getDealList() {
return; // Exit if there's no data return; // Exit if there's no data
} }
const dealList = dealData.project[0].investment_deal; const flattenedDeals = dealData.project.flatMap((proj) =>
proj.investment_deal.map((deal) => ({
deal_amount: deal.deal_amount,
created_time: deal.created_time,
investor_id: deal.investor_id,
}))
)
// Check for empty dealList // Check for empty dealList
if (!dealList.length) { if (!flattenedDeals.length) {
alert("No deal list available"); alert("No deal list available");
return; // Exit if there's no data return; // Exit if there's no data
} }
return flattenedDeals.sort(byCreatedTimeDesc);
// Sort the dealList by created_time in descending order
const byCreatedTimeDesc = (a: Deal, b: Deal) =>
new Date(b.created_time).getTime() - new Date(a.created_time).getTime();
return dealList.sort(byCreatedTimeDesc);
}; };
export async function getRecentDealData() {
const supabase = createSupabaseClient();
let dealList = await getDealList();
if (!dealList) {
// #TODO div no deals available?
return;
}
dealList = dealList.slice(0, 5)
const investorIdList: string[] = dealList.map(deal => deal.investor_id);
const { data: userData, error } = await supabase
.from("profiles")
.select("username, avatar_url") // #TODO add email
.in("id", investorIdList); // Filter by investor_id
if (error) {
// Handle the error and return a meaningful message
console.error("Error fetching usernames and avatars:", error);
}
alert(JSON.stringify(userData));
return userData || [];
}
// #TODO move to util // #TODO move to util
export function convertToGraphData(deals: Deal[]): Record<string, number> { export function convertToGraphData(deals: Deal[]): Record<string, number> {
// group by year & month
let graphData = deals.reduce((acc, deal) => { let graphData = deals.reduce((acc, deal) => {
const monthYear = new Date(deal.created_time).toISOString().slice(0, 7); // E.g., '2024-10' const monthYear = new Date(deal.created_time).toISOString().slice(0, 7); // E.g., '2024-10'
acc[monthYear] = (acc[monthYear] || 0) + deal.deal_amount; // Sum the deal_amount acc[monthYear] = (acc[monthYear] || 0) + deal.deal_amount; // Sum the deal_amount

View File

@ -1,5 +1,8 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Deal, getDealList, convertToGraphData } from "../api/dealApi"; import { Deal, getDealList, convertToGraphData, getRecentDealData } from "../api/dealApi";
type RecentDealData = { username: string; avatar_url: string }[]
// custom hook for deal list // custom hook for deal list
export function useDealList() { export function useDealList() {
@ -17,7 +20,7 @@ export function useDealList() {
} }
export function useGraphData() { export function useGraphData() {
const [graphData, setGraphData] = useState<Record<string, number>>({}); const [graphData, setGraphData] = useState({});
const fetchGraphData = async () => { const fetchGraphData = async () => {
const dealList = await getDealList(); const dealList = await getDealList();
@ -31,4 +34,18 @@ export function useGraphData() {
}, []); }, []);
return graphData; return graphData;
}
export function useRecentDealData() {
const [recentDealData, setRecentDealData] = useState<RecentDealData>();
const fetchRecentDealData = async () => {
setRecentDealData(await getRecentDealData());
}
useEffect(() => {
fetchRecentDealData();
}, []);
return recentDealData;
} }

View File

@ -12,12 +12,13 @@ import { Overview } from "@/components/ui/overview";
import { RecentFunds } from "@/components/recent-funds"; import { RecentFunds } from "@/components/recent-funds";
import { useState } from "react"; import { useState } from "react";
import { useDealList, useGraphData } from "./hook"; import { useDealList, useGraphData, useRecentDealData } from "./hook";
export default function Dashboard() { export default function Dashboard() {
const [graphType, setGraphType] = useState("line"); const [graphType, setGraphType] = useState("line");
const graphData = useGraphData(); const graphData = useGraphData();
const dealList = useDealList(); const dealList = useDealList();
const recentDealData = useRecentDealData();
const totalDealAmount = dealList?.reduce((sum, deal) => sum + deal.deal_amount, 0) || 0; const totalDealAmount = dealList?.reduce((sum, deal) => sum + deal.deal_amount, 0) || 0;
return ( return (
@ -198,7 +199,7 @@ export default function Dashboard() {
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<RecentFunds> <RecentFunds recentDealData={recentDealData!}>
</RecentFunds> </RecentFunds>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -1,59 +1,31 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
const data = [ type RecentDealData = {
{ username: string;
name: "Olivia Martin", avatar_url: string;
email: "olivia.martin@email.com", // email: string;
amount: "1900.00", };
avatar: "/avatars/01.png", // psuedo avatar image
initials: "OM",
},
{
name: "Jackson Lee",
email: "jackson.lee@email.com",
amount: "39.00",
avatar: "/avatars/02.png",
initials: "JL",
},
{
name: "Isabella Nguyen",
email: "isabella.nguyen@email.com",
amount: "299.00",
avatar: "/avatars/03.png",
initials: "IN",
},
{
name: "William Kim",
email: "will@email.com",
amount: "99.00",
avatar: "/avatars/04.png",
initials: "WK",
},
{
name: "Sofia Davis",
email: "sofia.davis@email.com",
amount: "39.00",
avatar: "/avatars/05.png",
initials: "SD",
},
];
export function RecentFunds() { interface RecentFundsProps {
recentDealData: RecentDealData[];
}
export function RecentFunds({ recentDealData }: RecentFundsProps) {
return ( return (
<div className="space-y-8"> <div className="space-y-8">
{data.map((person, index) => ( {recentDealData?.map((person, 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={person.avatar_url} alt={person.username} />
<AvatarFallback>{person.initials}</AvatarFallback> {<AvatarFallback>{person.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">{person.name}</p> <p className="text-sm font-medium leading-none">{person.username}</p>
<p className="text-sm text-muted-foreground">{person.email}</p> {/* <p className="text-sm text-muted-foreground">{person.email}</p> */}
</div> </div>
<div className="ml-auto font-medium">+${person.amount}</div> {/* <div className="ml-auto font-medium">+${person.amount}</div> */}
</div> </div>
))} ))}
</div> </div>
); );
} }

0
src/hooks/useDealList.ts Normal file
View File