hotfix: remove todo files
This commit is contained in:
parent
1efc5a702d
commit
bc8c261b52
|
@ -1,29 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import configureStore from 'redux-mock-store';
|
|
||||||
|
|
||||||
import { ADD_TODO, addTodo } from '../../app/redux/modules/todo';
|
|
||||||
|
|
||||||
const store = configureStore()();
|
|
||||||
|
|
||||||
describe('Todo Actions', () => {
|
|
||||||
beforeEach(() => store.clearActions());
|
|
||||||
|
|
||||||
test('should create an action to add a new todo', () => {
|
|
||||||
const text = 'Hello World!';
|
|
||||||
|
|
||||||
store.dispatch(addTodo(text));
|
|
||||||
|
|
||||||
expect(store.getActions()[0]).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
type: ADD_TODO,
|
|
||||||
payload: {
|
|
||||||
text,
|
|
||||||
id: expect.any(String),
|
|
||||||
editing: false,
|
|
||||||
createdAt: expect.any(Number),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import configureStore from 'redux-mock-store';
|
||||||
|
|
||||||
|
import { LOAD_WALLET_SUMMARY, loadWalletSummary } from '../../app/redux/modules/wallet';
|
||||||
|
|
||||||
|
const store = configureStore()();
|
||||||
|
|
||||||
|
describe('WalletSummary Actions', () => {
|
||||||
|
beforeEach(() => store.clearActions());
|
||||||
|
|
||||||
|
test('should create an action to load wallet summary', () => {
|
||||||
|
store.dispatch(loadWalletSummary());
|
||||||
|
|
||||||
|
expect(store.getActions()[0]).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: LOAD_WALLET_SUMMARY,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,30 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import todoReducer, { ADD_TODO } from '../../app/redux/modules/todo';
|
|
||||||
|
|
||||||
describe('Todo Reducer', () => {
|
|
||||||
test('should return the valid initial state', () => {
|
|
||||||
const initialState = [];
|
|
||||||
const action = {
|
|
||||||
type: 'UNKNOWN_ACTION',
|
|
||||||
payload: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(todoReducer(undefined, action)).toEqual(initialState);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should add a new todo', () => {
|
|
||||||
const action = {
|
|
||||||
type: ADD_TODO,
|
|
||||||
payload: {
|
|
||||||
id: 'abc123',
|
|
||||||
text: 'Hello World!',
|
|
||||||
editing: false,
|
|
||||||
createdAt: new Date().getTime(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const expectedState = [action.payload];
|
|
||||||
|
|
||||||
expect(todoReducer(undefined, action)).toEqual(expectedState);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// @flow
|
||||||
|
import walletSummaryReducer, { LOAD_WALLET_SUMMARY } from '../../app/redux/modules/wallet';
|
||||||
|
|
||||||
|
describe('WalletSummary Reducer', () => {
|
||||||
|
test('should return the valid initial state', () => {
|
||||||
|
const initialState = [];
|
||||||
|
const action = {
|
||||||
|
type: 'UNKNOWN_ACTION',
|
||||||
|
payload: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(walletSummaryReducer(undefined, action)).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should load the wallet summary', () => {
|
||||||
|
const action = {
|
||||||
|
type: LOAD_WALLET_SUMMARY,
|
||||||
|
payload: {},
|
||||||
|
};
|
||||||
|
const expectedState = {
|
||||||
|
total: 0,
|
||||||
|
shielded: 0,
|
||||||
|
transparent: 0,
|
||||||
|
error: null,
|
||||||
|
isLoading: true,
|
||||||
|
dollarValue: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(walletSummaryReducer(undefined, action)).toEqual(expectedState);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,68 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import type { TodoType } from '../types/todo';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
updateTodo: Function,
|
|
||||||
todo: TodoType,
|
|
||||||
cancelUpdateTodo: Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
value: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class TodoEditInput extends Component<Props, State> {
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
value: props.todo.text || '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit = (event: SyntheticInputEvent<HTMLInputElement>, id: string) => {
|
|
||||||
const { value } = this.state;
|
|
||||||
const { updateTodo } = this.props;
|
|
||||||
const trimValue = value.trim();
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (trimValue !== '') {
|
|
||||||
updateTodo(id, trimValue);
|
|
||||||
this.setState({ value: '' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleCancel = (id: string) => {
|
|
||||||
const { cancelUpdateTodo } = this.props;
|
|
||||||
cancelUpdateTodo(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleInputChange = (event: SyntheticInputEvent<HTMLInputElement>) => {
|
|
||||||
const {
|
|
||||||
target: { value },
|
|
||||||
} = event;
|
|
||||||
this.setState({ value });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value } = this.state;
|
|
||||||
const { todo } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='todo-item__view todo-item__view--edit'>
|
|
||||||
<form className='todo-item__input' onSubmit={e => this.handleSubmit(e, todo.id)}>
|
|
||||||
<input value={value} onChange={this.handleInputChange} className='todo-item__input-field' autoFocus />
|
|
||||||
<button type='submit' className='todo-item__input-button'>
|
|
||||||
Update
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<button type='button' className='todo-item__input-cancel' onClick={() => this.handleCancel(todo.id)}>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
addTodo: Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
value: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class TodoInput extends Component<Props, State> {
|
|
||||||
state = {
|
|
||||||
value: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSubmit = (event: SyntheticInputEvent<HTMLInputElement>) => {
|
|
||||||
const { value } = this.state;
|
|
||||||
const { addTodo } = this.props;
|
|
||||||
const trimValue = value.trim();
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (trimValue !== '') {
|
|
||||||
addTodo(trimValue);
|
|
||||||
this.setState({ value: '' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleInputChange = (event: SyntheticInputEvent<HTMLInputElement>) => {
|
|
||||||
const {
|
|
||||||
target: { value },
|
|
||||||
} = event;
|
|
||||||
this.setState({ value });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value } = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form className='todo__input' onSubmit={this.handleSubmit}>
|
|
||||||
<input value={value} onChange={this.handleInputChange} className='todo__input-field' />
|
|
||||||
<button type='submit' className='todo__input-button'>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
import type { TodoType } from '../types/todo';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
todo: TodoType,
|
|
||||||
deleteTodo: Function,
|
|
||||||
toggleEdit: Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class TodoListItem extends PureComponent<Props> {
|
|
||||||
handleDelete = (id: string) => {
|
|
||||||
if (!id) return;
|
|
||||||
|
|
||||||
const { deleteTodo } = this.props;
|
|
||||||
deleteTodo(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleEditToggle = (id: string) => {
|
|
||||||
if (!id) return;
|
|
||||||
|
|
||||||
const { toggleEdit } = this.props;
|
|
||||||
toggleEdit(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { todo } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='todo-item__view todo-item__view--view'>
|
|
||||||
<span className='todo-item__text'>{todo.text}</span>
|
|
||||||
<div className='todo-item__buttons'>
|
|
||||||
<button type='button' onClick={() => this.handleEditToggle(todo.id)} className='todo-item__button'>
|
|
||||||
<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 528.899 528.899'>
|
|
||||||
<path
|
|
||||||
className='todo-item__svg'
|
|
||||||
d='M328.883 89.125l107.59 107.589-272.34 272.34L56.604 361.465l272.279-272.34zm189.23-25.948l-47.981-47.981c-18.543-18.543-48.653-18.543-67.259 0l-45.961 45.961 107.59 107.59 53.611-53.611c14.382-14.383 14.382-37.577 0-51.959zM.3 512.69c-1.958 8.812 5.998 16.708 14.811 14.565l119.891-29.069L27.473 390.597.3 512.69z'
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button type='button' onClick={() => this.handleDelete(todo.id)} className='todo-item__button'>
|
|
||||||
<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 512 512'>
|
|
||||||
<path
|
|
||||||
className='todo-item__svg'
|
|
||||||
fill='#1D1D1B'
|
|
||||||
d='M459.232 60.687h-71.955c-1.121-17.642-15.631-31.657-33.553-31.657H161.669c-17.921 0-32.441 14.015-33.553 31.657H64.579c-18.647 0-33.767 15.12-33.767 33.768v8.442c0 18.648 15.12 33.768 33.767 33.768h21.04v342.113c0 13.784 11.179 24.963 24.963 24.963h308.996c13.784 0 24.964-11.179 24.964-24.963V136.665h14.691c18.663 0 33.768-15.12 33.768-33.768v-8.442c-.001-18.648-15.105-33.768-33.769-33.768zM196.674 443.725c0 12.58-10.197 22.803-22.802 22.803-12.598 0-22.803-10.223-22.803-22.803v-284.9c0-12.597 10.205-22.802 22.803-22.802 12.605 0 22.802 10.206 22.802 22.802v284.9zm91.213 0c0 12.58-10.205 22.803-22.803 22.803s-22.803-10.223-22.803-22.803v-284.9c0-12.597 10.205-22.802 22.803-22.802s22.803 10.206 22.803 22.802v284.9zm91.212 0c0 12.58-10.205 22.803-22.803 22.803-12.613 0-22.803-10.223-22.803-22.803v-284.9c0-12.597 10.189-22.802 22.803-22.802 12.598 0 22.803 10.206 22.803 22.802v284.9z'
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
import TodoEditInput from './todo-edit-input';
|
|
||||||
import TodoListItem from './todo-list-item';
|
|
||||||
import type { TodoType } from '../types/todo';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
todos: Array<TodoType>,
|
|
||||||
deleteTodo: Function,
|
|
||||||
toggleEdit: Function,
|
|
||||||
updateTodo: Function,
|
|
||||||
cancelUpdateTodo: Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class TodoList extends PureComponent<Props> {
|
|
||||||
renderTodoView = (todo: TodoType) => {
|
|
||||||
const { deleteTodo, toggleEdit } = this.props;
|
|
||||||
|
|
||||||
return <TodoListItem todo={todo} deleteTodo={deleteTodo} toggleEdit={toggleEdit} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
renderEditView = (todo: TodoType) => {
|
|
||||||
const { updateTodo, cancelUpdateTodo } = this.props;
|
|
||||||
|
|
||||||
return <TodoEditInput todo={todo} updateTodo={updateTodo} cancelUpdateTodo={cancelUpdateTodo} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
renderList = () => {
|
|
||||||
const { todos } = this.props;
|
|
||||||
const sortTodosByTime = todos.sort((a, b) => b.createdAt - a.createdAt);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ul className='todo__list'>
|
|
||||||
{sortTodosByTime.map(todo => (
|
|
||||||
<li key={todo.id} className='todo__list-item todo-item'>
|
|
||||||
{todo.editing ? this.renderEditView(todo) : this.renderTodoView(todo)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
renderEmptyState = () => <p className='todo__list todo__list--empty'>No todos right now</p>;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { todos } = this.props;
|
|
||||||
const hasTodos = todos.length;
|
|
||||||
|
|
||||||
return hasTodos ? this.renderList() : this.renderEmptyState();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import TodoView from '../views/todo';
|
|
||||||
import {
|
|
||||||
addTodo, deleteTodo, toggleEdit, updateTodo, cancelUpdateTodo,
|
|
||||||
} from '../redux/modules/todo';
|
|
||||||
|
|
||||||
import type { AppState } from '../types/app-state';
|
|
||||||
import type { Dispatch } from '../types/redux';
|
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState) => ({
|
|
||||||
todos: state.todos,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
|
||||||
addTodo: text => dispatch(addTodo(text)),
|
|
||||||
deleteTodo: id => dispatch(deleteTodo(id)),
|
|
||||||
toggleEdit: id => dispatch(toggleEdit(id)),
|
|
||||||
updateTodo: (id, text) => dispatch(updateTodo(id, text)),
|
|
||||||
cancelUpdateTodo: id => dispatch(cancelUpdateTodo(id)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps,
|
|
||||||
)(TodoView);
|
|
|
@ -1,78 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import UUID from 'uuid/v4';
|
|
||||||
|
|
||||||
import { getTimestamp } from '../../utils/timestamp';
|
|
||||||
|
|
||||||
import type { Action } from '../../types/redux';
|
|
||||||
import type { TodoType } from '../../types/todo';
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
export const ADD_TODO = 'ADD_TODO';
|
|
||||||
export const DELETE_TODO = 'DELETE_TODO';
|
|
||||||
export const UPDATE_TODO = 'UPDATE_TODO';
|
|
||||||
export const TOGGLE_EDIT_TODO = 'TOGGLE_EDIT_TODO';
|
|
||||||
export const CANCEL_UPDATE_TODO = 'CANCEL_UPDATE_TODO';
|
|
||||||
|
|
||||||
// Actions Creators
|
|
||||||
export const addTodo = (text: string) => ({
|
|
||||||
type: ADD_TODO,
|
|
||||||
payload: {
|
|
||||||
text,
|
|
||||||
id: UUID(),
|
|
||||||
editing: false,
|
|
||||||
createdAt: getTimestamp(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const cancelUpdateTodo = (id: string) => ({
|
|
||||||
type: CANCEL_UPDATE_TODO,
|
|
||||||
payload: { id },
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTodo = (id: string) => ({
|
|
||||||
type: DELETE_TODO,
|
|
||||||
payload: { id },
|
|
||||||
});
|
|
||||||
|
|
||||||
export const toggleEdit = (id: string) => ({
|
|
||||||
type: TOGGLE_EDIT_TODO,
|
|
||||||
payload: { id },
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateTodo = (id: string, text: string) => ({
|
|
||||||
type: UPDATE_TODO,
|
|
||||||
payload: {
|
|
||||||
text,
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial State
|
|
||||||
const initialState = [];
|
|
||||||
|
|
||||||
// Reducers
|
|
||||||
export default (state: Array<TodoType> = initialState, action: Action): Array<TodoType> => {
|
|
||||||
switch (action.type) {
|
|
||||||
case ADD_TODO:
|
|
||||||
return [...state, action.payload];
|
|
||||||
case DELETE_TODO:
|
|
||||||
return state.filter((todo: TodoType) => todo.id !== action.payload.id);
|
|
||||||
case TOGGLE_EDIT_TODO: {
|
|
||||||
const { id } = action.payload;
|
|
||||||
return state.map(todo => (todo.id === id ? { ...todo, editing: true } : todo));
|
|
||||||
}
|
|
||||||
case UPDATE_TODO: {
|
|
||||||
const { id, text } = action.payload;
|
|
||||||
return state.map(todo => (todo.id === id ? { ...todo, editing: false, text } : todo));
|
|
||||||
}
|
|
||||||
case CANCEL_UPDATE_TODO: {
|
|
||||||
const { id } = action.payload;
|
|
||||||
return state.map(todo => (todo.id === id ? { ...todo, editing: false } : todo));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// SideEffects
|
|
|
@ -1,42 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import TodoInput from '../components/todo-input';
|
|
||||||
import TodoList from '../components/todo-list';
|
|
||||||
|
|
||||||
import type { TodoType } from '../types/todo';
|
|
||||||
|
|
||||||
import checklist from '../assets/images/checklist.svg';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
addTodo: Function,
|
|
||||||
deleteTodo: Function,
|
|
||||||
toggleEdit: Function,
|
|
||||||
todos: Array<TodoType>,
|
|
||||||
updateTodo: Function,
|
|
||||||
cancelUpdateTodo: Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default (props: Props) => {
|
|
||||||
const {
|
|
||||||
addTodo, todos, deleteTodo, toggleEdit, updateTodo, cancelUpdateTodo,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='todo'>
|
|
||||||
<div className='todo__heading'>
|
|
||||||
<img src={checklist} alt='Testing File Loader' className='todo__image' />
|
|
||||||
<h1 className='todo__header'>Todo List App</h1>
|
|
||||||
</div>
|
|
||||||
<TodoInput addTodo={addTodo} />
|
|
||||||
<TodoList
|
|
||||||
todos={todos}
|
|
||||||
deleteTodo={deleteTodo}
|
|
||||||
toggleEdit={toggleEdit}
|
|
||||||
updateTodo={updateTodo}
|
|
||||||
cancelUpdateTodo={cancelUpdateTodo}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
Loading…
Reference in New Issue