-
Notifications
You must be signed in to change notification settings - Fork 1
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
5e50ecf
commit f2b4dde
Showing
10 changed files
with
368 additions
and
4 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 |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import axios from 'axios'; | ||
import keys from './keys'; | ||
|
||
class ContentFulAPI { | ||
constructor(space = keys.space, accessToken = keys.accessToken) { | ||
this.space = space; | ||
this.accessToken = accessToken; | ||
} | ||
|
||
async fethEntries(limit, skip) { | ||
const apiUrl = `https://cdn.contentful.com/spaces/${this.space}/entries?access_token=${this.accessToken}&limit=${limit}&skip=${skip}&order=sys.id`; | ||
|
||
const response = await axios.get(apiUrl); | ||
const { items, total } = response.data; | ||
|
||
return { | ||
items: items.map((item) => item.fields), | ||
total, | ||
}; | ||
} | ||
} | ||
|
||
export default ContentFulAPI; |
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,52 @@ | ||
import { sort } from 'fast-sort'; | ||
|
||
import ContentFulAPI from '../api'; | ||
import keys from '../keys'; | ||
|
||
const fetchNames = async ( | ||
space = keys.space, | ||
accessToken = keys.accessToken | ||
) => { | ||
const client = new ContentFulAPI(space, accessToken); | ||
const { items, total } = await client.fethEntries(1000, 0); | ||
let associates = [...items]; | ||
|
||
const loops = Math.ceil(total / 1000); | ||
let skip = 0; | ||
const requests = []; | ||
|
||
for (let i = 0; i < loops; i += 1) { | ||
skip += 1000; | ||
requests.push(client.fethEntries(1000, skip)); | ||
} | ||
|
||
const responses = await Promise.all(requests); | ||
const newAssociates = responses.reduce( | ||
(acc, response) => acc.concat(response.items), | ||
[] | ||
); | ||
|
||
associates = associates.concat(newAssociates); | ||
const sortedNames = sort(associates).asc([ | ||
(person) => person.name.last, | ||
(person) => person.name.first, | ||
(person) => person.name.middle, | ||
]); | ||
|
||
const grouped = sortedNames.reduce((acc, person) => { | ||
const firstLetter = person.name.last[0].toUpperCase(); | ||
if (!acc[firstLetter]) { | ||
acc[firstLetter] = []; | ||
} | ||
acc[firstLetter].push(person); | ||
return acc; | ||
}, {}); | ||
|
||
return { | ||
list: sortedNames, | ||
grouped, | ||
total: sortedNames.length, | ||
}; | ||
}; | ||
|
||
export default fetchNames; |
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,7 @@ | ||
// It's not necessary to set these as environment variables, they are public and being used on the client side. | ||
const keys = { | ||
space: '0f39zonxf59w', | ||
accessToken: '10OGNlSRGeKn81WAaTUxMjVL0nhXFEUszwRJIY7vPeI', | ||
}; | ||
|
||
export default keys; |
33 changes: 33 additions & 0 deletions
33
src/components/page-types/associatesDirectoryPage/Directory/Associate.jsx
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,33 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const AssociateProps = { | ||
isEnabled: PropTypes.bool, | ||
person: PropTypes.shape({ | ||
name: PropTypes.shape({ | ||
first: PropTypes.string, | ||
last: PropTypes.string, | ||
}), | ||
yearAdded: PropTypes.number, | ||
}), | ||
}; | ||
|
||
const Associate = ({ isEnabled = true, person }) => { | ||
if (!isEnabled) return null; | ||
|
||
return ( | ||
<div className="su-flex even:su-bg-black-10"> | ||
<div className="su-flex-1 su-w-[50%] su-py-10 su-pl-30"> | ||
{person.name.first} {person.name.last} | ||
</div> | ||
<div> </div> | ||
<div className="su-flex-1 su-w-[50%] su-py-10"> | ||
{Object.values(person.years || []).join(', ')} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
Associate.propTypes = AssociateProps; | ||
|
||
export default Associate; |
52 changes: 52 additions & 0 deletions
52
src/components/page-types/associatesDirectoryPage/Directory/AssociateList.jsx
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,52 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import Associate from './Associate'; | ||
|
||
const AssociateListProps = { | ||
isEnabled: PropTypes.bool, | ||
letter: PropTypes.string, | ||
associates: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
name: PropTypes.shape({ | ||
first: PropTypes.string, | ||
last: PropTypes.string, | ||
}), | ||
yearAdded: PropTypes.number, | ||
}) | ||
), | ||
onlyNewMembers: PropTypes.bool, | ||
recentYear: PropTypes.number, | ||
}; | ||
|
||
const AssociateList = ({ | ||
isEnabled, | ||
letter, | ||
associates, | ||
onlyNewMembers, | ||
recentYear, | ||
}) => { | ||
if (!isEnabled) return null; | ||
|
||
return ( | ||
<div> | ||
<h4 className="su-p-10 su-text-cardinal-red-xdark su-font-serif su-border-b su-border-dashed su-border-1 su-border-black-30-opacity-40"> | ||
{letter} | ||
</h4> | ||
<div> | ||
{associates?.map((person, index) => ( | ||
<Associate | ||
// eslint-disable-next-line react/no-array-index-key | ||
key={`person-${person.entryTitle}-${index}`} | ||
person={person} | ||
isEnabled={!onlyNewMembers || person.yearAdded === recentYear} | ||
/> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
AssociateList.propTypes = AssociateListProps; | ||
|
||
export default AssociateList; |
91 changes: 91 additions & 0 deletions
91
src/components/page-types/associatesDirectoryPage/Directory/Directory.jsx
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,91 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import fetchNames from '../../../../api/contentful/associates'; | ||
import Tabs from './Tabs'; | ||
import Results from './Results'; | ||
|
||
const Directory = () => { | ||
const [associatesData, setAssociatesData] = useState({}); | ||
const [onlyNewMembers, setOnlyNewMembers] = useState(false); | ||
const [recentYear, setRecentYear] = useState(null); | ||
const [search, setSearch] = useState(''); | ||
const [filteredList, setFilteredList] = useState([]); | ||
|
||
const filterResult = () => { | ||
const result = associatesData.list?.filter((person) => { | ||
const fullName = `${person.name.first} ${person.name.last}`; | ||
const isVisible = | ||
fullName.toLowerCase().includes(search.toLowerCase()) && | ||
(!onlyNewMembers || person.yearAdded === recentYear); | ||
return isVisible; | ||
}); | ||
setFilteredList(result); | ||
}; | ||
|
||
const handleNewMembersToggle = (event) => { | ||
setOnlyNewMembers(event.target.checked); | ||
}; | ||
|
||
const handleSearch = (event) => { | ||
setSearch(event.target.value); | ||
}; | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
const data = await fetchNames(); | ||
setAssociatesData(data); | ||
|
||
const mostRecent = Math.max( | ||
...data.list.map((person) => person.yearAdded || 0) | ||
); | ||
setRecentYear(mostRecent); | ||
}; | ||
|
||
fetchData(); | ||
}, []); | ||
|
||
useEffect(() => { | ||
filterResult(); | ||
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [onlyNewMembers, search]); | ||
|
||
return ( | ||
<div className="su-mt-30"> | ||
<div className="su-my-20">{associatesData.total} Associates Total</div> | ||
<div className="su-my-20"> | ||
<input | ||
type="text" | ||
className="su-py-10 su-px-20 su-text-19 su-border su-border-solid su-border-black-40" | ||
placeholder="Search for a Name" | ||
value={search} | ||
onChange={handleSearch} | ||
/> | ||
</div> | ||
<div className="su-mb-50"> | ||
<label> | ||
<input | ||
type="checkbox" | ||
checked={onlyNewMembers} | ||
value={onlyNewMembers} | ||
onChange={handleNewMembersToggle} | ||
className="su-peer su-form-checkbox su-text-digital-red-light su-mr-10 su-w-[1.5rem] su-h-[1.5rem] su-cursor-pointer su-rounded su-border-black-40 hocus:su-border-none hocus:su-ring hocus:su-ring-digital-red-light hocus:su-ring-offset-0" | ||
/>{' '} | ||
View Only New Members | ||
</label> | ||
</div> | ||
|
||
{search.length ? <Results filteredList={filteredList} /> : ''} | ||
|
||
{!search.length && ( | ||
<Tabs | ||
groupedNames={associatesData.grouped || {}} | ||
onlyNewMembers={onlyNewMembers} | ||
recentYear={recentYear} | ||
search={search} | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Directory; |
33 changes: 33 additions & 0 deletions
33
src/components/page-types/associatesDirectoryPage/Directory/Results.jsx
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,33 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import Associate from './Associate'; | ||
|
||
const ResultsProps = { | ||
onlyNewMembers: PropTypes.bool, | ||
recentYear: PropTypes.number, | ||
}; | ||
|
||
const Results = ({ filteredList }) => { | ||
const total = filteredList?.length; | ||
if (!total) { | ||
return <div className="su-my-50">No associates found.</div>; | ||
} | ||
return ( | ||
<div> | ||
<div className="su-my-20">{total} associates found:</div> | ||
<ul> | ||
{filteredList?.map((person, index) => ( | ||
<Associate | ||
// eslint-disable-next-line react/no-array-index-key | ||
key={`person-${person.entryTitle}-${index}`} | ||
person={person} | ||
/> | ||
))} | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
Results.propTypes = ResultsProps; | ||
|
||
export default Results; |
75 changes: 75 additions & 0 deletions
75
src/components/page-types/associatesDirectoryPage/Directory/Tabs.jsx
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,75 @@ | ||
import React, { useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import AssociateList from './AssociateList'; | ||
|
||
const TabsProps = { | ||
onlyNewMembers: PropTypes.bool, | ||
recentYear: PropTypes.number, | ||
}; | ||
|
||
const tabsGroups = { | ||
'A-B': ['A', 'B'], | ||
'C-D': ['C', 'D'], | ||
'E-F': ['E', 'F'], | ||
'G-H': ['G', 'H'], | ||
'I-J': ['I', 'J'], | ||
'K-L': ['K', 'L'], | ||
'M-N': ['M', 'N'], | ||
'O-P': ['O', 'P'], | ||
'Q-R': ['Q', 'R'], | ||
'S-T': ['S', 'T'], | ||
'U-V': ['U', 'V'], | ||
'W-X': ['W', 'X'], | ||
'Y-Z': ['Y', 'Z'], | ||
}; | ||
const Tabs = ({ groupedNames, onlyNewMembers, recentYear }) => { | ||
const [activeTab, setActiveTab] = useState('A-B'); | ||
|
||
const handleTabClick = (event) => { | ||
setActiveTab(event.target.dataset.group); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<nav> | ||
{Object.keys(tabsGroups).map((group) => ( | ||
<a | ||
key={`tab-${group}`} | ||
className={`${ | ||
activeTab === group | ||
? 'su-bg-cardinal-red-xdark' | ||
: 'su-bg-saa-black su-bg-opacity-[80%]' | ||
} su-py-5 su-px-10 su-text-white hover:su-text-white hover:su-no-underline focus:su-text-white focus:su-no-underline su-border su-border-solid su-border-1 su-border-black-30-opacity-40`} | ||
href={`#${group}`} | ||
onClick={handleTabClick} | ||
data-group={group} | ||
> | ||
{group} | ||
</a> | ||
))} | ||
</nav> | ||
<div className="su-my-20"> | ||
{Object.keys(tabsGroups).map((group) => ( | ||
<div key={`content-${group}`}> | ||
{tabsGroups[group].map((letter) => ( | ||
<AssociateList | ||
key={`content-${letter}`} | ||
isEnabled={activeTab === group} | ||
tabsGroups={tabsGroups} | ||
letter={letter} | ||
associates={groupedNames[letter]} | ||
onlyNewMembers={onlyNewMembers} | ||
recentYear={recentYear} | ||
/> | ||
))} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
Tabs.propTypes = TabsProps; | ||
|
||
export default Tabs; |
4 changes: 2 additions & 2 deletions
4
src/components/page-types/associatesDirectoryPage/associatesDirectory.js
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
Oops, something went wrong.