Skip to content
159 changes: 118 additions & 41 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,16 @@
* ...
* ]
*/
function getPersonList() {
return new Promise((resolve, reject) => {
fetch('https://willowtreeapps.com/api/v1.0/profiles')
.then(response => {
if (response.status !== 200) {
reject(new Error("Error!"));
}
async function getPersonList() {
let response = await fetch('https://willowtreeapps.com/api/v1.0/profiles');

response.json().then(imageList => {
resolve(imageList);
});
});
});
if(response.status !== 200) {
throw new Error("Error!");
}

let data = await response.json();

return data;
}


Expand All @@ -125,16 +122,21 @@


function getLastName(person) {
return person.lastName;
return person.lastName.trim();
}

const getFirstName = (person) => {
return person.firstName;
return person.firstName.trim();
};

// headshot URLs are scheme relative //
// prepend http: to prevent invalid schemes like file:// or uri://
// instead return null if the person does not have a headshot url defined
const getImageUrl = (person) => {
if(person.headshot.url === undefined) {
return null;
}

return `http:${person.headshot.url}`;
};

Expand All @@ -143,31 +145,71 @@
*/
function shuffleList(list) {
// Make a copy & don't mutate the passed in list
let result = list.slice(1);
let result = list.slice();

let tmp, j, i = list.length - 1
let tmp, j, i = result.length - 1

for (; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1));
tmp = list[i];
list[i] = list[j];
list[j] = tmp;
tmp = result[i];
result[i] = result[j];
result[j] = tmp;
}

return result;
}


/**
* Remove any people that do not have the name we are
* searching for.
* Get all the words from a phrase string.
*/
function getWords(phrase) {
let words = [];
let cleanedPhrase = phrase.replace(/[\s]+/g, ' ').trim();

if(phrase.length === 0 || cleanedPhrase === '') {
return words;
}

words = cleanedPhrase.split(' ');
return words;
}

/**
* Remove any people that do not have a name that
* contains one or more words from our search string.
*/
function filterByName(searchForName, personList) {
// Get each word from the search query.
const searchTerms = getWords(searchForName);

// Filter our list of people...
return personList.filter((person) => {
return person.firstName === searchForName || person.lastName === searchForName;
// If there are no search terms, return everyone in our list.
if(searchTerms.length === 0) {
return true;
}

// Make sure that one or more search term is found inside
return searchTerms.some((searchTerm) => {
// Transform our search term into lowercase.
searchTerm = searchTerm.trim().toLowerCase();

// Check if the first name or last name contains our search term.
return getFirstName(person).toLowerCase().indexOf(searchTerm) !== -1 ||
getLastName(person).toLowerCase().indexOf(searchTerm) !== -1;
});
});
}

/**
* Toggle the value passed in using the following rules:
* 1. If the current value is null, switch the value to true.
* 2. Otherwise, switch the value to !value.
*/
function toggleBool(currentBool) {
return currentBool === null ? true : !currentBool;
}

