<commit_before>import React from '../src/react';
import {withTask} from '../src/tasks';

import {XHR_TASK} from './tasks/xhr';

export const CHANGE_INPUT = (value : string) => ({type: CHANGE_INPUT, payload: {value}});

export const ADD_ITEM = () => ({type: ADD_ITEM});
export const ADD_ITEM_SUCCESS = () => ({type: ADD_ITEM_SUCCESS});
export const ADD_ITEM_ERROR = (error) => ({type: ADD_ITEM_ERROR, payload: {error}});

export const ADD_ITEM_EAGER = () => ({type: ADD_ITEM_EAGER});
export const ROLLBACK = ({error, previousState}) =>
  ({type: ROLLBACK, payload: {error, previousState}});
export const ADD_ITEM_EAGER_SUCCESS = () => ({type: ADD_ITEM_EAGER_SUCCESS});

interface ListState {
  items: string[];
  error: string;
  inputValue: string;
  isLoading: boolean;
}

const INITIAL_STATE : ListState = {
  items: ['hi'],
  error: '',
  inputValue: '',
  isLoading: false
};

export const listReducer = (state : ListState = INITIAL_STATE, action): ListState => {
  const item = state.inputValue;
  switch(action.type) {

  case CHANGE_INPUT:
    return merge(state, {inputValue: action.payload.value});

  case ADD_ITEM:
    return withTask(merge(state, {
      isLoading: true
    }), XHR_TASK({
      payload: {
        url: '/api/add-item',
        json: {item}
      },
      success: ADD_ITEM_SUCCESS,
      error: ADD_ITEM_ERROR
    }));
  case ADD_ITEM_SUCCESS:
    return merge(state, {
      items: state.items.concat([item]),
      error: '',
      isLoading: false
    });

  case ADD_ITEM_ERROR:
    return merge(state, {
      error: action.payload.error,
      isLoading: false
    });

  // Here's the same example with eager updates and rollback
  case ADD_ITEM_EAGER:
    return withTask(merge(state, {
      items: state.items.concat([item]),
      isLoading: true
    }), XHR_TASK({
      payload: {
        url: '/api/add-item',
        json: {item}
      },
      success: ADD_ITEM_EAGER_SUCCESS,
      error: (error) => ROLLBACK({previousState: state, error})
    }));
  case ADD_ITEM_EAGER_SUCCESS:
    return merge(state, {
      error: '',
      isLoading: false
    });
  case ROLLBACK:
    return merge(action.payload.previousState, {
      error: action.payload.error
    });

  default:
    return state;
  }
};


function merge<T>(original : T, updated : Object): T {
  return (Object as any).assign({}, original, updated);
}

export const ListComponent = ({items, error, inputValue, isLoading, dispatch}) => (
  <div>
    <h1>List</h1>
    <p>error message: {error}</p>
    <ul>{items.map((item, index) =>
      <li key={index}>{item}</li>)}
    </ul>
    <input<commit_msg>Example: use object spread, remove unused fns<commit_after>import React from '../src/react';
import {withTask} from '../src/tasks';

import {XHR_TASK} from './tasks/xhr';

export const CHANGE_INPUT = (value : string) => ({type: CHANGE_INPUT, payload: {value}});

export const ADD_ITEM = () => ({type: ADD_ITEM});
export const ADD_ITEM_SUCCESS = () => ({type: ADD_ITEM_SUCCESS});
export const ADD_ITEM_ERROR = (error) => ({type: ADD_ITEM_ERROR, payload: {error}});

export const ADD_ITEM_EAGER = () => ({type: ADD_ITEM_EAGER});
export const ROLLBACK = ({error, previousState}) =>
  ({type: ROLLBACK, payload: {error, previousState}});
export const ADD_ITEM_EAGER_SUCCESS = () => ({type: ADD_ITEM_EAGER_SUCCESS});

interface ListState {
  items: string[];
  error: string;
  inputValue: string;
  isLoading: boolean;
}

const INITIAL_STATE : ListState = {
  items: ['hi'],
  error: '',
  inputValue: '',
  isLoading: false
};

export const listReducer = (state : ListState = INITIAL_STATE, action): ListState => {
  const item = state.inputValue;
  switch(action.type) {

  case CHANGE_INPUT:
    return {...state, inputValue: action.payload.value};

  case ADD_ITEM:
    return withTask({
      ...state,
      isLoading: true
    }, XHR_TASK({
      payload: {
        url: '/api/add-item',
        json: {item}
      },
      success: ADD_ITEM_SUCCESS,
      error: ADD_ITEM_ERROR
    }));
  case ADD_ITEM_SUCCESS:
    return {
      ...state,
      items: state.items.concat([item]),
      error: '',
      isLoading: false
    };

  case ADD_ITEM_ERROR:
    return {
      ...state,
      error: action.payload.error,
      isLoading: false
    };

  // Here's the same example with eager updates and rollback
  case ADD_ITEM_EAGER:
    return withTask({
      ...state,
      items: state.items.concat([item]),
      isLoading: true
    }, XHR_TASK({
      payload: {
        url: '/api/add-item',
        json: {item}
      },
      success: ADD_ITEM_EAGER_SUCCESS,
      error: (error) => ROLLBACK({previousState: state, error})
    }));
  case ADD_ITEM_EAGER_SUCCESS:
    return {
      ...state,
      error: '',
      isLoading: false
    };
  case ROLLBACK:
    return {
      ...action.payload.previousState,
      error: action.payload.error
    };

  default:
    return state;
  }
};

export const ListComponent = ({items, error, inputValue, isLoading}) => (
  <div>
    <h1>List</h1>
    <p>error message: {error}</p>
    <ul>{items.map((item, index) =>
      <li key={index}>{item}</li>)}
    </ul>
    <input
{'fraction_non_alphanumeric': 0.15306718597857838, 'fraction_numerical': 0.0007789678675754625, 'mean_word_length': 3.089171974522293, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6295600', 'n_tokens_mistral': 1716, 'n_tokens_neox': 1692, 'n_words': 406}