0

I'm using material-ui to list group of violations to the user to select one or multiple violations, then during the selection i extract from each violation it's id and update the state so as a result i'll have an array of ids to send it to backend

here is my code

import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import get from 'lodash/get';
// Material-UI
import MaterialTable, { MTableToolbar } from 'material-table';
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import SaveIcon from '@material-ui/icons/Save';
import CancelIcon from '@material-ui/icons/Cancel';
// Forms
import Entity from '~/Components/Entity';
import { BaseFormComponent, Form, FormContainer, FormItem } from '~/Components/FormComponent';
import { LabelAndValue, LookupString } from '~/Components/FormComponent/Controls';
import { 
  isRequired,
  minNumbers,
  maxNumbers,
  onlyNumbers,
  noEnglish
} from '~/Services/Validators';
import Navigate from '~/Services/Navigate';
import Notifications from '~/Services/Notifications';
import Message from '~/Components/Message';
import Strings from '~/Services/Strings';

import styles from './styles';

@withStyles(styles)
class violationEditorScreen extends BaseFormComponent {
  constructor(props) {
    super(props);

    this.initState({
      error: false,
      errorMsg: '',
      requestId: null,
      complaintId: null,
      penalityTypeId: null,
      violations: [],
      inistitutionsData: [],
      selectedViolationsId: [],

      form: {
        id: {
          type: this.types.number,
          value: 0,
        },
        districtId: {
          type: this.types.number,
          value: 1,
          UIOnly: true
        },
        cityId: {
          type: this.types.number,
          value: 1,
          UIOnly: true
        },
        institutionTypeId: {
          type: this.types.number,
          value: 2,
          UIOnly: true
        },
        complaintTitle: {
          type: this.types.string,
          validators: [ isRequired(), noEnglish() ],
        },
        complaintDescription: {
          type: this.types.string,
          validators: [ isRequired(), noEnglish() ],
        },
        institutionId: {
          type: this.types.number,
          validators: [ isRequired() ],
        },
      }
    });
  }

  componentDidMount() {
    super.componentDidMount();

    // const id = get(this, 'props.match.params.id', null);

    // if (id) {   
    //   this.addFormFields({
    //   });
    // }

    this.getInstitutionsList();
  }

  getInstitutionsList() {
    const { form } = this.state;

    this.getInstitutionsEntity.get({
      cityId: form.cityId.value,
      districtId: form.districtId.value,
      institutionTypeId: form.institutionTypeId.value
    });
  }

  // On Institution Change
  onHandleInstitutionChange(institutionId) {
    this.getRequestIdEntity.post({ institutionId });
  }

  getRequestIdEntityPosted(data) {
    const requestId = data.requestId;
    const complaintId = data.id;

    this.setState({ 
      requestId,
      complaintId
    }, () => {
      this.getViolationsEntity.get({
        complaintId
      });
    });
  }

  onViolationsEntityReceived(data) {
    const violations = [];

    if(data && data.length > 0) {
      data.map(item => {
        violations.push({ ...item });
      });

      this.setState({ violations });
    }
    this.setState({ violations });
  }

  onInstitutionEntityReceived(data) {
    if(data && data.licensingInstitutionsModel && data.licensingInstitutionsModel.length > 0) {
      const arr = [];

      data.licensingInstitutionsModel.map(item => {
        arr.push({
          id: item.institutionId,
          nameAr: item.fullName
        });
      });
      this.setState({ inistitutionsData: arr });
    }
  }

  onEntityPosted(data) {
    const requestId = data.requestId;
    Notifications.notify('success', Strings.complaintHasBeenSuccessfullyPublished);
    this.getViolationsEntity.post({ requestId });
  }

  onSubmit() {
    const id = get(this, 'props.match.params.id', null);
    const { selectedViolationsId, requestId } = this.state;

    if (this.isFormValid) {

      if(selectedViolationsId.length === 0) {
        this.setState({ 
          error: true,
          errorMsg: Strings.addAtLeastOneViolation
        });
      }else {
        const payload = {
          ...this.formValues,
          selectedViolationsId,
          requestId,
          id: id ? id : 0 
        };

        this.entity.post(payload);
      }  
    } else {
      this.showFormErrors();
    }
  }

