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 ( - - - {alt} - - - - Image Preview - Click outside to close the image preview. - - {alt} - - - - ); -}; - -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 logo

{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 (
{" "} -
- Dashboard - Dashboard -
-
-
-
-

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) => ( - {`Carousel + {`Carousel )), [images] @@ -25,61 +50,60 @@ const Gallery = ({ images }: GalleryProps) => { const thumbnailImages = useMemo( () => images.map((image, index) => ( - handleClick(index)}> + handleClick(index)} + > {`Carousel )), - // 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 }); }