import { useState, useEffect, useRef } from 'react';
import { NumberInput, NumberDisplay, Slider, FieldValueList, CurrencyDisplay, Text, withConfiguration } from '@pega/cosmos-react-core';
import type { PConnFieldProps } from './PConnProps';
import './create-nonce';
// includes in bundle
import handleEvent from "./event-utils";
import { suggestionsHandler } from './suggestions-handler';
import StyledPegaDxilMyIntegerWrapper from './styles';
// interface for props
interface PegaDxilMyIntegerProps extends PConnFieldProps {
// If any, enter additional props that only exist on TextInput here
displayAs?: string;
defaultValue: number;
isTableFormatter?: boolean;
hasSuggestions?: boolean;
variant?: any;
formatter: string;
decimalPrecision: string;
allowDecimals: boolean;
currencyISOCode: string;
alwaysShowISOCode: boolean;
additionalProps: any;
showGroupSeparators: boolean;
currencyDisplay: 'symbol' | 'code' | 'name' | undefined;
negative: 'minus-sign' | 'parentheses' | undefined;
notation: 'standard' | 'compact' | undefined;
currencyDecimalPrecision: string;
showInput: boolean;
min: number;
max: number;
step: number;
showTicks: boolean;
}
// interface for StateProps object
interface StateProps {
value: string;
hasSuggestions: boolean;
}
// Duplicated runtime code from Constellation Design System Component
// props passed in combination of props from property panel (config.json) and run time props from Constellation
// any default values in config.pros should be set in defaultProps at bottom of this file
function PegaDxilMyInteger(props: PegaDxilMyIntegerProps) {
const {
getPConnect,
value,
defaultValue,
placeholder,
validatemessage,
label,
hideLabel = false,
helperText,
testId,
displayMode,
displayAs,
showInput = true,
min = 0,
max = 100,
step = 1,
showTicks = true,
additionalProps = {},
variant = 'inline',
formatter = 'defaultInteger',
negative = 'minus-sign',
notation = 'standard',
isTableFormatter = false,
hasSuggestions = false
} = props;
let { showGroupSeparators = false } = props;
let { currencyDisplay = 'symbol' } = props;
const pConn = getPConnect();
const actions = pConn.getActionsApi();
const stateProps = pConn.getStateProps() as StateProps;
const propName: string = stateProps.value;
const [integerValue, setIntegerValue] = useState(value?.toString());
const sliderDefaultValue = !defaultValue && defaultValue !== 0 ? max : defaultValue;
const hasValueChange = useRef(false);
let { readOnly = false, required = false, disabled = false } = props;
[readOnly, required, disabled] = [readOnly, required, disabled].map(
(prop) => prop === true || (typeof prop === 'string' && prop === 'true')
);
const [status, setStatus] = useState(hasSuggestions ? 'pending' : '');
useEffect(() => {
if (validatemessage !== '') {
setStatus('error');
}
if (hasSuggestions) {
setStatus('pending');
} else if (!hasSuggestions && status !== 'success') {
// @ts-ignore
setStatus(validatemessage !== '' ? 'error' : undefined);
}
}, [validatemessage, hasSuggestions, status]);
useEffect(() => {
setIntegerValue(value?.toString());
}, [value]);
useEffect(() => {
if (displayAs === 'slider' && value === '') {
handleEvent(actions, 'change', propName, sliderDefaultValue);
}
}, [actions, displayAs, propName, sliderDefaultValue, value]);
const { decimalPrecision, currencyDecimalPrecision = 'auto', currencyISOCode = 'USD' } = props;
let noOfDecimals : number | undefined = parseInt(decimalPrecision, 10);
if (Number.isNaN(noOfDecimals)) noOfDecimals = undefined;
let noOfFractionDigits = currencyDecimalPrecision === 'auto' ? undefined : parseInt(currencyDecimalPrecision, 10);
let unit;
if (['LABELS_LEFT', 'STACKED_LARGE_VAL', 'DISPLAY_ONLY'].includes(displayMode as string)) {
switch (formatter) {
case 'Decimal': {
break;
}
case 'Percentage': {
showGroupSeparators = false;
unit = '%';
break;
}
case 'Decimal-Auto': {
noOfDecimals = Number.isInteger(integerValue) ? 0 : 2;
break;
}
default: {
noOfDecimals = 0;
break;
}
}
if (isTableFormatter && displayMode === 'LABELS_LEFT') {
showGroupSeparators = true;
noOfFractionDigits = undefined;
if (formatter === 'Currency-Code') {
currencyDisplay = 'code';
}
}
const displayComp =
formatter === 'Currency' || formatter === 'Currency-Code' ? (
) : (
);
switch (displayMode) {
case 'DISPLAY_ONLY': {
return ( {displayComp} );
}
case 'LABELS_LEFT': {
return (
);
}
case 'STACKED_LARGE_VAL': {
return (
{displayComp}
)
}
]}
/>
);
}
// no default
}
}
function onChangeHandler(enteredValue: any) {
if (hasSuggestions) {
setStatus('');
}
setIntegerValue(enteredValue);
// const parsedValue = integerValue !== '' ? Number(integerValue) : '';
if (value !== (enteredValue !== '' ? Number(enteredValue) : '')) {
handleEvent(actions, 'change', propName, enteredValue !== '' ? Number(enteredValue) : '');
hasValueChange.current = true;
}
// In case of stepper variation there is no blur event as component is never focussed unless forced. Need to update redux on change.
if (displayAs === 'stepper') {
handleEvent(actions, 'changeNblur', propName, enteredValue !== '' ? Number(enteredValue) : '');
}
}
const onResolveSuggestionHandler = (accepted: boolean) => {
suggestionsHandler(accepted, pConn, setStatus);
};
return displayAs === 'slider' ? (
{
onChangeHandler(selectedValue.toString());
handleEvent(actions, 'changeNblur', propName, selectedValue);
}}
/>
) : (
{
onChangeHandler(enteredValue);
}}
onBlur={() => {
if (!readOnly && (hasValueChange.current || !value)) {
handleEvent(actions, 'blur', propName, integerValue !== '' ? Number(integerValue) : '');
if (hasSuggestions) {
pConn.ignoreSuggestion('');
}
hasValueChange.current = false;
}
}}
onResolveSuggestion={onResolveSuggestionHandler}
/>
);
}
export default withConfiguration(PegaDxilMyInteger);