From a1158907fb8f0826f5351143fa1b5ea7de6399f4 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 16:13:01 +0700 Subject: [PATCH 01/14] refactor: remove unused custom hooks for deal list and graph data --- src/app/dashboard/hook.ts | 53 ---------- src/app/dashboard/page.tsx | 210 ++++++++++++++++++------------------- 2 files changed, 105 insertions(+), 158 deletions(-) diff --git a/src/app/dashboard/hook.ts b/src/app/dashboard/hook.ts index 0b2cdb8..e69de29 100644 --- a/src/app/dashboard/hook.ts +++ b/src/app/dashboard/hook.ts @@ -1,53 +0,0 @@ -import { useEffect, useState } from "react"; -import { Deal, getDealList, convertToGraphData, getRecentDealData } from "../api/dealApi"; -import { RecentDealData } from "@/components/recent-funds"; -import { getCurrentUserID } from "../api/userApi"; - -// custom hook for deal list -export function useDealList() { - const [dealList, setDealList] = useState([]); - - const fetchDealList = async () => { - // set the state to the deal list of current business user - setDealList(await getDealList(await getCurrentUserID())); - }; - - useEffect(() => { - fetchDealList(); - }, []); - - return dealList; -} - -export function useGraphData() { - const [graphData, setGraphData] = useState({}); - - const fetchGraphData = async () => { - // fetch the state to the deal list of current business user - const dealList = await getDealList(await getCurrentUserID()); - if (dealList) { - setGraphData(convertToGraphData(dealList)); - } - }; - - useEffect(() => { - fetchGraphData(); - }, []); - - return graphData; -} - -export function useRecentDealData() { - const [recentDealData, setRecentDealData] = useState(); - - const fetchRecentDealData = async () => { - // set the state to the deal list of current business user - setRecentDealData(await getRecentDealData(await getCurrentUserID())); - }; - - useEffect(() => { - fetchRecentDealData(); - }, []); - - return recentDealData; -} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 78f14b9..d95c6f2 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -5,7 +5,6 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Overview } from "@/components/ui/overview"; import { RecentFunds } from "@/components/recent-funds"; import { useEffect, useState } from "react"; -import { useDealList } from "./hook"; import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; import useSession from "@/lib/supabase/useSession"; import { getProjectByUserId } from "@/lib/data/projectQuery"; @@ -70,8 +69,6 @@ export default function Dashboard() { >([]); const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); - const dealList = useDealList(); - const totalDealAmount = dealList?.reduce((sum, deal) => sum + deal.deal_amount, 0) || 0; useEffect(() => { const fetchProjects = async () => { if (userId) { @@ -91,6 +88,7 @@ export default function Dashboard() { }; fetchProjects(); }, [supabase, userId]); + // console.table(projects); return ( <> @@ -116,7 +114,7 @@ export default function Dashboard() {

Business Dashboard

