-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5a1d20a
commit 2d6158c
Showing
21 changed files
with
6,543 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
{ | ||
"presets": ["env", "react"], | ||
"plugins":["transform-class-properties"] | ||
"plugins":["transform-class-properties", | ||
"transform-object-rest-spread" ] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import uuid from 'uuid'; | ||
export const addExpense = ( | ||
{ description = '', | ||
note = '', | ||
amount = 0, | ||
createdAt = 0 | ||
} = {} | ||
|
||
) => ({ | ||
type: 'ADD_EXPENSE', | ||
expense:{ | ||
id: uuid(), | ||
description, | ||
note, | ||
amount, | ||
createdAt | ||
} | ||
}); | ||
|
||
export const removeExpense = ({id} = {}) => ({ | ||
type: 'REMOVE_EXPENSE', | ||
id | ||
}); | ||
|
||
export const editExpense = (id, updates) => ({ | ||
type: 'EDIT_EXPENSE', | ||
id, | ||
updates | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export const setTextFilter = (text = '') => ({ | ||
type: 'SET_TEXT_FILTER', | ||
text | ||
}); | ||
export const sortByAmount = () => ({ | ||
type: 'SORT_BY_AMOUNT', | ||
}); | ||
export const sortByDate = () => ({ | ||
type: 'SORT_BY_DATE', | ||
}); | ||
export const setStartDate = (startDate) => ({ | ||
type: 'SET_START_DATE', | ||
startDate | ||
}); | ||
export const setEndDate = (endDate) => ({ | ||
type: 'SET_END_DATE', | ||
endDate | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,35 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import configureStore from './store/configureStore'; | ||
import {Provider} from 'react-redux'; | ||
import {addExpense} from './actions/expenses'; | ||
import {setTextFilter} from './actions/filters'; | ||
import getVisibleExpenses from './selectors/expenses'; | ||
import 'normalize.css/normalize.css'; | ||
import './styles/styles.scss'; | ||
import AppRouter from './routers/AppRouter'; | ||
|
||
ReactDOM.render(<AppRouter />, document.getElementById('app')); | ||
const store = configureStore(); | ||
|
||
store.dispatch(addExpense({description:'Gas Bill', amount:0,createdAt: 1000})); | ||
store.dispatch(addExpense({description:'Water Bill', amount :4500, createdAt:0})); | ||
store.dispatch(addExpense({description:'Rent', amount :109000, createdAt:0})); | ||
//store.dispatch(setTextFilter('water')); | ||
|
||
// setTimeout(()=>{ | ||
// store.dispatch(setTextFilter('bill')) | ||
// },3000); | ||
|
||
const state = store.getState(); | ||
const visibleExpenses = getVisibleExpenses(state.expenses, state.filters); | ||
console.log(visibleExpenses); | ||
|
||
const jsx = ( | ||
<Provider store = {store}> | ||
<AppRouter /> | ||
</Provider> | ||
); | ||
|
||
ReactDOM.render(jsx, document.getElementById('app')); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,18 @@ | ||
import React from 'react'; | ||
import ExpenseForm from './ExpenseForm'; | ||
import { addExpense } from '../actions/expenses'; | ||
import { connect } from 'react-redux'; | ||
|
||
|
||
const AddExpensePage = () => ( | ||
const AddExpensePage = (props) => ( | ||
<div> | ||
Add Expense Page | ||
<h1> Add Expense Page</h1> | ||
<ExpenseForm | ||
onSubmit = {(expense)=>{ | ||
props.dispatch(addExpense(expense)); | ||
props.history.push('/'); | ||
}} | ||
/> | ||
</div> | ||
); | ||
|
||
export default AddExpensePage; | ||
export default connect()(AddExpensePage); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,32 @@ | ||
import React from 'react'; | ||
const EditExpensePage = (props) => { | ||
import {connect} from 'react-redux'; | ||
import ExpenseForm from './ExpenseForm'; | ||
import {editExpense, removeExpense} from '../actions/expenses'; | ||
|
||
const EditExpensePage = (props) => { | ||
console.log(props); | ||
return ( | ||
<div> | ||
Edit Expense Page with id of {props.match.params.id} | ||
<ExpenseForm | ||
expense = {props.expense} | ||
onSubmit = {(expense)=>{ | ||
props.dispatch(editExpense(props.expense.id,expense)); | ||
props.history.push('/'); | ||
console.log('updated', expense); | ||
}} | ||
/> | ||
<button onClick= {()=>{ | ||
props.dispatch(removeExpense({id:props.expense.id})); | ||
props.history.push('/'); | ||
}}>Remove</button> | ||
</div> | ||
); | ||
} | ||
export default EditExpensePage; | ||
const mapStateToProps = (state, props) => { | ||
return { | ||
expense: state.expenses.find((expense)=>{ | ||
return expense.id === props.match.params.id | ||
}) | ||
}; | ||
}; | ||
export default connect(mapStateToProps)(EditExpensePage); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
import React from 'react'; | ||
import ExpenseList from './ExpenseList'; | ||
import ExpenseListFilters from './ExpenseListFilters'; | ||
|
||
const ExpenseDashboardPage = () => ( | ||
<div> | ||
This is from my Dashboard Component | ||
<ExpenseList /> | ||
<ExpenseListFilters /> | ||
</div> | ||
); | ||
export default ExpenseDashboardPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React from 'react'; | ||
import moment from 'moment'; | ||
import {SingleDatePicker} from 'react-dates'; | ||
import 'react-dates/lib/css/_datepicker.css' | ||
|
||
export default class ExpenseForm extends React.Component{ | ||
constructor(props){ | ||
super(props); | ||
this.state = { | ||
description : props.expense ? props.expense.description : '', | ||
note: props.expense ? props.expense.note : '', | ||
amount: props.expense ? (props.expense.amount / 100).toString() : '', | ||
createdAt: props.expense ? moment(props.expense.createdAt):moment(), | ||
calendarFocused: false, | ||
error:'' | ||
}; | ||
} | ||
|
||
onDescriptionChange=(e)=>{ | ||
e.persist(); | ||
const description = e.target.value; | ||
this.setState(() => ({ description })); | ||
}; | ||
onNoteChange=(e)=>{ | ||
e.persist(); | ||
const note = e.target.value; | ||
this.setState(() => ({note})); | ||
}; | ||
onAmountChange = (e) => { | ||
const amount = e.target.value; | ||
if(!amount || amount.match(/^\d{1,}(\.\d{0,2})?$/)){ | ||
this.setState(() => ({amount})); | ||
} | ||
}; | ||
onDateChange = (createdAt) => { | ||
if(createdAt){ | ||
this.setState(() => ({ createdAt })); | ||
} | ||
}; | ||
onFocusChange = ({focused}) => { | ||
this.setState(() => ({calendarFocused: focused})); | ||
}; | ||
onSubmit = (e) => { | ||
e.preventDefault(); | ||
if(!this.state.amount || !this.state.description ){ | ||
this.setState({error:'Please provide Amount and Decsription'}); | ||
}else { | ||
this.setState({error:''}); | ||
this.props.onSubmit({ | ||
description: this.state.description, | ||
amount: parseFloat(this.state.amount, 10)*100, | ||
createdAt: this.state.createdAt.valueOf(), | ||
note: this.state.note | ||
}); | ||
} | ||
}; | ||
|
||
render(){ | ||
return ( | ||
<div> | ||
<form onSubmit={this.onSubmit}> | ||
<p>{this.state.error}</p> | ||
<input | ||
type = "text" | ||
placeholder = "Description" | ||
value ={this.state.description} | ||
onChange ={this.onDescriptionChange} | ||
autoFocus | ||
/> | ||
<input | ||
type = "text" | ||
value = {this.state.amount} | ||
placeholder = "Amount" | ||
onChange = {this.onAmountChange} | ||
/> | ||
<SingleDatePicker | ||
date = {this.state.createdAt} | ||
onDateChange = {this.onDateChange} | ||
focused = {this.state.calendarFocused} | ||
onFocusChange = {this.onFocusChange} | ||
numberOfMonths = {1} | ||
isOutsideRange= {() => false} | ||
/> | ||
<textarea | ||
placeholder = "Add a note(optional)" | ||
value ={this.state.note} | ||
onChange ={this.onNoteChange} | ||
> | ||
</textarea> | ||
<button>Add Expense</button> | ||
</form> | ||
</div> | ||
); | ||
}; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import { connect } from 'react-redux'; | ||
import ExpenseListItem from './ExpenseListItem'; | ||
import selectExpenses from '../selectors/expenses'; | ||
|
||
const ExpenseList = (props) => ( | ||
<div> | ||
<h1>Expense List</h1> | ||
{props.expenses.map((expense)=>{ | ||
return <ExpenseListItem key = {expense.id} {...expense} /> | ||
})} | ||
</div> | ||
); | ||
const mapStateToProps = (state) => { | ||
return { | ||
expenses: selectExpenses(state.expenses, state.filters) | ||
}; | ||
} | ||
const ConnectedExpenseList = connect(mapStateToProps)(ExpenseList); | ||
export default ConnectedExpenseList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React from 'react'; | ||
import { setTextFilter, sortByDate, sortByAmount, setStartDate, setEndDate } from '../actions/filters'; | ||
import {connect} from 'react-redux'; | ||
import { DateRangePicker } from 'react-dates'; | ||
|
||
class ExpenseListFilters extends React.Component{ | ||
state = { | ||
calendarFocused : null | ||
}; | ||
onFocusChange = (calendarFocused) => { | ||
this.setState(()=>({calendarFocused})); | ||
} | ||
onDatesChange = ({startDate, endDate}) => { | ||
this.props.dispatch(setStartDate(startDate)); | ||
this.props.dispatch(setEndDate(endDate)); | ||
} | ||
render(){ | ||
return( | ||
<div> | ||
<input type="text" value={this.props.filters.text} onChange = {(e) => { | ||
this.props.dispatch(setTextFilter(e.target.value)); | ||
}}/> | ||
<select value = {this.props.filters.sortBy} onChange = {(e) =>{ | ||
if(e.target.value === 'date'){ | ||
this.props.dispatch(sortByDate()); | ||
}else if(e.target.value === 'amount'){ | ||
this.props.dispatch(sortByAmount()); | ||
} | ||
}}> | ||
<option value = "date">Date</option> | ||
<option value = "amount">Amount</option> | ||
</select> | ||
<DateRangePicker | ||
startDate ={this.props.filters.startDate} | ||
endDate = {this.props.filters.endDate} | ||
onDatesChange = {this.onDatesChange} | ||
focusedInput= {this.state.calendarFocused} | ||
onFocusChange = {this.onFocusChange} | ||
numberOfMonths = {1} | ||
isOutsideRange= {()=> false} | ||
/> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
const mapStateToProps = (state) => { | ||
return { | ||
filters : state.filters | ||
} | ||
}; | ||
|
||
export default connect(mapStateToProps)(ExpenseListFilters); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import {Link} from 'react-router-dom'; | ||
|
||
|
||
const ExpenseListItem =({ id, description, amount, createdAt})=>( | ||
<div> | ||
<Link to = {`/edit/:${id}`}><h3>{description}</h3> </Link> | ||
<p>{amount} - {createdAt} </p> | ||
</div> | ||
); | ||
|
||
export default ExpenseListItem; |
Oops, something went wrong.