Skip to content

Commit

Permalink
Merge pull request #2671 from OneCommunityGlobal/reina-filter-UI-badg…
Browse files Browse the repository at this point in the history
…e-management

Reina - Added changes to allow badge filtering in the badge management page
  • Loading branch information
one-community authored Jan 10, 2025
2 parents 71e8487 + e8f7424 commit a2d97ee
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 102 deletions.
6 changes: 5 additions & 1 deletion src/components/Badge/Badge.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
overflow: inherit;
}

#rank-filter {
width: 200px;
}

.badge_image_md > img {
border-radius: 50%;
height: 100px;
Expand Down Expand Up @@ -161,4 +165,4 @@
.responsive-font-size {
font-size: 0.75rem !important;
}
}
}
82 changes: 13 additions & 69 deletions src/components/Badge/BadgeDevelopment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import '../Header/DarkMode.css';
import { matches } from 'lodash';

function BadgeDevelopment(props) {
const { darkMode, allBadgeData = [] } = props;

const { darkMode, allBadgeData = [] } = props;
const [isCreateNewBadgePopupOpen, setCreateNewBadgePopupOpen] = useState(false);
const [isAddFiltersOpen, setAddFiltersOpen] = useState(false);
const [searchType, setSearchType] = useState('');
Expand All @@ -20,34 +19,15 @@ function BadgeDevelopment(props) {
const toggle = () => setCreateNewBadgePopupOpen(prevIsOpen => !prevIsOpen);
const toggleFilters = () => setAddFiltersOpen(prevState => !prevState);

const resetFilters = () => {
setSearchName('');
setSearchType('');
setRankFilter(300);
setChooseRankFilter('');
};

// convert rank number into integer
const chooseRankFilterNumber = chooseRankFilter ? Number(chooseRankFilter) : null;

// filter badge data based on type, report, and rank
const filteredBadgeData = allBadgeData.filter(badge => {
const matchesType =
searchType === '' ||
badge.type
.replace(/\s+/g, '')
.toLowerCase()
.includes(searchType.replace(/\s+/g, '').toLowerCase());
const matchesType = searchType === '' || badge.type.replace(/\s+/g, '').toLowerCase().includes(searchType.replace(/\s+/g, '').toLowerCase());
const matchesRank = badge.ranking <= rankFilter;
const matchesChoosenRank =
chooseRankFilterNumber === null || badge.ranking === chooseRankFilterNumber;

const matchesName =
searchName === '' ||
badge.badgeName
.replace(/\s+/g, '')
.toLowerCase()
.includes(searchName.replace(/\s+/g, '').toLowerCase());
const matchesChoosenRank = chooseRankFilterNumber === null || badge.ranking === chooseRankFilterNumber;
const matchesName = searchName === '' || badge.badgeName.replace(/\s+/g, '').toLowerCase().includes(searchName.replace(/\s+/g, '').toLowerCase());

return matchesType && matchesRank && matchesName && matchesChoosenRank;
});
Expand All @@ -68,15 +48,6 @@ function BadgeDevelopment(props) {
>
Add Filters
</Button>
{isAddFiltersOpen && (
<Button
className="btn--dark-sea-green"
onClick={resetFilters}
style={darkMode ? { ...boxStyleDark, margin: 20 } : { ...boxStyle, margin: 20 }}
>
Reset Filters
</Button>
)}
{isAddFiltersOpen && (
<div style={{ marginTop: '20px', paddingLeft: '20px' }}>
<div style={{ marginBottom: '10px' }}>
Expand All @@ -85,66 +56,39 @@ function BadgeDevelopment(props) {
type="text"
placeholder="Enter name here"
value={searchName}
onChange={e => setSearchName(e.target.value)}
style={{
width: '200px',
padding: '8px',
border: '1px solid #ccc',
borderRadius: '4px',
boxSizing: 'border-box',
marginTop: '5px',
}}
onChange={(e) => setSearchName(e.target.value)}
/>
</div>
<div style={{ marginBottom: '10px' }}>
<p style={{ display: 'inline', marginRight: '8px' }}>Filter by type:</p>
<select
value={searchType}
onChange={e => setSearchType(e.target.value)}
style={{
width: '230px',
padding: '8px',
border: '1px solid #ccc',
borderRadius: '4px',
boxSizing: 'border-box',
marginTop: '5px',
}}
onChange={(e) => setSearchType(e.target.value)}
>
<option value="">Select a type</option>
{BadgeTypes.map((type, index) => (
<option key={index} value={type}>
{type}
</option>
<option key={index} value={type}>{type}</option>
))}
</select>
</div>
<div>
<p style={{ display: 'inline', marginRight: '8px' }}>
Filter by Rank (0 - {rankFilter}):
</p>
<p style={{ display: 'inline', marginRight: '8px' }}>Filter by Rank (0 - {rankFilter}):</p>
<input
type="range"
id="rank-filter"
min="0"
max="300"
value={rankFilter}
onChange={e => setRankFilter(e.target.value)}
onChange={(e) => setRankFilter(e.target.value)}
/>
<div style={{ display: 'inline-block', marginLeft: '8px', verticalAlign: 'middle' }}>
<p style={{ display: 'inline', marginRight: '8px' }}>Or choose a rank:</p>
<input
type="text"
placeholder="Rank Number"
value={chooseRankFilter}
onChange={e => setChooseRankFilter(e.target.value)}
style={{
width: '120px',
padding: '8px',
border: '1px solid #ccc',
borderRadius: '4px',
boxSizing: 'border-box',
marginTop: '5px',
}}
onChange={(e) => setChooseRankFilter(e.target.value)}
style={{ width: '80px', textAlign: 'center' }}
/>
</div>
</div>
Expand All @@ -163,7 +107,7 @@ function BadgeDevelopment(props) {
<CreateNewBadgePopup toggle={toggle} />
</ModalBody>
</Modal>
<br />
<br/>
{filteredBadgeData.length === 0 ? (
<p> No badges match the current filters.</p>
) : (
Expand All @@ -173,4 +117,4 @@ function BadgeDevelopment(props) {
);
}

export default BadgeDevelopment;
export default BadgeDevelopment;
111 changes: 94 additions & 17 deletions src/components/Badge/BadgeDevelopmentTable.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';

import {
Container,
Button,
Expand All @@ -25,6 +26,9 @@ import './Badge.css';
function BadgeDevelopmentTable(props) {
const { darkMode } = props;

const canUpdateBadges = hasPermission('update:badges');
const canDeleteBadges = hasPermission('delete:badges');

const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [type, setType] = useState('');
Expand All @@ -36,8 +40,13 @@ function BadgeDevelopmentTable(props) {
const [editBadgeValues, setEditBadgeValues] = useState('');
const [editPopup, setEditPopup] = useState(false);

const canDeleteBadges = props.hasPermission('deleteBadges');
const canUpdateBadges = props.hasPermission('updateBadges');
const [sortedBadges, setSortedBadges] = useState([]);
const [sortNameState, setSortNameState] = useState('default');
const [sortRankState, setSortRankState] = useState('default');

useEffect(() => {
setSortedBadges(props.allBadgeData);
}, [props.allBadgeData]);

const detailsText = badegValue => {
let returnText = '';
Expand Down Expand Up @@ -153,9 +162,52 @@ function BadgeDevelopmentTable(props) {
return filteredList;
};

const filteredBadges = filterBadges(props.allBadgeData);

const handleSortName = () => {
console.log("here sort name");
setSortRankState('default');
setSortNameState(prevState => {
// change the icon
let newState = 'ascending';
if (prevState === 'ascending') newState = 'descending';
if (prevState === 'descending') newState = 'none';

// Sort the badges by name
const sorted = [...sortedBadges].sort((a, b) => {
if (newState === 'ascending') return a.badgeName.toLowerCase() > b.badgeName.toLowerCase() ? 1 : -1;
if (newState === 'descending') return a.badgeName.toLowerCase() < b.badgeName.toLowerCase() ? 1 : -1;
return 0;
});

setSortedBadges(sorted);
return newState;
});
};

const handleSortRank = () => {
setSortNameState('default');
console.log("sort rank");
setSortRankState(prevState => {
// Change the icon state
let newState = 'ascending';
if (prevState === 'ascending') newState = 'descending';
if (prevState === 'descending') newState = 'none';

// Sort the badges by ranking
const sorted = [...sortedBadges].sort((a, b) => {
if (newState === 'ascending') return a.ranking - b.ranking;
if (newState === 'descending') return b.ranking - a.ranking;
return 0;
});

setSortedBadges(sorted);
return newState;
});

};

const filteredBadges = sortedBadges;

// Badge Development checkbox
const reportBadge = badgeValue => {
// Returns true for all checked badges and false for all unchecked
const checkValue = !!badgeValue.showReport;
Expand Down Expand Up @@ -184,25 +236,50 @@ function BadgeDevelopmentTable(props) {
);
};


const onNameSort = () => {
setSortNameState((prevState) => {
if (prevState === 'ascending') return 'descending';
if (prevState === 'descending') return 'default';
return 'ascending';
});

const sortedBadges = [...props.allBadgeData].sort((a, b) => {
if (sortNameState === 'ascending') {
return a.badgeName.toLowerCase() > b.badgeName.toLowerCase() ? 1 : -1;
} else if (sortNameState === 'descending') {
return a.badgeName.toLowerCase() < b.badgeName.toLowerCase() ? 1 : -1;
}
return 0;
});

return sortedBadges;
};

const onRankSort = () => {
setSortRankState((prevState) => {
if (prevState === 'ascending') return 'descending';
if (prevState === 'descending') return 'default';
return 'ascending';
});


};

return (
<Container fluid>
<table
className={`table table-bordered ${darkMode ? 'bg-yinmn-blue text-light dark-mode' : ''}`}
>
<thead>
<BadgeTableHeader darkMode={darkMode} />
<BadgeTableFilter
onBadgeNameSearch={onBadgeNameSearch}
onBadgeDescriptionSearch={onBadgeDescriptionSearch}
onBadgeTypeSearch={onBadgeTypeSearch}
onBadgeRankingSort={onBadgeRankingSort}
resetFilters={resetFilters}
name={name}
description={description}
type={type}
order={order}
<BadgeTableHeader
darkMode={darkMode}
sortNameState={sortNameState}
sortRankState={sortRankState}
onNameSort={handleSortName}
onRankSort={handleSortRank}
/>

</thead>
<tbody>
{filteredBadges.map(value => (
Expand Down Expand Up @@ -323,4 +400,4 @@ const mapDispatchToProps = dispatch => ({
hasPermission: permission => dispatch(hasPermission(permission)),
});

export default connect(mapStateToProps, mapDispatchToProps)(BadgeDevelopmentTable);
export default connect(mapStateToProps, mapDispatchToProps)(BadgeDevelopmentTable);
11 changes: 4 additions & 7 deletions src/components/Badge/BadgeTableHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { UncontrolledTooltip } from 'reactstrap';

function BadgeTableHeader({ darkMode }) {
return (
<tr className={darkMode ? 'bg-space-cadet' : ''}>
Expand All @@ -8,23 +8,20 @@ function BadgeTableHeader({ darkMode }) {
<th className="d-xl-table-cell d-none">Description</th>
<th>Type</th>
<th className="d-xl-table-cell d-none">Details</th>
<th>
Ranking{' '}
<th>Ranking{' '}
<i className="fa fa-info-circle" id="SortRankingInfo" style={{ marginLeft: '5px' }} />
<UncontrolledTooltip
placement="right"
target="SortRankingInfo"
style={{ backgroundColor: '#666', color: '#fff' }}
>
<p className="badge_info_icon_text">
{' '}
Sort the number by ascending or descending order. The lower the number (other than zero)
the higher the badge ranking.
</p>
<p className="badge_info_icon_text">
{' '}
Note that 0 is treated as the largest number (thus the lowest ranking). When no number
is specified for the ranking field, the default value is 0.{' '}
is specified for the ranking field, the default value is 0.
</p>
<p className="badge_info_icon_text">
All badges of the same number in ranking sort alphabetically by their names.
Expand All @@ -37,4 +34,4 @@ function BadgeTableHeader({ darkMode }) {
);
}

export default BadgeTableHeader;
export default BadgeTableHeader;
15 changes: 8 additions & 7 deletions src/components/Projects/Project/Project.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ const Project = props => {
const canSeeProjectManagementFullFunctionality = props.hasPermission('seeProjectManagement');
const canEditCategoryAndStatus = props.hasPermission('editProject');


const updateProject = (key, value) => {
setProjectData({
...projectData,
[key]: value,
});
const updateProject = ({ updatedProject, status }) => async dispatch => {
try {
dispatch(updateProject({ updatedProject, status }));
} catch (err) {
const status = err?.response?.status || 500;
const error = err?.response?.data || { message: 'An error occurred' };
dispatch(updateProject({ status, error }));
}
};

const onDisplayNameChange = (e) => {
Expand Down Expand Up @@ -219,4 +221,3 @@ const Project = props => {
};
const mapStateToProps = state => state;
export default connect(mapStateToProps, { hasPermission, modifyProject, clearError })(Project);

1 change: 0 additions & 1 deletion src/components/Projects/Project/Project.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,3 @@ describe('Project Component', () => {
expect(screen.queryByText('Confirm Archive')).not.toBeInTheDocument();
});
});

0 comments on commit a2d97ee

Please sign in to comment.