@commercetools-uikit/localized-money-input v20.0.0
LocalizedMoneyInput
Description
A controlled input component for localized money values with validation states.
Installation
yarn add @commercetools-uikit/localized-money-inputnpm --save install @commercetools-uikit/localized-money-inputAdditionally install the peer dependencies (if not present)
yarn add react react-dom react-intlnpm --save install react react-dom react-intlUsage
import LocalizedMoneyInput from '@commercetools-uikit/localized-money-input';
const Example = () => (
<LocalizedMoneyInput
value={{
USD: { currencyCode: 'USD', amount: '12.22' },
EUR: { currencyCode: 'EUR', amount: '41.44' },
}}
onChange={
(/** event */) => {
// alert(event.target.name, event.target.value)
}
}
/>
);
export default Example;Properties
| Props | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | Used as HTML id property. | ||
name | string | The prefix used to create a HTML name property for the amount input field (${name}.amount). | ||
value | Record | ✅ | value of possible currency the input doesn't accept a "currencies" prop, instead all possible currencies have to exist (with empty or filled strings) on the value: { EUR: {amount: '12.00', currencyCode: 'EUR'}, USD: {amount: '', currencyCode: 'USD'}} | |
onChange | FunctionSee signature. | Called with the event of the input. | ||
selectedCurrency | string | ✅ | the currently selected currency | |
onBlur | FunctionSee signature. | Called when input is blurred | ||
onFocus | FunctionSee signature. | Called when input is focused | ||
hideCurrencyExpansionControls | boolean | Will hide the currency expansion controls when set to true. All currencies will be shown when set to true. | ||
defaultExpandCurrencies | boolean | Controls whether one or all currencirs are visible by default | ||
isCondensed | boolean | Use this property to reduce the paddings of the component for a ui compact variant | ||
isDisabled | boolean | Indicates that the input cannot be modified (e.g not authorized, or changes currently saving). | ||
isReadOnly | boolean | Indicates that the field is displaying read-only content | ||
placeholder | Record | Placeholder text for the input | ||
horizontalConstraint | unionPossible values:, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'scale', 'auto' | 'scale' | Horizontal size limit of the input fields. | |
hasError | boolean | Indicates that input has errors | ||
hasWarning | boolean | Control to indicate on the input if there are values that are potentially invalid | ||
errors | Record | A map of errors. Error messages for known errors are rendered automatically.
Unknown errors will be forwarded to renderError | ||
warnings | Record | A map of warnings. | ||
hasHighPrecisionBadge | boolean | Shows high precision badge in case current value uses high precision. |
Signatures
Signature onChange
(event: TCustomEvent) => voidSignature onBlur
(event: TCustomEvent) => voidSignature onFocus
(event: TCustomEvent) => voidStatic methods
LocalizedMoneyInput.getEmptyCurrencies
Returns array of the empty currencies
LocalizedMoneyInput.getEmptyCurrencies({});
// -> []LocalizedMoneyInput.getEmptyCurrencies({
USD: { currencyCode: 'USD', amount: '' },
EUR: { currencyCode: 'EUR', amount: '' },
});
// -> ['USD', 'EUR']LocalizedMoneyInput.getEmptyCurrencies({
USD: { currencyCode: 'USD', amount: '12.43' },
EUR: { currencyCode: 'EUR', amount: '' },
});
// -> ['EUR']LocalizedMoneyInput.getHighPrecisionCurrencies
Returns array of the currencies that have high precision amount
LocalizedMoneyInput.getHighPrecisionCurrencies({});
// -> []LocalizedMoneyInput.getHighPrecisionCurrencies({
USD: {
currencyCode: 'USD',
amount: '12.2221',
},
EUR: {
currencyCode: 'EUR',
amount: '9.9999',
},
});
// -> ['USD', 'EUR']LocalizedMoneyInput.getHighPrecisionCurrencies({
USD: {
currencyCode: 'USD',
amount: '12.43',
},
EUR: {
currencyCode: 'EUR',
amount: '0.00001',
},
});
// -> ['EUR']LocalizedMoneyInput.convertToMoneyValues
The convertToMoneyValues function will turn a list of LocalizedMoneyInput values into a list of MoneyValue the API can handle. It automatically converts to centPrecision or highPrecision types when the number of supplied fraction digits exceeds the number of fraction digits used by the currency. If you want to forbid highPrecision, then the form's validation needs to add an error when it sees a highPrecision price. See example below.
Here are examples of centPrecision and highPrecision prices.
// 42.00 €
[
{
type: 'centPrecision',
currencyCode: 'EUR',
centAmount: 4200,
fractionDigits: 2,
},
];// 0.0123456 €
[
{
type: 'highPrecision',
currencyCode: 'EUR',
centAmount: 1,
preciseAmount: 123456,
fractionDigits: 7,
},
];LocalizedMoneyInput.parseMoneyValues
The parseMoneyValues function will turn a list of MoneyValue into a record of values the LocalizedMoneyInput component can handle.
LocalizedMoneyInput.parseMoneyValues([{ currencyCode: 'EUR', centAmount: 10 }]);
// -> { EUR: { currencyCode: 'EUR', centAmount: 10 } }LocalizedMoneyInput.getEmptyCurrencies
The getEmptyCurrencies function will return array of currencies that don't have amount .
LocalizedMoneyInput.getEmptyCurrencies({
EUR: { currencyCode: 'EUR', amount: '' },
USD: { currencyCode: 'USD', amount: '12.77' },
}); // -> ['EUR']
LocalizedMoneyInput.getEmptyCurrencies({
EUR: { currencyCode: 'EUR', amount: '12.77' },
}); // -> []Examples
Here's an example of how LocalizedMoneyInput would be used inside a form.
import { IntlProvider } from 'react-intl';
import { Formik } from 'formik';
import omitEmpty from 'omit-empty-es';
import { ErrorMessage } from '@commercetools-uikit/messages';
import LocalizedMoneyInput from '@commercetools-uikit/localized-money-input';
// the existing document, e.g. from the database
const doc = {
prices: [
{
currencyCode: 'EUR',
centAmount: 1200,
},
{
currencyCode: 'AMD',
centAmount: 3300,
},
],
};
// A function to convert a document to form values.
const docToFormValues = (doc) => ({
// The parseMoneyValue function will turn a MoneyValue into a
// value the LocalizedMoneyInput component can handle ({currency: amount})
prices: LocalizedMoneyInput.parseMoneyValues(doc.prices),
});
// a function to convert form values back to a document
const formValuesToDoc = (formValues) => ({
// The convertToMoneyValue function will convert a LocalizedMoneyInput
// value into a value the API can handle
// It automatically converts to centPrecision or highPrecision
// depending on the number of supplied fraction digits and the
// used currency code.
// If you want to forbid highPrecision, then the form's validation
// needs to add an error when it sees a highPrecision price.
// See example below
prices: LocalizedMoneyInput.convertToMoneyValues(formValues.prices),
});
const validate = (formValues) => {
const errors = { prices: {} };
Object.keys(formValues.prices).forEach((currency) => {
errors.prices[currency] = {};
});
const emptyCurrencies = LocalizedMoneyInput.getEmptyCurrencies(
formValues.prices
);
// ['EUR', 'USD']
// This form doesn't accept high precision prices
const highPrecisionCurrencies =
LocalizedMoneyInput.getHighPrecisionCurrencies(formValues.prices);
// ['CAD', 'USD']
emptyCurrencies.forEach((emptyCurrency) => {
errors.prices[emptyCurrency].missing = true;
});
highPrecisionCurrencies.forEach((highPrecisionCurrency) => {
errors.prices[highPrecisionCurrency].highPrecision = true;
});
return omitEmpty(errors);
};
const initialValues = docToFormValues(doc);
const renderErrors = (errors) => {
Object.keys(errors.prices).reduce((currency) => {
const error =
(errors.prices[currency] && errors.prices[currency].missing && (
<ErrorMessage>This field is required!</ErrorMessage>
)) ||
(errors.prices[currency] && errors.prices[currency].highPrecision && (
<ErrorMessage>High precision prices not supported here!</ErrorMessage>
));
return {
[currency]: touched.prices[currency] && error,
};
});
};
return (
<Formik
initialValues={initialValues}
validate={validate}
onSubmit={(formValues) => {
// doc will contain "prices" holding a MoneyValue,
// ready to be consumed by the API
const nextDoc = formValuesToDoc(formValues);
console.log(nextDoc);
}}
render={({
values,
errors,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<LocalizedMoneyInput
value={values.prices}
onChange={handleChange}
onBlur={handleBlur}
isDisabled={isSubmitting}
errors={renderErrors(errors)}
horizontalConstraint={10}
/>
<button type="submit">Submit</button>
</form>
)}
/>
);12 months ago
11 months ago
6 months ago
10 months ago
9 months ago
10 months ago
10 months ago
5 months ago
9 months ago
10 months ago
6 months ago
6 months ago
11 months ago
10 months ago
6 months ago
6 months ago
7 months ago
11 months ago
6 months ago
5 months ago
10 months ago
11 months ago
8 months ago
11 months ago
10 months ago
9 months ago
6 months ago
1 year ago
6 months ago
5 months ago
10 months ago
11 months ago
11 months ago
6 months ago
6 months ago
11 months ago
9 months ago
7 months ago
5 months ago
9 months ago
1 year ago
1 year ago
6 months ago
10 months ago
7 months ago
1 year ago
5 months ago
6 months ago
11 months ago
9 months ago
9 months ago
10 months ago
10 months ago
9 months ago
8 months ago
9 months ago
9 months ago
11 months ago
9 months ago
10 months ago
12 months ago
7 months ago
9 months ago
11 months ago
11 months ago
6 months ago
11 months ago
6 months ago
12 months ago
11 months ago
9 months ago
10 months ago
5 months ago
11 months ago
6 months ago
11 months ago
6 months ago
11 months ago
10 months ago
10 months ago
9 months ago
12 months ago
6 months ago
5 months ago
7 months ago
12 months ago
11 months ago
11 months ago
9 months ago
6 months ago
5 months ago
12 months ago
11 months ago
10 months ago
11 months ago
10 months ago
11 months ago
1 year ago
6 months ago
6 months ago
6 months ago
10 months ago
7 months ago
12 months ago
7 months ago
12 months ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago