diff --git a/package-lock.json b/package-lock.json index e1b7e63..0ce8bbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11230,9 +11230,9 @@ } }, "node_modules/supabase": { - "version": "1.207.9", - "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.207.9.tgz", - "integrity": "sha512-BJPwsAd2UBIpQawcQV3/xKHEZ8YrrkHYpgibxCZbG+RuxuhTtkHG7zR4I3LylIIEwcKp3hmDKu/hO1m2NT5RXA==", + "version": "1.215.0", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.215.0.tgz", + "integrity": "sha512-ITHqEnDl3F/b44AYdBUSzinqZhmGxrx205Yt2HfyaVTd5W/JppF3/naqVPIdRiUZBBLKkvfQO/wUk48W8SoVxw==", "dev": true, "hasInstallScript": true, "dependencies": { diff --git a/src/app/find/BusinessSection.tsx b/src/app/find/BusinessSection.tsx new file mode 100644 index 0000000..af688e3 --- /dev/null +++ b/src/app/find/BusinessSection.tsx @@ -0,0 +1,55 @@ +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { BusinessCard } from "@/components/BusinessCard"; +import { BusinessCardProps } from "@/types/BusinessCard"; +import { Separator } from "@/components/ui/separator"; +import Link from "next/link"; + +interface BusinessSectionProps extends BusinessCardProps { + user_id: string; +} + +export function BusinessSection({ businessData }: { businessData: BusinessSectionProps[] }) { + if (!businessData || businessData.length === 0) { + return ( + + + No Business Found + + +

Sorry, we could not find any businesses matching your search criteria.

+
+
+ ); + } + + return ( +
+
+ + + Businesses + Found {businessData.length} projects! + + + +
+ {businessData.map((business) => ( +
+ + + +
+ ))} +
+
+
+
+
+ ); +} diff --git a/src/app/find/ProjectSection.tsx b/src/app/find/ProjectSection.tsx new file mode 100644 index 0000000..31ef700 --- /dev/null +++ b/src/app/find/ProjectSection.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { ProjectCard } from "@/components/projectCard"; +import { Separator } from "@/components/ui/separator"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { ProjectCardProps } from "@/types/ProjectCard"; +import Link from "next/link"; + +export function ProjectSection({ projectsData }: { projectsData: ProjectCardProps[] | null }) { + if (!projectsData || projectsData.length === 0) { + return ( + + + No Project Found + + +

Sorry, we could not find any projects matching your search criteria.

+
+
+ ); + } + + return ( +
+
+ + + Projects + Found {projectsData.length} projects! + + + +
+ {projectsData.map((project) => ( +
+ + + + +
+ ))} +
+
+
+
+
+ ); +} diff --git a/src/app/find/page.tsx b/src/app/find/page.tsx index 729609c..eae1be7 100644 --- a/src/app/find/page.tsx +++ b/src/app/find/page.tsx @@ -1,89 +1,43 @@ -"use client"; - import React, { Suspense } from "react"; -import { useSearchParams } from "next/navigation"; -import { createSupabaseClient } from "@/lib/supabase/clientComponentClient"; -import { useQuery } from "@supabase-cache-helpers/postgrest-react-query"; -import { ProjectCard } from "@/components/projectCard"; +import { getBusinessByName } from "@/lib/data/businessQuery"; +import { createSupabaseClient } from "@/lib/supabase/serverComponentClient"; +import { BusinessSection } from "./BusinessSection"; +import { ProjectSection } from "./ProjectSection"; +import { getProjectCardData } from "@/lib/data/projectQuery"; import { Separator } from "@/components/ui/separator"; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { getBusinessAndProject } from "@/lib/data/businessQuery"; -function FindContent() { - const searchParams = useSearchParams(); - const query = searchParams.get("query"); +export default async function FindContent({ searchParams }: { searchParams: { query: string } }) { + const query = searchParams.query; - let supabase = createSupabaseClient(); + const supabase = createSupabaseClient(); - const { - data: businesses, - isLoading: isLoadingBusinesses, - error: businessError, - } = useQuery(getBusinessAndProject(supabase, { businessName: query })); + const { data: projectIds, error: projectIdsError } = await supabase + .from("project") + .select(`id`) + .ilike("project_name", `%${query}%`); - const isLoading = isLoadingBusinesses; - const error = businessError; + const { data: businessData, error: businessDataError } = await getBusinessByName(supabase, { businessName: query }); - if (isLoading) return

Loading...

; - if (error) return

Error fetching data: {error.message}

; + if (businessDataError || projectIdsError) { + throw new Error(businessDataError?.message || projectIdsError?.message || "Unknown error"); + } + + const projectIdList: string[] = projectIds.map((item) => item.id); + const { data: projectsData, error: projectsDataError } = await getProjectCardData(supabase, projectIdList); + + if (projectsDataError) { + throw new Error(projectsDataError || "Unknown error"); + } return ( -
-
-

Result

- - - - - - {businesses!.length === 0 &&

No results found.

} - {businesses!.length > 0 && ( -
    - {businesses!.map((business) => ( -
  • - - - {business.business_name} - - Joined Date: {new Date(business.joined_date).toLocaleDateString()} - - - - {business?.projects && business.projects.length > 0 ? ( - business.projects.map((project) => ( - String(tag.tag_value)) || []} - imageUri={project.card_image_url} - /> - )) - ) : ( -

    No Projects

    - )} -
    -
    -
  • - ))} -
- )} -
-
-
+
+ Loading Business and Projects...
}> + + + + Loading Projects...
}> + + ); } - -export default function Find() { - return ( - Loading search parameters...

}> - -
- ); -} diff --git a/src/components/businessCard.tsx b/src/components/businessCard.tsx index 64f3c9f..295bbbe 100644 --- a/src/components/businessCard.tsx +++ b/src/components/businessCard.tsx @@ -1,53 +1,34 @@ -import Image from "next/image"; -import { - Card, - CardFooter, - CardDescription, - CardHeader, - CardTitle, -} from "@/components/ui/card"; +import { Card, CardFooter, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { CalendarDaysIcon } from "lucide-react"; - -interface XMap { - // tagName: colorCode - [tag: string]: string; -} - -interface BusinessCardProps { - name: string; - description: string; - joinDate: string; - location: string; - tags: XMap | null; -} +import { BusinessCardProps } from "@/types/BusinessCard"; +import Image from "next/image"; export function BusinessCard(props: BusinessCardProps) { return ( - - -
+ + +
nvidia
- {props.name} - - {props.description} - - - Joined {props.joinDate} - - +
+ {props.business_name} + + + + Joined {props.joined_date} + + +
- - {props.location} - - Technology + + {props.location} + + {props.business_type}
diff --git a/src/components/projectCard.tsx b/src/components/projectCard.tsx index 3189ced..ff221f3 100644 --- a/src/components/projectCard.tsx +++ b/src/components/projectCard.tsx @@ -22,6 +22,18 @@ interface ProjectCardProps { } export function ProjectCard(props: ProjectCardProps) { + if (props.minInvestment === null) { + props.minInvestment = 0; + } + + if (props.totalInvestor === null) { + props.minInvestment = 0; + } + + if (props.totalRaised === null) { + props.minInvestment = 0; + } + return (
{ `); }; +export const getBusinessByName = ( + client: SupabaseClient, + params: { businessName?: string | null; single?: boolean } = { single: false } +) => { + const query = client.from("business").select(` + business_id:id, + location, + business_name, + ...business_type ( + business_type_id: id, + business_type: value + ), + joined_date, + user_id + `); + + if (params.businessName && params.businessName.trim() !== "") { + query.ilike("business_name", `%${params.businessName}%`); + } + + if (params.single) { + query.single(); + } + + return query; +}; + export const getBusinessAndProject = ( client: SupabaseClient, params: { businessName?: String | null; businessId?: number | null; single?: boolean } = { single: false } @@ -53,7 +80,7 @@ export const getBusinessAndProject = ( `); if (params.businessName && params.businessName.trim() !== "") { - return query.ilike("business_name", `%${params.businessName}%`); + return query.or(`business_name.ilike.%${params.businessName}%,project_name.ilike.%${params.businessName}%`); } if (params.businessId) { diff --git a/src/lib/data/projectQuery.ts b/src/lib/data/projectQuery.ts index 27ca3c3..9402632 100644 --- a/src/lib/data/projectQuery.ts +++ b/src/lib/data/projectQuery.ts @@ -1,4 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; +import { ProjectCardProps } from "@/types/ProjectCard"; async function getTopProjects(client: SupabaseClient, numberOfRecords: number = 4) { try { @@ -241,6 +242,62 @@ const getProjectByUserId = (client: SupabaseClient, userId: string) => { .eq("business.user_id", userId); }; +function getProjectByName(client: SupabaseClient, searchTerm: string) { + return client + .from("project") + .select( + ` + id, + project_name, + business_id, + published_time, + project_short_description, + card_image_url, + project_investment_detail ( + min_investment, + total_investment, + target_investment, + investment_deadline + ), + project_tag ( + tag ( + id, + value + ) + ), + business ( + location + ) + ` + ) + .ilike("project_name", `%${searchTerm}%`); +} + +const getProjectCardData = async (client: SupabaseClient, projectIds: string[]) => { + const { data, error } = await client.from("project_card").select("*").in("project_id", projectIds); + + if (error) { + return { data: null, error: error.message }; + } + + const projectSections = data.map((project) => { + const projectSection: ProjectCardProps = { + id: project.project_id, + project_name: project.project_name, + short_description: project.short_description, + image_url: project.image_url, + join_date: project.join_date, + location: project.location, + tags: project.tags || [], + min_investment: project.min_investment, + total_investor: project.total_investor, + total_raise: project.total_raise, + }; + return projectSection; + }); + + return { data: projectSections, error: null }; +}; export { getProjectData, getProjectDataQuery, @@ -248,4 +305,6 @@ export { searchProjectsQuery, getProjectByBusinessId, getProjectByUserId, + getProjectByName, + getProjectCardData, }; diff --git a/src/types/BusinessCard.ts b/src/types/BusinessCard.ts new file mode 100644 index 0000000..1371428 --- /dev/null +++ b/src/types/BusinessCard.ts @@ -0,0 +1,7 @@ +export interface BusinessCardProps { + business_id: number; + business_name: string; + joined_date: string; + location: string; + business_type: string; +} diff --git a/src/types/ProjectCard.ts b/src/types/ProjectCard.ts new file mode 100644 index 0000000..51e9955 --- /dev/null +++ b/src/types/ProjectCard.ts @@ -0,0 +1,12 @@ +export interface ProjectCardProps { + id?: number; + project_name: string; + short_description: string; + image_url: string; + join_date: string; + location: string; + tags: string[] | null; + min_investment: number; + total_investor: number; + total_raise: number; +} diff --git a/src/types/database.types.ts b/src/types/database.types.ts index 57dc0ac..9169905 100644 Binary files a/src/types/database.types.ts and b/src/types/database.types.ts differ