mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 23:19:39 -05:00
Allow users to unlink their x rank placements from profile
This commit is contained in:
parent
0f62f6a88a
commit
34f4af5547
|
|
@ -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();
|
||||
}
|
||||
40
app/features/top-search/actions/xsearch.player.$id.server.ts
Normal file
40
app/features/top-search/actions/xsearch.player.$id.server.ts
Normal 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");
|
||||
};
|
||||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
||||
|
|
|
|||
|
|
@ -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}`);
|
||||
Loading…
Reference in New Issue
Block a user