- + {projects.map((project) => ( @@ -124,81 +122,82 @@ export default function Dashboard() { ))} - -
- - - Total Funds Raised - - - - - -
${totalDealAmount}
- {/*

+ {projects.map((project) => ( + +

+ + + Total Funds Raised + + + + + +
${}
+ {/*

+20.1% from last month

*/} -
-
- - - Profile Views - - - - - - -
+2350
- {/*

+ + + + + Profile Views + + + + + + +

+2350
+ {/*

+180.1% from last month

*/} -
-
- - - Total Followers - - - - - - - -
+12,234
- {/*

+ + + + + Total Followers + + + + + + + +

+12,234
+ {/*

+19% from last month

*/} -
-
- {/* + + + {/* Active Now @@ -223,38 +222,39 @@ export default function Dashboard() {

*/} -
-
- - - Overview - - - - {/* tab to switch between line and bar graph */} - - - setGraphType("line")}> - Line - - setGraphType("bar")}> - Bar - - - - - - - - Recent Funds - You made {dealList?.length || 0} sales this month. - - - - - -
- +
+
+ + + Overview + + + + {/* tab to switch between line and bar graph */} + + + setGraphType("line")}> + Line + + setGraphType("bar")}> + Bar + + + + + + + + Recent Funds + You had {} investors invest this month. + + + + + +
+
+ ))}
From fa554bfb519133aa8691598ac3b3bced7d2832ae Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 16:20:26 +0700 Subject: [PATCH 02/14] feat: add investment query functionality to dashboard --- src/app/dashboard/page.tsx | 10 ++++++++++ src/app/dashboard/{hook.ts => query.ts} | 0 src/lib/data/investmentQuery.ts | 4 ++++ 3 files changed, 14 insertions(+) rename src/app/dashboard/{hook.ts => query.ts} (100%) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index d95c6f2..9eb0d3c 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -9,6 +9,8 @@ import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; import useSession from "@/lib/supabase/useSession"; 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"; const data = [ { @@ -69,6 +71,14 @@ export default function Dashboard() { >([]); const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); + const investmentDetail = useQuery( + getInvestmentByProjectsIds( + supabase, + projects.map((item) => { + return item.id.toString(); + }) + ) + ); useEffect(() => { const fetchProjects = async () => { if (userId) { diff --git a/src/app/dashboard/hook.ts b/src/app/dashboard/query.ts similarity index 100% rename from src/app/dashboard/hook.ts rename to src/app/dashboard/query.ts diff --git a/src/lib/data/investmentQuery.ts b/src/lib/data/investmentQuery.ts index da17b3b..bba485f 100644 --- a/src/lib/data/investmentQuery.ts +++ b/src/lib/data/investmentQuery.ts @@ -10,6 +10,10 @@ export const getInvestmentCountsByProjectsIds = (client: SupabaseClient, project .in("project_id", projectIds); }; +export const getInvestmentByProjectsIds = (client: SupabaseClient, projectIds: string[]) => { + return client.from("investment_deal").select("*").in("project_id", projectIds); +}; + export const getInvestmentByUserId = (client: SupabaseClient, userId: string) => { return client .from("investment_deal") From 9b37b76bd50bcd4e07ac053b2653a0cc07c598f1 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 16:57:41 +0700 Subject: [PATCH 03/14] feat: implement latest investment fetching for dashboard --- src/app/dashboard/page.tsx | 61 ++++++++++++++++++++++++++++++-- src/app/portfolio/[uid]/query.ts | 1 + 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 9eb0d3c..627ae12 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -11,6 +11,7 @@ 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 } from "../portfolio/[uid]/query"; const data = [ { @@ -69,8 +70,12 @@ export default function Dashboard() { 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 }[] + >([]); const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); + const [currentProjectId, setCurrentProjectId] = useState(projects[0]?.id); const investmentDetail = useQuery( getInvestmentByProjectsIds( supabase, @@ -79,6 +84,37 @@ 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, + })) + ); + // console.table(resolvedLatest); + }; + fetchLatestInvestment(); + }, [supabase, investmentDetail]); useEffect(() => { const fetchProjects = async () => { if (userId) { @@ -99,6 +135,7 @@ export default function Dashboard() { fetchProjects(); }, [supabase, userId]); // console.table(projects); + // console.table(latestInvestment); return ( <> @@ -124,14 +161,20 @@ export default function Dashboard() {

Business Dashboard

