Campaign Ordering/Editing Posting Requirements Changes
We have received feedback from ATSs regarding currency input validations in posting requirements form for contracts.
For some posting requirements, HAPI Backend has float
rule and HAPI Backend Job Post Implementation Guide suggests this type of validation for such fields should be: float - numbers with optional comma (,) as a thousand separator and optional period (.) as a decimal point
however HAPI Elements was preventing the comma from being entered. Some examples for this case are Minimum salary (not displayed on ad)
and Maximum salary (not displayed on ad)
fields for Seek Australia
.
With changes introduced in version 3.1, user can now enter commas. Because there are numerous ways a user can enter commas, depending on their locale, HAPI Elements converts the output to what HAPI Backend expects. We do this conversion via an overlay 1.5
second(s) after user stopped typing via a timeout.
The overlay looks like:
We also fix mistakes that a user can make. List of valid inputs:
1.00
10.50
100.00
1,000.00
10,000.25
100,000.00
1,000,000.00
10,000,000.00
100,000,000.00
1,000,000,000.00
5,000,000,000.50
List of invalid inputs that are corrected:
1,00
comma replaced with dot1,000,00
last comma replaced with dot100,000,000,000,00
last comma replaced with dot10,000.000
last zero removed for 2 fraction digits1.000.000
first dot replaced with comma1,000,000.000
last zero removed for 2 fraction digits
Here is how the function works:
export const getOccurrenceOf = (str: string | undefined, char: string) => {
if (!str) {
return 0
}
const regex = new RegExp(`\\${char}`, "g") // Escape special characters
return (str.match(regex) || []).length
}
export const replaceFirstOccurrence = (
str: string | undefined,
targetChar: string,
replacementChar: string,
) => {
if (!str) {
return ""
}
const escapedChar = targetChar.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") // Escape special regex chars
return str.replace(new RegExp(escapedChar), replacementChar)
}
export const replaceLastOccurrence = (
str: string | undefined,
targetChar: string,
replacementChar: string,
) => {
if (!str) {
return ""
}
const escapedChar = targetChar.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") // Escape special regex chars
const lastIndex = str.lastIndexOf(escapedChar)
if (lastIndex === -1) return str // If char not found, return original string
return str.slice(0, lastIndex) + replacementChar + str.slice(lastIndex + 1)
}
export const getStringifiedNumberToFloatProperties = (
num: string | undefined,
) => {
const dotCount = getOccurrenceOf(num, ".")
const commaCount = getOccurrenceOf(num, ",")
const containsDots = dotCount > 0
const containsCommas = commaCount > 0
return { dotCount, commaCount, containsDots, containsCommas }
}
export const convertStringifiedNumberToFloat = (
num: string | undefined,
isRequired: boolean,
) => {
const defaultFloat = isRequired ? "0.00" : ""
if (!num || num.trim() === "") {
num = defaultFloat
}
const {
commaCount: commaCountForFixingWronglyFormatted,
dotCount: dotCountForFixingWronglyFormatted,
containsDots: containsDotsForFixingWronglyFormatted,
containsCommas: containsCommasForFixingWronglyFormatted,
} = getStringifiedNumberToFloatProperties(num)
// first fix wrongly formatted num
if (
commaCountForFixingWronglyFormatted > 1 &&
!containsDotsForFixingWronglyFormatted
) {
num = replaceLastOccurrence(num, ",", ".")
} else if (
dotCountForFixingWronglyFormatted > 1 &&
!containsCommasForFixingWronglyFormatted
) {
num = replaceFirstOccurrence(num, ".", ",")
}
const {
containsDots: containsDotsForIntlFix,
containsCommas: containsCommasForIntlFix,
} = getStringifiedNumberToFloatProperties(num)
if (containsCommasForIntlFix && containsDotsForIntlFix) {
num = num.replace(/,/g, "")
} else if (!containsDotsForIntlFix && containsCommasForIntlFix) {
num = num.replace(/,/g, ".")
}
const numberCastedString = Number(num)
if (num.trim() === "" || isNaN(numberCastedString)) {
return defaultFloat
}
const intlFormatted = new Intl.NumberFormat("en-US", {
style: "decimal",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(numberCastedString)
return intlFormatted
}
As part of this change, the following translations were added:
Key | "en" value | "de" value | "nl" value | "fr" value |
---|---|---|---|---|
common.field-should-be-float | This field can only contain numbers, dots and commas. | Dieses Feld darf nur Zahlen, Punkte und Kommas enthalten. | Dit veld kan alleen cijfers, punten en komma's bevatten. | Ce champ ne peut contenir que des chiffres, des points et des virgules. |
common.autocorrection-must-be-applied | Following auto-correction must be applied, click to apply | Folgende Autokorrektur muss angewendet werden, klicken Sie zum Anwenden | De volgende automatische correctie moet worden toegepast, klik om toe te passen | La correction automatique suivante doit être appliquée, cliquez pour appliquer |
common.diff-added-removed | Red indicates removed values, green indicates added values | Rot zeigt entfernte Werte, Grün zeigt hinzugefügte Werte | Rood geeft verwijderde waarden aan, groen geeft toegevoegde waarden aan | Le rouge indique les valeurs supprimées, le vert indique les valeurs ajoutées |