  handleSelectedRows(rows) {
    const selectedViolationsId = [];
    const penalityTypeIds = [];

    if(rows.length > 0) {
      rows.map(row => {
        selectedViolationsId.push(row.id);
        penalityTypeIds.push(row.penaltyTypeId);
      });

      this.setState({ selectedViolationsId }, () => {
        if(penalityTypeIds.length > 0) {
          const validators= [ 
            isRequired(),
            minNumbers(1),
            onlyNumbers()
          ];    
          const penalityTypeId = penalityTypeIds.sort((a, b) => {
            if(a > b) return -1;
            if(b > a) return 1;
          })[0];

          if(penalityTypeId === 1 || penalityTypeId === 2) {
            validators.push(maxNumbers(30));
          } else {
            validators.push(maxNumbers(60));
          }

          this.addFormFields({
            settlementPeriodInDays: {
              type: this.types.number,
              validators
            },
          });
          this.setState({ penalityTypeId });
        } else {
          this.setState({ penalityTypeId: null });
        }
      });

    } else {
      this.setState({
        selectedViolationsId: [],
        penalityTypeId: null
      });
    }

  }

  get localization() {
    return {
      header: {
        actions: Strings.listActionsLabel,
      },
      body: {
        emptyDataSourceMessage: Strings.listEmptyLabel,
      },
      pagination: {
        labelRowsPerPage: Strings.rowsPerPageLabel,
        labelDisplayedRows: `{from}-{to} ${Strings.fromText} {count}`,
      },
      toolbar: {
        nRowsSelected: `${Strings.nSelected} {0} ${Strings.selectedViolations}`
      }
    };
  }

  get options() {
    return {
      actionsColumnIndex: -1,
      pageSize: 10,
      selection: true,
      filtering: true,
      columnsButton: true,
      maxBodyHeight: 600,
      pageSizeOptions: [ 5, 10 ] ,
      doubleHorizontalScroll: true,
      rowStyle: row => {
        if ( row.tableData.id % 2 ) {
          return { backgroundColor: '#f2f2f2' };
        }
      }
    };
  }

  get columns() {
    return [
      { title: Strings.violationReferenceNumber, field: 'referenceNumber', cellStyle: { width: 120 } },
      { title: Strings.violationDescription, field: 'description' },
    ];
  }

  get components() {
    const { classes } = this.props;

    return {
      Toolbar: props => (
        <div className={classes.toolbar}>
          <MTableToolbar {...props} />
        </div>
      ),
    };
  }

