Skip to content

Commit

Permalink
fix: make the verify and captures pages consistent (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
tranquanghuy0801 authored Sep 28, 2021
1 parent de4e1ba commit c8f5cd3
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 110 deletions.
11 changes: 11 additions & 0 deletions src/common/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { verificationStates } from './variables';

export const getVerificationStatus = (active, approved) => {
if (active === true && approved === false) {
return verificationStates.AWAITING;
} else if (active === true && approved === true) {
return verificationStates.APPROVED;
} else if (active === false && approved === false) {
return verificationStates.REJECTED;
}
};
223 changes: 139 additions & 84 deletions src/components/CaptureTable.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState, useContext, createRef } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import {
Button,
Grid,
Table,
TableHead,
Expand All @@ -11,12 +12,16 @@ import {
TableSortLabel,
Typography,
} from '@material-ui/core';

import IconFilter from '@material-ui/icons/FilterList';
import { getDateTimeStringLocale } from '../common/locale';
import Filter, { FILTER_WIDTH } from './Filter';
import CaptureDetails from './CaptureDetails.js';
import { getVerificationStatus } from '../common/utils';
import LinkToWebmap from './common/LinkToWebmap';
import { CapturesContext } from '../context/CapturesContext';
import CaptureDetailDialog from './CaptureDetailDialog';
import Navbar from './Navbar';
import FilterTop from './FilterTop';
import { tokenizationStates } from '../common/variables';
import api from '../api/treeTrackerApi';

// change 88 to unit spacing,
const useStyle = makeStyles((theme) => ({
Expand All @@ -25,10 +30,9 @@ const useStyle = makeStyles((theme) => ({
paddingLeft: theme.spacing(16),
overflowX: 'auto',
},
tableContainer: {
width: `calc(100vw - ${FILTER_WIDTH + theme.spacing(4)}px)`,
overflowY: 'auto',
height: '100%',
tableGrid: {
width: '100%',
overflow: 'hidden',
},
tableRow: {
cursor: 'pointer',
Expand Down Expand Up @@ -67,26 +71,30 @@ const columns = [
label: 'Planter ID',
},
{
attr: 'payment',
label: 'Payment',
noSort: true,
renderer: () => 'pending',
attr: 'deviceIdentifier',
label: 'Device Identifier',
noSort: false,
},
{
attr: 'country',
label: 'Country',
attr: 'planterIdentifier',
label: 'Planter Identifier',
noSort: false,
},
{
attr: 'verificationStatus',
label: 'Verification Status',
noSort: true,
renderer: () => 'pending',
},
{
attr: 'speciesId',
label: 'Species',
noSort: true,
renderer: () => 'pending',
},
{
attr: 'status',
label: 'Status',
attr: 'tokenId',
label: 'Token Status',
renderer: (val) =>
val ? tokenizationStates.TOKENIZED : tokenizationStates.NOT_TOKENIZED,
},
{
attr: 'timeCreated',
Expand All @@ -99,13 +107,25 @@ const CaptureTable = () => {
const capturesContext = useContext(CapturesContext);
const capturesArray = capturesContext.captures;
const [isDetailsPaneOpen, setIsDetailsPaneOpen] = useState(false);
const [isFilterShown, setFilterShown] = useState(true);
const [speciesState, setSpeciesState] = useState({});
const scrollRef = createRef();
const classes = useStyle();

useEffect(() => {
loadSpecies();
loadCaptures();
}, []);

const loadSpecies = async () => {
const speciesList = await api.getSpecies(true);
let species = {};
speciesList.map((s) => {
species[s.id] = s.name;
});
setSpeciesState(species);
}

const loadCaptures = (payload) => {
capturesContext.getCapturesAsync(payload).then(() => {
scrollRef.current && scrollRef.current.scrollTo(0, 0);
Expand Down Expand Up @@ -150,6 +170,10 @@ const CaptureTable = () => {
});
};

const handleFilterClick = () => {
setFilterShown(!isFilterShown);
}

const createSortHandler = (attr) => {
return () => {
const order =
Expand All @@ -176,85 +200,116 @@ const CaptureTable = () => {
};

return (
<div className={classes.tableContainer} ref={scrollRef}>
<Grid
container
direction="row"
justify="space-between"
alignItems="center"
>
<Typography variant="h5" className={classes.title}>
Captures
</Typography>
{tablePagination()}
</Grid>
<Table data-testid="captures-table">
<TableHead>
<TableRow>
{columns.map(({ attr, label, noSort }) => (
<TableCell
key={attr}
sortDirection={
capturesContext.orderBy === attr
? capturesContext.order
: false
}
<>
<Grid container direction="column" className={classes.tableGrid}>
<Grid item>
<Navbar
buttons={[
<Button
variant="text"
color="primary"
onClick={handleFilterClick}
startIcon={<IconFilter />}
key={1}
>
<TableSortLabel
active={capturesContext.orderBy === attr}
direction={
capturesContext.orderBy === attr
? capturesContext.order
: 'asc'
}
onClick={createSortHandler(attr)}
disabled={noSort}
>
{label}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody data-testid="captures-table-body">
{capturesArray.map((capture) => (
<TableRow
key={capture.id}
onClick={createToggleDrawerHandler(capture.id)}
className={classes.tableRow}
Filter
</Button>,
]}
>
{isFilterShown && (
<FilterTop
isOpen={isFilterShown}
onSubmit={handleFilterSubmit}
filter={capturesContext.filter}
onClick={handleFilterClick}
/>
)}
</Navbar>
</Grid>
<Grid item>
<div className={classes.tableContainer} ref={scrollRef}>
<Grid
container
direction="row"
justify="space-between"
alignItems="center"
>
{columns.map(({ attr, renderer }) => (
<TableCell key={attr}>
{formatCell(capture, attr, renderer)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
{tablePagination()}
<CaptureDetails
capture={capturesContext.capture}
isDetailsPaneOpen={isDetailsPaneOpen}
closeDrawer={closeDrawer}
/>
<Filter
isOpen={true}
onSubmit={handleFilterSubmit}
filter={capturesContext.filter}
/>
</div>
<Typography variant="h5" className={classes.title}>
Captures
</Typography>
{tablePagination()}
</Grid>
<Table data-testid="captures-table">
<TableHead>
<TableRow>
{columns.map(({ attr, label, noSort }) => (
<TableCell
key={attr}
sortDirection={
capturesContext.orderBy === attr
? capturesContext.order
: false
}
>
<TableSortLabel
active={capturesContext.orderBy === attr}
direction={
capturesContext.orderBy === attr
? capturesContext.order
: 'asc'
}
onClick={createSortHandler(attr)}
disabled={noSort}
>
{label}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody data-testid="captures-table-body">
{capturesArray.map((capture) => (
<TableRow
key={capture.id}
onClick={createToggleDrawerHandler(capture.id)}
className={classes.tableRow}
>
{columns.map(({ attr, renderer }) => (
<TableCell key={attr}>
{formatCell(capture, speciesState, attr, renderer)}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
{tablePagination()}
<CaptureDetailDialog
open={isDetailsPaneOpen}
capture={capturesContext.capture}
onClose={closeDrawer}
/>
</div>
</Grid>
</Grid>
</>
);
};

const formatCell = (capture, attr, renderer) => {
const formatCell = (capture, speciesState, attr, renderer) => {
if (attr === 'id' || attr === 'planterId') {
return (
<LinkToWebmap
value={capture[attr]}
type={attr === 'id' ? 'tree' : 'user'}
/>
);
} else if (attr === 'speciesId') {
return capture[attr] === null ? '--' : speciesState[capture[attr]];
} else if (attr === 'verificationStatus') {
return capture['active'] === null || capture['approved'] === null
? '--'
: getVerificationStatus(capture['active'], capture['approved']);
} else {
return renderer ? renderer(capture[attr]) : capture[attr];
}
Expand Down
12 changes: 1 addition & 11 deletions src/components/Filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
convertDateToDefaultSqlDate,
} from '../common/locale';
import { datePickerDefaultMinDate } from '../common/variables';

import { getVerificationStatus } from '../common/utils';
import { verificationStates, tokenizationStates } from '../common/variables';

export const FILTER_WIDTH = 330;
Expand Down Expand Up @@ -297,14 +297,4 @@ function Filter(props) {
);
}

const getVerificationStatus = (active, approved) => {
if (active === true && approved === false) {
return verificationStates.AWAITING;
} else if (active === true && approved === true) {
return verificationStates.APPROVED;
} else if (active === false && approved === false) {
return verificationStates.REJECTED;
}
};

export default withStyles(styles)(Filter);
13 changes: 2 additions & 11 deletions src/components/FilterTop.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
tokenizationStates,
datePickerDefaultMinDate,
} from '../common/variables';
import { getVerificationStatus } from '../common/utils';
import { AppContext } from '../context/AppContext';
import { SpeciesContext } from '../context/SpeciesContext';
import { TagsContext } from '../context/TagsContext';
Expand Down Expand Up @@ -177,7 +178,7 @@ function Filter(props) {
id: ORGANIZATION_NOT_SET,
name: 'Not set',
},
];
];

return (
<>
Expand Down Expand Up @@ -443,14 +444,4 @@ function Filter(props) {
);
}

const getVerificationStatus = (active, approved) => {
if (active === true && approved === false) {
return verificationStates.AWAITING;
} else if (active === true && approved === true) {
return verificationStates.APPROVED;
} else if (active === false && approved === false) {
return verificationStates.REJECTED;
}
};

export default withStyles(styles)(Filter);
5 changes: 5 additions & 0 deletions src/components/tests/captures.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,14 @@ describe.skip('Captures', () => {
id: true,
timeCreated: true,
status: true,
active: true,
approved: true,
planterId: true,
treeTags: true,
planterIdentifier: true,
deviceIdentifier: true,
speciesId: true,
tokenId: true,
},
});

Expand Down
Loading

0 comments on commit c8f5cd3

Please sign in to comment.