Allow users to unlink their x rank placements from profile

This commit is contained in:
Kalle 2025-04-09 22:27:55 +03:00
parent 0f62f6a88a
commit 34f4af5547
5 changed files with 83 additions and 19 deletions

View File

@ -0,0 +1,9 @@
import { db } from "~/db/sql";
export function unlinkPlayerByUserId(userId: number) {
return db
.updateTable("SplatoonPlayer")
.set({ userId: null })
.where("SplatoonPlayer.userId", "=", userId)
.execute();
}

View File

@ -0,0 +1,40 @@
import type { ActionFunctionArgs } from "@remix-run/node";
import { requireUser } from "~/features/auth/core/user.server";
import { syncXPBadges } from "~/features/badges/queries/syncXPBadges.server";
import { findPlacementsByPlayerId } from "~/features/top-search/queries/findPlacements.server";
import { logger } from "~/utils/logger";
import {
errorToastIfFalsy,
notFoundIfFalsy,
parseParams,
successToast,
} from "~/utils/remix.server";
import { idObject } from "~/utils/zod";
import * as SplatoonPlayerRepository from "../SplatoonPlayerRepository.server";
export const action = async ({ request, params }: ActionFunctionArgs) => {
const user = await requireUser(request);
const { id } = parseParams({
params,
schema: idObject,
});
const placements = notFoundIfFalsy(findPlacementsByPlayerId(id));
const currentLinkedUserDiscordId = placements[0].discordId;
errorToastIfFalsy(
currentLinkedUserDiscordId === user.discordId,
"This player is not linked to you",
);
logger.info("Unlinking player", {
id: id,
userId: user.id,
});
await SplatoonPlayerRepository.unlinkPlayerByUserId(user.id);
syncXPBadges();
return successToast("Unlink successful");
};

View File

@ -11,9 +11,14 @@ import {
userPage,
} from "~/utils/urls";
import { PlacementsTable } from "../components/Placements";
import { FormWithConfirm } from "~/components/FormWithConfirm";
import { SendouButton } from "~/components/elements/Button";
import { UnlinkIcon } from "~/components/icons/Unlink";
import { useUser } from "~/features/auth/core/user";
import { action } from "../actions/xsearch.player.$id.server";
import { loader } from "../loaders/xsearch.player.$id.server";
export { loader };
export { loader, action };
import "../top-search.css";
@ -58,9 +63,13 @@ export const meta: MetaFunction<typeof loader> = (args) => {
export default function XSearchPlayerPage() {
const { t } = useTranslation(["common"]);
const data = useLoaderData<typeof loader>();
const user = useUser();
const hasUserLinked = Boolean(data.placements[0].discordId);
const isLinkedToCurrentUser =
user && user?.discordId === data.placements[0].discordId;
return (
<Main halfWidth className="stack lg">
<div>
@ -79,6 +88,27 @@ export default function XSearchPlayerPage() {
) : null}
</div>
<PlacementsTable placements={data.placements} type="MODE_INFO" />
{isLinkedToCurrentUser ? <UnlinkFormWithButton /> : null}
</Main>
);
}
function UnlinkFormWithButton() {
const { t } = useTranslation(["common"]);
return (
<FormWithConfirm
dialogHeading={t("common:xsearch.unlink.title")}
deleteButtonText={t("common:xsearch.unlink.action.short")}
>
<SendouButton
icon={<UnlinkIcon />}
variant="destructive"
size="miniscule"
className="mt-2 self-start"
>
{t("common:xsearch.unlink.action.long")}
</SendouButton>
</FormWithConfirm>
);
}

View File

@ -250,6 +250,9 @@
"divisions.JPN": "Takoroka",
"xsearch.placements": "placements",
"xsearch.aliases": "Aliases:",
"xsearch.unlink.title": "Are you sure you want to unlink? This will remove placements from your profile as well as the associated badge (can only be relinked by sendou.ink staff)?",
"xsearch.unlink.action.long": "Unlink your user",
"xsearch.unlink.action.short": "Unlink",
"build.private": "Private",

View File

@ -1,18 +0,0 @@
import "dotenv/config";
import { sql } from "~/db/sql";
import invariant from "~/utils/invariant";
import { logger } from "~/utils/logger";
import { syncXPBadges } from "../app/features/badges/queries/syncXPBadges.server";
const discordId = process.argv[2]?.trim();
invariant(discordId, "discord id is required (argument 1)");
sql
.prepare(
'update "SplatoonPlayer" set userId = null where userId = (select id from "User" where discordId = @discordId)',
)
.run({ discordId });
syncXPBadges();
logger.info(`Unlinked player for discord id: ${discordId}`);