+ {projects.map((project) => ( - + setCurrentProjectId(project.id)} + > {project.project_name} ))} + {currentProjectId} {projects.map((project) => (
@@ -259,7 +302,21 @@ export default function Dashboard() { You had {} investors invest this month. - + { + if (item.projectId === currentProjectId) { + return { + name: item.name, + amount: item.amount, + avatar: item.logo_url, + date: item.date, + }; + } + return undefined; + }) + .filter((item) => item !== undefined)} + />
diff --git a/src/app/portfolio/[uid]/query.ts b/src/app/portfolio/[uid]/query.ts index 151d0eb..d3c147a 100644 --- a/src/app/portfolio/[uid]/query.ts +++ b/src/app/portfolio/[uid]/query.ts @@ -38,6 +38,7 @@ async function getLatestInvestment( } let url = fetchLogoURL(supabase, deals[i].project_id); llist.push({ + projectId: deals[i].project_id, name: project?.[0]?.project_name, amount: deals[i].deal_amount, date: new Date(deals[i].created_time), From 4c42b5e50d97ba50e4d018952422db9e9617d14a Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 17:08:16 +0700 Subject: [PATCH 04/14] feat: enhance dashboard overview with overall graph data and export Deal interface --- src/app/dashboard/page.tsx | 20 +++++++++++++++++--- src/app/portfolio/[uid]/query.ts | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 627ae12..da7870e 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -11,7 +11,7 @@ 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 } from "../portfolio/[uid]/query"; +import { getLatestInvestment, overAllGraphData, Deal } from "../portfolio/[uid]/query"; const data = [ { @@ -174,7 +174,6 @@ export default function Dashboard() { ))} - {currentProjectId} {projects.map((project) => (
@@ -282,7 +281,22 @@ export default function Dashboard() { Overview - + { + if (deal.project_id === currentProjectId) { + return { + deal_amount: deal.deal_amount, + created_time: deal.created_time, + }; + } + return undefined; + }) + .filter((deal) => deal !== undefined) as Deal[] + )} + /> {/* tab to switch between line and bar graph */} diff --git a/src/app/portfolio/[uid]/query.ts b/src/app/portfolio/[uid]/query.ts index d3c147a..28d8e42 100644 --- a/src/app/portfolio/[uid]/query.ts +++ b/src/app/portfolio/[uid]/query.ts @@ -105,7 +105,7 @@ async function getBusinessTypeName(supabase: SupabaseClient, projectId: number) } // only use deal that were made at most year ago -interface Deal { +export interface Deal { created_time: string | number | Date; deal_amount: any; } From 81cb94686c09a041a5b4356d6f58c557b47f7a60 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 17:09:03 +0700 Subject: [PATCH 05/14] refactor: remove hardcoded monthly data from dashboard component --- src/app/dashboard/page.tsx | 51 -------------------------------------- 1 file changed, 51 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index da7870e..85e5b2a 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -13,57 +13,6 @@ import { getInvestmentByProjectsIds } from "@/lib/data/investmentQuery"; import { useQuery } from "@supabase-cache-helpers/postgrest-react-query"; import { getLatestInvestment, overAllGraphData, Deal } from "../portfolio/[uid]/query"; -const data = [ - { - name: "Jan", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Feb", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Mar", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Apr", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "May", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Jun", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Jul", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Aug", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Sep", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Oct", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Nov", - value: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: "Dec", - value: Math.floor(Math.random() * 5000) + 1000, - }, -]; - export default function Dashboard() { let supabase = createSupabaseClient(); const userId = useSession().session?.user.id; From 0933f86fafe64ced0b325ab721307506824ad024 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Thu, 7 Nov 2024 18:24:57 +0700 Subject: [PATCH 06/14] feat: add investment status to recent funds and dashboard components --- src/app/dashboard/page.tsx | 11 ++++++----- src/app/portfolio/[uid]/query.ts | 2 +- src/components/recent-funds.tsx | 20 +++++++++++++++++++- src/lib/data/investmentQuery.ts | 14 +++++++++++++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 85e5b2a..eb7638b 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -20,7 +20,7 @@ export default function Dashboard() { { 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 }[] + { projectId: number; name: any; amount: number; date: Date; logo_url: string; status: string }[] >([]); const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); @@ -58,9 +58,10 @@ export default function Dashboard() { 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(resolvedLatest); + // console.table(investmentDetail); }; fetchLatestInvestment(); }, [supabase, investmentDetail]); @@ -230,7 +231,7 @@ export default function Dashboard() { Overview - deal !== undefined) as Deal[] )} - /> + /> */} {/* tab to switch between line and bar graph */} @@ -262,7 +263,6 @@ export default function Dashboard() { Recent Funds - You had {} investors invest this month. = 0 && llist.length < count; --i) { let { data: project, error } = await supabase.from("project").select("project_name").eq("id", deals[i].project_id); if (error) { diff --git a/src/components/recent-funds.tsx b/src/components/recent-funds.tsx index 3707d2d..5902524 100644 --- a/src/components/recent-funds.tsx +++ b/src/components/recent-funds.tsx @@ -6,11 +6,12 @@ export type RecentDealData = { investor_id: string; username: string; logo_url?: string; + status?: string; // email: string; }; interface RecentFundsProps { - data?: { name?: string; amount?: number; avatar?: string; date?: Date; logo_url?: string }[]; + data?: { name?: string; amount?: number; avatar?: string; date?: Date; logo_url?: string; status?: string }[]; } export function RecentFunds(props: RecentFundsProps) { @@ -25,6 +26,23 @@ export function RecentFunds(props: RecentFundsProps) {

{deal.name}

{deal?.date?.toLocaleDateString()}

+ {deal.status && ( +
+ + + + +

+ {deal?.status} +

+
+ )}
+${deal.amount}
diff --git a/src/lib/data/investmentQuery.ts b/src/lib/data/investmentQuery.ts index bba485f..9cae764 100644 --- a/src/lib/data/investmentQuery.ts +++ b/src/lib/data/investmentQuery.ts @@ -11,7 +11,19 @@ export const getInvestmentCountsByProjectsIds = (client: SupabaseClient, project }; export const getInvestmentByProjectsIds = (client: SupabaseClient, projectIds: string[]) => { - return client.from("investment_deal").select("*").in("project_id", projectIds); + return client + .from("investment_deal") + .select( + ` + id, + deal_status:deal_status_id(value), + project_id, + deal_amount, + investor:users_id(email), + created_time + ` + ) + .in("project_id", projectIds); }; export const getInvestmentByUserId = (client: SupabaseClient, userId: string) => { From 804de94cbe6cc507c6268e693a59474a5e12c1be Mon Sep 17 00:00:00 2001 From: Pattadon Date: Fri, 8 Nov 2024 15:08:05 +0700 Subject: [PATCH 07/14] feat: update dashboard to enhance investment data handling and display --- src/app/dashboard/page.tsx | 109 +++++++++++++------------ src/app/dashboard/query.ts | 1 + src/app/portfolio/[uid]/query.ts | 2 +- src/app/project/apply/page.tsx | 2 +- src/components/recent-funds.tsx | 135 ++++++++++++++++++++++++------- src/lib/data/investmentQuery.ts | 15 +++- 6 files changed, 181 insertions(+), 83 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index eb7638b..4c777c3 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -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 ( - <> +
Recent Funds - { - 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)} - /> + { + return { + name: item.username, + amount: item.dealAmount, + avatar: item.avatarUrl, + date: new Date(item.createdTime), + status: item.dealStatus, + profile_url: `/profile/${item.investorId}`, + }; + })} + />
@@ -289,6 +298,6 @@ export default function Dashboard() {
- + ); } diff --git a/src/app/dashboard/query.ts b/src/app/dashboard/query.ts index e69de29..8b13789 100644 --- a/src/app/dashboard/query.ts +++ b/src/app/dashboard/query.ts @@ -0,0 +1 @@ + diff --git a/src/app/portfolio/[uid]/query.ts b/src/app/portfolio/[uid]/query.ts index 47bb06f..aac9153 100644 --- a/src/app/portfolio/[uid]/query.ts +++ b/src/app/portfolio/[uid]/query.ts @@ -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; diff --git a/src/app/project/apply/page.tsx b/src/app/project/apply/page.tsx index 0509058..e5d184e 100644 --- a/src/app/project/apply/page.tsx +++ b/src/app/project/apply/page.tsx @@ -117,7 +117,7 @@ export default function ApplyProject() { confirmButtonColor: error == null ? "green" : "red", }).then((result) => { if (result.isConfirmed) { - // window.location.href = "/"; + window.location.href = "/"; } }); }; diff --git a/src/components/recent-funds.tsx b/src/components/recent-funds.tsx index 5902524..dd47e91 100644 --- a/src/components/recent-funds.tsx +++ b/src/components/recent-funds.tsx @@ -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 = ( +
+ +
+ ) return (
{(props?.data || []).map((deal, index) => ( -
- - - {(deal.name ?? "").slice(0, 2)} - -
-

{deal.name}

-

{deal?.date?.toLocaleDateString()}

- {deal.status && ( -
- - - - -

- {deal?.status} -

+
+ {deal.profile_url ? ( + + + + {(deal.name ?? "").slice(0, 2)} + +
+

{deal.name}

+

{deal?.date?.toLocaleDateString()}

+ {deal.status && ( +
+ + + + +

+ {deal?.status} +

+
+ )}
- )} -
-
+${deal.amount}
+
+${deal.amount}
+ + ) : ( +
+ + + {(deal.name ?? "").slice(0, 2)} + +
+

{deal.name}

+

{deal?.date?.toLocaleDateString()}

+ {deal.status && ( +
+ + + + +

+ {deal?.status} +

+
+ )} +
+
+${deal.amount}
+
+ )}
))}
); + } diff --git a/src/lib/data/investmentQuery.ts b/src/lib/data/investmentQuery.ts index 9cae764..df9a944 100644 --- a/src/lib/data/investmentQuery.ts +++ b/src/lib/data/investmentQuery.ts @@ -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) => { From 40b0c7dcdc010f5150a5d63715f954e4d02241c1 Mon Sep 17 00:00:00 2001 From: Pattadon Date: Fri, 8 Nov 2024 15:47:24 +0700 Subject: [PATCH 08/14] feat: implement tabbed graph display for investment data on dashboard --- src/app/dashboard/page.tsx | 97 ++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 4c777c3..3c678c3 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -11,14 +11,10 @@ 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 { 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"; +import { overAllGraphData, Deal, fourYearGraphData, dayOftheWeekData } from "../portfolio/[uid]/query"; export default function Dashboard() { 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 }[] @@ -33,6 +29,8 @@ export default function Dashboard() { username: string; }[] >([]); + const tabOptions = ["daily", "monthly", "yearly"]; + const [activeTab, setActiveTab] = useState("daily"); const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); const [currentProjectId, setCurrentProjectId] = useState(projects[0]?.id); @@ -44,6 +42,19 @@ export default function Dashboard() { }) ) ); + const handleTabChange = (tab: string) => { + setActiveTab(tab); + }; + let graphData = []; + const filteredData = (investmentDetail?.data || []).filter((deal) => deal.project_id === currentProjectId); + + if (activeTab === "daily") { + graphData = dayOftheWeekData(filteredData); + } else if (activeTab === "yearly") { + graphData = fourYearGraphData(filteredData); + } else { + graphData = overAllGraphData(filteredData); + } useEffect(() => { const setTopLatestInvestment = () => { if (investmentDetail?.data) { @@ -73,7 +84,7 @@ export default function Dashboard() { username: string; }[] ); - console.table(latestInvestment) + console.table(latestInvestment); } }; setTopLatestInvestment(); @@ -243,53 +254,47 @@ export default function Dashboard() { Overview - - {/* { - if (deal.project_id === currentProjectId) { - return { - deal_amount: deal.deal_amount, - created_time: deal.created_time, - }; - } - return undefined; - }) - .filter((deal) => deal !== undefined) as Deal[] - )} - /> */} - {/* tab to switch between line and bar graph */} - - - setGraphType("line")}> - Line + + + {tabOptions.map((tab) => ( + + {tab.charAt(0).toUpperCase() + tab.slice(1)} - setGraphType("bar")}> - Bar - - - - + ))} + + + + + + + setGraphType("line")}> + Line + + setGraphType("bar")}> + Bar + + + + + Recent Funds - { - return { - name: item.username, - amount: item.dealAmount, - avatar: item.avatarUrl, - date: new Date(item.createdTime), - status: item.dealStatus, - profile_url: `/profile/${item.investorId}`, - }; - })} - /> + { + return { + name: item.username, + amount: item.dealAmount, + avatar: item.avatarUrl, + date: new Date(item.createdTime), + status: item.dealStatus, + profile_url: `/profile/${item.investorId}`, + }; + })} + />
From 1c8d68183a15f00cbc095404aa84156e1c32d5af Mon Sep 17 00:00:00 2001 From: Pattadon Date: Fri, 8 Nov 2024 16:43:12 +0700 Subject: [PATCH 09/14] feat: improve tag display logic in ProjectCard component to filter out null or blank tags --- src/components/projectCard.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/components/projectCard.tsx b/src/components/projectCard.tsx index ded4889..86de0f5 100644 --- a/src/components/projectCard.tsx +++ b/src/components/projectCard.tsx @@ -71,15 +71,19 @@ export function ProjectCard(props: ProjectCardProps) { {props.location}
- {props.tags && Array.isArray(props.tags) ? ( - props.tags.map((tag) => ( - - {tag} - - )) - ) : ( - No tags available - )} + {props.tags?.length !== 0 && Array.isArray(props.tags) + ? props.tags + .filter((tag) => tag && tag.trim() !== "") // Filters out null or blank tags + .map((tag) => ( + + {tag} + + )) + : null}
From 1c46887cef8747c895b78ba7bac1766d1360d1e7 Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Sat, 9 Nov 2024 15:10:15 +0700 Subject: [PATCH 10/14] feat: enhance user experience by optimizing loading times for dashboard components --- src/app/dashboard/page.tsx | 273 ++++++++++++++++++------------------- 1 file changed, 136 insertions(+), 137 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 3c678c3..21f9dd1 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -93,13 +93,13 @@ export default function Dashboard() { const fetchProjects = async () => { if (userId) { const { data, error } = await getProjectByUserId(supabase, userId); - // alert(JSON.stringify(data)); if (error) { console.error("Error while fetching projects"); } if (data) { + // set project and current project id setProjects(data); - // console.table(data); + setCurrentProjectId(data[0].id); } } else { console.error("Error with UserId while fetching projects"); @@ -108,8 +108,6 @@ export default function Dashboard() { }; fetchProjects(); }, [supabase, userId]); - // console.table(projects); - // console.table(latestInvestment); return (
@@ -135,95 +133,95 @@ export default function Dashboard() {

Business Dashboard

- - - + {projects && projects.length > 0 && ( + + + {projects.map((project) => ( + setCurrentProjectId(project.id)} + > + {project.project_name} + + ))} + {projects.map((project) => ( - setCurrentProjectId(project.id)} - > - {project.project_name} - - ))} - - {projects.map((project) => ( - -
- - - Total Funds Raised - - - - - -
${}
- {/*

+ +

+ + + Total Funds Raised + + + + + +
${}
+ {/*

+20.1% from last month

*/} -
-
- - - Profile Views - - - - - - -
+2350
- {/*

+ + + + + Profile Views + + + + + + +

+2350
+ {/*

+180.1% from last month

*/} -
-
- - - Total Followers - - - - - - - -
+12,234
- {/*

+ + + + + Total Followers + + + + + + + +

+12,234
+ {/*

+19% from last month

*/} -
-
- {/* + + + {/* Active Now @@ -248,59 +246,60 @@ export default function Dashboard() {

*/} -
-
- - - Overview - - - - {tabOptions.map((tab) => ( - - {tab.charAt(0).toUpperCase() + tab.slice(1)} - - ))} - - - +
+
+ + + Overview + + + + {tabOptions.map((tab) => ( + + {tab.charAt(0).toUpperCase() + tab.slice(1)} + + ))} + + + - - - setGraphType("line")}> - Line - - setGraphType("bar")}> - Bar - - - + + + setGraphType("line")}> + Line + + setGraphType("bar")}> + Bar + + + + + + + + + Recent Funds + + + { + return { + name: item.username, + amount: item.dealAmount, + avatar: item.avatarUrl, + date: new Date(item.createdTime), + status: item.dealStatus, + profile_url: `/profile/${item.investorId}`, + }; + })} + /> - - - - - Recent Funds - - - { - return { - name: item.username, - amount: item.dealAmount, - avatar: item.avatarUrl, - date: new Date(item.createdTime), - status: item.dealStatus, - profile_url: `/profile/${item.investorId}`, - }; - })} - /> - - -
- - ))} - +
+
+
+ ))} +
+ )}
From 9c1564f8748fffbb6e42edfa4add13e4ccc5701e Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Sat, 9 Nov 2024 16:00:32 +0700 Subject: [PATCH 11/14] feat: add animated count-up for total completed deal amounts on dashboard --- src/app/dashboard/page.tsx | 19 +++++++++++++------ src/app/dashboard/query.ts | 1 - src/app/portfolio/[uid]/page.tsx | 19 ------------------- 3 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 src/app/dashboard/query.ts diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 21f9dd1..2742e29 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -12,6 +12,7 @@ import { Loader } from "@/components/loading/loader"; import { getInvestmentByProjectsIds } from "@/lib/data/investmentQuery"; import { useQuery } from "@supabase-cache-helpers/postgrest-react-query"; import { overAllGraphData, Deal, fourYearGraphData, dayOftheWeekData } from "../portfolio/[uid]/query"; +import CountUp from "react-countup"; export default function Dashboard() { const supabase = createSupabaseClient(); @@ -34,6 +35,7 @@ export default function Dashboard() { const [isSuccess, setIsSuccess] = useState(false); const [graphType, setGraphType] = useState("line"); const [currentProjectId, setCurrentProjectId] = useState(projects[0]?.id); + const investmentDetail = useQuery( getInvestmentByProjectsIds( supabase, @@ -42,11 +44,11 @@ export default function Dashboard() { }) ) ); + let graphData = []; + const filteredData = (investmentDetail?.data || []).filter((deal) => deal.project_id === currentProjectId); const handleTabChange = (tab: string) => { setActiveTab(tab); }; - let graphData = []; - const filteredData = (investmentDetail?.data || []).filter((deal) => deal.project_id === currentProjectId); if (activeTab === "daily") { graphData = dayOftheWeekData(filteredData); @@ -166,10 +168,15 @@ export default function Dashboard() { -
${}
- {/*

- +20.1% from last month -

*/} +
+ $ + project.deal_status === "Completed") + .reduce((sum, current) => sum + current.deal_amount, 0)} + duration={1} + /> +
diff --git a/src/app/dashboard/query.ts b/src/app/dashboard/query.ts deleted file mode 100644 index 8b13789..0000000 --- a/src/app/dashboard/query.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/portfolio/[uid]/page.tsx b/src/app/portfolio/[uid]/page.tsx index 8356d48..b154941 100644 --- a/src/app/portfolio/[uid]/page.tsx +++ b/src/app/portfolio/[uid]/page.tsx @@ -52,7 +52,6 @@ export default async function Portfolio({ params }: { params: { uid: string } }) ); } const username = localUser ? localUser.user.user_metadata.name : "Anonymous"; - // console.log(username) const overAllData = deals ? overAllGraphData(deals) : []; const fourYearData = deals ? fourYearGraphData(deals) : []; const dayOfWeekData = deals ? dayOftheWeekData(deals) : []; @@ -66,31 +65,13 @@ export default async function Portfolio({ params }: { params: { uid: string } }) ) : []; const totalInvestment = deals ? getTotalInvestment(deals) : 0; - // console.log(latestDeals); - const tagCount = countTags(tags); - // console.log(investedBusinessIds); const businessType = deals ? await Promise.all(deals.map(async (item) => await getBusinessTypeName(supabase, item.project_id))) : []; const countedBusinessType = countValues(businessType.filter((item) => item !== null)); - // console.log(countedBusinessType); - - // console.log(tagCount); return (
- {/* {JSON.stringify(params.uid)} */} - {/* {JSON.stringify(tagCount)} */} - {/* {JSON.stringify(deals)} */} - {/* {JSON.stringify(dayOfWeekData)} */} - {/* {JSON.stringify(overAllGraphData)} */} - {/* {JSON.stringify(threeYearGraphData)} */} - {/* {JSON.stringify(uniqueProjectIds)} */} - {/*
-

Total Invest :

-
{totalInvest}
-
*/} - {/* */}

