File tree Expand file tree Collapse file tree 8 files changed +62
-47
lines changed
Expand file tree Collapse file tree 8 files changed +62
-47
lines changed Original file line number Diff line number Diff line change @@ -14,6 +14,8 @@ export type ValidationResult = {
1414 errorMessage ?: string ;
1515} ;
1616
17+ export type IsValidResponse = true | string | { warning : string } ;
18+
1719export type Validation < T > = {
1820 /**
1921 * Zod schema to validate the input value against.
@@ -28,7 +30,7 @@ export type Validation<T> = {
2830 * @param thisPopup the current modal
2931 * @returns true if the `value` is valid, an errorMessage as string if it is invalid.
3032 */
31- isValid ?: ( value : T ) => Promise < true | string | { warning : string } > ;
33+ isValid ?: ( value : T ) => Promise < IsValidResponse > ;
3234
3335 /** custom debounce delay for `isValid` call. defaults to 100 */
3436 debounceDelay ?: number ;
Original file line number Diff line number Diff line change 11import Ape from "../ape" ;
22import * as DB from "../db" ;
3+ import { IsValidResponse } from "../elements/input-validation" ;
34import * as Settings from "../pages/settings" ;
45import AnimatedModal , { ShowOptions } from "../utils/animated-modal" ;
56import { SimpleModal , TextInput } from "../utils/simple-modal" ;
67import { TagNameSchema } from "@monkeytype/schemas/users" ;
78
89const cleanTagName = ( tagName : string ) : string => tagName . replaceAll ( " " , "_" ) ;
9- const tagNameValidation = async ( tagName : string ) : Promise < true | string > => {
10+ const tagNameValidation = async ( tagName : string ) : Promise < IsValidResponse > => {
1011 const validationResult = TagNameSchema . safeParse ( cleanTagName ( tagName ) ) ;
1112 if ( validationResult . success ) return true ;
1213 return validationResult . error . errors . map ( ( err ) => err . message ) . join ( ", " ) ;
Original file line number Diff line number Diff line change @@ -16,6 +16,7 @@ import AnimatedModal from "../utils/animated-modal";
1616import { resetIgnoreAuthCallback } from "../firebase" ;
1717import { validateWithIndicator } from "../elements/input-validation" ;
1818import { UserNameSchema } from "@monkeytype/schemas/users" ;
19+ import { remoteValidation } from "../utils/remote-validation" ;
1920
2021let signedInUser : UserCredential | undefined = undefined ;
2122
@@ -154,17 +155,10 @@ function disableInput(): void {
154155
155156validateWithIndicator ( nameInputEl , {
156157 schema : UserNameSchema ,
157- isValid : async ( name : string ) => {
158- const checkNameResponse = await Ape . users . getNameAvailability ( {
159- params : { name : name } ,
160- } ) ;
161-
162- return (
163- ( checkNameResponse . status === 200 &&
164- checkNameResponse . body . data . available ) ||
165- "Name not available"
166- ) ;
167- } ,
158+ isValid : remoteValidation (
159+ async ( name ) => Ape . users . getNameAvailability ( { params : { name } } ) ,
160+ { check : ( data ) => data . available || "Name not available" }
161+ ) ,
168162 debounceDelay : 1000 ,
169163 callback : ( result ) => {
170164 if ( result . status === "success" ) {
Original file line number Diff line number Diff line change @@ -45,6 +45,7 @@ import {
4545import { goToPage } from "../pages/leaderboards" ;
4646import FileStorage from "../utils/file-storage" ;
4747import { z } from "zod" ;
48+ import { remoteValidation } from "../utils/remote-validation" ;
4849
4950type PopupKey =
5051 | "updateEmail"
@@ -479,17 +480,10 @@ list.updateName = new SimpleModal({
479480 initVal : "" ,
480481 validation : {
481482 schema : UserNameSchema ,
482- isValid : async ( newName : string ) => {
483- const checkNameResponse = await Ape . users . getNameAvailability ( {
484- params : { name : newName } ,
485- } ) ;
486-
487- return (
488- ( checkNameResponse . status === 200 &&
489- checkNameResponse . body . data . available ) ||
490- "Name not available"
491- ) ;
492- } ,
483+ isValid : remoteValidation (
484+ async ( name ) => Ape . users . getNameAvailability ( { params : { name } } ) ,
485+ { check : ( data ) => data . available || "Name not available" }
486+ ) ,
493487 debounceDelay : 1000 ,
494488 } ,
495489 } ,
Original file line number Diff line number Diff line change @@ -29,6 +29,7 @@ import { Connection } from "@monkeytype/schemas/connections";
2929import { Friend , UserNameSchema } from "@monkeytype/schemas/users" ;
3030import * as Loader from "../elements/loader" ;
3131import { LocalStorageWithSchema } from "../utils/local-storage-with-schema" ;
32+ import { remoteValidation } from "../utils/remote-validation" ;
3233
3334const pageElement = $ ( ".page.pageFriends" ) ;
3435
@@ -75,17 +76,10 @@ const addFriendModal = new SimpleModal({
7576 initVal : "" ,
7677 validation : {
7778 schema : UserNameSchema ,
78- isValid : async ( name : string ) => {
79- const checkNameResponse = await Ape . users . getNameAvailability ( {
80- params : { name : name } ,
81- } ) ;
82-
83- return (
84- ( checkNameResponse . status === 200 &&
85- ! checkNameResponse . body . data . available ) ||
86- "Unknown user"
87- ) ;
88- } ,
79+ isValid : remoteValidation (
80+ async ( name ) => Ape . users . getNameAvailability ( { params : { name } } ) ,
81+ { check : ( data ) => ! data . available || "Unknown user" }
82+ ) ,
8983 debounceDelay : 1000 ,
9084 } ,
9185 } ,
Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ import {
1010import { validateWithIndicator } from "../elements/input-validation" ;
1111import { isDevEnvironment } from "../utils/misc" ;
1212import { z } from "zod" ;
13+ import { remoteValidation } from "../utils/remote-validation" ;
1314
1415let registerForm : {
1516 name ?: string ;
@@ -73,17 +74,10 @@ const nameInputEl = document.querySelector(
7374) as HTMLInputElement ;
7475validateWithIndicator ( nameInputEl , {
7576 schema : UserNameSchema ,
76- isValid : async ( name : string ) => {
77- const checkNameResponse = await Ape . users . getNameAvailability ( {
78- params : { name : name } ,
79- } ) ;
80-
81- return (
82- ( checkNameResponse . status === 200 &&
83- checkNameResponse . body . data . available ) ||
84- "Name not available"
85- ) ;
86- } ,
77+ isValid : remoteValidation (
78+ async ( name ) => Ape . users . getNameAvailability ( { params : { name } } ) ,
79+ { check : ( data ) => data . available || "Name not available" }
80+ ) ,
8781 debounceDelay : 1000 ,
8882 callback : ( result ) => {
8983 registerForm . name =
Original file line number Diff line number Diff line change 1+ import { IsValidResponse } from "../elements/input-validation" ;
2+
3+ type IsValidResonseOrFunction =
4+ | ( ( message : string ) => IsValidResponse )
5+ | IsValidResponse ;
6+ export function remoteValidation < V , T > (
7+ call : (
8+ val : V
9+ ) => Promise < { status : number ; body : { data ?: T ; message : string } } > ,
10+ options ?: {
11+ check ?: ( data : T ) => IsValidResponse ;
12+ on4xx ?: IsValidResonseOrFunction ;
13+ on5xx ?: IsValidResonseOrFunction ;
14+ }
15+ ) : ( val : V ) => Promise < IsValidResponse > {
16+ return async ( val ) => {
17+ const result = await call ( val ) ;
18+ if ( result . status <= 299 ) {
19+ return options ?. check ?.( result . body . data as T ) ?? true ;
20+ }
21+
22+ let handler : IsValidResonseOrFunction | undefined ;
23+ if ( result . status <= 499 ) {
24+ handler = options ?. on4xx ?? ( ( message ) => message ) ;
25+ } else {
26+ handler = options ?. on5xx ?? "Server unavailable. Please try again later." ;
27+ }
28+
29+ if ( typeof handler === "function" ) return handler ( result . body . message ) ;
30+ return handler ;
31+ } ;
32+ }
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import * as Loader from "../elements/loader";
55import * as Notifications from "../elements/notifications" ;
66import * as ConnectionState from "../states/connection" ;
77import {
8+ IsValidResponse ,
89 Validation ,
910 ValidationOptions ,
1011 ValidationResult ,
@@ -33,7 +34,10 @@ type CommonInput<TType, TValue> = {
3334 * @param thisPopup the current modal
3435 * @returns true if the `value` is valid, an errorMessage as string if it is invalid.
3536 */
36- isValid ?: ( value : string , thisPopup : SimpleModal ) => Promise < true | string > ;
37+ isValid ?: (
38+ value : string ,
39+ thisPopup : SimpleModal
40+ ) => Promise < IsValidResponse > ;
3741 } ;
3842} ;
3943
You can’t perform that action at this time.
0 commit comments