From: Alex-Laptop Date: Wed, 20 Mar 2019 18:44:17 +0000 (-0700) Subject: added reducers X-Git-Tag: v1.0.0~87 X-Git-Url: http://git.infiniteadaptability.org/?a=commitdiff_plain;h=4cbe5c39ec60b678de4439b1f8bd3059ad528f84;p=workouts added reducers --- diff --git a/src/classes/workout.js b/src/classes/workout.js index 1b69b57..774e37a 100644 --- a/src/classes/workout.js +++ b/src/classes/workout.js @@ -1,16 +1,12 @@ +import {constants} from '../constants.js'; +const {DEFAULT_ATTRIBUTES} = constants; + export default class workout { constructor() { - this.attributes = { - lower:false, - core:false, - back:false, - upper:false, - cardio:false, - martial:false, - other:false - }; + this.attributes = {...DEFAULT_ATTRIBUTES}; this.datesDone = []; - this.name = "New workout"; + this.name = "New Workout"; + this.description = ""; } add(dates) { // add new workout to if(!(dates instanceof Array)) { @@ -33,16 +29,29 @@ export default class workout { ]; this.datesDone.sort(); } + changeDescription(str) { + if(typeof str != "string") { + throw new TypeError('Workout::changeDescription(str) expects parameter `str` to be a string'); + } + this.description = str; + } export() { - + throw new Error("Not implemented"); + } + get last_done() { + throw new Error('Not implemented'); + } + remove(date) { + throw new Error("Not implemented"); } setName(name) { if(typeof name != "string") { - throw new TypeErorr('Workout::setName(name) expects parameter `name` to be a string'); + throw new TypeError('Workout::setName(name) expects parameter `name` to be a string'); } + this.name = name; } toggleAttribute(attr) { - if(this.attributes[attr] == void(0)) { + if(this.attributes[attr] === void(0)) { throw new TypeError('Workout::toggleAttribute(attr) expects parameter `attr` to be a valid attribute'); } this.attributes[attr] = !this.attributes[attr]; diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..08ab8e0 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,22 @@ +const constants = { + ADD_WORKOUT:"ADD_WORKOUT", + CHANGE_ATTRIBUTE:"CHANGE_ATTRIBUTE", + CHANGE_VIEW:"CHANGE_VIEW", + CHANGE_WORKOUT_DESCRIPTION:"CHANGE_WORKOUT_DESCRIPTION", + CHANGE_WORKOUT_NAME:"CHANGE_WORKOUT_NAME", + DEFAULT_ATTRIBUTES:{ + lower:false, + core:false, + back:false, + upper:false, + cardio:false, + martial:false, + other:false + }, + DELETE_WORKOUT:"DELETE_WORKOUT", + NEW_WORKOUT:"NEW_WORKOUT", + REMOVE_WORKOUT:"REMOVE_WORKOUT", + SORT_VIEW:"SORT_VIEW" +}; +Object.freeze(constants); +export constants; \ No newline at end of file diff --git a/src/reducers/combined.js b/src/reducers/combined.js new file mode 100644 index 0000000..6ba7c20 --- /dev/null +++ b/src/reducers/combined.js @@ -0,0 +1,9 @@ +import {combineReducers} from 'redux'; + +import workouts from './workouts.js'; +import view from './view.js'; + +export default combineReducers({ + workouts, + view +}); \ No newline at end of file diff --git a/src/reducers/view.js b/src/reducers/view.js new file mode 100644 index 0000000..af54542 --- /dev/null +++ b/src/reducers/view.js @@ -0,0 +1,77 @@ +import workout from '../classes/workout.js'; + +import {constants} from '../constants.js'; + +const {DEFAULT_ATTRIBUTES} = constants; +const defaultDaysAgo = {...DEFAULT_ATTRIBUTES}; +Object.keys(defaultDaysAgo).map((attr) => { + defaultDaysAgo[attr] = -1; +}); +const defaultState = { + view:"manage", + daysAgo:defaultDaysAgo, + data:[], + sortKey:"last_done", + sortOrder:"desc" +}; + +export default function view(state = defaultState,action) { + const {CHANGE_VIEW,SORT_VIEW} = constants; + if((action.workouts == void(0))||(!(action.workouts instanceof Array))) { + return state; + } + if(!action.workouts.every((x) => x instanceof workout)) { + return state; + } + switch(action.type) { + case CHANGE_VIEW: + if((action.view === void(0))||(action.view == state.view)) { + return state; + } + switch(action.view) { + case "manage": + const newStateManageView = {...state}; + newStateManageView.data = []; + for(let i=0;i-1) { + newSortOrder[sortIndex] = (newSortOrder[sortIndex]=="asc")?"desc":"asc"; + } else { + newSortkey*/ + return state; + default: + return state; + } +} \ No newline at end of file diff --git a/src/reducers/workouts.js b/src/reducers/workouts.js new file mode 100644 index 0000000..60d0159 --- /dev/null +++ b/src/reducers/workouts.js @@ -0,0 +1,86 @@ +import {constants} from '../constants.js'; + +export default function workouts(state = {},action) { + const {ADD_WORKOUT,CHANGE_ATTRIBUTE,CHANGE_WORKOUT_NAME,DEFAULT_ATTRIBUTES,DELETE_WORKOUT,NEW_WORKOUT,REMOVE_WORKOUT} = constants; + if(typeof action != "object") { + return state; + } + switch(action.type) { + case ADD_WORKOUT: + if(action.name === void(0)) { + return state; + } + if(!(state[action.name] instanceof workout)) { + return state; + } + const newStateAfterAdd = {...state}; + try { + newStateAfterAdd[action.name].add(action.toAdd); + return newStateAfterAdd; + } catch(err) { + return state; + } + case CHANGE_ATTRIBUTE: + if((action.workout === void(0))||(action.attribute === void(0))) { + return state; + } + if(state[action.workout] === void(0)) { + return state; + } + try { + const newStateAfterChangeAttribute = {...state}; + newStateAfterChangeAttribute[action.workout].toggleAttribute(action.attribute); + return newStateAfterChangeAttribute; + } catch(err) { + return state; + } + case CHANGE_WORKOUT_NAME: + if(action.workout === void(0)) { + return state; + } + if(state[action.workout] === void(0)) { + return state; + } + try { + const newStateAfterNameChange = {...state}; + newStateAfterNameChange[action.workout].setName(action.name); + return newStateAfterNameChange; + } catch(err) { + return state; + } + case DELETE_WORKOUT: + if(action.name === void(0)) { + return state; + } + if(!(state[action.name] instanceof workout)) { + return state; + } + try { + const newStateAfterDelete = {...state}; + newStateAfterDelete[action.workout].remove(toDel); + return newStateAfterDelete; + } catch(err) { + return state; + } + case NEW_WORKOUT: + if(state["New Workout"] !== void(0)) { + return state; + } + const newStateAfterNew = {...state}; + const newWorkout = new workout(); + newStateAfterNew[newWorkout.name] = newWorkout; + return newStateAfterNew; + case REMOVE_WORKOUT: + if(action.toRemove === void(0)) { + return state; + } + if(state[action.toRemove] === void(0)) { + return state; + } + const newStateAfterRemove = {...state}; + delete(newStateAfterRemove[action.toRemove]); + return newStateAfterRemove; + default: + return state; + } +} \ No newline at end of file diff --git a/test/view.reducer.tests.js b/test/view.reducer.tests.js new file mode 100644 index 0000000..9749ba0 --- /dev/null +++ b/test/view.reducer.tests.js @@ -0,0 +1,38 @@ +import assert from 'assert'; + +import view from '../src/reducers/view.js'; + +import {constants} from '../src/constants.js'; +const {CHANGE_VIEW,SORT_VIEW} = constants; + +describe('view reducers',() => { + + describe(CHANGE_VIEW,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should successfully change the state to the `manage` view',() => { + assert.fail('Not implemented'); + }); + + it('should successfully change the state to the `recent` view',() => { + assert.fail('Not implemented'); + }); + + }); + + describe(SORT_VIEW,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should successfully sort the view',() => { + assert.fail('Not implemented'); + }); + + }); + +}); \ No newline at end of file diff --git a/test/workouts.tests.js b/test/workout.tests.js similarity index 64% rename from test/workouts.tests.js rename to test/workout.tests.js index acf71a7..4640e24 100644 --- a/test/workouts.tests.js +++ b/test/workout.tests.js @@ -8,11 +8,23 @@ describe('workout object tests', () => { assert.fail('Not implemented'); }); + it('should successfully add dates', () => { + assert.fail('Not implemented'); + }); + + it('should successfully change description',() => { + assert.fail('Not implemented'); + }); + it('should successfully export', () => { assert.fail('Not implemented'); }); - it('should successfully add dates', () => { + it('should successfully output the last time the workout was completed',() => { + assert.fail('Not implemented'); + }); + + it('should successfully remove dates', () => { assert.fail('Not implemented'); }); diff --git a/test/workouts.reducer.tests.js b/test/workouts.reducer.tests.js new file mode 100644 index 0000000..70940c5 --- /dev/null +++ b/test/workouts.reducer.tests.js @@ -0,0 +1,101 @@ +import assert from 'assert'; + +import workouts from '../src/reducers/workouts.js'; + +import {constants} from '../src/constants.js'; +const {ADD_WORKOUT,CHANGE_ATTRIBUTE,CHANGE_WORKOUT_NAME,DELETE_WORKOUT,NEW_WORKOUT,REMOVE_WORKOUT} = constants; + +describe('workouts reducer',() => { + + describe(ADD_WORKOUT,() => { + + it('should not change the state when invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should successfully add a workout to an already existing workout',() => { + assert.fail('Not implemented'); + }); + + }); + + describe(CHANGE_ATTRIBUTE,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should not change the state when trying to change an attribute for a nonexistent workout',() => { + assert.fail('Not implemented'); + }); + + it('should successfully change the attribute of an already existing workout',() => { + assert.fail('Not implemented'); + }); + + }); + + describe(CHANGE_WORKOUT_NAME,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should not change the state when trying to change the name for a nonexistent workout',() => { + assert.fail('Not implemented'); + }); + + it('should successfully change the name of an already existing workout',() => { + assert.fail('Not implemented'); + }); + + }); + + describe(DELETE_WORKOUT,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should not change the state when action.name refers to a nonexistent workout',() => { + assert.fail('Not implemented'); + }); + + it('should successfully delete a workout from an existent workout',() => { + assert.fail('Not implemented'); + }); + + }); + + describe(NEW_WORKOUT,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should not change the state when "New Workout" workout already exists',() => { + assert.fail('Not implemented'); + }); + + it('should successfully add a new workout',() => { + assert.fail('Not implemented'); + }); + }); + + describe(REMOVE_WORKOUT,() => { + + it('should not change the state when an invalid action is given',() => { + assert.fail('Not implemented'); + }); + + it('should fail when action.toRemove refers to a nonexistent workout',() => { + assert.fail('Not implemented'); + }); + + it('should successfully remove a workout',() => { + assert.fail('Not implemented'); + }); + + }); + +}); \ No newline at end of file