diff --git a/frontend/src/components/Locality/Tabs/ClimateTab.tsx b/frontend/src/components/Locality/Tabs/ClimateTab.tsx
index 76af2635..361add3f 100755
--- a/frontend/src/components/Locality/Tabs/ClimateTab.tsx
+++ b/frontend/src/components/Locality/Tabs/ClimateTab.tsx
@@ -129,9 +129,12 @@ export const ClimateTab = () => {
]
const pollenRecord = [
- ['Arboreal pollen (AP%)', textField('pers_pollen_ap', { type: 'number' })],
- ['Non-arboreal pollen (NAP%)', textField('pers_pollen_nap', { type: 'number' })],
- ['Other pollen (OP%)', textField('pers_pollen_other', { type: 'number' })],
+ ['Arboreal pollen (AP%)', textField('pers_pollen_ap', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ [
+ 'Non-arboreal pollen (NAP%)',
+ textField('pers_pollen_nap', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
+ ['Other pollen (OP%)', textField('pers_pollen_other', { type: 'number', integerOnly: true, min: 0, max: 100 })],
]
const pollenTotalError = ['pers_pollen_ap', 'pers_pollen_nap', 'pers_pollen_other']
diff --git a/frontend/src/components/Locality/Tabs/EcometricsTab.tsx b/frontend/src/components/Locality/Tabs/EcometricsTab.tsx
index 12bc1fdb..787bca56 100755
--- a/frontend/src/components/Locality/Tabs/EcometricsTab.tsx
+++ b/frontend/src/components/Locality/Tabs/EcometricsTab.tsx
@@ -13,8 +13,11 @@ export const EcometricsTab = () => {
textField('estimate_precip', { type: 'number', integerOnly: true, min: 0 }),
],
['Estimate of mean annual temperature (°C)', textField('estimate_temp', { type: 'number' })],
- ['Estimate of net primary productivity (g/m2/yr)', textField('estimate_npp', { type: 'number' })],
- ['Woody cover percentage', textField('pers_woody_cover', { type: 'number' })],
+ [
+ 'Estimate of net primary productivity (g/m2/yr)',
+ textField('estimate_npp', { type: 'number', integerOnly: true, min: 0 }),
+ ],
+ ['Woody cover percentage', textField('pers_woody_cover', { type: 'number', integerOnly: true, min: 0, max: 100 })],
]
return (
diff --git a/frontend/src/components/Locality/Tabs/LocalityTab.tsx b/frontend/src/components/Locality/Tabs/LocalityTab.tsx
index 2f5a7699..8f753758 100755
--- a/frontend/src/components/Locality/Tabs/LocalityTab.tsx
+++ b/frontend/src/components/Locality/Tabs/LocalityTab.tsx
@@ -135,7 +135,7 @@ export const LocalityTab = () => {
'Approximate Coordinates'
),
],
- ['Altitude (m)', textField('altitude')],
+ ['Altitude (m)', textField('altitude', { type: 'number', integerOnly: true, min: -500, max: 9000 })],
]
const { notify } = useNotify()
diff --git a/frontend/src/components/Locality/Tabs/TaphonomyTab.tsx b/frontend/src/components/Locality/Tabs/TaphonomyTab.tsx
index 857b831a..192dbed6 100755
--- a/frontend/src/components/Locality/Tabs/TaphonomyTab.tsx
+++ b/frontend/src/components/Locality/Tabs/TaphonomyTab.tsx
@@ -118,9 +118,9 @@ export const TaphonomyTab = () => {
const taphonomy = [
['Time Represented (years)', dropdown('time_rep', timeRepresentedOptions, 'Time Represented (years)')],
['Vertebrate Preservation', dropdown('vert_pres', vertebratePreservationOptions, 'Vertebrate Preservation')],
- ['Approx. Number of Specimens', textField('appr_num_spm', { type: 'number' })],
- ['Exact Number of Specimens', textField('num_spm', { type: 'number' })],
- ['Number of Quadrats', textField('num_quad', { type: 'number' })],
+ ['Approx. Number of Specimens', textField('appr_num_spm', { type: 'number', integerOnly: true, min: 1 })],
+ ['Exact Number of Specimens', textField('num_spm', { type: 'number', integerOnly: true, min: 1 })],
+ ['Number of Quadrats', textField('num_quad', { type: 'number', integerOnly: true, min: 1 })],
['Unbiased Collecting', dropdown('true_quant', unbiasedCollectingOptions, 'Unbiased Collecting')],
['Species List Complete', dropdown('complete', speciesListCompleteOptions, 'Species List Complete')],
]
diff --git a/frontend/src/components/Occurrence/Tabs/OccurrenceCoreTab.tsx b/frontend/src/components/Occurrence/Tabs/OccurrenceCoreTab.tsx
index 67421ae5..90209194 100644
--- a/frontend/src/components/Occurrence/Tabs/OccurrenceCoreTab.tsx
+++ b/frontend/src/components/Occurrence/Tabs/OccurrenceCoreTab.tsx
@@ -43,10 +43,19 @@ export const OccurrenceCoreTab = () => {
key="counts"
title="Occurrence counts"
array={[
- ['NISP', mode.read ? toText(sourceData.nis) : textField('nis', { type: 'number' })],
+ [
+ 'NISP',
+ mode.read ? toText(sourceData.nis) : textField('nis', { type: 'number', integerOnly: true, min: 1 }),
+ ],
['Percent', mode.read ? toText(sourceData.pct) : textField('pct', { type: 'number' })],
- ['Quadrate', mode.read ? toText(sourceData.quad) : textField('quad', { type: 'number' })],
- ['MNI', mode.read ? toText(sourceData.mni) : textField('mni', { type: 'number' })],
+ [
+ 'Quadrate',
+ mode.read ? toText(sourceData.quad) : textField('quad', { type: 'number', integerOnly: true, min: 1 }),
+ ],
+ [
+ 'MNI',
+ mode.read ? toText(sourceData.mni) : textField('mni', { type: 'number', integerOnly: true, min: 1 }),
+ ],
['Quantity', mode.read ? formatQuantity(sourceData.qua) : dropdown('qua', quantityOptions, 'Quantity')],
]}
/>,
@@ -54,7 +63,12 @@ export const OccurrenceCoreTab = () => {
diff --git a/frontend/src/components/Occurrence/Tabs/OccurrenceIsotopeTab.tsx b/frontend/src/components/Occurrence/Tabs/OccurrenceIsotopeTab.tsx
index aafb23d5..91967682 100644
--- a/frontend/src/components/Occurrence/Tabs/OccurrenceIsotopeTab.tsx
+++ b/frontend/src/components/Occurrence/Tabs/OccurrenceIsotopeTab.tsx
@@ -16,7 +16,12 @@ export const OccurrenceIsotopeTab = () => {
title="δ13C"
array={[
['Mean', mode.read ? toText(sourceData.dc13_mean) : textField('dc13_mean', { type: 'number' })],
- ['N', mode.read ? toText(sourceData.dc13_n) : textField('dc13_n', { type: 'number' })],
+ [
+ 'N',
+ mode.read
+ ? toText(sourceData.dc13_n)
+ : textField('dc13_n', { type: 'number', integerOnly: true, min: 1 }),
+ ],
['Max', mode.read ? toText(sourceData.dc13_max) : textField('dc13_max', { type: 'number' })],
['Min', mode.read ? toText(sourceData.dc13_min) : textField('dc13_min', { type: 'number' })],
['Stdev', mode.read ? toText(sourceData.dc13_stdev) : textField('dc13_stdev', { type: 'number' })],
@@ -27,7 +32,12 @@ export const OccurrenceIsotopeTab = () => {
title="δ18O"
array={[
['Mean', mode.read ? toText(sourceData.do18_mean) : textField('do18_mean', { type: 'number' })],
- ['N', mode.read ? toText(sourceData.do18_n) : textField('do18_n', { type: 'number' })],
+ [
+ 'N',
+ mode.read
+ ? toText(sourceData.do18_n)
+ : textField('do18_n', { type: 'number', integerOnly: true, min: 1 }),
+ ],
['Max', mode.read ? toText(sourceData.do18_max) : textField('do18_max', { type: 'number' })],
['Min', mode.read ? toText(sourceData.do18_min) : textField('do18_min', { type: 'number' })],
['Stdev', mode.read ? toText(sourceData.do18_stdev) : textField('do18_stdev', { type: 'number' })],
diff --git a/frontend/src/components/Occurrence/Tabs/OccurrenceWearTab.tsx b/frontend/src/components/Occurrence/Tabs/OccurrenceWearTab.tsx
index 9ae7e8d2..3a3780ca 100644
--- a/frontend/src/components/Occurrence/Tabs/OccurrenceWearTab.tsx
+++ b/frontend/src/components/Occurrence/Tabs/OccurrenceWearTab.tsx
@@ -33,11 +33,36 @@ export const OccurrenceWearTab = () => {
'Mesowear',
mode.read ? formatMesowear(sourceData.mesowear) : dropdown('mesowear', mesowearOptions, 'Mesowear'),
],
- ['MW OR High', mode.read ? toText(sourceData.mw_or_high) : textField('mw_or_high', { type: 'number' })],
- ['MW OR Low', mode.read ? toText(sourceData.mw_or_low) : textField('mw_or_low', { type: 'number' })],
- ['MW CS Sharp', mode.read ? toText(sourceData.mw_cs_sharp) : textField('mw_cs_sharp', { type: 'number' })],
- ['MW CS Round', mode.read ? toText(sourceData.mw_cs_round) : textField('mw_cs_round', { type: 'number' })],
- ['MW CS Blunt', mode.read ? toText(sourceData.mw_cs_blunt) : textField('mw_cs_blunt', { type: 'number' })],
+ [
+ 'MW OR High',
+ mode.read
+ ? toText(sourceData.mw_or_high)
+ : textField('mw_or_high', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
+ [
+ 'MW OR Low',
+ mode.read
+ ? toText(sourceData.mw_or_low)
+ : textField('mw_or_low', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
+ [
+ 'MW CS Sharp',
+ mode.read
+ ? toText(sourceData.mw_cs_sharp)
+ : textField('mw_cs_sharp', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
+ [
+ 'MW CS Round',
+ mode.read
+ ? toText(sourceData.mw_cs_round)
+ : textField('mw_cs_round', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
+ [
+ 'MW CS Blunt',
+ mode.read
+ ? toText(sourceData.mw_cs_blunt)
+ : textField('mw_cs_blunt', { type: 'number', integerOnly: true, min: 0, max: 100 }),
+ ],
]}
/>,
@@ -47,11 +72,15 @@ export const OccurrenceWearTab = () => {
array={[
[
'MW scale min',
- mode.read ? toText(sourceData.mw_scale_min) : textField('mw_scale_min', { type: 'number' }),
+ mode.read
+ ? toText(sourceData.mw_scale_min)
+ : textField('mw_scale_min', { type: 'number', integerOnly: true, min: 0 }),
],
[
'MW scale max',
- mode.read ? toText(sourceData.mw_scale_max) : textField('mw_scale_max', { type: 'number' }),
+ mode.read
+ ? toText(sourceData.mw_scale_max)
+ : textField('mw_scale_max', { type: 'number', integerOnly: true, min: 0 }),
],
['MW value', mode.read ? toText(sourceData.mw_value) : textField('mw_value', { type: 'number' })],
['Normalized Score', normalizedScoreText],
diff --git a/frontend/src/components/Reference/Tabs/ReferenceTab.tsx b/frontend/src/components/Reference/Tabs/ReferenceTab.tsx
index fa86be68..7f13dd23 100755
--- a/frontend/src/components/Reference/Tabs/ReferenceTab.tsx
+++ b/frontend/src/components/Reference/Tabs/ReferenceTab.tsx
@@ -98,9 +98,13 @@ export const ReferenceTab = () => {
? bigTextField(field.field_name! as keyof ReferenceDetailsType)
: textField(field.field_name! as keyof ReferenceDetailsType)
if (field.field_name && numberFields.includes(field.field_name)) {
+ const isPageField = field.field_name === 'start_page' || field.field_name === 'end_page'
nonAuthorFieldsArray.push([
field.ref_field_name,
- textField(field.field_name as keyof ReferenceDetailsType, { type: 'number' }),
+ textField(field.field_name as keyof ReferenceDetailsType, {
+ type: 'number',
+ ...(isPageField ? { integerOnly: true, min: 1 } : {}),
+ }),
])
} else if (field.field_name == 'exact_date') {
nonAuthorFieldsArray.push([
diff --git a/frontend/src/components/Species/Tabs/SizeTab.tsx b/frontend/src/components/Species/Tabs/SizeTab.tsx
index 11d8631b..a48d03fc 100755
--- a/frontend/src/components/Species/Tabs/SizeTab.tsx
+++ b/frontend/src/components/Species/Tabs/SizeTab.tsx
@@ -26,8 +26,8 @@ export const SizeTab = () => {
]
const size = [
- ['Body Mass (g)', textField('body_mass', { type: 'number' })],
- ['Brain Mass (g)', textField('brain_mass', { type: 'number' })],
+ ['Body Mass (g)', textField('body_mass', { type: 'number', integerOnly: true, min: 1 })],
+ ['Brain Mass (g)', textField('brain_mass', { type: 'number', integerOnly: true, min: 1 })],
['Snout-Vent Length', dropdown('sv_length', snoutVentLengthOptions, 'Snout-Vent Length')],
]
diff --git a/frontend/src/components/Species/Tabs/TeethTab.tsx b/frontend/src/components/Species/Tabs/TeethTab.tsx
index ddf9eea3..bb94b0a0 100755
--- a/frontend/src/components/Species/Tabs/TeethTab.tsx
+++ b/frontend/src/components/Species/Tabs/TeethTab.tsx
@@ -135,13 +135,13 @@ export const TeethTab = () => {
const mesowear = [
['Mesowear'],
['Type', dropdown('mesowear', mesowearOptions, 'Type')],
- ['Cusp Relief Low (OR%)', textField('mw_or_low', { type: 'number' })],
- ['Cusp Relief High (OR%)', textField('mw_or_high', { type: 'number' })],
- ['Cusp Shape Sharp (CS%)', textField('mw_cs_sharp', { type: 'number' })],
- ['Cusp Shape Rounded (CS%)', textField('mw_cs_round', { type: 'number' })],
- ['Cusp Shape Blunt (CS%)', textField('mw_cs_blunt', { type: 'number' })],
- ['Scale Minimum', textField('mw_scale_min', { type: 'number' })],
- ['Scale Maximum', textField('mw_scale_max', { type: 'number' })],
+ ['Cusp Relief Low (OR%)', textField('mw_or_low', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ ['Cusp Relief High (OR%)', textField('mw_or_high', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ ['Cusp Shape Sharp (CS%)', textField('mw_cs_sharp', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ ['Cusp Shape Rounded (CS%)', textField('mw_cs_round', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ ['Cusp Shape Blunt (CS%)', textField('mw_cs_blunt', { type: 'number', integerOnly: true, min: 0, max: 100 })],
+ ['Scale Minimum', textField('mw_scale_min', { type: 'number', integerOnly: true, min: 0 })],
+ ['Scale Maximum', textField('mw_scale_max', { type: 'number', integerOnly: true, min: 0 })],
['Reported Value', textField('mw_value', { type: 'number' })],
[
'Normalized score',
diff --git a/frontend/src/shared/validators/locality.ts b/frontend/src/shared/validators/locality.ts
index 3ceec71a..d1684b0e 100755
--- a/frontend/src/shared/validators/locality.ts
+++ b/frontend/src/shared/validators/locality.ts
@@ -15,7 +15,18 @@ const validatePollenPercentage = (name: string, num: number) => {
}
const validateNonNegativeInteger = (name: string, num: number) => {
- if (!Number.isInteger(num) || num < 0) return `${name} must be a positive integer.`
+ if (!Number.isInteger(num) || num < 0) return `${name} must be a non-negative integer.`
+ return
+}
+
+const validateIntegerInRange = (name: string, num: number, min: number, max: number) => {
+ if (!Number.isInteger(num)) return `${name} must be an integer value`
+ if (num < min || num > max) return `${name} must be between ${min} and ${max}`
+ return
+}
+
+const validatePositiveInteger = (name: string, num: number) => {
+ if (!Number.isInteger(num) || num < 1) return `${name} must be a positive integer.`
return
}
@@ -202,6 +213,30 @@ export const validateLocality = (
name: 'Estimate of annual precipitation (mm)',
asNumber: (num: number) => validateNonNegativeInteger('Estimate of annual precipitation (mm)', num),
},
+ altitude: {
+ name: 'Altitude (m)',
+ asNumber: (num: number) => validateIntegerInRange('Altitude (m)', num, -500, 9000),
+ },
+ appr_num_spm: {
+ name: 'Approx. Number of Specimens',
+ asNumber: (num: number) => validatePositiveInteger('Approx. Number of Specimens', num),
+ },
+ num_spm: {
+ name: 'Exact Number of Specimens',
+ asNumber: (num: number) => validatePositiveInteger('Exact Number of Specimens', num),
+ },
+ num_quad: {
+ name: 'Number of Quadrats',
+ asNumber: (num: number) => validatePositiveInteger('Number of Quadrats', num),
+ },
+ estimate_npp: {
+ name: 'Estimate of net primary productivity (g/m2/yr)',
+ asNumber: (num: number) => validateNonNegativeInteger('Estimate of net primary productivity (g/m2/yr)', num),
+ },
+ pers_woody_cover: {
+ name: 'Woody cover percentage',
+ asNumber: (num: number) => validateIntegerInRange('Woody cover percentage', num, 0, 100),
+ },
}
return validator
>(validators, editData, fieldName)
diff --git a/frontend/src/shared/validators/occurrence.ts b/frontend/src/shared/validators/occurrence.ts
index a2623717..e9c2495e 100644
--- a/frontend/src/shared/validators/occurrence.ts
+++ b/frontend/src/shared/validators/occurrence.ts
@@ -23,6 +23,17 @@ const validatePositiveInteger = (name: string, value: number) => {
return
}
+const validateNonNegativeInteger = (name: string, value: number) => {
+ if (!Number.isInteger(value) || value < 0) return `${name} must be a non-negative integer.`
+ return
+}
+
+const validateIntegerInRange = (name: string, value: number, min: number, max: number) => {
+ if (!Number.isInteger(value)) return `${name} must be a whole number.`
+ if (value < min || value > max) return `${name} must be between ${min} and ${max}.`
+ return
+}
+
const validatePositiveDecimal = (name: string, value: number) => {
if (!Number.isFinite(value) || value <= 0) return `${name} must be a positive decimal number.`
return
@@ -61,15 +72,15 @@ export const validateOccurrence = (editData: EditableOccurrenceData, fieldName:
body_mass: { name: 'Body mass', asNumber: value => validatePositiveInteger('Body mass', value) },
dc13_n: { name: 'δ13C N', asNumber: value => validatePositiveInteger('δ13C N', value) },
do18_n: { name: 'δ18O N', asNumber: value => validatePositiveInteger('δ18O N', value) },
- mw_or_high: { name: 'MW OR High', asNumber: value => validatePositiveInteger('MW OR High', value) },
- mw_or_low: { name: 'MW OR Low', asNumber: value => validatePositiveInteger('MW OR Low', value) },
- mw_cs_sharp: { name: 'MW CS Sharp', asNumber: value => validatePositiveInteger('MW CS Sharp', value) },
- mw_cs_round: { name: 'MW CS Round', asNumber: value => validatePositiveInteger('MW CS Round', value) },
- mw_cs_blunt: { name: 'MW CS Blunt', asNumber: value => validatePositiveInteger('MW CS Blunt', value) },
+ mw_or_high: { name: 'MW OR High', asNumber: value => validateIntegerInRange('MW OR High', value, 0, 100) },
+ mw_or_low: { name: 'MW OR Low', asNumber: value => validateIntegerInRange('MW OR Low', value, 0, 100) },
+ mw_cs_sharp: { name: 'MW CS Sharp', asNumber: value => validateIntegerInRange('MW CS Sharp', value, 0, 100) },
+ mw_cs_round: { name: 'MW CS Round', asNumber: value => validateIntegerInRange('MW CS Round', value, 0, 100) },
+ mw_cs_blunt: { name: 'MW CS Blunt', asNumber: value => validateIntegerInRange('MW CS Blunt', value, 0, 100) },
mw_scale_min: {
name: 'Scale Minimum',
asNumber: value => {
- const positivityError = validatePositiveInteger('Scale Minimum', value)
+ const positivityError = validateNonNegativeInteger('Scale Minimum', value)
if (positivityError) return positivityError
if (hasNumericValue(editData.mw_scale_max) && value > editData.mw_scale_max)
return 'Scale Minimum cannot be greater than Scale Maximum.'
@@ -79,7 +90,7 @@ export const validateOccurrence = (editData: EditableOccurrenceData, fieldName:
mw_scale_max: {
name: 'Scale Maximum',
asNumber: value => {
- const positivityError = validatePositiveInteger('Scale Maximum', value)
+ const positivityError = validateNonNegativeInteger('Scale Maximum', value)
if (positivityError) return positivityError
if (hasNumericValue(editData.mw_scale_min) && value < editData.mw_scale_min)
return 'Scale Maximum cannot be less than Scale Minimum.'
diff --git a/frontend/src/shared/validators/reference.ts b/frontend/src/shared/validators/reference.ts
index 3bbe8ac5..15a8a26c 100755
--- a/frontend/src/shared/validators/reference.ts
+++ b/frontend/src/shared/validators/reference.ts
@@ -109,6 +109,13 @@ const yearCheck: (year: number) => ValidationError = (year: number) => {
return null
}
+const positiveIntegerCheck: (name: string, num: number) => ValidationError = (name: string, num: number) => {
+ if (!Number.isFinite(num)) return `${name} must be a valid number`
+ if (!Number.isInteger(num)) return `${name} must be a whole number`
+ if (num < 1) return `${name} must be a positive integer`
+ return null
+}
+
export type ReferenceFieldDisplayNames = Partial, string>>
export type ReferenceDisplayLabelMap = Partial>
@@ -217,12 +224,19 @@ export const validateReference = (
start_page: {
name: 'start_page',
required: false,
- asNumber: true,
+ asNumber: (num: number) => positiveIntegerCheck('start_page', num),
},
end_page: {
name: 'end_page',
required: false,
- asNumber: true,
+ asNumber: (num: number) => {
+ const base = positiveIntegerCheck('end_page', num)
+ if (base) return base
+ if (typeof editData.start_page === 'number' && num < editData.start_page) {
+ return 'end_page must be greater than or equal to start_page'
+ }
+ return null
+ },
},
date_secondary: {
name: 'date_secondary',
diff --git a/frontend/src/shared/validators/species.ts b/frontend/src/shared/validators/species.ts
index 91f9202f..abe59569 100755
--- a/frontend/src/shared/validators/species.ts
+++ b/frontend/src/shared/validators/species.ts
@@ -11,6 +11,22 @@ export const validateSpecies = (
editData: EditDataType,
fieldName: keyof EditDataType
) => {
+ const validatePositiveInteger = (name: string, value: number) => {
+ if (!Number.isInteger(value) || value < 1) return `${name} must be a positive integer.`
+ return
+ }
+
+ const validateNonNegativeInteger = (name: string, value: number) => {
+ if (!Number.isInteger(value) || value < 0) return `${name} must be a non-negative integer.`
+ return
+ }
+
+ const validateIntegerInRange = (name: string, value: number, min: number, max: number) => {
+ if (!Number.isInteger(value)) return `${name} must be a whole number.`
+ if (value < min || value > max) return `${name} must be between ${min} and ${max}.`
+ return
+ }
+
const validators: Validators>> = {
subclass_or_superorder_name: {
name: 'Subclass or Superorder',
@@ -103,11 +119,40 @@ export const validateSpecies = (
return
},
},
+ body_mass: {
+ name: 'Body Mass (g)',
+ asNumber: (value: number) => validatePositiveInteger('Body Mass (g)', value),
+ },
+ brain_mass: {
+ name: 'Brain Mass (g)',
+ asNumber: (value: number) => validatePositiveInteger('Brain Mass (g)', value),
+ },
+ mw_or_low: {
+ name: 'Cusp Relief Low (OR%)',
+ asNumber: (value: number) => validateIntegerInRange('Cusp Relief Low (OR%)', value, 0, 100),
+ },
+ mw_or_high: {
+ name: 'Cusp Relief High (OR%)',
+ asNumber: (value: number) => validateIntegerInRange('Cusp Relief High (OR%)', value, 0, 100),
+ },
+ mw_cs_sharp: {
+ name: 'Cusp Shape Sharp (CS%)',
+ asNumber: (value: number) => validateIntegerInRange('Cusp Shape Sharp (CS%)', value, 0, 100),
+ },
+ mw_cs_round: {
+ name: 'Cusp Shape Rounded (CS%)',
+ asNumber: (value: number) => validateIntegerInRange('Cusp Shape Rounded (CS%)', value, 0, 100),
+ },
+ mw_cs_blunt: {
+ name: 'Cusp Shape Blunt (CS%)',
+ asNumber: (value: number) => validateIntegerInRange('Cusp Shape Blunt (CS%)', value, 0, 100),
+ },
mw_scale_min: {
name: 'Scale Minimum',
asNumber: (value: number) => {
- if (value < 0) return 'Scale Minimum cannot be negative.'
+ const nonNegativeError = validateNonNegativeInteger('Scale Minimum', value)
+ if (nonNegativeError) return nonNegativeError
if (typeof editData.mw_scale_max === 'number' && value > editData.mw_scale_max)
return 'Scale Minimum cannot be greater than Scale Maximum.'
return
@@ -116,7 +161,8 @@ export const validateSpecies = (
mw_scale_max: {
name: 'Scale Maximum',
asNumber: (value: number) => {
- if (value < 0) return 'Scale Maximum cannot be negative.'
+ const nonNegativeError = validateNonNegativeInteger('Scale Maximum', value)
+ if (nonNegativeError) return nonNegativeError
if (typeof editData.mw_scale_min === 'number' && value < editData.mw_scale_min)
return 'Scale Maximum cannot be less than Scale Minimum.'
return