From 34c1b0e71a6ba0c3bc1255bc6406e8ca987d22a2 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Thu, 29 Sep 2022 23:26:25 +0300 Subject: [PATCH] User custom url, ign & sens initial --- app/constants.ts | 7 +- app/db/models/users/queries.server.ts | 13 ++- app/db/models/users/updateProfile.sql | 8 +- app/db/types.ts | 4 + app/routes/u.$identifier/edit.tsx | 116 +++++++++++++++++++------- app/utils/zod.ts | 6 ++ migrations/008-user-new-fields.js | 19 +++++ 7 files changed, 140 insertions(+), 33 deletions(-) create mode 100644 migrations/008-user-new-fields.js diff --git a/app/constants.ts b/app/constants.ts index 4e6db3697..87b464e14 100644 --- a/app/constants.ts +++ b/app/constants.ts @@ -5,7 +5,12 @@ import type { BuildAbilitiesTupleWithUnknown } from "./modules/in-game-lists"; export const TWEET_LENGTH_MAX_LENGTH = 280; export const DISCORD_MESSAGE_MAX_LENGTH = 2000; -export const USER_BIO_MAX_LENGTH = DISCORD_MESSAGE_MAX_LENGTH; +export const USER = { + BIO_MAX_LENGTH: DISCORD_MESSAGE_MAX_LENGTH, + CUSTOM_URL_MAX_LENGTH: 32, + IN_GAME_NAME_TEXT_MAX_LENGTH: 10, + IN_GAME_NAME_DISCRIMINATOR_LENGTH: 4, +}; export const PlUS_SUGGESTION_FIRST_COMMENT_MAX_LENGTH = 500; export const PlUS_SUGGESTION_COMMENT_MAX_LENGTH = TWEET_LENGTH_MAX_LENGTH; diff --git a/app/db/models/users/queries.server.ts b/app/db/models/users/queries.server.ts index 5c77ca888..6fd31fb62 100644 --- a/app/db/models/users/queries.server.ts +++ b/app/db/models/users/queries.server.ts @@ -30,7 +30,18 @@ export function upsert( } const updateProfileStm = sql.prepare(updateProfileSql); -export function updateProfile(args: Pick) { +export function updateProfile( + args: Pick< + User, + | "country" + | "id" + | "bio" + | "customUrl" + | "motionSens" + | "stickSens" + | "inGameName" + > +) { updateProfileStm.run(args); } diff --git a/app/db/models/users/updateProfile.sql b/app/db/models/users/updateProfile.sql index 64ab8628f..803911640 100644 --- a/app/db/models/users/updateProfile.sql +++ b/app/db/models/users/updateProfile.sql @@ -2,6 +2,10 @@ update "User" set "country" = @country, - "bio" = @bio + "bio" = @bio, + "customUrl" = @customUrl, + "stickSens" = @stickSens, + "motionSens" = @motionSens, + "inGameName" = @inGameName where - "id" = @id \ No newline at end of file + "id" = @id diff --git a/app/db/types.ts b/app/db/types.ts index 72a0c8f75..f5fdfdf5e 100644 --- a/app/db/types.ts +++ b/app/db/types.ts @@ -12,6 +12,10 @@ export interface User { youtubeId: string | null; bio: string | null; country: string | null; + customUrl: string | null; + stickSens: number | null; + motionSens: number | null; + inGameName: string | null; patronTier: number | null; patronSince: number | null; } diff --git a/app/routes/u.$identifier/edit.tsx b/app/routes/u.$identifier/edit.tsx index fd85fa9c2..011e1bad5 100644 --- a/app/routes/u.$identifier/edit.tsx +++ b/app/routes/u.$identifier/edit.tsx @@ -17,7 +17,7 @@ import { z } from "zod"; import { Button } from "~/components/Button"; import { Label } from "~/components/Label"; import { Main } from "~/components/Main"; -import { USER_BIO_MAX_LENGTH } from "~/constants"; +import { USER } from "~/constants"; import { db } from "~/db"; import { type User } from "~/db/types"; import { requireUser } from "~/modules/auth"; @@ -25,7 +25,7 @@ import { i18next } from "~/modules/i18n"; import styles from "~/styles/u-edit.css"; import { translatedCountry } from "~/utils/i18n.server"; import { parseRequestFormData } from "~/utils/remix"; -import { falsyToNull } from "~/utils/zod"; +import { falsyToNull, undefinedToNull } from "~/utils/zod"; import { type UserPageLoaderData } from "../u.$identifier"; export const links: LinksFunction = () => { @@ -44,18 +44,64 @@ const userEditActionSchema = z.object({ ), bio: z.preprocess( falsyToNull, - z.string().max(USER_BIO_MAX_LENGTH).nullable() + z.string().max(USER.BIO_MAX_LENGTH).nullable() + ), + customUrl: z.preprocess( + falsyToNull, + z + .string() + .max(USER.CUSTOM_URL_MAX_LENGTH) + .refine( + (val) => val === null || Number.isNaN(Number(val)), + // xxx: translate + "Name in the custom URL can't only contain numbers" + ) + .nullable() + ), + stickSens: z.preprocess( + undefinedToNull, + z + .number() + .min(-50) + .max(50) + .refine((val) => val % 5 === 0) + .nullable() + ), + motionSens: z.preprocess( + undefinedToNull, + z + .number() + .min(-50) + .max(50) + .refine((val) => val % 5 === 0) + .nullable() + ), + inGameNameText: z.preprocess( + falsyToNull, + z.string().max(USER.IN_GAME_NAME_TEXT_MAX_LENGTH).nullable() + ), + inGameNameDiscriminator: z.preprocess( + falsyToNull, + z.string().length(USER.IN_GAME_NAME_DISCRIMINATOR_LENGTH).nullable() ), }); export const action: ActionFunction = async ({ request }) => { - const data = await parseRequestFormData({ - request, - schema: userEditActionSchema, - }); + const { inGameNameText, inGameNameDiscriminator, ...data } = + await parseRequestFormData({ + request, + schema: userEditActionSchema, + }); const user = await requireUser(request); - db.users.updateProfile({ ...data, id: user.id }); + db.users.updateProfile({ + ...data, + inGameName: + inGameNameText && inGameNameDiscriminator + ? `${inGameNameText}#${inGameNameDiscriminator}` + : null, + id: user.id, + }); return null; }; @@ -79,8 +125,7 @@ export const loader = async ({ request }: LoaderArgs) => { }; export default function UserEditPage() { - const data = useLoaderData(); - const { t } = useTranslation(["common", "user"]); + const { t } = useTranslation(["common"]); const [, parentRoute] = useMatches(); invariant(parentRoute); const parentRouteData = parentRoute.data as UserPageLoaderData; @@ -89,23 +134,7 @@ export default function UserEditPage() { return (
-
- - -
+