diff --git a/api/controller/userController.ts b/api/controller/userController.ts index 9a1ae20..af1a115 100644 --- a/api/controller/userController.ts +++ b/api/controller/userController.ts @@ -12,7 +12,8 @@ import { insertUserBySuperToken } from "../gateway/userGateway"; export const updateUserTicketInfo = asyncHandler( async (req: Request, res: Response) => { - console.log(process.env.DOMAIN_DB); + // console.log(process.env.DOMAIN_DB); + console.log(req.body) try { const { name, email, phoneNumber, ticketId, answers } = req.body; diff --git a/api/gateway/userGateway.ts b/api/gateway/userGateway.ts index 962e709..7de2d4b 100644 --- a/api/gateway/userGateway.ts +++ b/api/gateway/userGateway.ts @@ -109,21 +109,22 @@ export async function insertUserTicket(data: { //figure out how to add People_ID link to userTickets //find people id by getting the email? but it will fail if the user isn't a member - let people = await db - .select() - .from(peoples) - .where(eq(peoples.email, data.email)) - .limit(1); - - const userTicketIdLink = await db - .insert(userTicketsTicketIdLinks) - .values({ - userTicketId: newUserTicket[0].userTicketId, - ticketId: data.ticketId, - }) - .returning(); - - console.log("insertUserTicket: userTicketIdLink: " + userTicketIdLink[0]); + // todo: I think this query fails if there is no one with that email in the db, and probs adding a catch would fix the issue + // let people = await db + // .select() + // .from(peoples) + // .where(eq(peoples.email, data.email)) + // .limit(1); + + // const userTicketIdLink = await db + // .insert(userTicketsTicketIdLinks) + // .values({ + // userTicketId: newUserTicket[0].userTicketId, + // ticketId: data.ticketId, + // }) + // .returning(); + + // console.log("insertUserTicket: userTicketIdLink: " + userTicketIdLink[0]); const ticketId = newUserTicket[0].userTicketId; @@ -182,23 +183,24 @@ export async function insertUserTicket(data: { "insertUserTicket: userTicketsPeopleIdLink: ticketId: ", data.ticketId ); - let userTicketsPeopleIdLink = await db - .insert(userTicketsPeopleIdLinks) - .values({ - peopleId: people[0].id, - userTicketId: ticketId, - }) - .returning() - .catch((error) => { - console.log( - "insertUserTicket: userTicketsPeopleIdLink: error occurred: ", - error - ); - }); - - console.log( - "insertUserTicket: userTicketsPeopleIdLink: " + userTicketsPeopleIdLink![0]! - ); + + // let userTicketsPeopleIdLink = await db + // .insert(userTicketsPeopleIdLinks) + // .values({ + // peopleId: people[0].id, + // userTicketId: ticketId, + // }) + // .returning() + // .catch((error) => { + // console.log( + // "insertUserTicket: userTicketsPeopleIdLink: error occurred: ", + // error + // ); + // }); + + // console.log( + // "insertUserTicket: userTicketsPeopleIdLink: " + userTicketsPeopleIdLink![0]! + // ); //for question: link the answer.id to this question. More of an admin type task. //let question = await db.update(questions).set().where(eq(questions.id, data.answers[0].questionId)); @@ -222,57 +224,57 @@ export async function updateUserMembershipExpiryDate( expand: ["line_items"], }); - try { - //since this is for memberships, get the current user by their email id - let customer = await db - .select() - .from(peoples) - .where(eq(peoples.email, checkoutSession.customer_details!.email!)) - .limit(1); - - console.log("updateUserMembershipExpiryDate: customer: " + customer); - - //then, retrieve the price id from metadata from purchaseableMemberships - let expiryDate = await db - .select() - .from(purchasableMemberships) - .where( - eq( - purchasableMemberships.stripeLink, - checkoutSession.metadata!["priceId"] - ) - ) - .limit(1); - - console.log("updateUserMembershipExpiryDate: expiryDate: " + expiryDate); - - // then, apply the retrieved expiry date into the users' field - let updateExpiryDate = await db - .update(peoples) - .set({ memberExpiryDate: expiryDate[0].expiry, isMember: true }) - .where(eq(peoples.email, checkoutSession.customer_details!.email!)) - .returning({ memberExpiryDate: peoples.memberExpiryDate }); - - console.log( - "updateUserMembershipExpiryDate: updateExpiryDate: " + updateExpiryDate - ); - - //update user metadata - //getUserIdByEmail - let customerEmail = await getUserEmail( - checkoutSession.customer_details!.email! - ); - - let userId = await getUserIdByEmail(customerEmail); - - await updateUserMetadata(userId, { - bIsMembershipPaymentComplete: true, - }); - } catch (error) { - throw new Error( - "Unknown error occurred while trying to update user membership: " + error - ); - } + // try { + // //since this is for memberships, get the current user by their email id + // let customer = await db + // .select() + // .from(peoples) + // .where(eq(peoples.email, checkoutSession.customer_details!.email!)) + // .limit(1); + + // console.log("updateUserMembershipExpiryDate: customer: " + customer); + + // //then, retrieve the price id from metadata from purchaseableMemberships + // let expiryDate = await db + // .select() + // .from(purchasableMemberships) + // .where( + // eq( + // purchasableMemberships.stripeLink, + // checkoutSession.metadata!["priceId"] + // ) + // ) + // .limit(1); + + // console.log("updateUserMembershipExpiryDate: expiryDate: " + expiryDate); + + // // then, apply the retrieved expiry date into the users' field + // let updateExpiryDate = await db + // .update(peoples) + // .set({ memberExpiryDate: expiryDate[0].expiry, isMember: true }) + // .where(eq(peoples.email, checkoutSession.customer_details!.email!)) + // .returning({ memberExpiryDate: peoples.memberExpiryDate }); + + // console.log( + // "updateUserMembershipExpiryDate: updateExpiryDate: " + updateExpiryDate + // ); + + // //update user metadata + // //getUserIdByEmail + // let customerEmail = await getUserEmail( + // checkoutSession.customer_details!.email! + // ); + + // let userId = await getUserIdByEmail(customerEmail); + + // await updateUserMetadata(userId, { + // bIsMembershipPaymentComplete: true, + // }); + // } catch (error) { + // throw new Error( + // "Unknown error occurred while trying to update user membership: " + error + // ); + // } } export async function insertUserBySuperToken( diff --git a/web/src/api/apiRequests.ts b/web/src/api/apiRequests.ts index f952b10..81bf7fa 100644 --- a/web/src/api/apiRequests.ts +++ b/web/src/api/apiRequests.ts @@ -1,7 +1,12 @@ import axios, { AxiosResponse } from "axios"; import { + AnswerList, AttendanceList, MembershipExpiryDate as MembershipExpiryDate, + QuestionAnswer, + stripeSessionStatus, + SubmitUpdateUserInfoOrNewUser, + UpdateUserInfoOrNewUser, } from "../types/types"; const apiClient = axios.create({ @@ -10,13 +15,14 @@ const apiClient = axios.create({ }); // Get user metadata -export const getUserMetadaData = async (): Promise => { +export const getUserMetaData = async (): Promise => { const response = await apiClient.get("/api/user/get-metadata", { headers: { "Content-Type": "application/json", }, }); - + console.log("getUserMetatdat") + console.log(response) return response; }; @@ -28,19 +34,35 @@ export const updateUserInfo = async (data: object): Promise => { }, data: { data }, }); + + console.log("update user info") + console.log(response) return response; }; export const updateUserTicketInfo = async ( - data: object -): Promise => { + + ticketId: number, + name: string, + email: string, + phoneNumber: string, + answers: AnswerList[] + +): Promise => { + const data = { + ticketId, + name, + email, + phoneNumber, + answers + } const response = await apiClient.post("/api/user/user-ticket-info", data, { headers: { "Content-Type": "application/json", }, - }); - - return response; + }) + console.log("update user ticket info worked") + return response.data; }; // User membership expiry @@ -85,7 +107,7 @@ export const postAttendanceUpdate = async ( // Get session status export const getSessionStatus = async ( sessionId: string -): Promise => { +): Promise => { const response = await apiClient.get( `/api/stripe/session-status?session_id=${sessionId}`, { @@ -93,7 +115,10 @@ export const getSessionStatus = async ( } ); - return response; + console.log("get session id") + console.log(response) + + return response.data; }; //Use this one to automatically create an Event or Membership checkout. Event checkout will decrement a ticket. @@ -109,7 +134,7 @@ export const fetchEventOrMembershipCheckoutSecret = async (payload: { headers: { "Content-Type": "application/json" }, } ); - + console.log("FETCH EVENT OR MEBERSHcK CHECKOUT SECRETYE") return response.data.clientSecret; }; diff --git a/web/src/components/forms/CheckoutInformation.tsx b/web/src/components/forms/CheckoutInformation.tsx index fe13465..8df8156 100644 --- a/web/src/components/forms/CheckoutInformation.tsx +++ b/web/src/components/forms/CheckoutInformation.tsx @@ -1,4 +1,4 @@ -import { QuestionAnswer, TicketAndQuestion } from "../../types/types"; +import { AnswerList, QuestionAnswer, TicketAndQuestion } from "../../types/types"; import { useEffect, useState } from "react"; import { useQuery } from "@apollo/client"; import { getTicketQuestions } from "../../graphql/queries"; @@ -7,6 +7,7 @@ import LoadingSpinner from "@components/navigation/LoadingSpinner"; import { useNavigate } from "react-router"; import CheckoutInformationForm from "./CheckoutInformationForm"; import { updateUserTicketInfo } from "../../api/apiRequests"; +import { useUpdateUserTicketInfo } from "../../hooks/api/useUpdateUserTicketInfo"; interface CheckoutInformationProps { ticketId: number; @@ -56,6 +57,7 @@ export default function CheckoutInformation({ window.scrollTo(0, 0); }, []); + // States const [ticketAndQuestions, setTicketAndQuestions] = useState(); @@ -65,32 +67,29 @@ export default function CheckoutInformation({ const [submitError, setSubmitError] = useState(false); const [submitLoading, setSubmitLoading] = useState(false); - // Submit ticket information to backend - const onSubmit = async (data: any) => { - try { - const response = await updateUserTicketInfo(data); - if (response.status === 200) { - // Form Submission Successful - setSubmitLoading(false); - console.log( - "CheckoutInformation", - response.data.updateUserInfoOrNewUser.userTicketId - ); - // Move user to payment screen after the user ticket id is received - navigateToPaymentScreen( - response.data.updateUserInfoOrNewUser.userTicketId - ); - } else { - setSubmitLoading(false); - setSubmitError(true); - } - } catch (error) { - setSubmitLoading(false); + + const { data : updateUserTicketInfoData, mutateAsync, status } = useUpdateUserTicketInfo(); + // Update status text as it changes + useEffect(() => { + if (status === "success") { + navigateToPaymentScreen( + updateUserTicketInfoData.updateUserInfoOrNewUser.userTicketId + ) + } + + if (status == "pending") { + setSubmitLoading(true); + }else { + setSubmitLoading(false) + } + + + if (status == "error") { setSubmitError(true); } - }; + }, [status]); - const handleSubmit = ( + const onSubmit = async ( event: React.FormEvent, name: string, email: string, @@ -98,21 +97,32 @@ export default function CheckoutInformation({ answers: QuestionAnswer[] ) => { event.preventDefault(); - setSubmitLoading(true); + // setSubmitLoading(true); // remove unused information for post request const answerList = answers.map(({ question, indexId, ...rest }) => { return rest; }); - + + // Mutation hook + + mutateAsync({ + ticketId: ticketId, + name: name, + email: email, + phoneNumber: phoneNumber, + answers: answerList, + }) + // const temp = await mutateAsync(data) // call post request - onSubmit({ - ticketId: ticketId, - name: name, - email: email, - phoneNumber: phoneNumber, - answers: answerList, - }); + // onSubmit({ + // // ticketId: ticketId, + // name: name, + // email: email, + // phoneNumber: phoneNumber, + // answers: answerList, + // }); + // mutateAsync() }; // Loading @@ -129,7 +139,7 @@ export default function CheckoutInformation({ return ticketAndQuestions ? (
diff --git a/web/src/hooks/api/useEventOrMembershipCheckoutSecret.ts b/web/src/hooks/api/useEventOrMembershipCheckoutSecret.ts new file mode 100644 index 0000000..e69de29 diff --git a/web/src/hooks/api/useSessionStatus.ts b/web/src/hooks/api/useSessionStatus.ts new file mode 100644 index 0000000..ad42e56 --- /dev/null +++ b/web/src/hooks/api/useSessionStatus.ts @@ -0,0 +1,10 @@ +import { useQuery } from "@tanstack/react-query"; +import { getSessionStatus } from "../../api/apiRequests"; +import { stripeSessionStatus } from "../../types/types"; + +export const useSessionStatus = (sessionId : string) => { + return useQuery({ + queryKey: ["attendanceList"], + queryFn: () => getSessionStatus(sessionId), + }); +}; diff --git a/web/src/hooks/api/useUpdateUserInfo.ts b/web/src/hooks/api/useUpdateUserInfo.ts new file mode 100644 index 0000000..e69de29 diff --git a/web/src/hooks/api/useUpdateUserTicketInfo.ts b/web/src/hooks/api/useUpdateUserTicketInfo.ts new file mode 100644 index 0000000..5743a27 --- /dev/null +++ b/web/src/hooks/api/useUpdateUserTicketInfo.ts @@ -0,0 +1,36 @@ +import { useMutation } from "@tanstack/react-query"; +import { updateUserTicketInfo } from "../../api/apiRequests"; +import { + AnswerList, + QuestionAnswer, + SubmitUpdateUserInfoOrNewUser, + UpdateUserInfoOrNewUser, +} from "../../types/types"; + +export const useUpdateUserTicketInfo = () => { + return useMutation< + UpdateUserInfoOrNewUser, + Error, + { + ticketId: number; + name: string; + email: string; + phoneNumber: string; + answers: AnswerList[]; + } + >({ + mutationFn: ({ + ticketId, + name, + email, + phoneNumber, + answers + }) => updateUserTicketInfo( + ticketId, + name, + email, + phoneNumber, + answers + ), + }); +}; diff --git a/web/src/hooks/api/useUserMetaData.ts b/web/src/hooks/api/useUserMetaData.ts new file mode 100644 index 0000000..ade49ef --- /dev/null +++ b/web/src/hooks/api/useUserMetaData.ts @@ -0,0 +1,10 @@ +// import { useQuery } from "@tanstack/react-query"; +// import { getUserMetaData } from "../../api/apiRequests"; +// import { AttendanceList } from "../../types/types"; + +// export const useUserMetaData = () => { +// return useQuery({ +// queryKey: ["userMetatdata"], +// queryFn: () => getUserMetaData(), +// }); +// }; diff --git a/web/src/main.tsx b/web/src/main.tsx index 4c2fa0a..2e5d3ab 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -38,7 +38,7 @@ import CheckoutInformationScreen from "./screens/CheckoutInformationScreen.tsx"; import AttendanceScreen from "./screens/AttendanceScreen.tsx"; import EventAttendanceSelectScreen from "./screens/EventAttendanceSelectScreen.tsx"; import { ExecRoute } from "@utils/AdminRouteProtection.tsx"; -import { getUserMetadaData } from "./api/apiRequests.ts"; +import { getUserMetaData } from "./api/apiRequests.ts"; console.log(`Frontend env vars : VITE_API_URL=${import.meta.env.VITE_API_URL} @@ -71,7 +71,7 @@ SuperTokens.init({ let redirectionURL = "/"; try { - const userMetadata = await getUserMetadaData(); + const userMetadata = await getUserMetaData(); if (userMetadata.status === 200) { if (userMetadata.data!.bIsUserInfoComplete === false) { diff --git a/web/src/screens/AboutUsScreen.tsx b/web/src/screens/AboutUsScreen.tsx index f3ecc8c..0a24eb3 100644 --- a/web/src/screens/AboutUsScreen.tsx +++ b/web/src/screens/AboutUsScreen.tsx @@ -159,7 +159,7 @@ export default function AboutUsScreen({ navbar }: { navbar: JSX.Element }) {

Our Values

{errorValues ? ( -
There are no values to display
+
There are no values to display
) : (
{values.map((value) => ( diff --git a/web/src/screens/AttendanceScreen.tsx b/web/src/screens/AttendanceScreen.tsx index fce1711..605d94d 100644 --- a/web/src/screens/AttendanceScreen.tsx +++ b/web/src/screens/AttendanceScreen.tsx @@ -6,6 +6,7 @@ import LoadingSpinner from "@components/navigation/LoadingSpinner"; import { useUpdateAttendance } from "../hooks/api/useAttendanceUpdateMutation"; import { IDetectedBarcode, + IScannerStyles, Scanner, useDevices, } from "@yudiel/react-qr-scanner"; @@ -137,11 +138,7 @@ export default function AttendanceScreen({ navbar }: { navbar: JSX.Element }) { if (loadingAttendanceList) { return ; } - - const abc: MediaTrackConstraints = { - deviceId: cameraId, - }; - + return (
{navbar} @@ -162,8 +159,9 @@ export default function AttendanceScreen({ navbar }: { navbar: JSX.Element }) { onScan={(result) => onQRcodeScanned(result)} allowMultiple={true} scanDelay={1000} - constraints={abc} + constraints={{deviceId: cameraId}} onError={() => setCameraError(true)} + styles={{}} /> )}
diff --git a/web/src/types/types.ts b/web/src/types/types.ts index bd025da..705dec8 100644 --- a/web/src/types/types.ts +++ b/web/src/types/types.ts @@ -134,3 +134,27 @@ export interface AttendanceList { export interface AttendanceReturn { name: string; } + +export interface stripeSessionStatus { + customer_email: string; + status: string; +} +// data { updateUserInfoOrNewUser { userTicketId}} +export interface UpdateUserInfoOrNewUser { + updateUserInfoOrNewUser: { + userTicketId: number; + }; +} + +export interface SubmitUpdateUserInfoOrNewUser { + ticketId: number; + name: string; + email: string; + phoneNumber: string; + answers: QuestionAnswer[]; +} + +export interface AnswerList { + questionId: number; + answer: string; +} \ No newline at end of file