Fixes #839: Allow user to select favorite badge (#1345)

* temp save

* temp save

* temp save

* tempsave

* rollback

* temp save

* added combobox

* finish combobox, discard

* restore combobox

* page load successfully

* finish

* rm excessive changes

* fix prettier

* fix prettier again
This commit is contained in:
Zen
2023-04-20 04:50:07 +08:00
committed by GitHub
parent c670237e4c
commit 28ca966256
10 changed files with 78 additions and 2 deletions

View File

@@ -11,4 +11,6 @@ where
"BadgeOwner"."userId" = @userId
group by
"BadgeOwner"."badgeId",
"BadgeOwner"."userId"
"BadgeOwner"."userId"
order by
"Badge"."id" = (select "favoriteBadgeId" from "User" where "id" = @userId) desc, "Badge"."id" asc

View File

@@ -65,6 +65,7 @@ export const updateProfile = sql.transaction(
| "stickSens"
| "inGameName"
| "css"
| "favoriteBadgeId"
> & { weapons: MainWeaponId[] }) => {
deleteUserWeaponsStm.run({ userId: rest.id });
for (const [i, weaponSplId] of weapons.entries()) {

View File

@@ -7,6 +7,7 @@ set
"stickSens" = @stickSens,
"motionSens" = @motionSens,
"inGameName" = @inGameName,
"css" = @css
"css" = @css,
"favoriteBadgeId" = @favoriteBadgeId
where
"id" = @id returning *

View File

@@ -68,6 +68,7 @@ const basicSeeds = [
realVideo,
realVideoCast,
xRankPlacements,
userFavBadges,
];
export function seed() {
@@ -1176,3 +1177,16 @@ function xRankPlacements() {
}
})();
}
function userFavBadges() {
// randomly choose Sendou's favorite badge
const badgeList = shuffle(
sql
.prepare(`select "badgeId" from "BadgeOwner" where "userId" = 1`)
.all()
.map((row) => row.badgeId)
);
sql
.prepare(`update "User" set "favoriteBadgeId" = $id where "id" = 1`)
.run({ id: badgeList[0] });
}

View File

@@ -29,6 +29,7 @@ export interface User {
/** Used to overwrite normal patron giving process and force give the patron status till this date */
patronTill: number | null;
isVideoAdder: number;
favoriteBadgeId: number;
}
/** User table after joined with PlusTier table */

View File

@@ -93,6 +93,7 @@ export const loader = ({ params }: LoaderArgs) => {
country: user.country,
css: canAddCustomizedColorsToUserProfile(user) ? user.css : undefined,
badges: db.badges.countsByUserId(user.id),
favoriteBadgeId: user.favoriteBadgeId,
results: db.calendarEvents.findResultsByUserId(user.id),
buildsCount: db.builds.countByUserId(user.id),
vods: findVods({ userId: user.id }),

View File

@@ -122,6 +122,20 @@ const userEditActionSchema = z
)
.max(USER.WEAPON_POOL_MAX_SIZE)
),
favoriteBadgeId: z.preprocess(
processMany(actualNumber, undefinedToNull),
z
.number()
.refine((val) => {
// unable to hook here
// return parentRouteData.badges
// .map((badge) => badge.id)
// .concat(0)
// .includes(val);
return val >= 0;
})
.default(0)
),
})
.refine(
(val) => {
@@ -217,6 +231,7 @@ export default function UserEditPage() {
<InGameNameInputs parentRouteData={parentRouteData} />
<SensSelects parentRouteData={parentRouteData} />
<CountrySelect parentRouteData={parentRouteData} />
<FavBadgeSelect parentRouteData={parentRouteData} />
<WeaponPoolSelect parentRouteData={parentRouteData} />
<BioTextarea initialValue={parentRouteData.bio} />
<FormMessage type="info">
@@ -449,3 +464,37 @@ function BioTextarea({ initialValue }: { initialValue: User["bio"] }) {
</div>
);
}
function FavBadgeSelect({
parentRouteData,
}: {
parentRouteData: UserPageLoaderData;
}) {
const { t } = useTranslation(["user"]);
// user's current favorite badge is the initial value
const initialBadge = parentRouteData.badges.find(
(badge) => badge.id === parentRouteData.favoriteBadgeId
);
return (
<div>
<label htmlFor="favoriteBadgeId">{t("user:favoriteBadge")}</label>
<select
className=""
name="favoriteBadgeId"
id="favoriteBadgeId"
defaultValue={initialBadge ? initialBadge.id : 0}
>
<option key={0} value={0}>
{"-"}
</option>
{parentRouteData.badges.map((badge) => (
<option key={badge.id} value={badge.id}>
{`${badge.displayName}`}
</option>
))}
</select>
</div>
);
}

View File

@@ -0,0 +1,5 @@
module.exports.up = function (db) {
db.prepare(
/* sql */ `alter table "User" add "favoriteBadgeId" integer not null default 0`
).run();
};

View File

@@ -11,6 +11,7 @@
"sens": "Sens",
"weaponPool": "Weapon pool",
"discordExplanation": "Username, profile picture, YouTube, Twitter and Twitch accounts come from your Discord account. See <1>FAQ</1> for more information.",
"favoriteBadge": "Favorite Badge",
"results.title": "Results",
"results.placing": "Placing",

View File

@@ -11,6 +11,7 @@
"sens": "感度",
"weaponPool": "武器池",
"discordExplanation": "用户名、头像、Youtube、Twitter和Twitch账号皆来自你的Discord账号。查看 <1>FAQ</1> 以获得更多相关信息。",
"favoriteBadge": "最喜爱的徽章",
"results.title": "成绩",
"results.placing": "排名",