/**
* Takes in a property of an object list, e.g. "name" below
Expand All @@ -177,29 +219,38 @@
* And returns a function that will sort that list, e.g.
*
* const sortPeopleByName = sortObjListByProp('name');
* const sortedPeople = sortPeopleByName(people);
* const sortedPeople = sortPeopleByName(people, true);
*
* We now have:
*
* console.log(sortedPeople)
* > [{ name: 'Jon' }, { name: 'Kevin' }, { name: 'Sam' }]
*
* You may also sort the list backwards, e.g.
*
* const sortPeopleByName = sortObjListByProp('name');
* const sortedPeopleBackwards = sortPeopleByName(people, false);
*
* We now have:
*
* console.log(sortedPeopleBackwards)
* > [{ name: 'Sam' }, { name: 'Kevin' }, { name: 'Jon' }]
*/
function sortObjListByProp(prop) {
return function(objList) {
return function(objList, forward) {
// Make a copy & don't mutate the passed in list
let result = objList.slice(1);
let result = objList.slice();

result.sort((a, b) => {
if (a[prop] < b[prop]) {
return -1;
return forward ? -1 : 1;
}

if (a[prop] > b[prop]) {
return 1;
return forward ? 1 : -1;
}

return 1;
return 0;
});

return result;
Expand All @@ -208,7 +259,7 @@

const sortByFirstName = sortObjListByProp('firstName');

const sortByLastName = (personList) => sortByFirstName(personList).reverse();
const sortByLastName = sortObjListByProp('lastName');


/*==================================================
Expand All @@ -227,11 +278,21 @@
src: props.src
});

const ListRow = (props) => React.DOM.tr({ key: `${props.person.firstName} ${props.person.lastName}` }, [
React.DOM.td({ key: 'thumb' }, React.createElement(Thumbnail, { src: getImageUrl(props.person) })),
React.DOM.td({ key: 'first' }, null, getFirstName(props.person)),
React.DOM.td({ key: 'last' }, null, getLastName(props.person)),
]);
const NotPictured = (props) => React.DOM.span({
className: 'not-pictured',
children: 'Not Pictured'
});

const ListRow = (props) => {
const imageUrl = getImageUrl(props.person);
const imageElement = imageUrl === null ? NotPictured : Thumbnail;

return React.DOM.tr({ key: `${props.person.firstName} ${props.person.lastName}` }, [
React.DOM.td({ key: 'thumb' }, React.createElement(imageElement, { src: imageUrl })),
React.DOM.td({ key: 'first' }, null, getFirstName(props.person)),
React.DOM.td({ key: 'last' }, null, getLastName(props.person)),
]);
};

const ListContainer = (props) => React.DOM.table({ className: 'list-container' }, [
React.DOM.thead({ key: 'thead' }, React.DOM.tr({}, [
Expand All @@ -247,7 +308,10 @@
getInitialState() {
return {
personList: [],
visiblePersonList: []
visiblePersonList: [],
sortFirstForward: null,
sortLastForward: null,
searchQuery: ''
};
},

Expand All @@ -260,38 +324,51 @@
},

_shuffleList() {
const searchResults = filterByName(this.state.searchQuery, this.state.personList);

this.setState({
visiblePersonList: shuffleList(this.state.personList)
visiblePersonList: shuffleList(searchResults)
});
},

_sortByFirst() {
const searchResults = filterByName(this.state.searchQuery, this.state.personList);

const newSortFirstForward = toggleBool(this.state.sortFirstForward);

this.setState({
visiblePersonList: sortByFirstName(this.state.personList)
sortFirstForward: newSortFirstForward,
sortLastForward: null,
visiblePersonList: sortByFirstName(searchResults, newSortFirstForward)
});
},

_sortByLast() {
const searchResults = filterByName(this.state.searchQuery, this.state.personList);

const newSortLastForward = toggleBool(this.state.sortLastForward);

this.setState({
visiblePersonList: sortByLastName(this.state.personList)
sortFirstForward: null,
sortLastForward: newSortLastForward,
visiblePersonList: sortByLastName(searchResults, newSortLastForward)
});
},

_onSearch(e) {
this.setState({
searchQuery: e.target.value,
visiblePersonList: filterByName(e.target.value, this.state.personList)
});
},

render() {
const { visiblePersonList } = this.state;

return React.DOM.div({ className: 'app-container' }, [
React.createElement(Search, { key: 'search', onChange: this._onSearch }),
React.DOM.button({ key: 'shuffle', onClick: this._shuffleList }, null, 'Shuffle'),
React.DOM.button({ key: 'sort-first', onClick: this._sortByFirst }, null, 'Sort (First Name)'),
React.DOM.button({ key: 'sort-last', onClick: this._sortByLast }, null, 'Sort (Last Name)'),
React.createElement(ListContainer, { key: 'list', personList: visiblePersonList })
React.createElement(ListContainer, { key: 'list', personList: this.state.visiblePersonList })
]);
}
});
Expand Down