feat: store investment statement in database

This commit is contained in:
sirin 2024-10-13 21:18:32 +07:00
parent fc1dd4b4d9
commit d8a2f13d6c
4 changed files with 148 additions and 53 deletions

View File

@ -1,7 +1,7 @@
"use client";
import React, { useEffect, useState } from "react";
import { useStripe, useElements, PaymentElement } from "@stripe/react-stripe-js";
import { useStripe, useElements, CardElement } from "@stripe/react-stripe-js";
import convertToSubcurrency from "@/lib/convertToSubcurrency";
import {
Dialog,
@ -14,12 +14,19 @@ import {
DialogClose,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import useSession from "@/lib/supabase/useSession";
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
import { useRouter } from "next/navigation";
const CheckoutPage = ({
amount,
project_id,
investor_id,
isAcceptTermAndService,
}: {
amount: number;
project_id: number;
investor_id: string;
isAcceptTermAndService: () => boolean;
}) => {
const stripe = useStripe();
@ -27,8 +34,12 @@ const CheckoutPage = ({
const [errorMessage, setErrorMessage] = useState<string>();
const [clientSecret, setClientSecret] = useState("");
const [loading, setLoading] = useState(false);
const [isDialogOpen, setIsDialogOpen] = useState(false); // State for dialog open/close
const [isDialogOpen, setIsDialogOpen] = useState(false);
const isAcceptTerm = isAcceptTermAndService();
const router = useRouter();
const { session } = useSession();
const user = session?.user;
useEffect(() => {
fetch("/api/create-payment-intent", {
@ -58,19 +69,39 @@ const CheckoutPage = ({
return;
}
const { error } = await stripe.confirmPayment({
elements,
clientSecret,
confirmParams: {
return_url: `http://www.localhost:3000/payment-success?amount=${amount}`,
await stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement)!,
},
});
})
.then(async (result) => {
if (result.error) {
setErrorMessage(result.error.message);
} else {
try {
const supabase = createSupabaseClient();
const { data, error } = await supabase.from("InvestmentDeal").insert([
{
investorId: investor_id,
projectId: project_id,
dealAmount: amount,
},
]);
console.log("ADADSADWADWWAD");
if (error) {
setErrorMessage(error.message);
console.error("Supabase Insert Error:", error.message);
} else {
console.log("Insert successful:", data);
router.push(`http://www.localhost:3000/payment-success?amount=${amount}`);
}
} catch (err) {
console.error("Unexpected error during Supabase insert:", err);
}
}
setLoading(false);
});
};
if (!clientSecret || !stripe || !elements) {
@ -89,7 +120,7 @@ const CheckoutPage = ({
return (
<div>
{clientSecret && <PaymentElement />}
{clientSecret && <CardElement />}
{errorMessage && <div>{errorMessage}</div>}

View File

@ -2,15 +2,21 @@
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useParams } from "next/navigation";
import { Separator } from "@/components/ui/separator";
import { Input } from "@/components/ui/input";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { useQuery } from "@supabase-cache-helpers/postgrest-react-query";
import convertToSubcurrency from "@/lib/convertToSubcurrency";
import CheckoutPage from "./checkoutPage";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import { getProjectDataQuery } from "@/lib/data/projectQuery";
import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
import useSession from "@/lib/supabase/useSession";
if (process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY === undefined) {
throw new Error("NEXT_PUBLIC_STRIPE_PUBLIC_KEY is not defined");
}
@ -47,6 +53,14 @@ export default function InvestPage() {
const [checkedTerms, setCheckedTerms] = useState(Array(term_data.length).fill(false));
const [investAmount, setInvestAmount] = useState(10);
const { session } = useSession();
const investor_id = session!.user.id;
const params = useParams<{ id: string }>();
const supabase = createSupabaseClient();
const { data: projectData, isLoading: isLoadingProject } = useQuery(getProjectDataQuery(supabase, Number(params.id)));
const handleCheckboxChange = (index: number) => {
const updatedCheckedTerms = [...checkedTerms];
updatedCheckedTerms[index] = !updatedCheckedTerms[index];
@ -62,7 +76,7 @@ export default function InvestPage() {
return (
<div className="mx-10 md:mx-40 my-10">
<h1 className="text-2xl md:text-4xl font-bold">Invest on NVIDIA</h1>
<h1 className="text-2xl md:text-4xl font-bold">Invest on ${projectData?.project_name}</h1>
<Separator className="my-4" />
<div></div>
<div>
@ -113,7 +127,12 @@ export default function InvestPage() {
amount: convertToSubcurrency(investAmount),
currency: "usd",
}}>
<CheckoutPage amount={investAmount} isAcceptTermAndService={isAcceptTermAndService} />
<CheckoutPage
amount={investAmount}
isAcceptTermAndService={isAcceptTermAndService}
project_id={Number(params.id)}
investor_id={investor_id}
/>
</Elements>
</div>
</div>

View File

@ -1,4 +1,10 @@
import { redirect } from "next/navigation";
export default function PaymentSuccess({ searchParams: { amount } }: { searchParams: { amount: string } }) {
if (!amount) {
redirect("/");
}
return (
<main className="max-w-6xl mx-auto p-10 text-white text-center border m-10 rounded-md bg-gradient-to-tr from-blue-500 to-purple-500">
<div className="mb-10">

View File

@ -1,6 +1,9 @@
import { SupabaseClient } from "@supabase/supabase-js";
async function getTopProjects(client: SupabaseClient, numberOfRecords: number = 4) {
async function getTopProjects(
client: SupabaseClient,
numberOfRecords: number = 4,
) {
try {
const { data, error } = await client
.from("Project")
@ -27,7 +30,7 @@ async function getTopProjects(client: SupabaseClient, numberOfRecords: number =
Business (
location
)
`
`,
)
.order("publishedTime", { ascending: false })
.limit(numberOfRecords);
@ -42,7 +45,29 @@ async function getTopProjects(client: SupabaseClient, numberOfRecords: number =
console.error("Unexpected error:", err);
return { data: null, error: "An unexpected error occurred." };
}
}
}
function getProjectDataQuery(client: SupabaseClient, projectId: number) {
return client.from("Project").select(
`
project_name:projectName,
project_short_description:projectShortDescription,
project_description:projectDescription,
published_time:publishedTime,
...ProjectInvestmentDetail!inner (
min_investment:minInvestment,
total_investment:totalInvestment,
target_investment:targetInvestment,
investment_deadline:investmentDeadline
),
tags:ItemTag!inner (
...Tag!inner (
tag_name:value
)
)
`,
).eq("id", projectId).single();
}
async function getProjectData(client: SupabaseClient, projectId: number) {
const query = client.from("Project").select(
@ -62,11 +87,11 @@ async function getProjectData(client: SupabaseClient, projectId: number) {
tag_name:value
)
)
`
).eq("id", projectId).single()
`,
).eq("id", projectId).single();
const {data, error} = await query;
return { data, error }
const { data, error } = await query;
return { data, error };
}
export interface FilterParams {
@ -79,11 +104,22 @@ export interface FilterParams {
}
export interface FilterProjectQueryParams extends FilterParams {
page: number,
pageSize: number
page: number;
pageSize: number;
}
function searchProjectsQuery(client: SupabaseClient, {searchTerm, tagsFilter, projectStatus, businessTypeFilter, sortByTimeFilter, page = 1, pageSize = 4}: FilterProjectQueryParams) {
function searchProjectsQuery(
client: SupabaseClient,
{
searchTerm,
tagsFilter,
projectStatus,
businessTypeFilter,
sortByTimeFilter,
page = 1,
pageSize = 4,
}: FilterProjectQueryParams,
) {
const start = (page - 1) * pageSize;
const end = start + pageSize - 1;
@ -114,8 +150,8 @@ function searchProjectsQuery(client: SupabaseClient, {searchTerm, tagsFilter, pr
),
business_location:location
)
`
).order("publishedTime", { ascending: false }).range(start, end)
`,
).order("publishedTime", { ascending: false }).range(start, end);
if (sortByTimeFilter === "all") {
sortByTimeFilter = undefined;
@ -134,24 +170,27 @@ function searchProjectsQuery(client: SupabaseClient, {searchTerm, tagsFilter, pr
}
if (searchTerm) {
query = query.ilike('projectName', `%${searchTerm}%`)
query = query.ilike("projectName", `%${searchTerm}%`);
}
if (tagsFilter) {
query = query.in('ItemTag.Tag.value', tagsFilter)
query = query.in("ItemTag.Tag.value", tagsFilter);
}
if (projectStatus) {
query = query.eq("ProjectStatus.value", projectStatus)
query = query.eq("ProjectStatus.value", projectStatus);
}
if (businessTypeFilter) {
query = query.eq("Business.businessType.value", businessTypeFilter)
query = query.eq("Business.businessType.value", businessTypeFilter);
}
return query;
}
export { getTopProjects, getProjectData, searchProjectsQuery };
export {
getProjectData,
getProjectDataQuery,
getTopProjects,
searchProjectsQuery,
};