mahaplatform/reframe

View on GitHub
src/components/infinite/reducer.js

Summary

Maintainability
B
5 hrs
Test Coverage
import type { FetchRequest, FetchSuccess, FetchFailure, FetchDelay, FetchTimeout, Select, SelectAll, State, Action } from './types'

import _ from 'lodash'

const INITIAL_STATE: State = {
  records: null,
  request_id: null,
  selectAll: false,
  selected: [],
  status: 'pending'
}

const fetchRequest = (state: State, action: FetchRequest): State => ({
  ...state,
  request_id: action.request_id,
  status: (status !== 'pending' && action.request.params.$page.skip === 0) ? 'loading' : 'refreshing'
})

const fetchSuccess = (state: State, action: FetchSuccess): State => {
  if(action.request_id !== state.request_id) return state
  if(!_.includes(['loading','refreshing','delayed'], state.status)) return state
  const loaded = state.records ? state.records.length : 0
  if(action.result.pagination.all !== undefined) {
    return {
      ...state,
      all: action.result.pagination.all,
      request_id: null,
      records: (action.result.pagination.skip > 0) ? [
        ...state.records || [],
        ...action.result.data
      ] : action.result.data,
      total: action.result.pagination.total,
      status: (loaded + action.result.data.length >= action.result.pagination.total) ? 'completed' : 'loaded'
    }
  } else if(action.result.pagination.next !== undefined) {
    return {
      ...state,
      next: action.result.pagination.next,
      request_id: null,
      records: (action.result.pagination.skip > 0) ? [
        ...state.records || [],
        ...action.result.data
      ] : action.result.data,
      status: action.result.pagination.next === null ? 'completed' : 'loaded'
    }
  }
}

const fetchFailure = (state: State, action: FetchFailure): State => ({
  ...state,
  status: 'failed'
})

const fetchDelay = (state: State, action: FetchDelay): State => ({
  ...state,
  status: 'delayed'
})

const fetchTimeout = (state: State, action: FetchTimeout): State => ({
  ...state,
  status: 'timeout'
})

const select = (state: State, action: Select): State => {
  const selected = (!_.includes(state.selected, action.id)) ? [
    ...state.selected,
    action.id
  ] : state.selected.filter(id => id !== action.id)
  const all = state.records ? state.records.map(record => record.id) : []
  const selectAll = _.isEqual(all.sort(), selected.sort())
  return {
    ...state,
    selectAll,
    selected
  }
}

const selectAll = (state: State, action: SelectAll): State => {
  const all = state.records ? state.records.map(record => record.id) : []
  const selectAll = !_.isEqual(all.sort(), state.selected.sort())
  return {
    ...state,
    selectAll,
    selected: selectAll ? all : []
  }
}

const reducer = (state: State = INITIAL_STATE, action: Action): State => {

  switch (action.type) {

  case 'FETCH_REQUEST':
    return fetchRequest(state, action)

  case 'FETCH_SUCCESS':
    return fetchSuccess(state, action)

  case 'FETCH_FAILURE':
    return fetchFailure(state, action)

  case 'FETCH_DELAY':
    return fetchDelay(state, action)

  case 'FETCH_TIMEOUT':
    return fetchTimeout(state, action)

  case 'SELECT':
    return select(state, action)

  case 'SELECT_ALL':
    return selectAll(state, action)

  default:
    return state
  }

}

export default reducer