diff --git a/package-lock.json b/package-lock.json
index b7aa8bd..a6c4ea1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,6 +39,7 @@
"@tailwindcss/line-clamp": "^0.4.4",
"@tanstack/react-query": "^5.59.0",
"@tanstack/react-query-devtools": "^5.59.0",
+ "@tanstack/react-table": "^8.20.5",
"b2d-ventures": "file:",
"chart.js": "^4.4.6",
"class-variance-authority": "^0.7.0",
@@ -47,7 +48,7 @@
"date-fns": "^3.0.0",
"dotenv": "^16.4.5",
"embla-carousel-react": "^8.2.0",
- "framer-motion": "^11.11.15",
+ "framer-motion": "^11.11.17",
"lucide-react": "^0.428.0",
"next": "^14.2.15",
"next-themes": "^0.3.0",
@@ -4212,6 +4213,39 @@
"react": "^18 || ^19"
}
},
+ "node_modules/@tanstack/react-table": {
+ "version": "8.20.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz",
+ "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/table-core": "8.20.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/@tanstack/table-core": {
+ "version": "8.20.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz",
+ "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
"node_modules/@trivago/prettier-plugin-sort-imports": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz",
@@ -7916,9 +7950,10 @@
}
},
"node_modules/framer-motion": {
- "version": "11.11.15",
- "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.15.tgz",
- "integrity": "sha512-fib+OpUe4nap4W1vhaDohnPU+42B5s1q+jNkNkb6TfzmDYtRhDyvn4mkRCAD5a2cQKOI3nJZP7yqGYtxnlmleg==",
+ "version": "11.11.17",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.17.tgz",
+ "integrity": "sha512-O8QzvoKiuzI5HSAHbcYuL6xU+ZLXbrH7C8Akaato4JzQbX2ULNeniqC2Vo5eiCtFktX9XsJ+7nUhxcl2E2IjpA==",
+ "license": "MIT",
"dependencies": {
"tslib": "^2.4.0"
},
diff --git a/package.json b/package.json
index 7e469b6..d5b293b 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"@tailwindcss/line-clamp": "^0.4.4",
"@tanstack/react-query": "^5.59.0",
"@tanstack/react-query-devtools": "^5.59.0",
+ "@tanstack/react-table": "^8.20.5",
"b2d-ventures": "file:",
"chart.js": "^4.4.6",
"class-variance-authority": "^0.7.0",
@@ -49,7 +50,7 @@
"date-fns": "^3.0.0",
"dotenv": "^16.4.5",
"embla-carousel-react": "^8.2.0",
- "framer-motion": "^11.11.15",
+ "framer-motion": "^11.11.17",
"lucide-react": "^0.428.0",
"next": "^14.2.15",
"next-themes": "^0.3.0",
diff --git a/src/app/(investment)/deals/[id]/displayImage.tsx b/src/app/(investment)/deals/[id]/displayImage.tsx
deleted file mode 100644
index 6bea6bf..0000000
--- a/src/app/(investment)/deals/[id]/displayImage.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-"use client";
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from "@/components/ui/dialog";
-import Image from "next/image";
-import { StaticImport } from "next/dist/shared/lib/get-img-props";
-
-interface ItemProps {
- src: string | StaticImport;
- alt: string;
- width: number;
- height: number;
- className?: string;
-}
-
-const ImageModal = ({ src, alt, width, height, className }: ItemProps) => {
- return (
-
- );
-};
-
-export function DisplayFullImage({ src, alt, width, height, className }: ItemProps) {
- return ;
-}
diff --git a/src/app/(investment)/deals/[id]/followShareButton.tsx b/src/app/(investment)/deals/[id]/followShareButton.tsx
index 5a2c8de..f6bb4b8 100644
--- a/src/app/(investment)/deals/[id]/followShareButton.tsx
+++ b/src/app/(investment)/deals/[id]/followShareButton.tsx
@@ -3,7 +3,7 @@
/* eslint-disable */
import { useState, useEffect } from "react";
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
+import CustomTooltip from "@/components/customToolTip";
import { ShareIcon, StarIcon } from "lucide-react";
import { deleteFollow, getFollow, insertFollow } from "@/lib/data/followQuery";
import toast from "react-hot-toast";
@@ -13,9 +13,10 @@ import { useQuery } from "@supabase-cache-helpers/postgrest-react-query";
interface FollowShareButtons {
userId: string;
projectId: number;
+ projectName: string;
}
-const FollowShareButtons = ({ userId, projectId }: FollowShareButtons) => {
+const FollowShareButtons = ({ userId, projectId, projectName }: FollowShareButtons) => {
const supabase = createSupabaseClient();
const { data: follow, isLoading: followIsLoading } = useQuery(getFollow(supabase, userId, projectId), {
staleTime: 0,
@@ -71,16 +72,9 @@ const FollowShareButtons = ({ userId, projectId }: FollowShareButtons) => {
return (
-
-
-
-
-
-
- Follow NVIDIA
-
-
-
+
+
+
diff --git a/src/app/(investment)/deals/[id]/page.tsx b/src/app/(investment)/deals/[id]/page.tsx
index 73ef4be..8cb6b8b 100644
--- a/src/app/(investment)/deals/[id]/page.tsx
+++ b/src/app/(investment)/deals/[id]/page.tsx
@@ -1,8 +1,6 @@
import Image from "next/image";
import Link from "next/link";
-
import ReactMarkdown from "react-markdown";
-
import * as Tabs from "@radix-ui/react-tabs";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
@@ -10,7 +8,6 @@ import { Progress } from "@/components/ui/progress";
import { Separator } from "@/components/ui/separator";
import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
import FollowShareButtons from "./followShareButton";
-
import { getProjectData } from "@/lib/data/projectQuery";
import { getDealList } from "@/app/api/dealApi";
import { sumByKey, toPercentage } from "@/lib/utils";
@@ -89,7 +86,7 @@ export default async function ProjectDealPage({ params }: { params: { id: number
{projectData?.project_name}
-
+
{/* end of pack */}
{projectData?.project_short_description}
diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx
index c1c58cc..7bed7a5 100644
--- a/src/app/dashboard/page.tsx
+++ b/src/app/dashboard/page.tsx
@@ -16,6 +16,8 @@ import { overAllGraphData, fourYearGraphData, dayOftheWeekData } from "../portfo
import CountUp from "react-countup";
import { Button } from "@/components/ui/button";
import { useRouter } from "next/navigation";
+import Link from "next/link";
+import { Modal } from "@/components/modal";
export default function Dashboard() {
const supabase = createSupabaseClient();
@@ -50,17 +52,17 @@ export default function Dashboard() {
)
);
let graphData = [];
- const filteredData = (investmentDetail?.data || []).filter((deal) => deal.project_id === currentProjectId);
+ const filteredProject = (investmentDetail?.data || []).filter((deal) => deal.project_id === currentProjectId);
const handleTabChange = (tab: string) => {
setActiveTab(tab);
};
if (activeTab === "daily") {
- graphData = dayOftheWeekData(filteredData);
+ graphData = dayOftheWeekData(filteredProject);
} else if (activeTab === "yearly") {
- graphData = fourYearGraphData(filteredData);
+ graphData = fourYearGraphData(filteredProject);
} else {
- graphData = overAllGraphData(filteredData);
+ graphData = overAllGraphData(filteredProject);
}
useEffect(() => {
@@ -116,193 +118,191 @@ export default function Dashboard() {
return (
{" "}
-
-
-
-
-
-
-
-
Business Dashboard
-
- {projects && projects.length > 0 && (
-
-
- {projects.map((project) => (
- setCurrentProjectId(project.id)}
- >
- {project.project_name}
-
- ))}
-
+
+
+
Business Dashboard
+
+ {projects && projects.length > 0 && (
+
+
{projects.map((project) => (
-
-
-
-
- Total Funds Raised
-
-
-
-
- $
- project.deal_status === "Completed")
- .reduce((sum, current) => sum + current.deal_amount, 0)}
- duration={1}
- />
-
-
-
-
-
- Profile Views
-
-
-
-
- +
-
- {/*
+ setCurrentProjectId(project.id)}
+ >
+ {project.project_name}
+
+ ))}
+
+ {projects.map((project) => (
+
+
+
+
+ Total Funds Raised
+
+
+
+
+ $
+ project.deal_status === "Completed")
+ .reduce((sum, current) => sum + current.deal_amount, 0)}
+ duration={1}
+ />
+
+
+
+
+
+ Profile Views
+
+
+
+
+ +
+
+ {/*
+180.1% from last month
*/}
-
-
-
-
- Total Followers
-
-
-
-
- +
-
- {/*
+
+
+
+
+ Total Followers
+
+
+
+
+ +
+
+ {/*
+19% from last month
*/}
-
-
-
-
-
-
-
- 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
-
-
-
-
-
-
-
-
- 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}`,
- };
- })}
- />
+
+
+ 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}`,
+ };
+ })}
+ />
+
+ {filteredProject && filteredProject.length > 1 ? (
+ {
+ return {
+ date: item.created_time,
+ name: item.username,
+ amount: item.deal_amount,
+ status: item.deal_status,
+ logoURL: Array.isArray(item.avatar_url) ? item.avatar_url[0] : item.avatar_url,
+ profileURL: `/profile/${item.investor_id}`,
+ };
+ })}
+ />
+ ) : undefined}
+
+
+
+
+
+ ))}
+
+ )}
);
diff --git a/src/app/portfolio/[uid]/page.tsx b/src/app/portfolio/[uid]/page.tsx
index 00115a6..4dee08c 100644
--- a/src/app/portfolio/[uid]/page.tsx
+++ b/src/app/portfolio/[uid]/page.tsx
@@ -24,6 +24,10 @@ import { NoDataAlert } from "@/components/alert/noData/alert";
import { error } from "console";
import { UnAuthorizedAlert } from "@/components/alert/unauthorized/alert";
import Link from "next/link";
+import { DataTable } from "@/components/dataTable";
+import { Button } from "@/components/ui/button";
+import CustomTooltip from "@/components/customToolTip";
+import { Modal } from "@/components/modal";
export default async function Portfolio({ params }: { params: { uid: string } }) {
const supabase = createSupabaseClient();
@@ -53,6 +57,7 @@ export default async function Portfolio({ params }: { params: { uid: string } })
if (investorDealError) {
console.error(investorDealError);
}
+
const { data: localUser, error: localUserError } = await supabase.auth.getUser();
if (localUserError) {
console.error("Error while fetching user" + error);
@@ -72,7 +77,16 @@ export default async function Portfolio({ params }: { params: { uid: string } })
const tags = deals ? await getInvestorProjectTag(supabase, deals) : [];
const latestDeals = deals
? await Promise.all(
- (await getLatestInvestment(supabase, deals)).map(async (deal) => ({
+ (
+ await getLatestInvestment(
+ supabase,
+ deals.map((deal) => ({
+ ...deal,
+ status: deal.deal_status,
+ project_id: deal.project_id,
+ }))
+ )
+ ).map(async (deal) => ({
...deal,
logo_url: await deal.logo_url,
}))
@@ -96,7 +110,6 @@ export default async function Portfolio({ params }: { params: { uid: string } })
-
@@ -175,8 +188,8 @@ export default async function Portfolio({ params }: { params: { uid: string } })
-
-
+
+
Categories of Invested Projects
@@ -201,7 +214,7 @@ export default async function Portfolio({ params }: { params: { uid: string } })
/>
-
+
Types of Businesses Invested In
@@ -226,12 +239,39 @@ export default async function Portfolio({ params }: { params: { uid: string } })
/>
-
+
Recent investment
-
-
+
+ {
+ return {
+ name: item.name,
+ amount: item.amount,
+ avatar: item.logo_url,
+ date: new Date(item.date),
+ status: item.status,
+ profile_url: `/deals/${item.projectId}`,
+ };
+ })}
+ />
+
+ {deals && deals.length > 5 ? (
+ {
+ return {
+ date: item.created_time,
+ name: item.project_name,
+ amount: item.deal_amount,
+ status: item.deal_status,
+ logoURL: Array.isArray(item.avatar_url) ? item.avatar_url[0] : item.avatar_url,
+ profileURL: `/deals/${item.project_id}`,
+ };
+ })}
+ />
+ ) : undefined}
+
diff --git a/src/app/portfolio/[uid]/query.ts b/src/app/portfolio/[uid]/query.ts
index 3333de8..311a865 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; status: string }[]
) {
const llist = [];
const count = 5;
@@ -43,6 +43,7 @@ async function getLatestInvestment(
amount: deals[i].deal_amount,
date: new Date(deals[i].created_time),
logo_url: url,
+ status: deals[i].status,
});
}
diff --git a/src/components/ProjectSection.tsx b/src/components/ProjectSection.tsx
index 92dbd06..13b41ad 100644
--- a/src/components/ProjectSection.tsx
+++ b/src/components/ProjectSection.tsx
@@ -20,7 +20,7 @@ export function ProjectSection({ projectsData }: { projectsData: ProjectCardProp
}
return (
-
+
{projectsData.map((project) => (
diff --git a/src/components/carousel.tsx b/src/components/carousel.tsx
index eb994e1..7951303 100644
--- a/src/components/carousel.tsx
+++ b/src/components/carousel.tsx
@@ -1,5 +1,5 @@
"use client";
-import { useEffect, useState, useMemo } from "react";
+import { useEffect, useState, useMemo, useCallback } from "react";
import { Carousel, CarouselContent, CarouselItem, type CarouselApi } from "./ui/carousel";
import Image from "next/image";
@@ -8,15 +8,40 @@ interface GalleryProps {
}
const Gallery = ({ images }: GalleryProps) => {
- const [mainApi, setMainApi] = useState
();
- const [thumbnailApi, setThumbnailApi] = useState();
+ const [mainApi, setMainApi] = useState(null);
+ const [thumbnailApi, setThumbnailApi] = useState(null);
const [current, setCurrent] = useState(0);
+ const [isReady, setIsReady] = useState(false);
+
+ const syncCarousels = useCallback(
+ (index: number) => {
+ if (mainApi && thumbnailApi) {
+ setCurrent(index);
+ mainApi.scrollTo(index);
+ thumbnailApi.scrollTo(index);
+ }
+ },
+ [mainApi, thumbnailApi]
+ );
+
+ const handleClick = useCallback(
+ (index: number) => {
+ syncCarousels(index);
+ },
+ [syncCarousels]
+ );
const mainImage = useMemo(
() =>
images.map((image, index) => (
-
+
)),
[images]
@@ -25,61 +50,60 @@ const Gallery = ({ images }: GalleryProps) => {
const thumbnailImages = useMemo(
() =>
images.map((image, index) => (
- handleClick(index)}>
+ handleClick(index)}
+ >
)),
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [images, current]
+ [images, current, handleClick]
);
useEffect(() => {
- if (!mainApi || !thumbnailApi) {
- return;
- }
+ if (!mainApi || !thumbnailApi) return;
+ if (isReady) return;
- const handleTopSelect = () => {
+ const handleMainSelect = () => {
const selected = mainApi.selectedScrollSnap();
- setCurrent(selected);
- thumbnailApi.scrollTo(selected);
+ if (selected !== current) {
+ syncCarousels(selected);
+ }
};
- const handleBottomSelect = () => {
+ const handleThumbnailSelect = () => {
const selected = thumbnailApi.selectedScrollSnap();
- setCurrent(selected);
- mainApi.scrollTo(selected);
+ if (selected !== current) {
+ syncCarousels(selected);
+ }
};
- mainApi.on("select", handleTopSelect);
- thumbnailApi.on("select", handleBottomSelect);
+ mainApi.on("select", handleMainSelect);
+ thumbnailApi.on("select", handleThumbnailSelect);
+
+ syncCarousels(0);
+ setIsReady(true);
return () => {
- mainApi.off("select", handleTopSelect);
- thumbnailApi.off("select", handleBottomSelect);
+ mainApi.off("select", handleMainSelect);
+ thumbnailApi.off("select", handleThumbnailSelect);
};
- }, [mainApi, thumbnailApi]);
-
- const handleClick = (index: number) => {
- if (!mainApi || !thumbnailApi) {
- return;
- }
- thumbnailApi.scrollTo(index);
- mainApi.scrollTo(index);
- setCurrent(index);
- };
+ }, [mainApi, thumbnailApi, current, syncCarousels, isReady]);
return (
-
+
{mainImage}
-
+
{thumbnailImages}
diff --git a/src/components/dataTable.tsx b/src/components/dataTable.tsx
new file mode 100644
index 0000000..8385d7e
--- /dev/null
+++ b/src/components/dataTable.tsx
@@ -0,0 +1,294 @@
+"use client";
+
+import * as React from "react";
+import {
+ ColumnDef,
+ ColumnFiltersState,
+ SortingState,
+ VisibilityState,
+ flexRender,
+ getCoreRowModel,
+ getFilteredRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable,
+} from "@tanstack/react-table";
+import { ArrowUpDown, ChevronDown } from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+import { Checkbox } from "@/components/ui/checkbox";
+import {
+ DropdownMenu,
+ DropdownMenuCheckboxItem,
+ DropdownMenuContent,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Input } from "@/components/ui/input";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
+import Link from "next/link";
+
+export type ModalProps = {
+ date: Date;
+ amount: number;
+ name: string;
+ investorId?: string;
+ profileURL?: string;
+ logoURL?: string;
+ status?: string;
+};
+
+export const columns: ColumnDef[] = [
+ {
+ id: "select",
+ header: ({ table }) => (
+ table.toggleAllPageRowsSelected(!!value)}
+ aria-label="Select all"
+ />
+ ),
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ aria-label="Select row"
+ />
+ ),
+ enableSorting: false,
+ enableHiding: false,
+ },
+ {
+ accessorKey: "name",
+ header: ({ column }) => {
+ return (
+
+ );
+ },
+ cell: ({ row }) => (
+
+
+
+ ),
+ },
+ {
+ accessorKey: "date",
+ header: () => Date
,
+ cell: ({ row }) => {
+ const formatted = new Date(row.getValue("date")).toUTCString();
+ return {formatted}
;
+ },
+ },
+ {
+ accessorKey: "status",
+ header: "Status",
+ cell: ({ row }) => (
+
+
+
+
+
+
+
+
+ {row.getValue("status")}
+
+
+ ),
+ },
+ {
+ accessorKey: "amount",
+ header: () => Amount
,
+ cell: ({ row }) => {
+ const amount = parseFloat(row.getValue("amount"));
+
+ // Format the amount as a dollar amount
+ const formatted = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ }).format(amount);
+
+ return {formatted}
;
+ },
+ },
+ {
+ accessorKey: "logoURL",
+ id: "logoURL",
+ header: () => null,
+ cell: () => null,
+ },
+ {
+ accessorKey: "profileURL",
+ id: "profileURL",
+ header: () => null,
+ cell: () => null,
+ },
+];
+
+export function DataTable({ data }: { data: ModalProps[] }) {
+ const [sorting, setSorting] = React.useState([]);
+ const [columnFilters, setColumnFilters] = React.useState([]);
+ const [columnVisibility, setColumnVisibility] = React.useState({});
+ const [rowSelection, setRowSelection] = React.useState({});
+ const [pagination, setPagination] = React.useState({
+ pageIndex: 0,
+ pageSize: 5,
+ });
+
+ const table = useReactTable({
+ data,
+ columns,
+ onSortingChange: setSorting,
+ onColumnFiltersChange: setColumnFilters,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ getFilteredRowModel: getFilteredRowModel(),
+ onColumnVisibilityChange: setColumnVisibility,
+ onPaginationChange: setPagination,
+ onRowSelectionChange: setRowSelection,
+ state: {
+ sorting,
+ columnFilters,
+ columnVisibility,
+ rowSelection,
+ pagination,
+ },
+ });
+
+ return (
+
+
+ table.getColumn("name")?.setFilterValue(event.target.value)}
+ className="max-w-sm"
+ />
+
+
+
+
+
+ {table
+ .getAllColumns()
+ .filter((column) => column.getCanHide() && column.id != "logoURL" && column.id != "profileURL")
+ .map((column) => {
+ return (
+ column.toggleVisibility(!!value)}
+ >
+ {column.id}
+
+ );
+ })}
+
+
+
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ return (
+
+ {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
+
+ );
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+ ))}
+
+ ))
+ ) : (
+
+
+ No results.
+
+
+ )}
+
+
+
+
+
+ {table.getFilteredSelectedRowModel().rows.length} of {table.getFilteredRowModel().rows.length} row(s)
+ selected.
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/mobileMenu.tsx b/src/components/mobileMenu.tsx
new file mode 100644
index 0000000..9c513a8
--- /dev/null
+++ b/src/components/mobileMenu.tsx
@@ -0,0 +1,27 @@
+"use client";
+import { useState } from "react";
+import { Menu, X } from "lucide-react";
+import { Button } from "./ui/button";
+import { motion } from "framer-motion";
+
+export function MobileMenu() {
+ const [isVisible, setIsVisible] = useState(false);
+ return (
+
+
+ {isVisible && (
+
+ setIsVisible(false)} />
+
+ )}
+
+ );
+}
diff --git a/src/components/modal.tsx b/src/components/modal.tsx
new file mode 100644
index 0000000..7b9fb5e
--- /dev/null
+++ b/src/components/modal.tsx
@@ -0,0 +1,29 @@
+"use client";
+import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
+import { Button } from "./ui/button";
+import { DataTable } from "./dataTable";
+
+export type ModalProps = {
+ date: Date;
+ amount: number;
+ name: string;
+ investorId?: string;
+ profileURL?: string;
+ logoURL?: string;
+ status?: string;
+};
+
+export function Modal({ data }: { data: ModalProps[] }) {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/navigationBar/AuthenticatedComponents.tsx b/src/components/navigationBar/AuthenticatedComponents.tsx
index c2d45b3..1a9a004 100644
--- a/src/components/navigationBar/AuthenticatedComponents.tsx
+++ b/src/components/navigationBar/AuthenticatedComponents.tsx
@@ -34,9 +34,12 @@ export const AuthenticatedComponents = ({ uid, avatarUrl, notificationCount }: A
{notificationCount >= 1 && (
-
- {notificationCount}
-
+
+
+
+ {notificationCount}
+
+
)}
diff --git a/src/components/navigationBar/nav.tsx b/src/components/navigationBar/nav.tsx
index 5d27fa3..e4f0233 100644
--- a/src/components/navigationBar/nav.tsx
+++ b/src/components/navigationBar/nav.tsx
@@ -21,6 +21,8 @@ import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
import { getUserId } from "@/lib/supabase/actions/getUserId";
import { getUnreadNotificationCountByUserId } from "@/lib/data/notificationQuery";
+import { MobileMenu } from "../mobileMenu";
+
const ListItem = React.forwardRef, React.ComponentPropsWithoutRef<"a">>(
({ className, title, children, ...props }, ref) => {
return (
@@ -97,8 +99,10 @@ export async function NavigationBar() {
-
-
+
+
+
+
@@ -146,7 +150,7 @@ export async function NavigationBar() {
-
+
diff --git a/src/components/ui/carousel.tsx b/src/components/ui/carousel.tsx
index 59831f9..2ff1992 100644
--- a/src/components/ui/carousel.tsx
+++ b/src/components/ui/carousel.tsx
@@ -115,14 +115,16 @@ const Carousel = React.forwardRef
+ }}
+ >
+ {...props}
+ >
{children}
@@ -183,7 +185,8 @@ const CarouselPrevious = React.forwardRef
+ {...props}
+ >
Previous slide
@@ -210,7 +213,8 @@ const CarouselNext = React.forwardRef
+ {...props}
+ >
Next slide
diff --git a/src/lib/data/investmentQuery.ts b/src/lib/data/investmentQuery.ts
index df9a944..dfbabd2 100644
--- a/src/lib/data/investmentQuery.ts
+++ b/src/lib/data/investmentQuery.ts
@@ -20,6 +20,9 @@ export const getInvestmentByProjectsIds = (client: SupabaseClient, projectIds: s
deal_status:value
),
project_id,
+ ...project_id (
+ project_name
+ ),
deal_amount,
created_time,
...profiles (
@@ -56,7 +59,25 @@ export const getInvestmentByUserId = (client: SupabaseClient, userId: string) =>
export function getInvestorDeal(client: SupabaseClient, userId: string) {
return client
.from("investment_deal")
- .select("*")
+ .select(
+ `
+ id,
+ ...deal_status_id(
+ deal_status:value
+ ),
+ project_id,
+ ...project_id (
+ project_name
+ ),
+ deal_amount,
+ created_time,
+ ...profiles (
+ investor_id:id,
+ username,
+ avatar_url
+ )
+ `
+ )
.in("investor_id", [userId])
.order("created_time", { ascending: true });
}