FormFields.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import React from 'react';
  2. import { Form, FormInputProps, FormTextAreaProps, Label, LabelProps, Checkbox } from 'semantic-ui-react';
  3. import { FormikProps } from 'formik';
  4. import LabelWithHelp from './LabelWithHelp';
  5. import { FormErrorLabelsProps } from './errorHandling';
  6. import { formatBalance } from '@polkadot/util';
  7. import styled from 'styled-components';
  8. /*
  9. * Generic form field components
  10. *
  11. * The idea is to provide an easy way of introducing new logic,
  12. * that will affect all of the exsiting form fields (or all fields of given type)
  13. * and to easily switch the structure/display of a typical form field.
  14. */
  15. type InputFormFieldProps = Omit<FormInputProps, 'error'> & {
  16. help?: string;
  17. unit?: string;
  18. error?: LabelProps;
  19. };
  20. export function InputFormField (props: InputFormFieldProps) {
  21. const { unit } = props;
  22. const fieldProps = { ...props, label: undefined, error: undefined };
  23. return (
  24. <FormField {...props} showErrorMsg={true}>
  25. <Form.Input
  26. {...fieldProps}
  27. style={ unit ? { display: 'flex', alignItems: 'center' } : undefined }>
  28. <input />
  29. { unit && <div style={{ margin: '0 0 0 1rem' }}>{unit}</div> }
  30. </Form.Input>
  31. </FormField>
  32. );
  33. }
  34. type TextareaFormFieldProps = Omit<FormTextAreaProps, 'error'> & {
  35. help?: string;
  36. error?: LabelProps;
  37. };
  38. export function TextareaFormField (props: TextareaFormFieldProps) {
  39. const fieldProps = { ...props, label: undefined, error: undefined };
  40. return (
  41. <FormField {...props} showErrorMsg={true}>
  42. <Form.TextArea {...fieldProps}/>
  43. </FormField>
  44. );
  45. }
  46. type FormFieldProps = Omit<(InputFormFieldProps | TextareaFormFieldProps), 'error'> & {
  47. error?: LabelProps;
  48. showErrorMsg?: boolean;
  49. };
  50. const StyledFormField = styled(Form.Field)`
  51. & .field {
  52. margin-bottom: 0 !important;
  53. }
  54. `;
  55. export function FormField (props: React.PropsWithChildren<FormFieldProps>) {
  56. const { error, showErrorMsg = false, label, help, children } = props;
  57. return (
  58. <StyledFormField error={!!error}>
  59. { (label && help)
  60. ? <LabelWithHelp text={ label.toString() } help={ help }/>
  61. : (label ? <label>{ label.toString() }</label> : null)
  62. }
  63. { children }
  64. { Boolean(showErrorMsg && error) && <Label {...error} prompt/> }
  65. </StyledFormField>
  66. );
  67. }
  68. type ReawrdPolicyFieldsType = {
  69. rewardAmount: string;
  70. rewardNextBlock: string;
  71. rewardRecurring: boolean;
  72. rewardInterval: string;
  73. }
  74. type RewardPolicyFieldsProps<ValuesT extends ReawrdPolicyFieldsType> =
  75. Pick<FormikProps<ValuesT>, 'values' | 'handleChange' | 'setFieldValue'> & {
  76. errorLabelsProps: FormErrorLabelsProps<ValuesT>;
  77. };
  78. export function RewardPolicyFields<ValuesT extends ReawrdPolicyFieldsType> ({
  79. values,
  80. errorLabelsProps,
  81. handleChange,
  82. setFieldValue
  83. }: RewardPolicyFieldsProps<ValuesT>) {
  84. return (
  85. <>
  86. <InputFormField
  87. label="Amount per payout"
  88. unit={formatBalance.getDefaults().unit}
  89. onChange={handleChange}
  90. name={'rewardAmount'}
  91. error={errorLabelsProps.rewardAmount}
  92. value={values.rewardAmount}
  93. placeholder={'ie. 100'}
  94. />
  95. <InputFormField
  96. label="Next payment at block"
  97. onChange={handleChange}
  98. name={'rewardNextBlock'}
  99. error={errorLabelsProps.rewardNextBlock}
  100. value={values.rewardNextBlock}
  101. />
  102. <FormField>
  103. <Checkbox
  104. toggle
  105. onChange={(e, data) => { setFieldValue('rewardRecurring', data.checked); }}
  106. label={'Recurring'}
  107. checked={values.rewardRecurring}/>
  108. </FormField>
  109. { values.rewardRecurring && (
  110. <InputFormField
  111. label="Reward interval"
  112. onChange={handleChange}
  113. name={'rewardInterval'}
  114. error={errorLabelsProps.rewardInterval}
  115. value={values.rewardInterval}
  116. unit={'Blocks'}
  117. />
  118. ) }
  119. </>
  120. );
  121. }
  122. export default FormField;