Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c623967
refactor(profile): migrate edit profile modal to SolidJS
AzureNightlock May 3, 2026
26e124c
impr(submit-button): use isDefaultValue instead of isDirty
AzureNightlock May 7, 2026
77106d8
add indicator to TextareaField
AzureNightlock May 11, 2026
dfce5cb
merge refactor/edit-profile-modal
AzureNightlock May 11, 2026
33c9836
temp
AzureNightlock May 11, 2026
f893afc
add twitter validation change
AzureNightlock May 11, 2026
24ca977
refactor(profile): migrate edit profile modal to SolidJS
AzureNightlock May 12, 2026
e08acdf
lint fix
AzureNightlock May 12, 2026
22b496a
refactor badge selection
fehmer May 12, 2026
666c430
fix roundness on none badge, fix snapshot usage
fehmer May 12, 2026
d2ad2e2
Merge branch 'master' into refactor/edit-profile-modal
fehmer May 12, 2026
c83c30f
fix snapshot not updating
fehmer May 12, 2026
2b6d247
resize user badge
AzureNightlock May 13, 2026
0b03a53
fix badge not getting updated, public profile showing outdated inform…
fehmer May 13, 2026
d8ed4dd
fix hover on badge selector
fehmer May 13, 2026
8c7629e
add none to badge-controller
fehmer May 13, 2026
08edfa7
cosmetics
fehmer May 13, 2026
379168a
use null
AzureNightlock May 14, 2026
be14ca9
remove selectedBadgeId from user.spec.ts
AzureNightlock May 14, 2026
a882dac
Revert "remove selectedBadgeId from user.spec.ts"
fehmer May 14, 2026
82d62b3
Revert "use null"
fehmer May 14, 2026
05ea82c
Merge branch 'master' into refactor/edit-profile-modal
fehmer May 19, 2026
9bef970
Merge branch 'master' into refactor/edit-profile-modal
fehmer May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/__tests__/api/controllers/result.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ describe("result controller test", () => {
xp: 0,
dailyXpBonus: false,
xpBreakdown: {
configMultiplier: 0,
accPenalty: 28,
base: 20,
incomplete: 5,
Expand Down
4 changes: 2 additions & 2 deletions backend/__tests__/api/controllers/user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3347,7 +3347,7 @@ describe("user controller test", () => {
bio: new Array(251).fill("x").join(""),
keyboard: new Array(76).fill("x").join(""),
socialProfiles: {
twitter: new Array(21).fill("x").join(""),
twitter: new Array(16).fill("x").join(""),
github: new Array(40).fill("x").join(""),
website:
"https://" +
Expand All @@ -3362,7 +3362,7 @@ describe("user controller test", () => {
validationErrors: [
'"bio" String must contain at most 250 character(s)',
'"keyboard" String must contain at most 75 character(s)',
'"socialProfiles.twitter" String must contain at most 20 character(s)',
'"socialProfiles.twitter" String must contain at most 15 character(s)',
'"socialProfiles.github" String must contain at most 39 character(s)',
'"socialProfiles.website" String must contain at most 200 character(s)',
],
Expand Down
14 changes: 13 additions & 1 deletion backend/src/api/controllers/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,18 @@ export async function addResult(
streak,
);

if (isNaN(xpGained.xp)) {
Comment thread
fehmer marked this conversation as resolved.
throw new MonkeyError(
500,
"Calculated XP is NaN",
JSON.stringify({
xpGained,
result: completedEvent,
}),
uid,
);
}

if (xpGained.xp < 0) {
throw new MonkeyError(
500,
Expand Down Expand Up @@ -813,7 +825,7 @@ async function calculateXp(
const totalXp =
Math.round((xpAfterAccuracy + incompleteXp) * gainMultiplier) + dailyBonus;

if (gainMultiplier > 1) {
if (gainMultiplier !== 1) {
// breakdown.push([
// "configMultiplier",
// Math.round((xpAfterAccuracy + incompleteXp) * (gainMultiplier - 1)),
Expand Down
18 changes: 8 additions & 10 deletions frontend/__tests__/components/ui/form/SubmitButton.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ import { render, screen } from "@solidjs/testing-library";
import { JSXElement } from "solid-js";
import { describe, it, expect } from "vitest";

import { SubmitButton } from "../../../../src/ts/components/ui/form/SubmitButton";
import {
FormStateSlice,
SubmitButton,
} from "../../../../src/ts/components/ui/form/SubmitButton";

type FormState = {
canSubmit: boolean;
isSubmitting: boolean;
isValid: boolean;
isDirty: boolean;
};
type FormState = FormStateSlice;

function makeForm(state: Partial<FormState> = {}) {
const fullState: FormState = {
canSubmit: true,
isSubmitting: false,
isValid: true,
isDirty: true,
isDefaultValue: false,
...state,
};

Expand All @@ -39,9 +37,9 @@ describe("SubmitButton", () => {
expect(screen.getByRole("button")).toHaveAttribute("type", "submit");
});

it("disables when form is not dirty", () => {
it("disables when form is unchanged", () => {
render(() => (
<SubmitButton form={makeForm({ isDirty: false })} text="Save" />
<SubmitButton form={makeForm({ isDefaultValue: true })} text="Save" />
));
expect(screen.getByRole("button")).toBeDisabled();
});
Expand Down
75 changes: 0 additions & 75 deletions frontend/src/html/popups.html
Original file line number Diff line number Diff line change
Expand Up @@ -349,78 +349,3 @@
<div class="suggestions"></div>
</div>
</dialog>

<dialog id="editProfileModal" class="modalWrapper hidden">
<form class="modal">
<div class="title">Edit Profile</div>
<div>
<label>name</label>
<div>
To update your name, go to Account Settings > Account > Update account
name
</div>
</div>
<div>
<label>avatar</label>
<div>
To update your avatar make sure your Discord account is linked, then go
to Account Settings > Account > Discord Integration and click "Update
Avatar"
</div>
</div>
<div>
<label>bio</label>
<textarea class="bio" autocomplete="off" maxlength="250"></textarea>
</div>
<div>
<label>keyboard</label>
<textarea class="keyboard" autocomplete="off" maxlength="75"></textarea>
</div>
<div>
<label>github</label>
<div class="socialURL">
<p>https://github.com/</p>
<input
class="github"
type="text"
value=""
placeholder="username"
maxlength="39"
/>
</div>
</div>
<div>
<label>twitter</label>
<div class="socialURL">
<p>https://x.com/</p>
<input
class="twitter"
type="text"
value=""
placeholder="username"
maxlength="20"
/>
</div>
</div>
<div>
<label>website</label>
<input class="website" type="text" value="" maxlength="200" />
</div>
<div>
<label>badge</label>
<div class="badgeSelectionContainer"></div>
</div>
<div>
<label>public activity</label>
<label class="checkbox">
<input
class="editProfileShowActivityOnPublicProfile"
type="checkbox"
checked
/>
<span>Include test activity graph on your public profile.</span>
</label>
</div>
<button class="edit-profile-submit" type="submit">save</button>
</form>
</dialog>
59 changes: 0 additions & 59 deletions frontend/src/styles/popups.scss
Original file line number Diff line number Diff line change
Expand Up @@ -658,62 +658,3 @@ body.darkMode {
}
}
}

#editProfileModal {
.modal {
max-width: 600px;
max-height: 100%;
label {
color: var(--sub-color);
margin-bottom: 0.25em;
display: block;
}
input:not([type="checkbox"]) {
width: 100%;
}
input[type="checkbox"] {
vertical-align: text-bottom;
}
textarea {
resize: vertical;
width: 100%;
padding: 10px;
line-height: 1.2rem;
min-height: 5rem;
max-height: 10rem;
}

.socialURL {
display: flex;
}

.socialURL > p {
margin-block: 0.5rem;
margin-inline-end: 0.5rem;
}

.badgeSelectionContainer {
display: flex;
flex-wrap: wrap;
}

.badgeSelectionItem {
width: max-content;
opacity: 25%;
cursor: pointer;
margin-right: 0.5rem;
margin-bottom: 0.5rem;
padding: 0;
border-radius: calc(var(--roundness) / 2);
}

.badgeSelectionItem.selected,
.badgeSelectionItem:hover {
opacity: 100%;
}

span {
color: var(--text-color);
}
}
}
38 changes: 38 additions & 0 deletions frontend/src/ts/components/common/BadgeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { badges, UserBadge } from "../../controllers/badge-controller";

export function BadgeButton(props: {
Comment thread
fehmer marked this conversation as resolved.
Outdated
id: number;
selected: boolean;
onClick: () => void;
}) {
const badge = (): UserBadge | undefined =>
props.id !== -1 ? badges[props.id] : undefined;

return (
<button
type="button"
class="mr-2 mb-2 w-max cursor-pointer rounded-half p-0"
classList={{
"opacity-100": props.selected,
"opacity-25 hover:opacity-100": !props.selected,
}}
onClick={() => props.onClick()}
>
<div
class="badge"
style={
badge()
? {
background: badge()?.background,
color: badge()?.color,
...badge()?.customStyle,
}
: undefined
}
>
<i class={`fas ${badge()?.icon ?? "fa-frown-open"}`}></i>
<div class="text">{badge()?.name ?? "none"}</div>
</div>
</button>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function CustomTestDurationModal(): JSXElement {
form={form}
variant="button"
text="apply"
skipDirtyCheck
skipUnchangedCheck
/>
</form>
</AnimatedModal>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/components/modals/CustomTextModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ export function CustomTextModal(): JSXElement {
</div>
<SubmitButton
form={form}
skipDirtyCheck
skipUnchangedCheck
variant="button"
text="ok"
class="lg:col-start-1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function CustomWordAmountModal(): JSXElement {
form={form}
variant="button"
text="apply"
skipDirtyCheck
skipUnchangedCheck
/>
</form>
</AnimatedModal>
Expand Down
Loading
Loading