diff --git a/.eslintcache b/.eslintcache
index 940425a5..2e11b89e 100644
--- a/.eslintcache
+++ b/.eslintcache
@@ -1 +1 @@
-[{"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js":"1","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js":"2","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js":"3","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js":"4","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js":"5","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js":"6","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js":"7","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js":"8","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js":"9","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js":"10","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Footer.js":"11","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Profile.js":"12","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Public.js":"13","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileList.js":"14","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileCard.js":"15"},{"size":329,"mtime":1607895960007,"results":"16","hashOfConfig":"17"},{"size":87,"mtime":1607504507181,"results":"18","hashOfConfig":"17"},{"size":8418,"mtime":1607984579751,"results":"19","hashOfConfig":"17"},{"size":243,"mtime":1607696817140,"results":"20","hashOfConfig":"17"},{"size":73,"mtime":1607504507180,"results":"21","hashOfConfig":"17"},{"size":231,"mtime":1607504507174,"results":"22","hashOfConfig":"17"},{"size":10797,"mtime":1607984388997,"results":"23","hashOfConfig":"17"},{"size":14176,"mtime":1607980037183,"results":"24","hashOfConfig":"17"},{"size":20007,"mtime":1607986570260,"results":"25","hashOfConfig":"17"},{"size":10382,"mtime":1607549930730,"results":"26","hashOfConfig":"17"},{"size":741,"mtime":1607964943027,"results":"27","hashOfConfig":"17"},{"size":3893,"mtime":1607984355538,"results":"28","hashOfConfig":"17"},{"size":1636,"mtime":1607976735762,"results":"29","hashOfConfig":"17"},{"size":4781,"mtime":1607980012105,"results":"30","hashOfConfig":"17"},{"size":5169,"mtime":1607984429598,"results":"31","hashOfConfig":"17"},{"filePath":"32","messages":"33","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1uc84gl",{"filePath":"34","messages":"35","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"38","messages":"39","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"40","messages":"41","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"44","messages":"45","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"46","messages":"47","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"50","messages":"51","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"52","messages":"53","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"54","messages":"55","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"56","messages":"57","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"58","messages":"59","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"60","messages":"61","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Footer.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Profile.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Public.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileList.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileCard.js",[]]
\ No newline at end of file
+[{"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js":"1","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js":"2","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js":"3","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js":"4","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js":"5","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js":"6","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js":"7","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js":"8","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js":"9","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js":"10","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Footer.js":"11","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Profile.js":"12","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Public.js":"13","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileList.js":"14","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileCard.js":"15"},{"size":329,"mtime":1607895960007,"results":"16","hashOfConfig":"17"},{"size":87,"mtime":1607504507181,"results":"18","hashOfConfig":"17"},{"size":8418,"mtime":1607984579751,"results":"19","hashOfConfig":"17"},{"size":243,"mtime":1607696817140,"results":"20","hashOfConfig":"17"},{"size":73,"mtime":1607504507180,"results":"21","hashOfConfig":"17"},{"size":231,"mtime":1607504507174,"results":"22","hashOfConfig":"17"},{"size":11009,"mtime":1608047298479,"results":"23","hashOfConfig":"17"},{"size":17663,"mtime":1609808956867,"results":"24","hashOfConfig":"17"},{"size":20797,"mtime":1609808618083,"results":"25","hashOfConfig":"17"},{"size":10382,"mtime":1607549930730,"results":"26","hashOfConfig":"17"},{"size":741,"mtime":1607964943027,"results":"27","hashOfConfig":"17"},{"size":3953,"mtime":1608044855021,"results":"28","hashOfConfig":"17"},{"size":1636,"mtime":1607976735762,"results":"29","hashOfConfig":"17"},{"size":8206,"mtime":1609808971716,"results":"30","hashOfConfig":"17"},{"size":5518,"mtime":1609808743974,"results":"31","hashOfConfig":"17"},{"filePath":"32","messages":"33","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},"1uc84gl",{"filePath":"35","messages":"36","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"37","messages":"38","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"39","messages":"40","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"41","messages":"42","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"43","messages":"44","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"47","messages":"48","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"49","usedDeprecatedRules":"34"},{"filePath":"50","messages":"51","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"52","messages":"53","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"54","messages":"55","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"56","messages":"57","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"58","messages":"59","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"34"},{"filePath":"60","messages":"61","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"62","usedDeprecatedRules":"34"},{"filePath":"63","messages":"64","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\index.js",[],["65","66"],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\History.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\App.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Dash.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Constants\\constants.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Loading.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\System.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Memberlist.js",["67"],"import React, { useEffect, useState, useCallback } from 'react';\r\nimport * as BS from 'react-bootstrap'\r\nimport Popup from 'reactjs-popup';\r\nimport 'reactjs-popup/dist/index.css';\r\nimport { useForm } from \"react-hook-form\";\r\n\r\nimport MemberCard from './MemberCard.js'\r\nimport Loading from \"./Loading.js\";\r\nimport API_URL from \"../Constants/constants.js\";\r\n\r\nimport { FaPlus } from \"react-icons/fa\";\r\n\r\nexport default function Memberlist(props) {\r\n \r\n const user = JSON.parse(localStorage.getItem('user'));\r\n const userId = user.id;\r\n\r\n const [isLoading, setIsLoading ] = useState(false);\r\n const [isError, setIsError ] = useState(false);\r\n const [errorAlert, setErrorAlert ] = useState(false);\r\n\r\n const [proxyView, setProxyView] = useState(false);\r\n const [privacyView, setPrivacyView] = useState(false);\r\n const [currentPage, setCurrentPage] = useState(1);\r\n const [membersPerPage, setMembersPerPage] = useState(25);\r\n\r\n const [open, setOpen] = useState(false);\r\n const closeModal = () => setOpen(false);\r\n\r\n const [members, setMembers ] = useState([]);\r\n const [memberData, setMemberData ] = useState([]);\r\n const [filteredMembers, setFilteredMembers ] = useState([]);\r\n const [sortedMembers, setSortedMembers ] = useState([]);\r\n\r\n const [searchBy, setSearchBy] = useState('name')\r\n const [sortBy, setSortBy] = useState('name')\r\n\r\n const [value, setValue] = useState('');\r\n const [proxyTags, setProxyTags] = useState([{\r\n prefix: \"\", suffix: \"\"\r\n }]);\r\n\r\n const {register, handleSubmit} = useForm();\r\n\r\n const fetchMembers = useCallback( () => {\r\n setIsLoading(true);\r\n setIsError(false);\r\n setMembersPerPage(25);\r\n\r\n fetch(`${API_URL}s/${userId}/members`,{\r\n method: 'GET',\r\n headers: {\r\n 'Authorization': JSON.stringify(localStorage.getItem(\"token\")).slice(1, -1)\r\n }}).then ( res => res.json()\r\n ).then (data => { \r\n setMembers(data)\r\n setIsLoading(false);\r\n })\r\n .catch (error => { \r\n console.log(error);\r\n setIsError(true);\r\n setIsLoading(false);\r\n })\r\n }, [userId])\r\n\r\n useEffect(() => {\r\n fetchMembers();\r\n }, [fetchMembers])\r\n\r\n useEffect(() => {\r\n let Members = members.map(member => {\r\n if (member.display_name) {\r\n return {...member, displayName: member.display_name}\r\n } return {...member, displayName: member.name}\r\n }) \r\n let Members1 = Members.map(member => {\r\n if (member.description) {\r\n return {...member, desc: member.description}\r\n } return {...member, desc: \"(no description)\"}\r\n })\r\n setMemberData(Members1);\r\n }, [members])\r\n\r\n function addProxyField() {\r\n setProxyTags(oldTags => [...oldTags, {prefix: '', suffix: ''}] )\r\n }\r\n\r\n const submitMember = data => {\r\n setIsLoading(true);\r\n\r\n const newdata = data.proxy_tags ? {...data, proxy_tags: data.proxy_tags.filter(tag => !(tag.prefix === \"\" && tag.suffix === \"\"))} : data\r\n\r\n fetch(`${API_URL}m/`,{\r\n method: 'POST',\r\n body: JSON.stringify(newdata),\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': JSON.stringify(localStorage.getItem(\"token\")).slice(1, -1)\r\n }}).then (res => res.json()\r\n ).then (data => { \r\n setErrorAlert(false);\r\n closeModal();\r\n }\r\n ).catch (error => {\r\n console.error(error);\r\n setErrorAlert(true);\r\n });\r\n }\r\n\r\n const indexOfLastMember = currentPage * membersPerPage;\r\n const indexOfFirstMember = indexOfLastMember - membersPerPage;\r\n \r\n useEffect(() => {\r\n searchMembers();\r\n }, [value, memberData, searchBy])\r\n\r\n function searchMembers() {\r\n const currentMembers = memberData.filter(member => {\r\n if (!value) return true;\r\n \r\n if (searchBy === 'name') {\r\n if (member.name.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n } else if (searchBy === 'display name') {\r\n if (member.displayName.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false\r\n } else if (searchBy === 'description') {\r\n if (member.desc.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n } else if (searchBy === 'ID') {\r\n if (member.id.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n return false;\r\n })\r\n setFilteredMembers(currentMembers);\r\n }\r\n\r\n useEffect (() => { \r\n if (sortBy === 'name') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'display name') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.displayName.localeCompare(b.displayName)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'ID') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.id.localeCompare(b.id)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'date created') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.created.localeCompare(b.created)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n }\r\n }, [sortBy, filteredMembers, indexOfFirstMember, indexOfLastMember])\r\n \r\n\r\n\r\n const active = currentPage;\r\n const pageAmount = Math.ceil(filteredMembers.length / membersPerPage);\r\n \r\n const memberList = sortedMembers.map((member) => \r\n \r\n \r\n );\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n \r\n {\r\n setMembersPerPage(e.target.value);\r\n setCurrentPage(1);\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n setSearchBy(e.target.value)\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n setSortBy(e.target.value)\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {setValue(e.target.value); setCurrentPage(1);}} placeholder={`Search by ${searchBy}`}/>\r\n \r\n \r\n \r\n fetchMembers()}>Refresh\r\n \r\n \r\n \r\n \r\n { currentPage === 1 ? : setCurrentPage(currentPage - 1)} />}\r\n { currentPage < 3 ? \"\" : setCurrentPage(1)} active={1 === active}>{1}}\r\n { currentPage < 4 ? \"\" :}\r\n { currentPage > 1 ? setCurrentPage(currentPage - 1)}>{currentPage - 1} : \"\" }\r\n setCurrentPage(currentPage)} active={currentPage === active}>{currentPage}\r\n { currentPage < pageAmount ? setCurrentPage(currentPage + 1)}>{currentPage + 1} : \"\" }\r\n { currentPage > pageAmount - 3 ? \"\" : }\r\n { currentPage > pageAmount - 2 ? \"\" : setCurrentPage(pageAmount)} active={pageAmount === active}>{pageAmount}}\r\n { currentPage === pageAmount ? : setCurrentPage(currentPage + 1)} />}\r\n \r\n \r\n { isLoading ? : isError ? \r\n Error fetching members. :\r\n <>\r\n \r\n \r\n setOpen(o => !o)}>Add Member \r\n \r\n \r\n \r\n \r\n Add member
\r\n \r\n \r\n { errorAlert ? Something went wrong, please try logging in and out again. : \"\" }\r\n \r\n \r\n \r\n \r\n \r\n Name:\r\n \r\n \r\n \r\n Display name: \r\n \r\n \r\n \r\n Birthday:\r\n \r\n (YYYY-MM-DD)\r\n \r\n \r\n Pronouns:\r\n \r\n \r\n \r\n Avatar url: \r\n \r\n \r\n \r\n Color: \r\n \r\n (hexcode)\r\n \r\n \r\n Proxy tags: \r\n setProxyView(view => !view)}> { proxyView ? \"Hide\" : \"Show\" }\r\n \r\n \r\n Privacy settings: \r\n setPrivacyView(view => !view)}> { privacyView ? \"Hide\" : \"Show\" }\r\n \r\n \r\n
\r\n { proxyView ? <>\r\n Proxy Tags
\r\n \r\n { proxyTags.map((item, index) => (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ))} addProxyField()}>Add new\r\n \r\n
> : \"\" }\r\n { privacyView ? <>privacy settings
\r\n \r\n \r\n Visibility:\r\n \r\n \r\n \r\n \r\n \r\n \r\n Name:\r\n \r\n \r\n \r\n \r\n \r\n \r\n Description:\r\n \r\n \r\n \r\n \r\n \r\n \r\n Birthday:\r\n \r\n \r\n \r\n \r\n \r\n \r\n Pronouns:\r\n \r\n \r\n \r\n \r\n \r\n \r\n Meta:\r\n \r\n \r\n \r\n \r\n \r\n \r\n
> : \"\" }\r\n \r\n Description:\r\n \r\n \r\n Submit Cancel\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {memberList}\r\n \r\n >\r\n }\r\n >\r\n )\r\n}","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\MemberCard.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Functions\\discord-parser.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Footer.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Profile.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\Public.js",[],"C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileList.js",["68"],"import React, { useEffect, useState, useCallback } from 'react';\r\nimport * as BS from 'react-bootstrap'\r\nimport 'reactjs-popup/dist/index.css';\r\n\r\nimport ProfileCard from './ProfileCard.js'\r\nimport Loading from \"./Loading.js\";\r\nimport API_URL from \"../Constants/constants.js\";\r\n\r\nexport default function Memberlist(props) {\r\n \r\n const sysID = props.sysID;\r\n\r\n const [isLoading, setIsLoading ] = useState(false);\r\n const [isError, setIsError ] = useState(false);\r\n\r\n const [currentPage, setCurrentPage] = useState(1);\r\n const [membersPerPage, setMembersPerPage] = useState(25);\r\n\r\n const [members, setMembers ] = useState([]);\r\n const [memberData, setMemberData ] = useState([]);\r\n const [filteredMembers, setFilteredMembers ] = useState([]);\r\n const [sortedMembers, setSortedMembers ] = useState([]);\r\n\r\n const [searchBy, setSearchBy] = useState('name')\r\n const [sortBy, setSortBy] = useState('name')\r\n\r\n const [value, setValue] = useState('');\r\n\r\n const fetchMembers = useCallback( () => {\r\n setIsLoading(true);\r\n setIsError(false);\r\n setMembersPerPage(25);\r\n\r\n fetch(`${API_URL}s/${sysID}/members`,{\r\n method: 'GET',\r\n }).then ( res => res.json()\r\n ).then (data => { \r\n setMembers(data)\r\n setIsLoading(false);\r\n })\r\n .catch (error => { \r\n console.log(error);\r\n setIsError(true);\r\n setIsLoading(false);\r\n })\r\n }, [sysID])\r\n\r\n useEffect(() => {\r\n fetchMembers();\r\n }, [fetchMembers])\r\n\r\n useEffect(() => {\r\n let Members = members.map(member => {\r\n if (member.display_name) {\r\n return {...member, displayName: member.display_name}\r\n } return {...member, displayName: member.name}\r\n }) \r\n let Members1 = Members.map(member => {\r\n if (member.description) {\r\n return {...member, desc: member.description}\r\n } return {...member, desc: \"(no description)\"}\r\n })\r\n setMemberData(Members1);\r\n }, [members])\r\n\r\n const indexOfLastMember = currentPage * membersPerPage;\r\n const indexOfFirstMember = indexOfLastMember - membersPerPage;\r\n\r\n useEffect(() => {\r\n searchMembers();\r\n }, [value, memberData, searchBy])\r\n\r\n function searchMembers() {\r\n const currentMembers = memberData.filter(member => {\r\n if (!value) return true;\r\n \r\n if (searchBy === 'name') {\r\n if (member.name.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n } else if (searchBy === 'display name') {\r\n if (member.displayName.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false\r\n } else if (searchBy === 'description') {\r\n if (member.desc.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n } else if (searchBy === 'ID') {\r\n if (member.id.toLowerCase().includes(value.toLowerCase())) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n return false;\r\n })\r\n setFilteredMembers(currentMembers);\r\n }\r\n\r\n useEffect (() => { \r\n if (sortBy === 'name') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'display name') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.displayName.localeCompare(b.displayName)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'ID') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.id.localeCompare(b.id)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n } else if (sortBy === 'date created') {\r\n const sortMembers = filteredMembers.sort((a, b) => a.created.localeCompare(b.created)).slice(indexOfFirstMember, indexOfLastMember);\r\n setSortedMembers(sortMembers);\r\n }\r\n }, [sortBy, filteredMembers, indexOfFirstMember, indexOfLastMember])\r\n \r\n\r\n const active = currentPage;\r\n const pageAmount = Math.ceil(filteredMembers.length / membersPerPage);\r\n \r\n const memberList = sortedMembers.map((member) => \r\n \r\n \r\n );\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n \r\n \r\n {\r\n setMembersPerPage(e.target.value);\r\n setCurrentPage(1);\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n setSearchBy(e.target.value)\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {\r\n setSortBy(e.target.value)\r\n }}>\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {setValue(e.target.value); setCurrentPage(1);}} placeholder={`Search by ${searchBy}`}/>\r\n \r\n \r\n \r\n fetchMembers()}>Refresh\r\n \r\n \r\n \r\n \r\n { currentPage === 1 ? : setCurrentPage(currentPage - 1)} />}\r\n { currentPage < 3 ? \"\" : setCurrentPage(1)} active={1 === active}>{1}}\r\n { currentPage < 4 ? \"\" :}\r\n { currentPage > 1 ? setCurrentPage(currentPage - 1)}>{currentPage - 1} : \"\" }\r\n setCurrentPage(currentPage)} active={currentPage === active}>{currentPage}\r\n { currentPage < pageAmount ? setCurrentPage(currentPage + 1)}>{currentPage + 1} : \"\" }\r\n { currentPage > pageAmount - 3 ? \"\" : }\r\n { currentPage > pageAmount - 2 ? \"\" : setCurrentPage(pageAmount)} active={pageAmount === active}>{pageAmount}}\r\n { currentPage === pageAmount ? : setCurrentPage(currentPage + 1)} />}\r\n \r\n \r\n { isLoading ? : isError ? \r\n Error fetching members. :\r\n <>\r\n \r\n {memberList}\r\n \r\n >\r\n }\r\n >\r\n )\r\n}","C:\\Users\\Fleur\\Desktop\\website projects etc\\pk-web\\src\\Components\\ProfileCard.js",[],{"ruleId":"69","replacedBy":"70"},{"ruleId":"71","replacedBy":"72"},{"ruleId":"73","severity":1,"message":"74","line":115,"column":8,"nodeType":"75","endLine":115,"endColumn":37,"suggestions":"76"},{"ruleId":"73","severity":1,"message":"74","line":71,"column":8,"nodeType":"75","endLine":71,"endColumn":37,"suggestions":"77"},"no-native-reassign",["78"],"no-negated-in-lhs",["79"],"react-hooks/exhaustive-deps","React Hook useEffect has a missing dependency: 'searchMembers'. Either include it or remove the dependency array.","ArrayExpression",["80"],["81"],"no-global-assign","no-unsafe-negation",{"desc":"82","fix":"83"},{"desc":"82","fix":"84"},"Update the dependencies array to be: [value, memberData, searchBy, searchMembers]",{"range":"85","text":"86"},{"range":"87","text":"86"},[3668,3697],"[value, memberData, searchBy, searchMembers]",[2142,2171]]
\ No newline at end of file
diff --git a/src/Components/Memberlist.js b/src/Components/Memberlist.js
index a8f4c308..d1257bc6 100644
--- a/src/Components/Memberlist.js
+++ b/src/Components/Memberlist.js
@@ -28,7 +28,13 @@ export default function Memberlist(props) {
const closeModal = () => setOpen(false);
const [members, setMembers ] = useState([]);
- const [newMember, setNewMember ] = useState('');
+ const [memberData, setMemberData ] = useState([]);
+ const [filteredMembers, setFilteredMembers ] = useState([]);
+ const [sortedMembers, setSortedMembers ] = useState([]);
+
+ const [searchBy, setSearchBy] = useState('name')
+ const [sortBy, setSortBy] = useState('name')
+
const [value, setValue] = useState('');
const [proxyTags, setProxyTags] = useState([{
prefix: "", suffix: ""
@@ -47,7 +53,7 @@ export default function Memberlist(props) {
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
}}).then ( res => res.json()
).then (data => {
- newMember ? setMembers([...data, newMember]) : setMembers(data)
+ setMembers(data)
setIsLoading(false);
})
.catch (error => {
@@ -55,12 +61,26 @@ export default function Memberlist(props) {
setIsError(true);
setIsLoading(false);
})
- }, [newMember, userId])
+ }, [userId])
useEffect(() => {
fetchMembers();
}, [fetchMembers])
+ useEffect(() => {
+ let Members = members.map(member => {
+ if (member.display_name) {
+ return {...member, displayName: member.display_name}
+ } return {...member, displayName: member.name}
+ })
+ let Members1 = Members.map(member => {
+ if (member.description) {
+ return {...member, desc: member.description}
+ } return {...member, desc: "(no description)"}
+ })
+ setMemberData(Members1);
+ }, [members])
+
function addProxyField() {
setProxyTags(oldTags => [...oldTags, {prefix: '', suffix: ''}] )
}
@@ -78,7 +98,6 @@ export default function Memberlist(props) {
'Authorization': JSON.stringify(localStorage.getItem("token")).slice(1, -1)
}}).then (res => res.json()
).then (data => {
- setNewMember(data);
setErrorAlert(false);
closeModal();
}
@@ -90,19 +109,63 @@ export default function Memberlist(props) {
const indexOfLastMember = currentPage * membersPerPage;
const indexOfFirstMember = indexOfLastMember - membersPerPage;
- const currentMembers = members.filter(member => {
+
+ useEffect(() => {
+ searchMembers();
+ }, [value, memberData, searchBy])
+
+ function searchMembers() {
+ const currentMembers = memberData.filter(member => {
if (!value) return true;
+
+ if (searchBy === 'name') {
if (member.name.toLowerCase().includes(value.toLowerCase())) {
return true;
}
return false;
- }).sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);
+ } else if (searchBy === 'display name') {
+ if (member.displayName.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false
+ } else if (searchBy === 'description') {
+ if (member.desc.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false;
+ } else if (searchBy === 'ID') {
+ if (member.id.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ })
+ setFilteredMembers(currentMembers);
+ }
+
+ useEffect (() => {
+ if (sortBy === 'name') {
+ const sortMembers = filteredMembers.sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'display name') {
+ const sortMembers = filteredMembers.sort((a, b) => a.displayName.localeCompare(b.displayName)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'ID') {
+ const sortMembers = filteredMembers.sort((a, b) => a.id.localeCompare(b.id)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'date created') {
+ const sortMembers = filteredMembers.sort((a, b) => a.created.localeCompare(b.created)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ }
+ }, [sortBy, filteredMembers, indexOfFirstMember, indexOfLastMember])
+
const active = currentPage;
- const pageAmount = Math.ceil(members.length / membersPerPage);
+ const pageAmount = Math.ceil(filteredMembers.length / membersPerPage);
- const memberList = currentMembers.map((member) =>
+ const memberList = sortedMembers.map((member) =>
@@ -111,29 +174,58 @@ export default function Memberlist(props) {
return (
<>
- { isLoading ? : isError ?
- Error fetching members. :
- <>
-
-
+
+
- {
+ {
setMembersPerPage(e.target.value);
setCurrentPage(1);
}}>
-
+
-
+
- {setValue(e.target.value); setCurrentPage(1)}} placeholder="Search"/>
+
+
+ {
+ setSearchBy(e.target.value)
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setSortBy(e.target.value)
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+ {setValue(e.target.value); setCurrentPage(1);}} placeholder={`Search by ${searchBy}`}/>
@@ -153,6 +245,9 @@ export default function Memberlist(props) {
{ currentPage === pageAmount ? : setCurrentPage(currentPage + 1)} />}
+ { isLoading ? : isError ?
+ Error fetching members. :
+ <>
setOpen(o => !o)}>Add Member
diff --git a/src/Components/ProfileList.js b/src/Components/ProfileList.js
index 70a0745c..4bc3a90a 100644
--- a/src/Components/ProfileList.js
+++ b/src/Components/ProfileList.js
@@ -17,6 +17,13 @@ export default function Memberlist(props) {
const [membersPerPage, setMembersPerPage] = useState(25);
const [members, setMembers ] = useState([]);
+ const [memberData, setMemberData ] = useState([]);
+ const [filteredMembers, setFilteredMembers ] = useState([]);
+ const [sortedMembers, setSortedMembers ] = useState([]);
+
+ const [searchBy, setSearchBy] = useState('name')
+ const [sortBy, setSortBy] = useState('name')
+
const [value, setValue] = useState('');
const fetchMembers = useCallback( () => {
@@ -42,21 +49,78 @@ export default function Memberlist(props) {
fetchMembers();
}, [fetchMembers])
+ useEffect(() => {
+ let Members = members.map(member => {
+ if (member.display_name) {
+ return {...member, displayName: member.display_name}
+ } return {...member, displayName: member.name}
+ })
+ let Members1 = Members.map(member => {
+ if (member.description) {
+ return {...member, desc: member.description}
+ } return {...member, desc: "(no description)"}
+ })
+ setMemberData(Members1);
+ }, [members])
+
const indexOfLastMember = currentPage * membersPerPage;
const indexOfFirstMember = indexOfLastMember - membersPerPage;
- const currentMembers = members.filter(member => {
+
+ useEffect(() => {
+ searchMembers();
+ }, [value, memberData, searchBy])
+
+ function searchMembers() {
+ const currentMembers = memberData.filter(member => {
if (!value) return true;
+
+ if (searchBy === 'name') {
if (member.name.toLowerCase().includes(value.toLowerCase())) {
return true;
}
return false;
- }).sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);
+ } else if (searchBy === 'display name') {
+ if (member.displayName.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false
+ } else if (searchBy === 'description') {
+ if (member.desc.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false;
+ } else if (searchBy === 'ID') {
+ if (member.id.toLowerCase().includes(value.toLowerCase())) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ })
+ setFilteredMembers(currentMembers);
+ }
+ useEffect (() => {
+ if (sortBy === 'name') {
+ const sortMembers = filteredMembers.sort((a, b) => a.name.localeCompare(b.name)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'display name') {
+ const sortMembers = filteredMembers.sort((a, b) => a.displayName.localeCompare(b.displayName)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'ID') {
+ const sortMembers = filteredMembers.sort((a, b) => a.id.localeCompare(b.id)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ } else if (sortBy === 'date created') {
+ const sortMembers = filteredMembers.sort((a, b) => a.created.localeCompare(b.created)).slice(indexOfFirstMember, indexOfLastMember);
+ setSortedMembers(sortMembers);
+ }
+ }, [sortBy, filteredMembers, indexOfFirstMember, indexOfLastMember])
+
const active = currentPage;
- const pageAmount = Math.ceil(members.length / membersPerPage);
+ const pageAmount = Math.ceil(filteredMembers.length / membersPerPage);
- const memberList = currentMembers.map((member) =>
+ const memberList = sortedMembers.map((member) =>
@@ -64,49 +128,81 @@ export default function Memberlist(props) {
);
return (
- <>
- { isLoading ? : isError ?
- Error fetching members. Perhaps the member list has been set to private. :
- <>
-
-
-
-
-
- {
- setMembersPerPage(e.target.value);
- setCurrentPage(1);
- }}>
-
-
-
-
-
-
-
-
-
-
- {setValue(e.target.value); setCurrentPage(1)}} placeholder="Search"/>
-
-
-
- fetchMembers()}>Refresh
-
-
-
-
- { currentPage === 1 ? : setCurrentPage(currentPage - 1)} />}
- { currentPage < 3 ? "" : setCurrentPage(1)} active={1 === active}>{1}}
- { currentPage < 4 ? "" :}
- { currentPage > 1 ? setCurrentPage(currentPage - 1)}>{currentPage - 1} : "" }
- setCurrentPage(currentPage)} active={currentPage === active}>{currentPage}
- { currentPage < pageAmount ? setCurrentPage(currentPage + 1)}>{currentPage + 1} : "" }
- { currentPage > pageAmount - 3 ? "" : }
- { currentPage > pageAmount - 2 ? "" : setCurrentPage(pageAmount)} active={pageAmount === active}>{pageAmount}}
- { currentPage === pageAmount ? : setCurrentPage(currentPage + 1)} />}
-
-
+ <>
+
+
+
+
+
+ {
+ setMembersPerPage(e.target.value);
+ setCurrentPage(1);
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setSearchBy(e.target.value)
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setSortBy(e.target.value)
+ }}>
+
+
+
+
+
+
+
+
+
+
+
+
+ {setValue(e.target.value); setCurrentPage(1);}} placeholder={`Search by ${searchBy}`}/>
+
+
+
+ fetchMembers()}>Refresh
+
+
+
+
+ { currentPage === 1 ? : setCurrentPage(currentPage - 1)} />}
+ { currentPage < 3 ? "" : setCurrentPage(1)} active={1 === active}>{1}}
+ { currentPage < 4 ? "" :}
+ { currentPage > 1 ? setCurrentPage(currentPage - 1)}>{currentPage - 1} : "" }
+ setCurrentPage(currentPage)} active={currentPage === active}>{currentPage}
+ { currentPage < pageAmount ? setCurrentPage(currentPage + 1)}>{currentPage + 1} : "" }
+ { currentPage > pageAmount - 3 ? "" : }
+ { currentPage > pageAmount - 2 ? "" : setCurrentPage(pageAmount)} active={pageAmount === active}>{pageAmount}}
+ { currentPage === pageAmount ? : setCurrentPage(currentPage + 1)} />}
+
+
+ { isLoading ? : isError ?
+ Error fetching members. :
+ <>
{memberList}