feat: build generic voting api, build useVote hook

This commit is contained in:
MTG2000
2022-05-21 13:36:34 +03:00
parent 5ff83ddc62
commit cdbd10da4e
12 changed files with 243 additions and 220 deletions

View File

@@ -3,11 +3,10 @@ import React, { FormEvent, useState } from 'react';
import { AiFillThunderbolt } from 'react-icons/ai'
import { IoClose } from 'react-icons/io5'
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer';
import { useAppSelector } from 'src/utils/hooks';
import { PaymentStatus, useVote } from 'src/utils/hooks';
import Confetti from "react-confetti";
import { Wallet_Service } from 'src/services';
import { useWindowSize } from '@react-hookz/web';
import { useConfirmVoteMutation, useVoteMutation } from 'src/graphql';
import { Vote_Item_Type } from 'src/graphql';
const defaultOptions = [
{ text: '100 sat', value: 100 },
@@ -16,17 +15,6 @@ const defaultOptions = [
]
enum PaymentStatus {
DEFAULT,
FETCHING_PAYMENT_DETAILS,
PAID,
AWAITING_PAYMENT,
PAYMENT_CONFIRMED,
NOT_PAID,
CANCELED
}
interface Props extends ModalCard {
projectId: number;
initVotes?: number;
@@ -35,57 +23,24 @@ interface Props extends ModalCard {
export default function VoteCard({ onClose, direction, projectId, initVotes, ...props }: Props) {
const { width, height } = useWindowSize()
const { isWalletConnected } = useAppSelector(state => ({
isWalletConnected: state.wallet.isConnected,
initVotes: state.vote.voteAmount,
projectId: state.project.openId
}));
const [selectedOption, setSelectedOption] = useState(10);
const [voteAmount, setVoteAmount] = useState<number>(initVotes ?? 10);
const [paymentStatus, setPaymentStatus] = useState<PaymentStatus>(PaymentStatus.DEFAULT);
const [vote, { data }] = useVoteMutation({
onCompleted: async (votingData) => {
try {
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
const webln = await Wallet_Service.getWebln()
const paymentResponse = await webln.sendPayment(votingData.vote.payment_request);
setPaymentStatus(PaymentStatus.PAID);
confirmVote({
variables: {
paymentRequest: votingData.vote.payment_request,
preimage: paymentResponse.preimage
}
})
} catch (error) {
console.log(error);
setPaymentStatus(PaymentStatus.NOT_PAID);
}
const { vote, paymentStatus } = useVote({
onSuccess: () => {
setTimeout(() => {
onClose?.();
}, 4000);
},
onError: (error) => {
console.log(error);
alert("Something wrong happened...")
setPaymentStatus(PaymentStatus.NOT_PAID);
onError: () => {
setTimeout(() => {
onClose?.();
}, 4000);
}
});
})
const [confirmVote, { data: confirmedVoteData }] = useConfirmVoteMutation({
onCompleted: (votingData) => {
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
setTimeout(() => {
onClose?.();
}, 4000);
},
onError: () => { }
});
const onChangeInput = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectedOption(-1);
@@ -99,8 +54,7 @@ export default function VoteCard({ onClose, direction, projectId, initVotes, ...
const requestPayment = (e: FormEvent) => {
e.preventDefault();
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS);
vote({ variables: { "amountInSat": voteAmount, "projectId": projectId! } });
vote({ variables: { "amountInSat": voteAmount, "itemId": projectId!, itemType: Vote_Item_Type.Project } });
}
return (

View File

@@ -75,7 +75,6 @@ export type Mutation = {
__typename?: 'Mutation';
confirmVote: Vote;
vote: Vote;
vote2: Vote2;
};
@@ -86,12 +85,6 @@ export type MutationConfirmVoteArgs = {
export type MutationVoteArgs = {
amount_in_sat: Scalars['Int'];
project_id: Scalars['Int'];
};
export type MutationVote2Args = {
amount_in_sat: Scalars['Int'];
item_id: Scalars['Int'];
item_type: Vote_Item_Type;
@@ -274,7 +267,7 @@ export type User = {
export enum Vote_Item_Type {
Bounty = 'Bounty',
Comment = 'Comment',
PostComment = 'PostComment',
Project = 'Project',
Question = 'Question',
Story = 'Story',
@@ -285,16 +278,6 @@ export type Vote = {
__typename?: 'Vote';
amount_in_sat: Scalars['Int'];
id: Scalars['Int'];
paid: Scalars['Boolean'];
payment_hash: Scalars['String'];
payment_request: Scalars['String'];
project: Project;
};
export type Vote2 = {
__typename?: 'Vote2';
amount_in_sat: Scalars['Int'];
id: Scalars['Int'];
item_id: Scalars['Int'];
item_type: Vote_Item_Type;
paid: Scalars['Boolean'];
@@ -372,12 +355,13 @@ export type ProjectDetailsQueryVariables = Exact<{
export type ProjectDetailsQuery = { __typename?: 'Query', getProject: { __typename?: 'Project', id: number, title: string, description: string, cover_image: string, thumbnail_image: string, screenshots: Array<string>, website: string, lightning_address: string | null, lnurl_callback_url: string | null, votes_count: number, category: { __typename?: 'Category', id: number, title: string }, awards: Array<{ __typename?: 'Award', title: string, image: string, url: string, id: number }>, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
export type VoteMutationVariables = Exact<{
projectId: Scalars['Int'];
itemType: Vote_Item_Type;
itemId: Scalars['Int'];
amountInSat: Scalars['Int'];
}>;
export type VoteMutation = { __typename?: 'Mutation', vote: { __typename?: 'Vote', id: number, amount_in_sat: number, payment_request: string, payment_hash: string, paid: boolean } };
export type VoteMutation = { __typename?: 'Mutation', vote: { __typename?: 'Vote', id: number, amount_in_sat: number, payment_request: string, payment_hash: string, paid: boolean, item_type: Vote_Item_Type, item_id: number } };
export type ConfirmVoteMutationVariables = Exact<{
paymentRequest: Scalars['String'];
@@ -385,7 +369,7 @@ export type ConfirmVoteMutationVariables = Exact<{
}>;
export type ConfirmVoteMutation = { __typename?: 'Mutation', confirmVote: { __typename?: 'Vote', id: number, amount_in_sat: number, payment_request: string, payment_hash: string, paid: boolean, project: { __typename?: 'Project', id: number, votes_count: number } } };
export type ConfirmVoteMutation = { __typename?: 'Mutation', confirmVote: { __typename?: 'Vote', id: number, amount_in_sat: number, payment_request: string, payment_hash: string, paid: boolean, item_type: Vote_Item_Type, item_id: number } };
export const NavCategoriesDocument = gql`
@@ -1029,13 +1013,15 @@ export type ProjectDetailsQueryHookResult = ReturnType<typeof useProjectDetailsQ
export type ProjectDetailsLazyQueryHookResult = ReturnType<typeof useProjectDetailsLazyQuery>;
export type ProjectDetailsQueryResult = Apollo.QueryResult<ProjectDetailsQuery, ProjectDetailsQueryVariables>;
export const VoteDocument = gql`
mutation Vote($projectId: Int!, $amountInSat: Int!) {
vote(project_id: $projectId, amount_in_sat: $amountInSat) {
mutation Vote($itemType: VOTE_ITEM_TYPE!, $itemId: Int!, $amountInSat: Int!) {
vote(item_type: $itemType, item_id: $itemId, amount_in_sat: $amountInSat) {
id
amount_in_sat
payment_request
payment_hash
paid
item_type
item_id
}
}
`;
@@ -1054,7 +1040,8 @@ export type VoteMutationFn = Apollo.MutationFunction<VoteMutation, VoteMutationV
* @example
* const [voteMutation, { data, loading, error }] = useVoteMutation({
* variables: {
* projectId: // value for 'projectId'
* itemType: // value for 'itemType'
* itemId: // value for 'itemId'
* amountInSat: // value for 'amountInSat'
* },
* });
@@ -1074,10 +1061,8 @@ export const ConfirmVoteDocument = gql`
payment_request
payment_hash
paid
project {
id
votes_count
}
item_type
item_id
}
}
`;

View File

@@ -5,3 +5,4 @@ export * from "./useInfiniteQuery";
export * from "./useReachedBottom";
export * from "./useAutoResizableTextArea";
export * from "./useCopyToClipboard";
export * from "./useVote";

View File

@@ -0,0 +1 @@
export * from './useVote'

View File

@@ -0,0 +1,96 @@
import { gql } from '@apollo/client';
import { useState } from 'react';
import { useConfirmVoteMutation, useVoteMutation } from 'src/graphql';
import { Wallet_Service } from 'src/services';
export enum PaymentStatus {
DEFAULT,
FETCHING_PAYMENT_DETAILS,
PAID,
AWAITING_PAYMENT,
PAYMENT_CONFIRMED,
NOT_PAID,
CANCELED
}
export const useVote = ({ onSuccess, onError }: {
onSuccess?: () => void
onError?: (error: any) => void
}) => {
const [paymentStatus, setPaymentStatus] = useState<PaymentStatus>(PaymentStatus.DEFAULT);
const [voteMutaion] = useVoteMutation({
onCompleted: async (votingData) => {
try {
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
const webln = await Wallet_Service.getWebln()
const paymentResponse = await webln.sendPayment(votingData.vote.payment_request);
setPaymentStatus(PaymentStatus.PAID);
confirmVote({
variables: {
paymentRequest: votingData.vote.payment_request,
preimage: paymentResponse.preimage
}
})
} catch (error) {
console.log(error);
setPaymentStatus(PaymentStatus.NOT_PAID);
}
},
onError: (error) => {
console.log(error);
alert("Something wrong happened...")
setPaymentStatus(PaymentStatus.NOT_PAID);
onError?.(error)
}
});
const [confirmVote] = useConfirmVoteMutation({
onCompleted: () => {
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
onSuccess?.();
},
update(cache, { data }) {
try {
const { item_id, item_type, amount_in_sat } = data!.confirmVote;
const { votes_count } = cache.readFragment({
id: `${item_type}:${item_id}`,
fragment: gql`
fragment My${item_type} on ${item_type} {
votes_count
}`
}) ?? {};
cache.writeFragment({
id: `${item_type}:${item_id}`,
fragment: gql`
fragment My${item_type} on ${item_type} {
votes_count
}
`,
data: {
votes_count: votes_count + amount_in_sat
},
})
} catch (error) {
}
},
onError: () => { }
});
const vote = (...params: Parameters<typeof voteMutaion>) => {
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS)
voteMutaion(...params)
}
return {
paymentStatus,
vote
}
}

View File

@@ -1,10 +1,12 @@
mutation Vote($projectId: Int!, $amountInSat: Int!) {
vote(project_id: $projectId, amount_in_sat: $amountInSat) {
mutation Vote($itemType: VOTE_ITEM_TYPE!, $itemId: Int!, $amountInSat: Int!) {
vote(item_type: $itemType, item_id: $itemId, amount_in_sat: $amountInSat) {
id
amount_in_sat
payment_request
payment_hash
paid
item_type
item_id
}
}
@@ -15,9 +17,7 @@ mutation ConfirmVote($paymentRequest: String!, $preimage: String!) {
payment_request
payment_hash
paid
project {
id
votes_count
}
item_type
item_id
}
}