From 151780173579d4408ca8156693210366e28c6b07 Mon Sep 17 00:00:00 2001 From: Sohan Date: Tue, 14 Nov 2023 16:14:59 +0530 Subject: [PATCH] added firstname and lastname to user onboarding flow --- backend/native/backpack-api/src/db/users.ts | 4 + .../backpack-api/src/routes/v1/users.ts | 4 +- .../backpack-api/src/validation/user.ts | 12 ++ backend/native/zeus/src/zeus/const.ts | 14 ++ backend/native/zeus/src/zeus/index.ts | 145 ++++++++++++++++-- .../databases/default/tables/auth_users.yaml | 6 + .../down.sql | 4 + .../up.sql | 2 + .../down.sql | 4 + .../up.sql | 2 + .../Onboarding/pages/OnboardAccount.tsx | 4 +- .../Onboarding/pages/UsernameForm.tsx | 50 +++++- packages/common/src/constants.ts | 2 +- .../recoil/src/context/OnboardingProvider.tsx | 9 +- 14 files changed, 243 insertions(+), 19 deletions(-) create mode 100644 backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/down.sql create mode 100644 backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/up.sql create mode 100644 backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/down.sql create mode 100644 backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/up.sql diff --git a/backend/native/backpack-api/src/db/users.ts b/backend/native/backpack-api/src/db/users.ts index c1a1755b7..13adbf1d3 100644 --- a/backend/native/backpack-api/src/db/users.ts +++ b/backend/native/backpack-api/src/db/users.ts @@ -302,6 +302,8 @@ const transformUser = ( */ export const createUser = async ( username: string, + firstname: string, + lastname: string, blockchainPublicKeys: Array<{ blockchain: Blockchain; publicKey: string }>, waitlistId?: string | null, referrerId?: string @@ -329,6 +331,8 @@ export const createUser = async ( { object: { username: username, + firstname: firstname, + lastname: lastname, public_keys: { data: blockchainPublicKeys.map((b) => ({ blockchain: b.blockchain, diff --git a/backend/native/backpack-api/src/routes/v1/users.ts b/backend/native/backpack-api/src/routes/v1/users.ts index 9e2db77dd..8d92d247a 100644 --- a/backend/native/backpack-api/src/routes/v1/users.ts +++ b/backend/native/backpack-api/src/routes/v1/users.ts @@ -124,7 +124,7 @@ router.get("/jwt/xnft", extractUserId, async (req, res) => { * Create a new user. */ router.post("/", async (req, res) => { - const { username, waitlistId, blockchainPublicKeys } = + const { username, firstname, lastname, waitlistId, blockchainPublicKeys } = CreateUserWithPublicKeys.parse(req.body); // Validate all the signatures @@ -182,6 +182,8 @@ router.post("/", async (req, res) => { const user = await createUser( username, + firstname, + lastname, blockchainPublicKeys.map((b) => ({ ...b, // Cast blockchain to correct type diff --git a/backend/native/backpack-api/src/validation/user.ts b/backend/native/backpack-api/src/validation/user.ts index 82e4319ab..ea9ce4426 100644 --- a/backend/native/backpack-api/src/validation/user.ts +++ b/backend/native/backpack-api/src/validation/user.ts @@ -9,6 +9,18 @@ export const BaseCreateUser = z.object({ /^[a-z0-9_]{3,15}$/, "should be between 3-15 characters and can only contain numbers, letters, and underscores." ), + firstname: z + .string() + .regex( + /^[a-z]{3,15}$/, + "should be between 3-15 characters and can only contain letters." + ), + lastname: z + .string() + .regex( + /^[a-z]{3,15}$/, + "should be between 3-15 characters and can only contain letters." + ), inviteCode: z .string() .regex( diff --git a/backend/native/zeus/src/zeus/const.ts b/backend/native/zeus/src/zeus/const.ts index 8f9ff9757..2bf1b79af 100644 --- a/backend/native/zeus/src/zeus/const.ts +++ b/backend/native/zeus/src/zeus/const.ts @@ -763,8 +763,10 @@ export const AllTypesProps: Record = { _or: "auth_users_bool_exp", created_at: "timestamptz_comparison_exp", dropzone_public_key: "auth_public_keys_bool_exp", + firstname: "String_comparison_exp", id: "uuid_comparison_exp", invitation: "auth_invitations_bool_exp", + lastname: "String_comparison_exp", public_keys: "auth_public_keys_bool_exp", public_keys_aggregate: "auth_public_keys_aggregate_bool_exp", referred_users: "auth_users_bool_exp", @@ -784,12 +786,16 @@ export const AllTypesProps: Record = { }, auth_users_max_order_by: { created_at: "order_by", + firstname: "order_by", id: "order_by", + lastname: "order_by", username: "order_by", }, auth_users_min_order_by: { created_at: "order_by", + firstname: "order_by", id: "order_by", + lastname: "order_by", username: "order_by", }, auth_users_obj_rel_insert_input: { @@ -804,8 +810,10 @@ export const AllTypesProps: Record = { auth_users_order_by: { created_at: "order_by", dropzone_public_key_aggregate: "auth_public_keys_aggregate_order_by", + firstname: "order_by", id: "order_by", invitation: "auth_invitations_order_by", + lastname: "order_by", public_keys_aggregate: "auth_public_keys_aggregate_order_by", referred_users_aggregate: "auth_users_aggregate_order_by", referrer: "auth_users_order_by", @@ -2084,8 +2092,10 @@ export const ReturnTypes: Record = { auth_users: { created_at: "timestamptz", dropzone_public_key: "auth_public_keys", + firstname: "String", id: "uuid", invitation: "auth_invitations", + lastname: "String", public_keys: "auth_public_keys", public_keys_aggregate: "auth_public_keys_aggregate", referred_users: "auth_users", @@ -2104,12 +2114,16 @@ export const ReturnTypes: Record = { }, auth_users_max_fields: { created_at: "timestamptz", + firstname: "String", id: "uuid", + lastname: "String", username: "citext", }, auth_users_min_fields: { created_at: "timestamptz", + firstname: "String", id: "uuid", + lastname: "String", username: "citext", }, auth_users_mutation_response: { diff --git a/backend/native/zeus/src/zeus/index.ts b/backend/native/zeus/src/zeus/index.ts index 7a02dfb8c..28279ecba 100644 --- a/backend/native/zeus/src/zeus/index.ts +++ b/backend/native/zeus/src/zeus/index.ts @@ -51,7 +51,7 @@ const handleFetchResponse = (response: Response): Promise => { .catch(reject); }); } - return response.json(); + return response.json() as Promise; }; export const apiFetch = @@ -362,12 +362,17 @@ export const traverseResponse = ({ ) { return o; } - return Object.fromEntries( - Object.entries(o).map(([k, v]) => [ - k, - ibb(k, v, [...p, purifyGraphQLKey(k)]), - ]) + const entries = Object.entries(o).map( + ([k, v]) => [k, ibb(k, v, [...p, purifyGraphQLKey(k)])] as const ); + const objectFromEntries = entries.reduce>( + (a, [k, v]) => { + a[k] = v; + return a; + }, + {} + ); + return objectFromEntries; }; return ibb; }; @@ -759,8 +764,8 @@ export const resolverFor = < source: any ) => Z extends keyof ModelTypes[T] ? ModelTypes[T][Z] | Promise | X - : any -) => fn as (args?: any, source?: any) => any; + : never +) => fn as (args?: any, source?: any) => ReturnType; export type UnwrapPromise = T extends Promise ? R : T; export type ZeusState Promise> = NonNullable< @@ -816,9 +821,13 @@ type IsInterfaced< : DST[P], SCLR > - : Record + : IsArray< + R, + "__typename" extends keyof DST ? { __typename: true } : never, + SCLR + > : never; - }[keyof DST] & { + }[keyof SRC] & { [P in keyof Omit< Pick< SRC, @@ -4033,9 +4042,11 @@ export type ValueTypes = { }, ValueTypes["auth_public_keys"] ]; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; /** An object relationship */ invitation?: ValueTypes["auth_invitations"]; + lastname?: boolean | `@${string}`; public_keys?: [ { /** distinct select on columns */ @@ -4272,6 +4283,11 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: + | ValueTypes["String_comparison_exp"] + | undefined + | null + | Variable; id?: | ValueTypes["uuid_comparison_exp"] | undefined @@ -4282,6 +4298,11 @@ export type ValueTypes = { | undefined | null | Variable; + lastname?: + | ValueTypes["String_comparison_exp"] + | undefined + | null + | Variable; public_keys?: | ValueTypes["auth_public_keys_bool_exp"] | undefined @@ -4317,6 +4338,7 @@ export type ValueTypes = { ["auth_users_constraint"]: auth_users_constraint; /** input type for inserting data into table "auth.users" */ ["auth_users_insert_input"]: { + firstname?: string | undefined | null | Variable; invitation?: | ValueTypes["auth_invitations_obj_rel_insert_input"] | undefined @@ -4327,6 +4349,7 @@ export type ValueTypes = { | undefined | null | Variable; + lastname?: string | undefined | null | Variable; public_keys?: | ValueTypes["auth_public_keys_arr_rel_insert_input"] | undefined @@ -4349,7 +4372,9 @@ export type ValueTypes = { /** aggregate max on columns */ ["auth_users_max_fields"]: AliasType<{ created_at?: boolean | `@${string}`; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; + lastname?: boolean | `@${string}`; username?: boolean | `@${string}`; __typename?: boolean | `@${string}`; }>; @@ -4360,7 +4385,17 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; id?: ValueTypes["order_by"] | undefined | null | Variable; + lastname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; username?: | ValueTypes["order_by"] | undefined @@ -4370,7 +4405,9 @@ export type ValueTypes = { /** aggregate min on columns */ ["auth_users_min_fields"]: AliasType<{ created_at?: boolean | `@${string}`; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; + lastname?: boolean | `@${string}`; username?: boolean | `@${string}`; __typename?: boolean | `@${string}`; }>; @@ -4381,7 +4418,17 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; id?: ValueTypes["order_by"] | undefined | null | Variable; + lastname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; username?: | ValueTypes["order_by"] | undefined @@ -4430,12 +4477,22 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; id?: ValueTypes["order_by"] | undefined | null | Variable; invitation?: | ValueTypes["auth_invitations_order_by"] | undefined | null | Variable; + lastname?: + | ValueTypes["order_by"] + | undefined + | null + | Variable; public_keys_aggregate?: | ValueTypes["auth_public_keys_aggregate_order_by"] | undefined @@ -4470,6 +4527,8 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: string | undefined | null | Variable; + lastname?: string | undefined | null | Variable; updated_at?: | ValueTypes["timestamptz"] | undefined @@ -4496,7 +4555,9 @@ export type ValueTypes = { | undefined | null | Variable; + firstname?: string | undefined | null | Variable; id?: ValueTypes["uuid"] | undefined | null | Variable; + lastname?: string | undefined | null | Variable; username?: ValueTypes["citext"] | undefined | null | Variable; }; /** update columns of table "auth.users" */ @@ -10898,9 +10959,11 @@ export type ResolverInputTypes = { }, ResolverInputTypes["auth_public_keys"] ]; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; /** An object relationship */ invitation?: ResolverInputTypes["auth_invitations"]; + lastname?: boolean | `@${string}`; public_keys?: [ { /** distinct select on columns */ @@ -11069,11 +11132,13 @@ export type ResolverInputTypes = { | ResolverInputTypes["auth_public_keys_bool_exp"] | undefined | null; + firstname?: ResolverInputTypes["String_comparison_exp"] | undefined | null; id?: ResolverInputTypes["uuid_comparison_exp"] | undefined | null; invitation?: | ResolverInputTypes["auth_invitations_bool_exp"] | undefined | null; + lastname?: ResolverInputTypes["String_comparison_exp"] | undefined | null; public_keys?: | ResolverInputTypes["auth_public_keys_bool_exp"] | undefined @@ -11097,11 +11162,13 @@ export type ResolverInputTypes = { ["auth_users_constraint"]: auth_users_constraint; /** input type for inserting data into table "auth.users" */ ["auth_users_insert_input"]: { + firstname?: string | undefined | null; invitation?: | ResolverInputTypes["auth_invitations_obj_rel_insert_input"] | undefined | null; invitation_id?: ResolverInputTypes["uuid"] | undefined | null; + lastname?: string | undefined | null; public_keys?: | ResolverInputTypes["auth_public_keys_arr_rel_insert_input"] | undefined @@ -11121,27 +11188,35 @@ export type ResolverInputTypes = { /** aggregate max on columns */ ["auth_users_max_fields"]: AliasType<{ created_at?: boolean | `@${string}`; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; + lastname?: boolean | `@${string}`; username?: boolean | `@${string}`; __typename?: boolean | `@${string}`; }>; /** order by max() on columns of table "auth.users" */ ["auth_users_max_order_by"]: { created_at?: ResolverInputTypes["order_by"] | undefined | null; + firstname?: ResolverInputTypes["order_by"] | undefined | null; id?: ResolverInputTypes["order_by"] | undefined | null; + lastname?: ResolverInputTypes["order_by"] | undefined | null; username?: ResolverInputTypes["order_by"] | undefined | null; }; /** aggregate min on columns */ ["auth_users_min_fields"]: AliasType<{ created_at?: boolean | `@${string}`; + firstname?: boolean | `@${string}`; id?: boolean | `@${string}`; + lastname?: boolean | `@${string}`; username?: boolean | `@${string}`; __typename?: boolean | `@${string}`; }>; /** order by min() on columns of table "auth.users" */ ["auth_users_min_order_by"]: { created_at?: ResolverInputTypes["order_by"] | undefined | null; + firstname?: ResolverInputTypes["order_by"] | undefined | null; id?: ResolverInputTypes["order_by"] | undefined | null; + lastname?: ResolverInputTypes["order_by"] | undefined | null; username?: ResolverInputTypes["order_by"] | undefined | null; }; /** response of any mutation on the table "auth.users" */ @@ -11174,11 +11249,13 @@ export type ResolverInputTypes = { | ResolverInputTypes["auth_public_keys_aggregate_order_by"] | undefined | null; + firstname?: ResolverInputTypes["order_by"] | undefined | null; id?: ResolverInputTypes["order_by"] | undefined | null; invitation?: | ResolverInputTypes["auth_invitations_order_by"] | undefined | null; + lastname?: ResolverInputTypes["order_by"] | undefined | null; public_keys_aggregate?: | ResolverInputTypes["auth_public_keys_aggregate_order_by"] | undefined @@ -11199,6 +11276,8 @@ export type ResolverInputTypes = { /** input type for updating data in table "auth.users" */ ["auth_users_set_input"]: { avatar_nft?: ResolverInputTypes["citext"] | undefined | null; + firstname?: string | undefined | null; + lastname?: string | undefined | null; updated_at?: ResolverInputTypes["timestamptz"] | undefined | null; }; /** Streaming cursor of the table "auth_users" */ @@ -11211,7 +11290,9 @@ export type ResolverInputTypes = { /** Initial value of the column from where the streaming should start */ ["auth_users_stream_cursor_value_input"]: { created_at?: ResolverInputTypes["timestamptz"] | undefined | null; + firstname?: string | undefined | null; id?: ResolverInputTypes["uuid"] | undefined | null; + lastname?: string | undefined | null; username?: ResolverInputTypes["citext"] | undefined | null; }; /** update columns of table "auth.users" */ @@ -15978,9 +16059,11 @@ export type ModelTypes = { created_at: ModelTypes["timestamptz"]; /** the user's first solana public key inside an array due to hasura limitation */ dropzone_public_key?: Array | undefined; + firstname?: string | undefined; id: ModelTypes["uuid"]; /** An object relationship */ invitation: ModelTypes["auth_invitations"]; + lastname?: string | undefined; /** An array relationship */ public_keys: Array; /** An aggregate relationship */ @@ -16032,8 +16115,10 @@ export type ModelTypes = { _or?: Array | undefined; created_at?: ModelTypes["timestamptz_comparison_exp"] | undefined; dropzone_public_key?: ModelTypes["auth_public_keys_bool_exp"] | undefined; + firstname?: ModelTypes["String_comparison_exp"] | undefined; id?: ModelTypes["uuid_comparison_exp"] | undefined; invitation?: ModelTypes["auth_invitations_bool_exp"] | undefined; + lastname?: ModelTypes["String_comparison_exp"] | undefined; public_keys?: ModelTypes["auth_public_keys_bool_exp"] | undefined; public_keys_aggregate?: | ModelTypes["auth_public_keys_aggregate_bool_exp"] @@ -16048,10 +16133,12 @@ export type ModelTypes = { ["auth_users_constraint"]: auth_users_constraint; /** input type for inserting data into table "auth.users" */ ["auth_users_insert_input"]: { + firstname?: string | undefined; invitation?: | ModelTypes["auth_invitations_obj_rel_insert_input"] | undefined; invitation_id?: ModelTypes["uuid"] | undefined; + lastname?: string | undefined; public_keys?: | ModelTypes["auth_public_keys_arr_rel_insert_input"] | undefined; @@ -16064,25 +16151,33 @@ export type ModelTypes = { /** aggregate max on columns */ ["auth_users_max_fields"]: { created_at?: ModelTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: ModelTypes["uuid"] | undefined; + lastname?: string | undefined; username?: ModelTypes["citext"] | undefined; }; /** order by max() on columns of table "auth.users" */ ["auth_users_max_order_by"]: { created_at?: ModelTypes["order_by"] | undefined; + firstname?: ModelTypes["order_by"] | undefined; id?: ModelTypes["order_by"] | undefined; + lastname?: ModelTypes["order_by"] | undefined; username?: ModelTypes["order_by"] | undefined; }; /** aggregate min on columns */ ["auth_users_min_fields"]: { created_at?: ModelTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: ModelTypes["uuid"] | undefined; + lastname?: string | undefined; username?: ModelTypes["citext"] | undefined; }; /** order by min() on columns of table "auth.users" */ ["auth_users_min_order_by"]: { created_at?: ModelTypes["order_by"] | undefined; + firstname?: ModelTypes["order_by"] | undefined; id?: ModelTypes["order_by"] | undefined; + lastname?: ModelTypes["order_by"] | undefined; username?: ModelTypes["order_by"] | undefined; }; /** response of any mutation on the table "auth.users" */ @@ -16110,8 +16205,10 @@ export type ModelTypes = { dropzone_public_key_aggregate?: | ModelTypes["auth_public_keys_aggregate_order_by"] | undefined; + firstname?: ModelTypes["order_by"] | undefined; id?: ModelTypes["order_by"] | undefined; invitation?: ModelTypes["auth_invitations_order_by"] | undefined; + lastname?: ModelTypes["order_by"] | undefined; public_keys_aggregate?: | ModelTypes["auth_public_keys_aggregate_order_by"] | undefined; @@ -16129,6 +16226,8 @@ export type ModelTypes = { /** input type for updating data in table "auth.users" */ ["auth_users_set_input"]: { avatar_nft?: ModelTypes["citext"] | undefined; + firstname?: string | undefined; + lastname?: string | undefined; updated_at?: ModelTypes["timestamptz"] | undefined; }; /** Streaming cursor of the table "auth_users" */ @@ -16141,7 +16240,9 @@ export type ModelTypes = { /** Initial value of the column from where the streaming should start */ ["auth_users_stream_cursor_value_input"]: { created_at?: ModelTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: ModelTypes["uuid"] | undefined; + lastname?: string | undefined; username?: ModelTypes["citext"] | undefined; }; ["auth_users_update_column"]: auth_users_update_column; @@ -18876,9 +18977,11 @@ export type GraphQLTypes = { created_at: GraphQLTypes["timestamptz"]; /** the user's first solana public key inside an array due to hasura limitation */ dropzone_public_key?: Array | undefined; + firstname?: string | undefined; id: GraphQLTypes["uuid"]; /** An object relationship */ invitation: GraphQLTypes["auth_invitations"]; + lastname?: string | undefined; /** An array relationship */ public_keys: Array; /** An aggregate relationship */ @@ -18932,8 +19035,10 @@ export type GraphQLTypes = { _or?: Array | undefined; created_at?: GraphQLTypes["timestamptz_comparison_exp"] | undefined; dropzone_public_key?: GraphQLTypes["auth_public_keys_bool_exp"] | undefined; + firstname?: GraphQLTypes["String_comparison_exp"] | undefined; id?: GraphQLTypes["uuid_comparison_exp"] | undefined; invitation?: GraphQLTypes["auth_invitations_bool_exp"] | undefined; + lastname?: GraphQLTypes["String_comparison_exp"] | undefined; public_keys?: GraphQLTypes["auth_public_keys_bool_exp"] | undefined; public_keys_aggregate?: | GraphQLTypes["auth_public_keys_aggregate_bool_exp"] @@ -18949,10 +19054,12 @@ export type GraphQLTypes = { ["auth_users_constraint"]: auth_users_constraint; /** input type for inserting data into table "auth.users" */ ["auth_users_insert_input"]: { + firstname?: string | undefined; invitation?: | GraphQLTypes["auth_invitations_obj_rel_insert_input"] | undefined; invitation_id?: GraphQLTypes["uuid"] | undefined; + lastname?: string | undefined; public_keys?: | GraphQLTypes["auth_public_keys_arr_rel_insert_input"] | undefined; @@ -18968,26 +19075,34 @@ export type GraphQLTypes = { ["auth_users_max_fields"]: { __typename: "auth_users_max_fields"; created_at?: GraphQLTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: GraphQLTypes["uuid"] | undefined; + lastname?: string | undefined; username?: GraphQLTypes["citext"] | undefined; }; /** order by max() on columns of table "auth.users" */ ["auth_users_max_order_by"]: { created_at?: GraphQLTypes["order_by"] | undefined; + firstname?: GraphQLTypes["order_by"] | undefined; id?: GraphQLTypes["order_by"] | undefined; + lastname?: GraphQLTypes["order_by"] | undefined; username?: GraphQLTypes["order_by"] | undefined; }; /** aggregate min on columns */ ["auth_users_min_fields"]: { __typename: "auth_users_min_fields"; created_at?: GraphQLTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: GraphQLTypes["uuid"] | undefined; + lastname?: string | undefined; username?: GraphQLTypes["citext"] | undefined; }; /** order by min() on columns of table "auth.users" */ ["auth_users_min_order_by"]: { created_at?: GraphQLTypes["order_by"] | undefined; + firstname?: GraphQLTypes["order_by"] | undefined; id?: GraphQLTypes["order_by"] | undefined; + lastname?: GraphQLTypes["order_by"] | undefined; username?: GraphQLTypes["order_by"] | undefined; }; /** response of any mutation on the table "auth.users" */ @@ -19016,8 +19131,10 @@ export type GraphQLTypes = { dropzone_public_key_aggregate?: | GraphQLTypes["auth_public_keys_aggregate_order_by"] | undefined; + firstname?: GraphQLTypes["order_by"] | undefined; id?: GraphQLTypes["order_by"] | undefined; invitation?: GraphQLTypes["auth_invitations_order_by"] | undefined; + lastname?: GraphQLTypes["order_by"] | undefined; public_keys_aggregate?: | GraphQLTypes["auth_public_keys_aggregate_order_by"] | undefined; @@ -19036,6 +19153,8 @@ export type GraphQLTypes = { /** input type for updating data in table "auth.users" */ ["auth_users_set_input"]: { avatar_nft?: GraphQLTypes["citext"] | undefined; + firstname?: string | undefined; + lastname?: string | undefined; updated_at?: GraphQLTypes["timestamptz"] | undefined; }; /** Streaming cursor of the table "auth_users" */ @@ -19048,7 +19167,9 @@ export type GraphQLTypes = { /** Initial value of the column from where the streaming should start */ ["auth_users_stream_cursor_value_input"]: { created_at?: GraphQLTypes["timestamptz"] | undefined; + firstname?: string | undefined; id?: GraphQLTypes["uuid"] | undefined; + lastname?: string | undefined; username?: GraphQLTypes["citext"] | undefined; }; /** update columns of table "auth.users" */ @@ -20330,12 +20451,16 @@ export const enum auth_users_constraint { /** select columns of table "auth.users" */ export const enum auth_users_select_column { created_at = "created_at", + firstname = "firstname", id = "id", + lastname = "lastname", username = "username", } /** update columns of table "auth.users" */ export const enum auth_users_update_column { avatar_nft = "avatar_nft", + firstname = "firstname", + lastname = "lastname", updated_at = "updated_at", } /** unique or primary key constraints on table "auth.xnft_preferences" */ diff --git a/backend/reef/hasura/metadata/databases/default/tables/auth_users.yaml b/backend/reef/hasura/metadata/databases/default/tables/auth_users.yaml index b10ae380d..70a14bedd 100644 --- a/backend/reef/hasura/metadata/databases/default/tables/auth_users.yaml +++ b/backend/reef/hasura/metadata/databases/default/tables/auth_users.yaml @@ -65,7 +65,9 @@ insert_permissions: permission: check: {} columns: + - firstname - invitation_id + - lastname - referrer_id - username - waitlist_id @@ -82,7 +84,9 @@ select_permissions: permission: columns: - created_at + - firstname - id + - lastname - username filter: {} allow_aggregations: true @@ -110,6 +114,8 @@ update_permissions: permission: columns: - avatar_nft + - firstname + - lastname - updated_at filter: {} check: null diff --git a/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/down.sql b/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/down.sql new file mode 100644 index 000000000..7db112a7b --- /dev/null +++ b/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "auth"."users" add column "firstname" text +-- null; diff --git a/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/up.sql b/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/up.sql new file mode 100644 index 000000000..49c1a1e68 --- /dev/null +++ b/backend/reef/hasura/migrations/default/1699888086738_alter_table_auth_users_add_column_firstname/up.sql @@ -0,0 +1,2 @@ +alter table "auth"."users" add column "firstname" text + null; diff --git a/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/down.sql b/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/down.sql new file mode 100644 index 000000000..814c82e36 --- /dev/null +++ b/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "auth"."users" add column "lastname" text +-- null; diff --git a/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/up.sql b/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/up.sql new file mode 100644 index 000000000..6079594d8 --- /dev/null +++ b/backend/reef/hasura/migrations/default/1699888097908_alter_table_auth_users_add_column_lastname/up.sql @@ -0,0 +1,2 @@ +alter table "auth"."users" add column "lastname" text + null; diff --git a/packages/app-extension/src/components/Onboarding/pages/OnboardAccount.tsx b/packages/app-extension/src/components/Onboarding/pages/OnboardAccount.tsx index b1564812f..07055d363 100644 --- a/packages/app-extension/src/components/Onboarding/pages/OnboardAccount.tsx +++ b/packages/app-extension/src/components/Onboarding/pages/OnboardAccount.tsx @@ -77,8 +77,8 @@ export const OnboardAccount = ({ { - setOnboardingData({ username }); + onNext={(username, firstname, lastname) => { + setOnboardingData({ username, firstname, lastname }); nextStep(); }} />, diff --git a/packages/app-extension/src/components/Onboarding/pages/UsernameForm.tsx b/packages/app-extension/src/components/Onboarding/pages/UsernameForm.tsx index 627494a16..f0b531d7c 100644 --- a/packages/app-extension/src/components/Onboarding/pages/UsernameForm.tsx +++ b/packages/app-extension/src/components/Onboarding/pages/UsernameForm.tsx @@ -1,5 +1,5 @@ import { type FormEvent, useCallback, useEffect, useState } from "react"; -import { PrimaryButton,TextInput } from "@coral-xyz/react-common"; +import { PrimaryButton, TextInput } from "@coral-xyz/react-common"; import { useCustomTheme } from "@coral-xyz/themes"; import { AlternateEmail } from "@mui/icons-material"; import { Box, InputAdornment } from "@mui/material"; @@ -11,9 +11,11 @@ export const UsernameForm = ({ onNext, }: { inviteCode: string; - onNext: (username: string) => void; + onNext: (username: string, firstname: string, lastname: string) => void; }) => { const [username, setUsername] = useState(""); + const [firstname, setFirstname] = useState(""); + const [lastname, setLastname] = useState(""); const [error, setError] = useState(""); const theme = useCustomTheme(); @@ -34,12 +36,12 @@ export const UsernameForm = ({ const json = await res.json(); if (!res.ok) throw new Error(json.message || "There was an error"); - onNext(username); + onNext(username, firstname, lastname); } catch (err: any) { setError(err.message); } }, - [username] + [username, firstname, lastname] ); return ( @@ -73,6 +75,46 @@ export const UsernameForm = ({ marginBottom: "16px", }} > + + { + setFirstname( + e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, "") + ); + }} + error={error ? true : false} + errorMessage={error} + /> + + + { + setLastname( + e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, "") + ); + }} + error={error ? true : false} + errorMessage={error} + /> + ) => { - const { inviteCode, userId, username, keyringType } = data; + const { inviteCode, userId, username, keyringType, firstname, lastname } = + data; // If userId is provided, then we are onboarding via the recover flow. if (userId) { @@ -312,6 +317,8 @@ export function OnboardingProvider({ // const body = JSON.stringify({ username, + firstname, + lastname, inviteCode, waitlistId: getWaitlistId?.(), blockchainPublicKeys,