import { is, predicates } from "@sealcode/ts-predicates"; import { Context } from "koa"; import { SimpleInput } from "../controls/simple-input.js"; import { FormDataValue } from "../form-types.js"; import { FieldParseResult, FormField } from "./field.js"; export class NumberField< DefaultValue extends number | null = number, Required extends boolean = boolean, > extends FormField { constructor( required: Required, public default_value: DefaultValue, public options: Partial<{ max: number; min: number; decimalDigits: number; }> = {} ) { super(required); } predicate = predicates.number; public async isValueValid(_: Context, value: unknown) { if ( (is(value, predicates.string) && !isNaN(parseFloat(value)) && parseFloat(value).toString() == value.trim()) || is(value, predicates.number) || ((is(value, predicates.undefined) || value == "") && !this.required) ) { return { valid: true, message: "" }; } return { valid: false, message: "Proszę wprowadzić liczbę" }; } async parse( _: Context, value: FormDataValue ): Promise> { if ( (is(value, predicates.string) && !isNaN(parseFloat(value)) && parseFloat(value).toString() == value.trim()) || is(value, predicates.number) ) { return { parsable: true, parsed_value: this.options.decimalDigits ? parseFloat( parseFloat(value.toString()).toFixed( this.options.decimalDigits ) ) : parseFloat(value.toString()), error: null, }; } else { return { parsable: false, parsed_value: null, error: "Please enter a number", }; } } public getEmptyValue(): DefaultValue { return this.default_value; } getControl(): SimpleInput { return new SimpleInput(this as FormField, { type: "number", }); } }