From 773eb5027356cd25431dcdc0dda775c7fe528ed8 Mon Sep 17 00:00:00 2001 From: Jose Lezama Date: Fri, 1 Nov 2024 13:45:09 -0300 Subject: [PATCH] feat(): accept transfered ticket from My Events notification --- app/api/gql/gql.ts | 8 ++ app/api/gql/graphql.ts | 119 ++++++++++++++++ app/api/gql/schema.gql | 10 ++ app/components/MyEvents/MyTicketsList.tsx | 101 ++++++++++++-- .../graphql/myReceivedTransfers.generated.tsx | 130 ++++++++++++++++++ .../MyEvents/graphql/myReceivedTransfers.gql | 23 ++++ 6 files changed, 381 insertions(+), 10 deletions(-) create mode 100644 app/components/MyEvents/graphql/myReceivedTransfers.generated.tsx create mode 100644 app/components/MyEvents/graphql/myReceivedTransfers.gql diff --git a/app/api/gql/gql.ts b/app/api/gql/gql.ts index 544aeb8..dd7f025 100644 --- a/app/api/gql/gql.ts +++ b/app/api/gql/gql.ts @@ -21,6 +21,8 @@ const documents = { types.TransferTicketDocument, "query myEvents($input: PaginatedInputEventsSearchInput!, $userTicketSearchInput: EventsTicketsSearchInput) {\n searchEvents(input: $input) {\n data {\n id\n name\n description\n startDateTime\n address\n previewImage {\n url\n }\n community {\n id\n name\n }\n status\n usersTickets(input: $userTicketSearchInput) {\n id\n approvalStatus\n paymentStatus\n redemptionStatus\n ticketTemplate {\n description\n id\n }\n }\n }\n pagination {\n currentPage\n pageSize\n totalPages\n totalRecords\n }\n }\n}": types.MyEventsDocument, + "query myReceivedTransfers {\n myTicketTransfers(type: RECEIVED) {\n createdAt\n expirationDate\n id\n sender {\n email\n name\n }\n status\n transferMessage\n userTicket {\n id\n ticketTemplate {\n name\n event {\n id\n name\n }\n }\n }\n }\n}": + types.MyReceivedTransfersDocument, "query MyPurchaseOrders($input: PaginatedInputMyPurchaseOrdersInput!) {\n myPurchaseOrders(input: $input) {\n data {\n id\n finalPrice\n paymentPlatform\n createdAt\n currency {\n id\n currency\n }\n tickets {\n id\n ticketTemplate {\n id\n name\n event {\n id\n name\n }\n }\n }\n }\n }\n}": types.MyPurchaseOrdersDocument, "mutation AcceptTransferredTicket($transferId: String!) {\n acceptTransferredTicket(transferId: $transferId) {\n id\n status\n userTicket {\n id\n user {\n id\n }\n }\n }\n}": @@ -81,6 +83,12 @@ export function graphql( export function graphql( source: "query myEvents($input: PaginatedInputEventsSearchInput!, $userTicketSearchInput: EventsTicketsSearchInput) {\n searchEvents(input: $input) {\n data {\n id\n name\n description\n startDateTime\n address\n previewImage {\n url\n }\n community {\n id\n name\n }\n status\n usersTickets(input: $userTicketSearchInput) {\n id\n approvalStatus\n paymentStatus\n redemptionStatus\n ticketTemplate {\n description\n id\n }\n }\n }\n pagination {\n currentPage\n pageSize\n totalPages\n totalRecords\n }\n }\n}", ): (typeof documents)["query myEvents($input: PaginatedInputEventsSearchInput!, $userTicketSearchInput: EventsTicketsSearchInput) {\n searchEvents(input: $input) {\n data {\n id\n name\n description\n startDateTime\n address\n previewImage {\n url\n }\n community {\n id\n name\n }\n status\n usersTickets(input: $userTicketSearchInput) {\n id\n approvalStatus\n paymentStatus\n redemptionStatus\n ticketTemplate {\n description\n id\n }\n }\n }\n pagination {\n currentPage\n pageSize\n totalPages\n totalRecords\n }\n }\n}"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: "query myReceivedTransfers {\n myTicketTransfers(type: RECEIVED) {\n createdAt\n expirationDate\n id\n sender {\n email\n name\n }\n status\n transferMessage\n userTicket {\n id\n ticketTemplate {\n name\n event {\n id\n name\n }\n }\n }\n }\n}", +): (typeof documents)["query myReceivedTransfers {\n myTicketTransfers(type: RECEIVED) {\n createdAt\n expirationDate\n id\n sender {\n email\n name\n }\n status\n transferMessage\n userTicket {\n id\n ticketTemplate {\n name\n event {\n id\n name\n }\n }\n }\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/app/api/gql/graphql.ts b/app/api/gql/graphql.ts index 2294b50..2382061 100644 --- a/app/api/gql/graphql.ts +++ b/app/api/gql/graphql.ts @@ -406,6 +406,8 @@ export type Mutation = { approvalUserTicket: UserTicket; /** Cancel a ticket */ cancelUserTicket: UserTicket; + /** Cancel multiple user ticket addons */ + cancelUserTicketAddons: Array; /** Check the status of a purchase order */ checkPurchaseOrderStatus: PurchaseOrder; /** Attempt to claim and/or transfer tickets */ @@ -490,6 +492,10 @@ export type MutationCancelUserTicketArgs = { userTicketId: Scalars["String"]["input"]; }; +export type MutationCancelUserTicketAddonsArgs = { + userTicketAddonIds: Array; +}; + export type MutationCheckPurchaseOrderStatusArgs = { input: CheckForPurchaseOrderInput; }; @@ -1674,6 +1680,23 @@ export type MyEventsQuery = { }; }; +export type MyReceivedTransfersQueryVariables = Exact<{ [key: string]: never }>; + +export type MyReceivedTransfersQuery = { + myTicketTransfers: Array<{ + createdAt: string; + expirationDate: string; + id: string; + status: TicketTransferAttemptStatus; + transferMessage?: string | null; + sender: { email: string; name?: string | null }; + userTicket: { + id: string; + ticketTemplate: { name: string; event: { id: string; name: string } }; + }; + }>; +}; + export type MyPurchaseOrdersQueryVariables = Exact<{ input: PaginatedInputMyPurchaseOrdersInput; }>; @@ -2625,6 +2648,102 @@ export const MyEventsDocument = { }, ], } as unknown as DocumentNode; +export const MyReceivedTransfersDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "query", + name: { kind: "Name", value: "myReceivedTransfers" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "myTicketTransfers" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "type" }, + value: { kind: "EnumValue", value: "RECEIVED" }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "createdAt" } }, + { + kind: "Field", + name: { kind: "Name", value: "expirationDate" }, + }, + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "sender" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "email" } }, + { kind: "Field", name: { kind: "Name", value: "name" } }, + ], + }, + }, + { kind: "Field", name: { kind: "Name", value: "status" } }, + { + kind: "Field", + name: { kind: "Name", value: "transferMessage" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "userTicket" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "ticketTemplate" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "name" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "event" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "id" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "name" }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables +>; export const MyPurchaseOrdersDocument = { kind: "Document", definitions: [ diff --git a/app/api/gql/schema.gql b/app/api/gql/schema.gql index b7e3d46..be48844 100644 --- a/app/api/gql/schema.gql +++ b/app/api/gql/schema.gql @@ -430,6 +430,16 @@ type Mutation { """ cancelUserTicket(userTicketId: String!): UserTicket! + """ + Cancel multiple user ticket addons + """ + cancelUserTicketAddons( + """ + The IDs of the user ticket addons to cancel + """ + userTicketAddonIds: [String!]! + ): [UserTicketAddon!]! + """ Check the status of a purchase order """ diff --git a/app/components/MyEvents/MyTicketsList.tsx b/app/components/MyEvents/MyTicketsList.tsx index e14a677..a2d4896 100644 --- a/app/components/MyEvents/MyTicketsList.tsx +++ b/app/components/MyEvents/MyTicketsList.tsx @@ -1,16 +1,24 @@ import { Link } from "@remix-run/react"; -import { Calendar, MapPin } from "lucide-react"; -import { useMemo } from "react"; +import { Bell, Calendar, MapPin } from "lucide-react"; +import { useMemo, useState } from "react"; +import { toast } from "sonner"; +import { TicketTransferAttemptStatus } from "~/api/gql/graphql"; import { MyEventsQuery, useMyEventsSuspenseQuery, } from "~/components/MyEvents/graphql/myEvents.generated"; +import { useAcceptTransferredTicketMutation } from "~/components/MyTransfers/graphql/acceptTransferedTicket.generated"; +import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert"; import { Badge } from "~/components/ui/badge"; +import { Button, buttonVariants } from "~/components/ui/button"; import { Card, CardDescription, CardTitle } from "~/components/ui/card"; import { formatDate, formatTime } from "~/utils/date"; import { pluralize } from "~/utils/string"; import { urls } from "~/utils/urls"; +import { cn } from "~/utils/utils"; + +import { useMyReceivedTransfersSuspenseQuery } from "./graphql/myReceivedTransfers.generated"; const EventCard = ({ event, @@ -78,7 +86,7 @@ export const MyTicketsList = ({ startDateTimeTo?: string | null; order?: string; }) => { - const { data } = useMyEventsSuspenseQuery({ + const { data, refetch: refetchMyEvents } = useMyEventsSuspenseQuery({ variables: { input: { search: { @@ -97,6 +105,10 @@ export const MyTicketsList = ({ }, }, }); + const { data: receivedTransfersData, refetch: refetchReceivedTransfers } = + useMyReceivedTransfersSuspenseQuery(); + const [acceptTicket] = useAcceptTransferredTicketMutation(); + const [isDisabled, setIsDisabled] = useState(false); const { groupedByDate, orderedDates } = useMemo(() => { const groupedByDate = data.searchEvents.data.reduce( @@ -140,13 +152,82 @@ export const MyTicketsList = ({ groupedByDate[date].map((event) => event), ); + const myTicketTransfers = + receivedTransfersData?.myTicketTransfers.filter( + (ticketTransfer) => + ticketTransfer.status === TicketTransferAttemptStatus.Pending, + ) ?? []; + const ticketTransfer = myTicketTransfers?.[0]; + + const handleAcceptTransfer = async () => { + setIsDisabled(true); + + await acceptTicket({ + variables: { + transferId: ticketTransfer.id, + }, + onCompleted(data) { + if (data.acceptTransferredTicket.id) { + setIsDisabled(false); + toast.success( + `La transferenciaha se ha confirmado exitosamente. Hemos notificado al ${ticketTransfer.sender.email}.`, + ); + void refetchReceivedTransfers(); + void refetchMyEvents(); + } else { + setIsDisabled(false); + toast.error( + "Ocurrió un error al intentar confirmar la transferencia. Por favor intenta de nuevo.", + ); + } + }, + onError() { + setIsDisabled(false); + toast.error( + "Ocurrió un error al intentar confirmar la transferencia. Por favor intenta de nuevo.", + ); + }, + }); + }; + return ( -
- {sorted.map((event, index) => ( -
- -
- ))} -
+ <> + {ticketTransfer ? ( + + + Te han envíado un Ticket + +
+ Te han envíado un ticket:{" "} + {ticketTransfer.userTicket.ticketTemplate.name} para el evento:{" "} + {ticketTransfer.userTicket.ticketTemplate.event.name}. +
+
+ + Ver mis Transferencia + + +
+
+
+ ) : null} +
+ {sorted.map((event, index) => ( +
+ +
+ ))} +
+ ); }; diff --git a/app/components/MyEvents/graphql/myReceivedTransfers.generated.tsx b/app/components/MyEvents/graphql/myReceivedTransfers.generated.tsx new file mode 100644 index 0000000..b5cbba6 --- /dev/null +++ b/app/components/MyEvents/graphql/myReceivedTransfers.generated.tsx @@ -0,0 +1,130 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck +/* eslint-disable */ +/* prettier-ignore */ +/* This file is automatically generated. Please do not modify it manually. */ +import * as Types from '../../../api/gql/graphql'; + +import { gql } from "graphql-tag"; +import * as Apollo from "@apollo/client"; +const defaultOptions = {} as const; +export type MyReceivedTransfersQueryVariables = Types.Exact<{ + [key: string]: never; +}>; + +export type MyReceivedTransfersQuery = { + __typename?: "Query"; + myTicketTransfers: Array<{ + __typename?: "UserTicketTransfer"; + createdAt: any; + expirationDate: any; + id: string; + status: Types.TicketTransferAttemptStatus; + transferMessage?: string | null; + sender: { + __typename?: "TicketTransferUserInfo"; + email: string; + name?: string | null; + }; + userTicket: { + __typename?: "UserTicket"; + id: string; + ticketTemplate: { + __typename?: "Ticket"; + name: string; + event: { __typename?: "Event"; id: string; name: string }; + }; + }; + }>; +}; + +export const MyReceivedTransfersDocument = gql` + query myReceivedTransfers { + myTicketTransfers(type: RECEIVED) { + createdAt + expirationDate + id + sender { + email + name + } + status + transferMessage + userTicket { + id + ticketTemplate { + name + event { + id + name + } + } + } + } + } +`; + +/** + * __useMyReceivedTransfersQuery__ + * + * To run a query within a React component, call `useMyReceivedTransfersQuery` and pass it any options that fit your needs. + * When your component renders, `useMyReceivedTransfersQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useMyReceivedTransfersQuery({ + * variables: { + * }, + * }); + */ +export function useMyReceivedTransfersQuery( + baseOptions?: Apollo.QueryHookOptions< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >(MyReceivedTransfersDocument, options); +} +export function useMyReceivedTransfersLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >(MyReceivedTransfersDocument, options); +} +export function useMyReceivedTransfersSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useSuspenseQuery< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables + >(MyReceivedTransfersDocument, options); +} +export type MyReceivedTransfersQueryHookResult = ReturnType< + typeof useMyReceivedTransfersQuery +>; +export type MyReceivedTransfersLazyQueryHookResult = ReturnType< + typeof useMyReceivedTransfersLazyQuery +>; +export type MyReceivedTransfersSuspenseQueryHookResult = ReturnType< + typeof useMyReceivedTransfersSuspenseQuery +>; +export type MyReceivedTransfersQueryResult = Apollo.QueryResult< + MyReceivedTransfersQuery, + MyReceivedTransfersQueryVariables +>; diff --git a/app/components/MyEvents/graphql/myReceivedTransfers.gql b/app/components/MyEvents/graphql/myReceivedTransfers.gql new file mode 100644 index 0000000..e2ec525 --- /dev/null +++ b/app/components/MyEvents/graphql/myReceivedTransfers.gql @@ -0,0 +1,23 @@ +query myReceivedTransfers { + myTicketTransfers(type: RECEIVED) { + createdAt + expirationDate + id + sender { + email + name + } + status + transferMessage + userTicket { + id + ticketTemplate { + name + event { + id + name + } + } + } + } +}