  render() {
    const { form, error, errorMsg, inistitutionsData, violations, penalityTypeId } = this.state;
    const { classes } = this.props;
    const {
      TextField,
      LookupSelectField,
      SelectAutocompleteField,
    } = this;

    return (
      <React.Fragment>
        <Entity
          storeId={'Supervision-Complaints-Editor'}
          entityRef={ref => { this.entity = ref; }}
          onEntityReceived={data => this.onEntityReceived(data)}
          onEntityPosted={data => this.onEntityPosted(data)}
          onEntityPostedError={data => this.onEntityPostedError(data)}
          render={store => (
            <React.Fragment>
              <If condition={error}>
                <Grid item xs={12}>
                  <Message variant={'error'} text={errorMsg} />
                </Grid>
              </If>
              <Form loading={store.loading}>
                <Grid container spacing={24}>
                  <Grid item xs={9}>
                    <Paper elevation={1} className={classes.box1}>
                      <fieldset className={classes.fieldSet}>
                        <legend>{Strings.complaintDetails}</legend> 
                        <FormContainer>
                          <FormItem lg={4}>
                            <LookupSelectField 
                              name={'districtId'}
                              label={Strings.selectDistrictToSearch}
                              lookup={'Districts'}
                              onChange={() => this.getInstitutionsList()}
                              autocomplete
                            />
                          </FormItem>
                          <FormItem lg={4}>
                            <LookupSelectField 
                              name={'cityId'}
                              label={Strings.selectCityToSearch}
                              lookup={`City/LookupItemsByParentId/${form.districtId.value}`}
                              onChange={() => this.getInstitutionsList()}
                              autocomplete
                            />
                          </FormItem>

                          <FormItem lg={4}>
                            <LookupSelectField 
                              name={'institutionTypeId'}
                              label={Strings.selectInstitutionTypeToSearch}
                              lookup={'InstitutionTypes'}
                              onChange={() => this.getInstitutionsList()}
                            />
                          </FormItem>

                          <FormItem lg={4}>
                            <div className={classnames(classes.placeholder, {})}>
                              <SelectAutocompleteField
                                name={'institutionId'}
                                label={Strings.assignmentInstitutionName}
                                emptyString={Strings.searchByNameAndLicense}
                                data={inistitutionsData}
                                onChange={field => this.onHandleInstitutionChange(field.value)}
                              />
                            </div>
                          </FormItem>

                          <FormItem lg={4}>
                            <TextField 
                              name={'complaintTitle'}
                              label={Strings.complaintTitle}
                              setBorder={false}
                            />
                          </FormItem>

                          <If condition={penalityTypeId}>
                            <FormItem lg={4}>
                              <TextField 
                                name={'settlementPeriodInDays'}
                                label={Strings.insertSettlementPeriodInDays}
                                setBorder={false}
                              />
                            </FormItem>
                          </If>

                          <FormItem fullWidth>
                            <TextField
                              multiline
                              name={'complaintDescription'}
                              label={Strings.complaintDescription}
                            />
                          </FormItem>

                        </FormContainer>
                      </fieldset>
                    </Paper>

                    <Paper elevation={1} className={classes.box}>
                      <fieldset className={classes.fieldSet}>
                        <legend>{Strings.complaintAttachments}</legend> 
                        <FormContainer>

                        </FormContainer>
                      </fieldset>
                      {/* Attachment Here */}
                    </Paper>

                    <If condition={violations.length > 0}>
                      <Paper elevation={1} className={classes.box}>
                        <MaterialTable
                          title={Strings.complaintsAddViolationList}
                          data={violations}
                          options={this.options}
                          localization={this.localization}
                          columns={this.columns}
                          components={this.components}
                          onSelectionChange={rows => this.handleSelectedRows(rows)}
                        />
                      </Paper>
                    </If>
                  </Grid>
                  <Grid item xs={3}>
                    {/* =========== Sidebar ============= */}                  
                    <If condition={penalityTypeId}>
                      <Paper elevation={1} className={classes.box}>
                        <FormItem fullWidth style={{ marginBottom: 10 }}>
                          <LabelAndValue 
                            label={Strings.earnedPenality}
                            className={classes.deservedPenality}
                            value={(<LookupString 
                              lookup={'PenaltyType'}
                              value={penalityTypeId}
                            />)}
                          />
                        </FormItem>
                      </Paper>
                    </If>

                    <Paper elevation={1} className={classes.box}>
                      <FormItem fullWidth style={{ marginBottom: 10 }}>
                        <Button
                          fullWidth
                          size={'large'}
                          color={'primary'}
                          variant={'contained'}
                          className={classes.submitButton}
                          onClick={() => this.onSubmit()}
                        >
                          <SaveIcon className={classes.rightIcon} /> 
                          {Strings.saveText}
                        </Button>

                        <Button
                          fullWidth
                          size={'large'}
                          color={'secondary'}
                          variant={'contained'}
                          className={classes.cancelButton}
                          onClick={() => Navigate.goBack()}
                        >
                          <CancelIcon className={classes.rightIcon} /> 
                          {Strings.cancelText}
                        </Button>
                      </FormItem>
                    </Paper>
                  </Grid>
                </Grid>
              </Form>
            </React.Fragment>
          )}
        />
        {/* Get Institutions */}
        <Entity
          storeId={'Supervision-PlannedVisit-Schedule-List'}
          entityRef={ref => { this.getInstitutionsEntity = ref; }}
          onEntityReceived={data => this.onInstitutionEntityReceived(data)}
        />
        {/* Get Request Id */}
        <Entity
          storeId={'Supervision-Complaints-GetRequestId'}
          entityRef={ref => { this.getRequestIdEntity = ref; }}
          onEntityPosted={data => this.getRequestIdEntityPosted(data)}
        />
        {/* Get Violation By Request Id --- And Initiate Request in Admin Screens */}
        <Entity
          storeId={'Supervision-Complaints-Violations-By-ComplaintId'}
          entityRef={ref => { this.getViolationsEntity = ref; }}
          onEntityReceived={data => this.onViolationsEntityReceived(data)}
          onEntityPosted={data => Navigate.goBack()}
        />
      </React.Fragment>
    );
  }
}

violationEditorScreen.propTypes = {
  classes: PropTypes.object,
};

export default violationEditorScreen;

componentDidMount() {
if(id) {
// grap the data from back end and upadte the table with checked rows that matches the ids that i got from Back-End
 }
}

i expect receive array of Ids then mark each row that it's id is in the array Of Ids to let the user knows What he selected before.

Thx in Advance.

1 Answers1

0

if I understand you correct, you want change the style of the row if it selected, so could you check this url and see the last example in order to modify it to adapt to your situation? https://material-table.com/#/docs/features/styling

Orestes
  • 637
  • 1
  • 4
  • 19