can mutate profile

This commit is contained in:
Kalle (Sendou) 2020-10-22 00:14:17 +03:00
parent 87cf160553
commit 0886a2b4c9
10 changed files with 127 additions and 189 deletions

View File

@ -43,6 +43,38 @@ export type QueryGetUserByIdentifierArgs = {
identifier: Scalars['String'];
};
export type UpdateUserProfileInput = {
twitterName?: Maybe<Scalars['String']>;
customUrlPath?: Maybe<Scalars['String']>;
twitchName?: Maybe<Scalars['String']>;
youtubeId?: Maybe<Scalars['String']>;
country?: Maybe<Scalars['String']>;
bio?: Maybe<Scalars['String']>;
sensStick?: Maybe<Scalars['Float']>;
sensMotion?: Maybe<Scalars['Float']>;
weaponPool?: Maybe<Array<Scalars['String']>>;
};
export type Mutation = {
__typename?: 'Mutation';
updateUserProfile: Scalars['Boolean'];
};
export type MutationUpdateUserProfileArgs = {
profile?: Maybe<UpdateUserProfileInput>;
};
export type UpdateUserProfileMutationVariables = Exact<{
profile: UpdateUserProfileInput;
}>;
export type UpdateUserProfileMutation = (
{ __typename?: 'Mutation' }
& Pick<Mutation, 'updateUserProfile'>
);
export type GetUserByIdentifierQueryVariables = Exact<{
identifier: Scalars['String'];
}>;
@ -61,6 +93,36 @@ export type GetUserByIdentifierQuery = (
);
export const UpdateUserProfileDocument = gql`
mutation UpdateUserProfile($profile: UpdateUserProfileInput!) {
updateUserProfile(profile: $profile)
}
`;
export type UpdateUserProfileMutationFn = Apollo.MutationFunction<UpdateUserProfileMutation, UpdateUserProfileMutationVariables>;
/**
* __useUpdateUserProfileMutation__
*
* To run a mutation, you first call `useUpdateUserProfileMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateUserProfileMutation` 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 [updateUserProfileMutation, { data, loading, error }] = useUpdateUserProfileMutation({
* variables: {
* profile: // value for 'profile'
* },
* });
*/
export function useUpdateUserProfileMutation(baseOptions?: Apollo.MutationHookOptions<UpdateUserProfileMutation, UpdateUserProfileMutationVariables>) {
return Apollo.useMutation<UpdateUserProfileMutation, UpdateUserProfileMutationVariables>(UpdateUserProfileDocument, baseOptions);
}
export type UpdateUserProfileMutationHookResult = ReturnType<typeof useUpdateUserProfileMutation>;
export type UpdateUserProfileMutationResult = Apollo.MutationResult<UpdateUserProfileMutation>;
export type UpdateUserProfileMutationOptions = Apollo.BaseMutationOptions<UpdateUserProfileMutation, UpdateUserProfileMutationVariables>;
export const GetUserByIdentifierDocument = gql`
query GetUserByIdentifier($identifier: String!) {
getUserByIdentifier(identifier: $identifier) {

View File

@ -13,7 +13,7 @@ export const schema = makeSchema({
typegen: path.join(process.cwd(), "nexus-typegen.ts"),
},
nonNullDefaults: {
input: true,
input: false,
output: true,
},
typegenAutoConfig: {

View File

@ -100,7 +100,7 @@ export const UpdateUserProfileInput = inputObjectType({
export const Mutation = mutationType({
definition(t) {
t.field("updateUserProfile", {
type: Profile,
type: "Boolean",
nullable: false,
args: {
profile: UpdateUserProfileInput,
@ -113,12 +113,14 @@ export const Mutation = mutationType({
console.log({ session });
// FIXME: set custom url to lowerCase
return await ctx.prisma.profile.upsert({
await ctx.prisma.profile.upsert({
create: { user: { connect: { id: 4 } }, ...args.profile },
// FIXME: doing it like this makes removing values impossible?
update: args.profile,
where: { userId: 4 },
});
return true;
},
});
},

View File

@ -21,15 +21,15 @@ declare global {
export interface NexusGenInputs {
UpdateUserProfileInput: { // input type
bio: string; // String!
country: string; // String!
customUrlPath: string; // String!
sensMotion: number; // Float!
sensStick: number; // Float!
twitchName: string; // String!
twitterName: string; // String!
weaponPool: string[]; // [String!]!
youtubeId: string; // String!
bio?: string | null; // String
country?: string | null; // String
customUrlPath?: string | null; // String
sensMotion?: number | null; // Float
sensStick?: number | null; // Float
twitchName?: string | null; // String
twitterName?: string | null; // String
weaponPool?: string[] | null; // [String!]
youtubeId?: string | null; // String
}
}
@ -62,7 +62,7 @@ export interface NexusGenAllTypes extends NexusGenRootTypes {
export interface NexusGenFieldTypes {
Mutation: { // field return type
updateUserProfile: NexusGenRootTypes['Profile']; // Profile!
updateUserProfile: boolean; // Boolean!
}
Profile: { // field return type
bio: string | null; // String
@ -90,7 +90,7 @@ export interface NexusGenFieldTypes {
export interface NexusGenArgTypes {
Mutation: {
updateUserProfile: { // args
profile: NexusGenInputs['UpdateUserProfileInput']; // UpdateUserProfileInput!
profile?: NexusGenInputs['UpdateUserProfileInput'] | null; // UpdateUserProfileInput
}
}
Query: {

View File

@ -18,18 +18,17 @@ const extendedTheme = extendTheme({
},
}),
},
// FIXME:
// 1) round iconButton
// 2) table-like lime green input addons
// 3) input styling
// 4) focus color
components: {
Button: {
defaultProps: {
colorScheme: "lime",
color: "black",
colorScheme: "theme",
},
},
// IconButton: {
// defaultProps: {
// isRound: true,
// },
// },
Modal: {
baseStyle: (props) => ({
content: {
@ -42,7 +41,7 @@ const extendedTheme = extendTheme({
},
},
colors: {
lime: {
theme: {
50: "#e4ffdf",
100: "#bbffb0",
200: "#92ff7f",

View File

@ -91,7 +91,7 @@ const AvatarWithInfo: React.FC<AvatarWithInfoProps> = ({ user }) => {
/>
</a>
)}
{user.profile?.weaponPool.length && (
{user.profile?.weaponPool && user.profile?.weaponPool.length > 0 && (
<Flex
mt="0.2rem"
w="100%"

View File

@ -15,6 +15,10 @@ import {
ModalOverlay,
} from "@chakra-ui/core";
import { zodResolver } from "@hookform/resolvers/zod";
import {
UpdateUserProfileInput,
useUpdateUserProfileMutation,
} from "generated/graphql";
import { useTranslation } from "lib/useMockT";
import { useForm } from "react-hook-form";
import { ProfileSchema } from "validators/Profile";
@ -26,17 +30,21 @@ interface Props {
const ProfileModal: React.FC<Props> = ({ isOpen, onClose }) => {
const { t } = useTranslation();
const { handleSubmit, errors, register } = useForm({
const { handleSubmit, errors, register } = useForm<UpdateUserProfileInput>({
resolver: zodResolver(ProfileSchema),
});
const [updateUserProfile] = useUpdateUserProfileMutation();
const onSubmit = (data) => {
const onSubmit = async (data: UpdateUserProfileInput) => {
Object.keys(data).forEach((key) => {
if (data[key] === "") {
data[key] = null;
const typedKey = key as keyof typeof data;
if (data[typedKey] === "") {
data[typedKey] = null;
}
});
await updateUserProfile({ variables: { profile: data } });
console.log(data);
};

View File

@ -0,0 +1,3 @@
mutation UpdateUserProfile($profile: UpdateUserProfileInput!) {
updateUserProfile(profile: $profile)
}

View File

@ -3,7 +3,7 @@
type Mutation {
updateUserProfile(profile: UpdateUserProfileInput!): Profile!
updateUserProfile(profile: UpdateUserProfileInput): Boolean!
}
type Profile {
@ -23,15 +23,15 @@ type Query {
}
input UpdateUserProfileInput {
bio: String!
country: String!
customUrlPath: String!
sensMotion: Float!
sensStick: Float!
twitchName: String!
twitterName: String!
weaponPool: [String!]!
youtubeId: String!
bio: String
country: String
customUrlPath: String
sensMotion: Float
sensStick: Float
twitchName: String
twitterName: String
weaponPool: [String!]
youtubeId: String
}
type User {

View File

@ -1,173 +1,37 @@
//import isISO31661Alpha2 from "validator/es/lib/isISO31661Alpha2";
import { weaponsWithHero } from "lib/lists/weaponsWithHero";
import * as z from "zod";
export const ProfileSchema = z.object({
bio: z.string().max(10000).optional(),
bio: z.string().max(10000).optional().nullable(),
country: z
.string()
//.refine((val) => isISO31661Alpha2(val))
.optional(),
customUrlPath: z.string().max(32).optional(),
.optional()
.nullable(),
customUrlPath: z.string().max(32).optional().nullable(),
sensMotion: z
.number()
.min(5)
.max(5)
.refine((val) => (val * 10) % 5 === 0)
.optional(),
.optional()
.nullable(),
sensStick: z
.number()
.min(5)
.max(5)
.refine((val) => (val * 10) % 5 === 0)
.optional(),
twitchName: z.string().max(25).optional(),
twitterName: z.string().max(15).optional(),
youtubeId: z.string().optional(),
.optional()
.nullable(),
twitchName: z.string().max(25).optional().nullable(),
twitterName: z.string().max(15).optional().nullable(),
youtubeId: z.string().optional().nullable(),
// weaponsWithHero
weaponPool: z
.array(
z.enum([
"Sploosh-o-matic",
"Neo Sploosh-o-matic",
"Sploosh-o-matic 7",
"Splattershot Jr.",
"Custom Splattershot Jr.",
"Kensa Splattershot Jr.",
"Splash-o-matic",
"Neo Splash-o-matic",
"Aerospray MG",
"Aerospray RG",
"Aerospray PG",
"Splattershot",
"Hero Shot Replica",
"Tentatek Splattershot",
"Octo Shot Replica",
"Kensa Splattershot",
".52 Gal",
".52 Gal Deco",
"Kensa .52 Gal",
"N-ZAP '85",
"N-ZAP '89",
"N-ZAP '83",
"Splattershot Pro",
"Forge Splattershot Pro",
"Kensa Splattershot Pro",
".96 Gal",
".96 Gal Deco",
"Jet Squelcher",
"Custom Jet Squelcher",
"L-3 Nozzlenose",
"L-3 Nozzlenose D",
"Kensa L-3 Nozzlenose",
"H-3 Nozzlenose",
"H-3 Nozzlenose D",
"Cherry H-3 Nozzlenose",
"Squeezer",
"Foil Squeezer",
"Luna Blaster",
"Luna Blaster Neo",
"Kensa Luna Blaster",
"Blaster",
"Hero Blaster Replica",
"Custom Blaster",
"Range Blaster",
"Custom Range Blaster",
"Grim Range Blaster",
"Rapid Blaster",
"Rapid Blaster Deco",
"Kensa Rapid Blaster",
"Rapid Blaster Pro",
"Rapid Blaster Pro Deco",
"Clash Blaster",
"Clash Blaster Neo",
"Carbon Roller",
"Carbon Roller Deco",
"Splat Roller",
"Hero Roller Replica",
"Krak-On Splat Roller",
"Kensa Splat Roller",
"Dynamo Roller",
"Gold Dynamo Roller",
"Kensa Dynamo Roller",
"Flingza Roller",
"Foil Flingza Roller",
"Inkbrush",
"Inkbrush Nouveau",
"Permanent Inkbrush",
"Octobrush",
"Herobrush Replica",
"Octobrush Nouveau",
"Kensa Octobrush",
"Classic Squiffer",
"New Squiffer",
"Fresh Squiffer",
"Splat Charger",
"Hero Charger Replica",
"Firefin Splat Charger",
"Kensa Charger",
"Splatterscope",
"Firefin Splatterscope",
"Kensa Splatterscope",
"E-liter 4K",
"Custom E-liter 4K",
"E-liter 4K Scope",
"Custom E-liter 4K Scope",
"Bamboozler 14 Mk I",
"Bamboozler 14 Mk II",
"Bamboozler 14 Mk III",
"Goo Tuber",
"Custom Goo Tuber",
"Slosher",
"Hero Slosher Replica",
"Slosher Deco",
"Soda Slosher",
"Tri-Slosher",
"Tri-Slosher Nouveau",
"Sloshing Machine",
"Sloshing Machine Neo",
"Kensa Sloshing Machine",
"Bloblobber",
"Bloblobber Deco",
"Explosher",
"Custom Explosher",
"Mini Splatling",
"Zink Mini Splatling",
"Kensa Mini Splatling",
"Heavy Splatling",
"Hero Splatling Replica",
"Heavy Splatling Deco",
"Heavy Splatling Remix",
"Hydra Splatling",
"Custom Hydra Splatling",
"Ballpoint Splatling",
"Ballpoint Splatling Nouveau",
"Nautilus 47",
"Nautilus 79",
"Dapple Dualies",
"Dapple Dualies Nouveau",
"Clear Dapple Dualies",
"Splat Dualies",
"Hero Dualie Replicas",
"Enperry Splat Dualies",
"Kensa Splat Dualies",
"Glooga Dualies",
"Glooga Dualies Deco",
"Kensa Glooga Dualies",
"Dualie Squelchers",
"Custom Dualie Squelchers",
"Dark Tetra Dualies",
"Light Tetra Dualies",
"Splat Brella",
"Hero Brella Replica",
"Sorella Brella",
"Tenta Brella",
"Tenta Sorella Brella",
"Tenta Camo Brella",
"Undercover Brella",
"Undercover Sorella Brella",
"Kensa Undercover Brella",
])
)
.array(z.string())
.max(5)
.optional(),
.refine((arr) => arr.every((val) => weaponsWithHero.includes(val as any)))
.optional()
.nullable(),
});