Skip to content

Commit 7d04637

Browse files
authored
impr: validate username on google signup (@fehmer) (monkeytypegame#6895)
1 parent 76597e6 commit 7d04637

File tree

1 file changed

+25
-54
lines changed

1 file changed

+25
-54
lines changed

frontend/src/ts/modals/google-sign-up.ts

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as Notifications from "../elements/notifications";
2-
import { debounce } from "throttle-debounce";
32
import {
43
sendEmailVerification,
54
updateProfile,
@@ -13,9 +12,10 @@ import * as AccountController from "../auth";
1312
import * as CaptchaController from "../controllers/captcha-controller";
1413
import * as Loader from "../elements/loader";
1514
import { subscribe as subscribeToSignUpEvent } from "../observables/google-sign-up-event";
16-
import { InputIndicator } from "../elements/input-indicator";
1715
import AnimatedModal from "../utils/animated-modal";
1816
import { resetIgnoreAuthCallback } from "../firebase";
17+
import { validateWithIndicator } from "../elements/input-validation";
18+
import { UserNameSchema } from "@monkeytype/schemas/users";
1919

2020
let signedInUser: UserCredential | undefined = undefined;
2121

@@ -140,73 +140,44 @@ function disableButton(): void {
140140
$("#googleSignUpModal button").prop("disabled", true);
141141
}
142142

143+
const nameInputEl = document.querySelector(
144+
"#googleSignUpModal input"
145+
) as HTMLInputElement;
146+
143147
function enableInput(): void {
144-
$("#googleSignUpModal input").prop("disabled", false);
148+
nameInputEl.disabled = false;
145149
}
146150

147151
function disableInput(): void {
148-
$("#googleSignUpModal input").prop("disabled", true);
152+
nameInputEl.disabled = true;
149153
}
150154

151-
const nameIndicator = new InputIndicator($("#googleSignUpModal input"), {
152-
available: {
153-
icon: "fa-check",
154-
level: 1,
155-
},
156-
unavailable: {
157-
icon: "fa-times",
158-
level: -1,
159-
},
160-
taken: {
161-
icon: "fa-user",
162-
level: -1,
155+
validateWithIndicator(nameInputEl, {
156+
schema: UserNameSchema,
157+
isValid: async (name: string) => {
158+
const checkNameResponse = (
159+
await Ape.users.getNameAvailability({
160+
params: { name: name },
161+
})
162+
).status;
163+
164+
return checkNameResponse === 200 ? true : "Name not available";
163165
},
164-
checking: {
165-
icon: "fa-circle-notch",
166-
spinIcon: true,
167-
level: 0,
166+
debounceDelay: 1000,
167+
callback: (result) => {
168+
if (result.status === "success") {
169+
enableButton();
170+
} else {
171+
disableButton();
172+
}
168173
},
169174
});
170175

171-
const checkNameDebounced = debounce(1000, async () => {
172-
const val = $("#googleSignUpModal input").val() as string;
173-
if (!val) return;
174-
const response = await Ape.users.getNameAvailability({
175-
params: { name: val },
176-
});
177-
178-
if (response.status === 200) {
179-
nameIndicator.show("available", response.body.message);
180-
enableButton();
181-
} else if (response.status === 422) {
182-
nameIndicator.show("unavailable", response.body.message);
183-
} else if (response.status === 409) {
184-
nameIndicator.show("taken", response.body.message);
185-
} else {
186-
nameIndicator.show("unavailable");
187-
Notifications.add(
188-
"Failed to check name availability: " + response.body.message,
189-
-1
190-
);
191-
}
192-
});
193-
194176
async function setup(modalEl: HTMLElement): Promise<void> {
195177
modalEl.addEventListener("submit", (e) => {
196178
e.preventDefault();
197179
void apply();
198180
});
199-
modalEl.querySelector("input")?.addEventListener("input", () => {
200-
disableButton();
201-
const val = $("#googleSignUpModal input").val() as string;
202-
if (val === "") {
203-
nameIndicator.hide();
204-
return;
205-
} else {
206-
nameIndicator.show("checking");
207-
checkNameDebounced();
208-
}
209-
});
210181
}
211182

212183
subscribeToSignUpEvent((signedInUser, isNewUser) => {

0 commit comments

Comments
 (0)