feat: add update/delete wallet keys api & widgets

This commit is contained in:
MTG2000
2022-08-09 13:05:21 +03:00
parent 30dc59dded
commit 4dfa4800da
9 changed files with 479 additions and 57 deletions

View File

@@ -49,6 +49,10 @@ export interface NexusGenInputs {
twitter?: string | null; // String
website?: string | null; // String
}
UserKeyInputType: { // input type
key: string; // String!
name: string; // String!
}
}
export interface NexusGenEnums {
@@ -204,6 +208,10 @@ export interface NexusGenObjects {
twitter?: string | null; // String
website?: string | null; // String
}
UserKey: { // root type
key: string; // String!
name: string; // String!
}
Vote: { // root type
amount_in_sat: number; // Int!
id: number; // Int!
@@ -314,6 +322,7 @@ export interface NexusGenFieldTypes {
deleteStory: NexusGenRootTypes['Story'] | null; // Story
donate: NexusGenRootTypes['Donation']; // Donation!
updateProfile: NexusGenRootTypes['User'] | null; // User
updateUserWalletKeys: NexusGenRootTypes['UserKey'][]; // [UserKey!]!
vote: NexusGenRootTypes['Vote']; // Vote!
}
PostComment: { // field return type
@@ -353,6 +362,7 @@ export interface NexusGenFieldTypes {
getTrendingPosts: NexusGenRootTypes['Post'][]; // [Post!]!
hottestProjects: NexusGenRootTypes['Project'][]; // [Project!]!
me: NexusGenRootTypes['User'] | null; // User
myWalletsKeys: NexusGenRootTypes['UserKey'][]; // [UserKey!]!
newProjects: NexusGenRootTypes['Project'][]; // [Project!]!
officialTags: NexusGenRootTypes['Tag'][]; // [Tag!]!
popularTags: NexusGenRootTypes['Tag'][]; // [Tag!]!
@@ -415,6 +425,10 @@ export interface NexusGenFieldTypes {
twitter: string | null; // String
website: string | null; // String
}
UserKey: { // field return type
key: string; // String!
name: string; // String!
}
Vote: { // field return type
amount_in_sat: number; // Int!
id: number; // Int!
@@ -523,6 +537,7 @@ export interface NexusGenFieldTypeNames {
deleteStory: 'Story'
donate: 'Donation'
updateProfile: 'User'
updateUserWalletKeys: 'UserKey'
vote: 'Vote'
}
PostComment: { // field return type name
@@ -562,6 +577,7 @@ export interface NexusGenFieldTypeNames {
getTrendingPosts: 'Post'
hottestProjects: 'Project'
me: 'User'
myWalletsKeys: 'UserKey'
newProjects: 'Project'
officialTags: 'Tag'
popularTags: 'Tag'
@@ -624,6 +640,10 @@ export interface NexusGenFieldTypeNames {
twitter: 'String'
website: 'String'
}
UserKey: { // field return type name
key: 'String'
name: 'String'
}
Vote: { // field return type name
amount_in_sat: 'Int'
id: 'Int'
@@ -667,6 +687,9 @@ export interface NexusGenArgTypes {
updateProfile: { // args
data?: NexusGenInputs['UpdateProfileInput'] | null; // UpdateProfileInput
}
updateUserWalletKeys: { // args
data?: NexusGenInputs['UserKeyInputType'][] | null; // [UserKeyInputType!]
}
vote: { // args
amount_in_sat: number; // Int!
item_id: number; // Int!

View File

@@ -100,6 +100,7 @@ type Mutation {
deleteStory(id: Int!): Story
donate(amount_in_sat: Int!): Donation!
updateProfile(data: UpdateProfileInput): User
updateUserWalletKeys(data: [UserKeyInputType!]): [UserKey!]!
vote(amount_in_sat: Int!, item_id: Int!, item_type: VOTE_ITEM_TYPE!): Vote!
}
@@ -161,6 +162,7 @@ type Query {
getTrendingPosts: [Post!]!
hottestProjects(skip: Int = 0, take: Int = 50): [Project!]!
me: User
myWalletsKeys: [UserKey!]!
newProjects(skip: Int = 0, take: Int = 50): [Project!]!
officialTags: [Tag!]!
popularTags: [Tag!]!
@@ -251,6 +253,16 @@ type User {
website: String
}
type UserKey {
key: String!
name: String!
}
input UserKeyInputType {
key: String!
name: String!
}
enum VOTE_ITEM_TYPE {
Bounty
PostComment

View File

@@ -1,6 +1,6 @@
const { prisma } = require('../../../prisma');
const { objectType, extendType, intArg, nonNull, inputObjectType } = require("nexus");
const { objectType, extendType, intArg, nonNull, inputObjectType, list } = require("nexus");
const { getUserByPubKey } = require("../../../auth/utils/helperFuncs");
const { removeNulls } = require("./helpers");
@@ -117,14 +117,123 @@ const updateProfile = extendType({
})
const UserKey = objectType({
name: 'UserKey',
definition(t) {
t.nonNull.string('key');
t.nonNull.string('name');
}
})
const myWalletsKeys = extendType({
type: "Query",
definition(t) {
t.nonNull.list.nonNull.field('myWalletsKeys', {
type: "UserKey",
async resolve(_, __, ctx) {
const user = await getUserByPubKey(ctx.userPubKey);
if (!user)
throw new Error("You have to login");
return prisma.userKey.findMany({
where: {
user_id: user.id,
}
})
}
})
}
})
const UserKeyInputType = inputObjectType({
name: 'UserKeyInputType',
definition(t) {
t.nonNull.string('key');
t.nonNull.string('name');
}
})
const updateUserWalletKeys = extendType({
type: 'Mutation',
definition(t) {
t.nonNull.list.nonNull.field('updateUserWalletKeys', {
type: 'UserKey',
args: { data: list(nonNull(UserKeyInputType)) },
async resolve(_root, args, ctx) {
const user = await getUserByPubKey(ctx.userPubKey);
if (!user)
throw new Error("You have to login");
// Check if all the sent keys belong to the user
const userKeys = (await prisma.userKey.findMany({
where: {
AND: {
user_id: {
equals: user.id,
},
key: {
in: args.data.map(i => i.key)
}
},
},
select: {
key: true
}
})).map(i => i.key);
const newKeys = [];
for (let i = 0; i < args.data.length; i++) {
const item = args.data[i];
if (userKeys.includes(item.key))
newKeys.push(item);
}
if (newKeys.length === 0)
throw new Error("You can't delete all your keys")
await prisma.userKey.deleteMany({
where: {
user_id: user.id
}
})
await prisma.userKey.createMany({
data: newKeys.map(i => ({
user_id: user.id,
key: i.key,
name: i.name,
}))
})
return newKeys;
}
})
}
})
module.exports = {
// Types
User,
UpdateProfileInput,
UserKey,
// Queries
me,
profile,
myWalletsKeys,
// Mutations
updateProfile,
updateUserWalletKeys,
}

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "UserKey" ADD COLUMN "name" TEXT NOT NULL DEFAULT E'New Key Name';

View File

@@ -68,7 +68,8 @@ model User {
}
model UserKey {
key String @id
key String @id
name String @default("New Key Name")
user User? @relation(fields: [user_id], references: [id])
user_id Int?

View File

@@ -1,20 +1,119 @@
import Button from 'src/Components/Button/Button';
import { useAppDispatch } from 'src/utils/hooks';
import { openModal } from 'src/redux/features/modals.slice';
import { useMyWalletsKeysQuery, useUpdateUserWalletsKeysMutation } from 'src/graphql';
import Skeleton from 'react-loading-skeleton';
import { useReducer } from 'react';
interface Props {
}
type State = {
hasNewChanges: boolean,
keys: Array<{ key: string, name: string }>,
oldKeys: Array<{ key: string, name: string }>
}
type Action =
| {
type: 'set'
payload: State['keys']
}
| {
type: 'delete',
payload: { idx: number }
}
| {
type: 'update',
payload: {
idx: number,
value: string,
}
}
| {
type: 'cancel'
}
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'set':
return {
hasNewChanges: false,
keys: [...action.payload],
oldKeys: [...action.payload],
}
case 'delete':
if (state.keys.length === 1)
return state;
return {
hasNewChanges: true,
oldKeys: state.oldKeys,
keys: [...state.keys.slice(0, action.payload.idx), ...state.keys.slice(action.payload.idx + 1)]
};
case 'update':
return {
hasNewChanges: true,
oldKeys: state.oldKeys,
keys: state.keys.map((item, idx) => {
if (idx === action.payload.idx)
return {
...item,
name: action.payload.value
}
return item;
}),
}
case 'cancel':
return {
hasNewChanges: false,
keys: [...state.oldKeys],
oldKeys: state.oldKeys,
}
}
}
export default function AccountCard({ }: Props) {
const dispatch = useAppDispatch()
const dispatch = useAppDispatch();
const [keysState, keysDispatch] = useReducer(reducer, { keys: [], oldKeys: [], hasNewChanges: false, });
const myKeysQuery = useMyWalletsKeysQuery({
onCompleted: data => {
keysDispatch({
type: 'set',
payload: data.myWalletsKeys
})
}
});
const [updateKeys, updatingKeysStatus] = useUpdateUserWalletsKeysMutation({
onCompleted: data => {
keysDispatch({
type: "set",
payload: data.updateUserWalletKeys
})
}
})
const connectNewWallet = () => {
dispatch(openModal({ Modal: "LinkingAccountModal" }))
}
const saveChanges = () => {
updateKeys({
variables: {
data: keysState.keys.map(v => ({ key: v.key, name: v.name }))
}
})
}
const cancelChanges = () => {
keysDispatch({ type: 'cancel' });
}
return (
<div className="rounded-16 bg-white border-2 border-gray-200 p-24">
@@ -28,9 +127,64 @@ export default function AccountCard({ }: Props) {
<br />
You can add a new wallet from the button below.
</p>
<Button color='primary' className='' onClick={connectNewWallet}>
Connect new wallet
</Button>
{
myKeysQuery.loading ?
<ul className="mt-8 relative flex flex-col gap-8">
{Array(2).fill(0).map((_, idx) =>
<li key={idx} className="text-body4 border-b py-12 px-16 border border-gray-200 rounded-16">
<Skeleton width='15ch' />
</li>
)}
</ul>
:
<>
<ul className="mt-8 relative flex flex-col gap-8">
{keysState.keys.map((item, idx) =>
<li key={item.key} className="flex justify-between items-center text-body4 border-b py-12 px-16 border border-gray-200 rounded-16">
<input
type="text"
value={item.name}
onChange={e => {
keysDispatch({
type: 'update',
payload: {
idx,
value: e.target.value
}
})
}}
className='p-0 border-0 focus:border-0 focus:outline-none grow
focus:ring-0 placeholder:!text-gray-400' />
<Button size='sm' color='none' className='text-red-500 !p-0' onClick={() => keysDispatch({ type: 'delete', payload: { idx } })}>Delete key</Button>
</li>
)}
</ul>
<div className="flex justify-end gap-8">
<Button
color='gray'
className=''
disabled={!keysState.hasNewChanges || updatingKeysStatus.loading}
onClick={cancelChanges}
>
Cancel
</Button>
<Button
color='black'
className=''
disabled={!keysState.hasNewChanges}
isLoading={updatingKeysStatus.loading}
onClick={saveChanges}
>
Save Changes
</Button>
</div>
{keysState.keys.length < 3 && <Button color='primary' className='mt-16' onClick={connectNewWallet}>
Connect new wallet
</Button>}
</>
}
</div>

View File

@@ -7,6 +7,7 @@ import { QRCodeSVG } from 'qrcode.react';
import Button from "src/Components/Button/Button";
import { FiCopy } from "react-icons/fi";
import useCopyToClipboard from "src/utils/hooks/useCopyToClipboard";
import { useApolloClient } from '@apollo/client';
@@ -57,7 +58,8 @@ export default function LinkingAccountModal({ onClose, direction, ...props }: Mo
const [copied, setCopied] = useState(false);
const { loadingLnurl, data: { lnurl }, error } = useLnurlQuery();
const clipboard = useCopyToClipboard()
const clipboard = useCopyToClipboard();
const apolloClient = useApolloClient();
@@ -71,6 +73,13 @@ export default function LinkingAccountModal({ onClose, direction, ...props }: Mo
clipboard(lnurl);
}
const done = () => {
apolloClient.refetchQueries({
include: ['MyWalletsKeys']
})
onClose?.()
}
let content = <></>
@@ -114,7 +123,7 @@ export default function LinkingAccountModal({ onClose, direction, ...props }: Mo
>{copied ? "Copied" : "Copy"} <FiCopy /></Button>
<Button
color='primary'
onClick={onClose}
onClick={done}
fullWidth
className='mt-16'
>

View File

@@ -0,0 +1,13 @@
query MyWalletsKeys {
myWalletsKeys {
key
name
}
}
mutation UpdateUserWalletsKeys($data: [UserKeyInputType!]) {
updateUserWalletKeys(data: $data) {
key
name
}
}

View File

@@ -122,6 +122,7 @@ export type Mutation = {
deleteStory: Maybe<Story>;
donate: Donation;
updateProfile: Maybe<User>;
updateUserWalletKeys: Array<UserKey>;
vote: Vote;
};
@@ -158,6 +159,11 @@ export type MutationUpdateProfileArgs = {
};
export type MutationUpdateUserWalletKeysArgs = {
data: InputMaybe<Array<UserKeyInputType>>;
};
export type MutationVoteArgs = {
amount_in_sat: Scalars['Int'];
item_id: Scalars['Int'];
@@ -225,6 +231,7 @@ export type Query = {
getTrendingPosts: Array<Post>;
hottestProjects: Array<Project>;
me: Maybe<User>;
myWalletsKeys: Array<UserKey>;
newProjects: Array<Project>;
officialTags: Array<Tag>;
popularTags: Array<Tag>;
@@ -396,6 +403,17 @@ export type User = {
website: Maybe<Scalars['String']>;
};
export type UserKey = {
__typename?: 'UserKey';
key: Scalars['String'];
name: Scalars['String'];
};
export type UserKeyInputType = {
key: Scalars['String'];
name: Scalars['String'];
};
export enum Vote_Item_Type {
Bounty = 'Bounty',
PostComment = 'PostComment',
@@ -515,12 +533,17 @@ export type PostDetailsQueryVariables = Exact<{
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, applications: Array<{ __typename?: 'BountyApplication', id: number, date: string, workplan: string, author: { __typename?: 'Author', id: number, name: string, avatar: string } }> } | { __typename?: 'Question', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, is_published: boolean | null, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
export type ProfileQueryVariables = Exact<{
profileId: Scalars['Int'];
export type MyWalletsKeysQueryVariables = Exact<{ [key: string]: never; }>;
export type MyWalletsKeysQuery = { __typename?: 'Query', myWalletsKeys: Array<{ __typename?: 'UserKey', key: string, name: string }> };
export type UpdateUserWalletsKeysMutationVariables = Exact<{
data: InputMaybe<Array<UserKeyInputType> | UserKeyInputType>;
}>;
export type ProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: number, name: string, avatar: string, join_date: any, role: string | null, email: string | null, jobTitle: string | null, lightning_address: string | null, website: string | null, twitter: string | null, github: string | null, linkedin: string | null, bio: string | null, location: string | null, nostr_prv_key: string | null, nostr_pub_key: string | null, stories: Array<{ __typename?: 'Story', id: number, title: string, createdAt: any, tags: Array<{ __typename?: 'Tag', id: number, title: string, icon: string | null }> }> } | null };
export type UpdateUserWalletsKeysMutation = { __typename?: 'Mutation', updateUserWalletKeys: Array<{ __typename?: 'UserKey', key: string, name: string }> };
export type UpdateProfileAboutMutationVariables = Exact<{
data: InputMaybe<UpdateProfileInput>;
@@ -529,6 +552,13 @@ export type UpdateProfileAboutMutationVariables = Exact<{
export type UpdateProfileAboutMutation = { __typename?: 'Mutation', updateProfile: { __typename?: 'User', id: number, name: string, avatar: string, join_date: any, website: string | null, role: string | null, email: string | null, lightning_address: string | null, jobTitle: string | null, twitter: string | null, github: string | null, linkedin: string | null, bio: string | null, location: string | null } | null };
export type ProfileQueryVariables = Exact<{
profileId: Scalars['Int'];
}>;
export type ProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: number, name: string, avatar: string, join_date: any, role: string | null, email: string | null, jobTitle: string | null, lightning_address: string | null, website: string | null, twitter: string | null, github: string | null, linkedin: string | null, bio: string | null, location: string | null, nostr_prv_key: string | null, nostr_pub_key: string | null, stories: Array<{ __typename?: 'Story', id: number, title: string, createdAt: any, tags: Array<{ __typename?: 'Tag', id: number, title: string, icon: string | null }> }> } | null };
export type CategoryPageQueryVariables = Exact<{
categoryId: Scalars['Int'];
}>;
@@ -1306,6 +1336,121 @@ export function usePostDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOption
export type PostDetailsQueryHookResult = ReturnType<typeof usePostDetailsQuery>;
export type PostDetailsLazyQueryHookResult = ReturnType<typeof usePostDetailsLazyQuery>;
export type PostDetailsQueryResult = Apollo.QueryResult<PostDetailsQuery, PostDetailsQueryVariables>;
export const MyWalletsKeysDocument = gql`
query MyWalletsKeys {
myWalletsKeys {
key
name
}
}
`;
/**
* __useMyWalletsKeysQuery__
*
* To run a query within a React component, call `useMyWalletsKeysQuery` and pass it any options that fit your needs.
* When your component renders, `useMyWalletsKeysQuery` 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 } = useMyWalletsKeysQuery({
* variables: {
* },
* });
*/
export function useMyWalletsKeysQuery(baseOptions?: Apollo.QueryHookOptions<MyWalletsKeysQuery, MyWalletsKeysQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MyWalletsKeysQuery, MyWalletsKeysQueryVariables>(MyWalletsKeysDocument, options);
}
export function useMyWalletsKeysLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MyWalletsKeysQuery, MyWalletsKeysQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MyWalletsKeysQuery, MyWalletsKeysQueryVariables>(MyWalletsKeysDocument, options);
}
export type MyWalletsKeysQueryHookResult = ReturnType<typeof useMyWalletsKeysQuery>;
export type MyWalletsKeysLazyQueryHookResult = ReturnType<typeof useMyWalletsKeysLazyQuery>;
export type MyWalletsKeysQueryResult = Apollo.QueryResult<MyWalletsKeysQuery, MyWalletsKeysQueryVariables>;
export const UpdateUserWalletsKeysDocument = gql`
mutation UpdateUserWalletsKeys($data: [UserKeyInputType!]) {
updateUserWalletKeys(data: $data) {
key
name
}
}
`;
export type UpdateUserWalletsKeysMutationFn = Apollo.MutationFunction<UpdateUserWalletsKeysMutation, UpdateUserWalletsKeysMutationVariables>;
/**
* __useUpdateUserWalletsKeysMutation__
*
* To run a mutation, you first call `useUpdateUserWalletsKeysMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateUserWalletsKeysMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateUserWalletsKeysMutation, { data, loading, error }] = useUpdateUserWalletsKeysMutation({
* variables: {
* data: // value for 'data'
* },
* });
*/
export function useUpdateUserWalletsKeysMutation(baseOptions?: Apollo.MutationHookOptions<UpdateUserWalletsKeysMutation, UpdateUserWalletsKeysMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateUserWalletsKeysMutation, UpdateUserWalletsKeysMutationVariables>(UpdateUserWalletsKeysDocument, options);
}
export type UpdateUserWalletsKeysMutationHookResult = ReturnType<typeof useUpdateUserWalletsKeysMutation>;
export type UpdateUserWalletsKeysMutationResult = Apollo.MutationResult<UpdateUserWalletsKeysMutation>;
export type UpdateUserWalletsKeysMutationOptions = Apollo.BaseMutationOptions<UpdateUserWalletsKeysMutation, UpdateUserWalletsKeysMutationVariables>;
export const UpdateProfileAboutDocument = gql`
mutation updateProfileAbout($data: UpdateProfileInput) {
updateProfile(data: $data) {
id
name
avatar
join_date
website
role
email
lightning_address
jobTitle
twitter
github
linkedin
bio
location
}
}
`;
export type UpdateProfileAboutMutationFn = Apollo.MutationFunction<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>;
/**
* __useUpdateProfileAboutMutation__
*
* To run a mutation, you first call `useUpdateProfileAboutMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateProfileAboutMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateProfileAboutMutation, { data, loading, error }] = useUpdateProfileAboutMutation({
* variables: {
* data: // value for 'data'
* },
* });
*/
export function useUpdateProfileAboutMutation(baseOptions?: Apollo.MutationHookOptions<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>(UpdateProfileAboutDocument, options);
}
export type UpdateProfileAboutMutationHookResult = ReturnType<typeof useUpdateProfileAboutMutation>;
export type UpdateProfileAboutMutationResult = Apollo.MutationResult<UpdateProfileAboutMutation>;
export type UpdateProfileAboutMutationOptions = Apollo.BaseMutationOptions<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>;
export const ProfileDocument = gql`
query profile($profileId: Int!) {
profile(id: $profileId) {
@@ -1366,52 +1511,6 @@ export function useProfileLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<Pr
export type ProfileQueryHookResult = ReturnType<typeof useProfileQuery>;
export type ProfileLazyQueryHookResult = ReturnType<typeof useProfileLazyQuery>;
export type ProfileQueryResult = Apollo.QueryResult<ProfileQuery, ProfileQueryVariables>;
export const UpdateProfileAboutDocument = gql`
mutation updateProfileAbout($data: UpdateProfileInput) {
updateProfile(data: $data) {
id
name
avatar
join_date
website
role
email
lightning_address
jobTitle
twitter
github
linkedin
bio
location
}
}
`;
export type UpdateProfileAboutMutationFn = Apollo.MutationFunction<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>;
/**
* __useUpdateProfileAboutMutation__
*
* To run a mutation, you first call `useUpdateProfileAboutMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateProfileAboutMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateProfileAboutMutation, { data, loading, error }] = useUpdateProfileAboutMutation({
* variables: {
* data: // value for 'data'
* },
* });
*/
export function useUpdateProfileAboutMutation(baseOptions?: Apollo.MutationHookOptions<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>(UpdateProfileAboutDocument, options);
}
export type UpdateProfileAboutMutationHookResult = ReturnType<typeof useUpdateProfileAboutMutation>;
export type UpdateProfileAboutMutationResult = Apollo.MutationResult<UpdateProfileAboutMutation>;
export type UpdateProfileAboutMutationOptions = Apollo.BaseMutationOptions<UpdateProfileAboutMutation, UpdateProfileAboutMutationVariables>;
export const CategoryPageDocument = gql`
query CategoryPage($categoryId: Int!) {
projectsByCategory(category_id: $categoryId) {