Welcome to your Portfolio, {username}!

From b2bc8766e19a7c818be039c28d66c68f3dccde7b Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Sat, 9 Nov 2024 16:46:13 +0700 Subject: [PATCH 12/14] feat: add edit button for project navigation on dashboard --- src/app/dashboard/page.tsx | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 2742e29..d55711d 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -13,6 +13,7 @@ import { getInvestmentByProjectsIds } from "@/lib/data/investmentQuery"; import { useQuery } from "@supabase-cache-helpers/postgrest-react-query"; import { overAllGraphData, Deal, fourYearGraphData, dayOftheWeekData } from "../portfolio/[uid]/query"; import CountUp from "react-countup"; +import { Button } from "@/components/ui/button"; export default function Dashboard() { const supabase = createSupabaseClient(); @@ -228,31 +229,20 @@ export default function Dashboard() {

*/} - {/* - - - Active Now - - { + window.location.href = `/project/${project.id}/edit`; + }} + className="h-full bg-emerald-500 hover:bg-emerald-800 font-bold text-xl" > - - - - -
+573
-

- +201 since last hour -

-
-
*/} + Edit Project + + + +
From 7e4a237075eb9a9d3c875ec316cdbeef51328edc Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Sun, 10 Nov 2024 13:25:12 +0700 Subject: [PATCH 13/14] feat: replace static values with animated count-up for investment totals on dashboard --- src/app/dashboard/page.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index d55711d..f285c25 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -87,7 +87,7 @@ export default function Dashboard() { username: string; }[] ); - console.table(latestInvestment); + // console.table(latestInvestment); } }; setTopLatestInvestment(); @@ -198,7 +198,9 @@ export default function Dashboard() { -
+2350
+
+ + +
{/*

+180.1% from last month

*/} @@ -223,7 +225,9 @@ export default function Dashboard() { -
+12,234
+
+ + +
{/*

+19% from last month

*/} From 493d2805e659fd07343b67392a3dbad629471ebd Mon Sep 17 00:00:00 2001 From: THIS ONE IS A LITTLE BIT TRICKY KRUB Date: Sun, 10 Nov 2024 20:05:50 +0700 Subject: [PATCH 14/14] feat: implement image gallery component for project deal page --- src/app/(investment)/deals/[id]/page.tsx | 36 ++-------- src/components/carousel.tsx | 88 ++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 32 deletions(-) create mode 100644 src/components/carousel.tsx diff --git a/src/app/(investment)/deals/[id]/page.tsx b/src/app/(investment)/deals/[id]/page.tsx index f6d8280..8060968 100644 --- a/src/app/(investment)/deals/[id]/page.tsx +++ b/src/app/(investment)/deals/[id]/page.tsx @@ -5,19 +5,19 @@ import ReactMarkdown from "react-markdown"; import * as Tabs from "@radix-ui/react-tabs"; import { Button } from "@/components/ui/button"; -import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import { Separator } from "@/components/ui/separator"; import { createSupabaseClient } from "@/lib/supabase/serverComponentClient"; import FollowShareButtons from "./followShareButton"; -import { DisplayFullImage } from "./displayImage"; + import { getProjectData } from "@/lib/data/projectQuery"; import { getDealList } from "@/app/api/dealApi"; import { sumByKey, toPercentage } from "@/lib/utils"; import { redirect } from "next/navigation"; import { isOwnerOfProject } from "./query"; import remarkGfm from "remark-gfm"; +import Gallery from "@/components/carousel"; const PHOTO_MATERIAL_ID = 2; @@ -75,7 +75,6 @@ export default async function ProjectDealPage({ params }: { params: { id: number ? projectMaterial.flatMap((item) => (item.material_url || ["/boiler1.jpg"]).map((url: string) => ({ src: url, - alt: "Image", })) ) : [{ src: "/boiler1.jpg", alt: "Default Boiler Image" }]; @@ -106,35 +105,8 @@ export default async function ProjectDealPage({ params }: { params: { id: number
{/* image carousel */} -