@iapps/ng-dhis2-ui 1.2.133 → 1.2.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -6536,6 +6536,157 @@ const CoordinatePickerField = ({ label, name, value, required, disabled, error,
|
|
|
6536
6536
|
React__default.createElement(Button$1, { primary: true, onClick: handleConfirmFromMap, disabled: !pendingCoordinate }, "Use Selected Location")))))));
|
|
6537
6537
|
};
|
|
6538
6538
|
|
|
6539
|
+
const ALL_COUNTRIES = [
|
|
6540
|
+
// East Africa first (for convenience)
|
|
6541
|
+
{ isoCode: 'TZ', dialCode: '+255', name: 'Tanzania', flag: '🇹🇿' },
|
|
6542
|
+
{ isoCode: 'KE', dialCode: '+254', name: 'Kenya', flag: '🇰🇪' },
|
|
6543
|
+
{ isoCode: 'UG', dialCode: '+256', name: 'Uganda', flag: '🇺🇬' },
|
|
6544
|
+
{ isoCode: 'RW', dialCode: '+250', name: 'Rwanda', flag: '🇷🇼' },
|
|
6545
|
+
{ isoCode: 'BI', dialCode: '+257', name: 'Burundi', flag: '🇧🇮' },
|
|
6546
|
+
{ isoCode: 'SS', dialCode: '+211', name: 'South Sudan', flag: '🇸🇸' },
|
|
6547
|
+
{ isoCode: 'ET', dialCode: '+251', name: 'Ethiopia', flag: '🇪🇹' },
|
|
6548
|
+
// A few examples from other regions:
|
|
6549
|
+
{ isoCode: 'GB', dialCode: '+44', name: 'United Kingdom', flag: '🇬🇧' },
|
|
6550
|
+
{ isoCode: 'US', dialCode: '+1', name: 'United States', flag: '🇺🇸' },
|
|
6551
|
+
{ isoCode: 'CA', dialCode: '+1', name: 'Canada', flag: '🇨🇦' },
|
|
6552
|
+
{ isoCode: 'DE', dialCode: '+49', name: 'Germany', flag: '🇩🇪' },
|
|
6553
|
+
{ isoCode: 'IN', dialCode: '+91', name: 'India', flag: '🇮🇳' },
|
|
6554
|
+
{ isoCode: 'CN', dialCode: '+86', name: 'China', flag: '🇨🇳' },
|
|
6555
|
+
{ isoCode: 'BR', dialCode: '+55', name: 'Brazil', flag: '🇧🇷' },
|
|
6556
|
+
// 👉 Here you add the rest of the world.
|
|
6557
|
+
// You can load a standard JSON of all countries (isoCode, dialCode, name, flag)
|
|
6558
|
+
// and generate this array at build time if you prefer.
|
|
6559
|
+
];
|
|
6560
|
+
|
|
6561
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
6562
|
+
const DEFAULT_COUNTRY_ISO = 'TZ';
|
|
6563
|
+
const FilterableSingleSelectField = SingleSelectField;
|
|
6564
|
+
function normalizeTanzaniaLocal(raw) {
|
|
6565
|
+
const digits = (raw || '').replace(/\D/g, '');
|
|
6566
|
+
if (!digits)
|
|
6567
|
+
return '';
|
|
6568
|
+
if (digits.startsWith('255')) {
|
|
6569
|
+
let sub = digits.slice(3);
|
|
6570
|
+
if (sub.startsWith('0'))
|
|
6571
|
+
sub = sub.slice(1);
|
|
6572
|
+
return ('0' + sub).slice(0, 10);
|
|
6573
|
+
}
|
|
6574
|
+
if (digits.startsWith('0')) {
|
|
6575
|
+
return digits.slice(0, 10);
|
|
6576
|
+
}
|
|
6577
|
+
if (/^[67]\d{7,9}$/.test(digits)) {
|
|
6578
|
+
return ('0' + digits).slice(0, 10);
|
|
6579
|
+
}
|
|
6580
|
+
if (digits.length >= 9 && !digits.startsWith('0')) {
|
|
6581
|
+
return ('0' + digits.slice(0, 9)).slice(0, 10);
|
|
6582
|
+
}
|
|
6583
|
+
return digits.slice(0, 10);
|
|
6584
|
+
}
|
|
6585
|
+
const InternationalPhoneField = ({ name, label, placeholder, value, required, disabled, error, validationText, inputWidth, defaultCountryIsoCode = DEFAULT_COUNTRY_ISO, onChange, onBlur, }) => {
|
|
6586
|
+
const [selectedIsoCode, setSelectedIsoCode] = React__default.useState(defaultCountryIsoCode);
|
|
6587
|
+
const [filterText, setFilterText] = React__default.useState('');
|
|
6588
|
+
const [leadingZeroWarning, setLeadingZeroWarning] = React__default.useState(null);
|
|
6589
|
+
const selectedCountry = ALL_COUNTRIES.find((c) => c.isoCode === selectedIsoCode) ??
|
|
6590
|
+
ALL_COUNTRIES.find((c) => c.isoCode === DEFAULT_COUNTRY_ISO);
|
|
6591
|
+
const [localNumber, setLocalNumber] = React__default.useState('');
|
|
6592
|
+
React__default.useEffect(() => {
|
|
6593
|
+
const raw = value ?? '';
|
|
6594
|
+
if (selectedCountry.isoCode === 'TZ') {
|
|
6595
|
+
const normalizedStored = normalizeTanzaniaLocal(raw);
|
|
6596
|
+
if (!normalizedStored) {
|
|
6597
|
+
setLocalNumber('');
|
|
6598
|
+
return;
|
|
6599
|
+
}
|
|
6600
|
+
const digits = normalizedStored.replace(/\D/g, '');
|
|
6601
|
+
const ui = digits.startsWith('0') ? digits.slice(1) : digits;
|
|
6602
|
+
setLocalNumber(ui);
|
|
6603
|
+
}
|
|
6604
|
+
else {
|
|
6605
|
+
const digits = raw.replace(/\D/g, '').slice(0, 15);
|
|
6606
|
+
setLocalNumber(digits);
|
|
6607
|
+
}
|
|
6608
|
+
setLeadingZeroWarning(null);
|
|
6609
|
+
}, [value, selectedCountry.isoCode]);
|
|
6610
|
+
const filteredCountries = React__default.useMemo(() => {
|
|
6611
|
+
const term = filterText.trim().toLowerCase();
|
|
6612
|
+
if (!term)
|
|
6613
|
+
return ALL_COUNTRIES;
|
|
6614
|
+
return ALL_COUNTRIES.filter((c) => {
|
|
6615
|
+
const haystack = `${c.name} ${c.dialCode} ${c.isoCode}`.toLowerCase();
|
|
6616
|
+
return haystack.includes(term);
|
|
6617
|
+
});
|
|
6618
|
+
}, [filterText]);
|
|
6619
|
+
const handleCountryChange = ({ selected }) => {
|
|
6620
|
+
setSelectedIsoCode(selected);
|
|
6621
|
+
};
|
|
6622
|
+
const handleLocalChange = ({ value }) => {
|
|
6623
|
+
const digitsOnly = (value || '').replace(/\D/g, '');
|
|
6624
|
+
if (selectedCountry.isoCode === 'TZ') {
|
|
6625
|
+
let ui = digitsOnly;
|
|
6626
|
+
if (ui.startsWith('0')) {
|
|
6627
|
+
setLeadingZeroWarning('For Tanzania, do not start the number with 0. Enter it without the leading 0 (e.g. 767000000).');
|
|
6628
|
+
ui = ui.slice(1);
|
|
6629
|
+
}
|
|
6630
|
+
else {
|
|
6631
|
+
setLeadingZeroWarning(null);
|
|
6632
|
+
}
|
|
6633
|
+
ui = ui.slice(0, 9);
|
|
6634
|
+
const stored = ui ? '0' + ui : '';
|
|
6635
|
+
setLocalNumber(ui);
|
|
6636
|
+
onChange(stored);
|
|
6637
|
+
}
|
|
6638
|
+
else {
|
|
6639
|
+
const ui = digitsOnly.slice(0, 15);
|
|
6640
|
+
setLocalNumber(ui);
|
|
6641
|
+
onChange(ui);
|
|
6642
|
+
setLeadingZeroWarning(null);
|
|
6643
|
+
}
|
|
6644
|
+
};
|
|
6645
|
+
const effectiveValidationText = leadingZeroWarning ??
|
|
6646
|
+
validationText ??
|
|
6647
|
+
'Enter the phone number without the leading 0 (e.g. 767000000). The country code is already applied, and the system will store it as 0767000000 for Tanzania.';
|
|
6648
|
+
const hasError = Boolean(error || leadingZeroWarning);
|
|
6649
|
+
const wrapperStyle = {
|
|
6650
|
+
maxWidth: typeof inputWidth === 'number' ? inputWidth : inputWidth || 480,
|
|
6651
|
+
display: 'flex',
|
|
6652
|
+
flexDirection: 'column',
|
|
6653
|
+
gap: '0.5rem',
|
|
6654
|
+
};
|
|
6655
|
+
return (React__default.createElement("div", { style: wrapperStyle },
|
|
6656
|
+
label && (React__default.createElement("label", { htmlFor: name, style: {
|
|
6657
|
+
fontSize: '0.875rem',
|
|
6658
|
+
fontWeight: 500,
|
|
6659
|
+
color: '#1f2933',
|
|
6660
|
+
} },
|
|
6661
|
+
label,
|
|
6662
|
+
required ? (React__default.createElement("span", { style: { color: '#e53935', marginLeft: 4 } }, "*")) : null)),
|
|
6663
|
+
React__default.createElement("div", { style: {
|
|
6664
|
+
display: 'flex',
|
|
6665
|
+
width: '100%',
|
|
6666
|
+
gap: '0.75rem',
|
|
6667
|
+
alignItems: 'stretch',
|
|
6668
|
+
} },
|
|
6669
|
+
React__default.createElement("div", { style: {
|
|
6670
|
+
flex: '0 0 auto',
|
|
6671
|
+
width: 260,
|
|
6672
|
+
} },
|
|
6673
|
+
React__default.createElement(FilterableSingleSelectField, { selected: selectedIsoCode, onChange: handleCountryChange, disabled: disabled, dense: true, filterable: true, onFilterChange: ({ value }) => setFilterText(value), noMatchText: "No matching country" }, filteredCountries.map((country) => (React__default.createElement(SingleSelectOption, { key: country.isoCode, value: country.isoCode, label: `${country.flag} ${country.name} (${country.dialCode})` }))))),
|
|
6674
|
+
React__default.createElement("div", { style: { flex: '1 1 0', minWidth: 0 } },
|
|
6675
|
+
React__default.createElement(InputField$1, { type: "tel", name: name, placeholder: placeholder ?? '767000000', value: localNumber, required: required, disabled: disabled, error: hasError, validationText: effectiveValidationText, autoComplete: "tel", max: selectedCountry.isoCode === 'TZ' ? '9' : '15', onChange: handleLocalChange, onBlur: () => {
|
|
6676
|
+
if (selectedCountry.isoCode === 'TZ') {
|
|
6677
|
+
const digits = (localNumber || '')
|
|
6678
|
+
.replace(/\D/g, '')
|
|
6679
|
+
.slice(0, 9);
|
|
6680
|
+
const stored = digits ? '0' + digits : '';
|
|
6681
|
+
if (digits !== localNumber) {
|
|
6682
|
+
setLocalNumber(digits);
|
|
6683
|
+
onChange(stored);
|
|
6684
|
+
}
|
|
6685
|
+
}
|
|
6686
|
+
onBlur?.();
|
|
6687
|
+
} })))));
|
|
6688
|
+
};
|
|
6689
|
+
|
|
6539
6690
|
// Copyright 2024 UDSM DHIS2 Lab. All rights reserved.
|
|
6540
6691
|
// Use of this source code is governed by a BSD-style
|
|
6541
6692
|
// license that can be found in the LICENSE file.
|
|
@@ -6661,7 +6812,6 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
6661
6812
|
value &&
|
|
6662
6813
|
value.length > 0 &&
|
|
6663
6814
|
touched)) {
|
|
6664
|
-
// if (this.field().unique && value && value.length > 0 && touched) {
|
|
6665
6815
|
setCheckingUniqueness(true);
|
|
6666
6816
|
setRecordExistError(undefined);
|
|
6667
6817
|
try {
|
|
@@ -6684,6 +6834,18 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
6684
6834
|
};
|
|
6685
6835
|
const formFieldContent = () => {
|
|
6686
6836
|
switch (this.field().controlType) {
|
|
6837
|
+
case 'number':
|
|
6838
|
+
return (React__default.createElement(InputField$1, { error: hasError, validationText: validationError, type: this.field().type, inputWidth: inputWidth, required: this.field().required, name: this.field().id, label: this.label(), min: this.field().min?.toString(), max: this.field().max?.toString(), placeholder: this.placeholder(), value: value, readOnly: disabled, onChange: (event) => {
|
|
6839
|
+
onValueChange(event.value);
|
|
6840
|
+
}, onBlur: () => {
|
|
6841
|
+
checkValueUniqueness();
|
|
6842
|
+
} }));
|
|
6843
|
+
case 'tel':
|
|
6844
|
+
return (React__default.createElement(InternationalPhoneField, { name: this.field().id, label: this.label(), placeholder: this.placeholder(), value: value ?? '', required: this.field().required, disabled: disabled, error: hasError, validationText: validationError, inputWidth: this.fieldConfig()?.inputWidth, defaultCountryIsoCode: "TZ", onChange: (localNumber) => {
|
|
6845
|
+
onValueChange(localNumber);
|
|
6846
|
+
}, onBlur: () => {
|
|
6847
|
+
checkValueUniqueness();
|
|
6848
|
+
} }));
|
|
6687
6849
|
case 'coordinate':
|
|
6688
6850
|
return (React__default.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
|
|
6689
6851
|
React__default.createElement(NoticeBox, { title: "Location capture required" },
|
|
@@ -6772,9 +6934,7 @@ class BaseFormFieldComponent extends ReactWrapperModule {
|
|
|
6772
6934
|
case 'date-time': {
|
|
6773
6935
|
const field = this.field();
|
|
6774
6936
|
const isDateTimeField = field.type === 'date-time';
|
|
6775
|
-
const inputType = isDateTimeField
|
|
6776
|
-
? 'datetime-local'
|
|
6777
|
-
: 'date';
|
|
6937
|
+
const inputType = isDateTimeField ? 'datetime-local' : 'date';
|
|
6778
6938
|
// Value coming from DHIS2 store
|
|
6779
6939
|
const htmlValue = this.formatValueForHtmlInputFromDhis(value, isDateTimeField);
|
|
6780
6940
|
const htmlMin = field.min
|
|
@@ -7780,9 +7940,9 @@ class FieldUtil {
|
|
|
7780
7940
|
case FieldType.TRUE_ONLY:
|
|
7781
7941
|
return 'checkbox';
|
|
7782
7942
|
case FieldType.NUMBER:
|
|
7783
|
-
return '
|
|
7943
|
+
return 'number';
|
|
7784
7944
|
case FieldType.PHONE_NUMBER:
|
|
7785
|
-
return '
|
|
7945
|
+
return 'tel';
|
|
7786
7946
|
case FieldType.ORG_UNIT:
|
|
7787
7947
|
return 'org-unit';
|
|
7788
7948
|
case FieldType.DATE:
|
|
@@ -7826,7 +7986,9 @@ class FieldControlTypeUtil {
|
|
|
7826
7986
|
case FieldType.TRUE_ONLY:
|
|
7827
7987
|
return 'checkbox';
|
|
7828
7988
|
case FieldType.NUMBER:
|
|
7829
|
-
return '
|
|
7989
|
+
return 'number';
|
|
7990
|
+
case FieldType.PHONE_NUMBER:
|
|
7991
|
+
return 'tel';
|
|
7830
7992
|
case FieldType.INTEGER_ZERO_OR_POSITIVE:
|
|
7831
7993
|
return 'textbox';
|
|
7832
7994
|
case FieldType.ORG_UNIT:
|
|
@@ -7864,6 +8026,8 @@ class FormFieldTypeUtil {
|
|
|
7864
8026
|
return 'coordinate';
|
|
7865
8027
|
case FieldType.DATE_TIME:
|
|
7866
8028
|
return 'date-time';
|
|
8029
|
+
case FieldType.PHONE_NUMBER:
|
|
8030
|
+
return 'tel';
|
|
7867
8031
|
default:
|
|
7868
8032
|
return 'text';
|
|
7869
8033
|
}
|