Skip to content

Commit 6c7281b

Browse files
authored
Merge pull request #284 from CodeForPhilly/ui-updates
UI updates
2 parents 4681add + 7483ce9 commit 6c7281b

File tree

13 files changed

+662
-210
lines changed

13 files changed

+662
-210
lines changed

src/client/src/App.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ function AuthenticatedApp() {
8888
const hdr = userRole === 'admin' ? <AdminHeader/> : <Header/> // If we're going to display a header, which one?
8989

9090
const history = useHistory();
91-
debugger;
9291

9392
return (
9493
<Router>

src/client/src/pages/DataView360/View/View360.js

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {Component} from 'react';
22
import {withStyles} from '@material-ui/core/styles';
3-
import {withRouter} from "react-router";
3+
import {withRouter, matchPath} from "react-router";
44

55
import {
66
Paper,
@@ -14,10 +14,10 @@ import {
1414
import _ from 'lodash';
1515
import moment from 'moment';
1616
import ContactInfo from './components/ContactInfo';
17-
import Volunteer from './components/Volunteer';
1817
import Donations from './components/Donations';
19-
import Adoptions from './components/Adoptions';
20-
import {matchPath} from "react-router";
18+
import AnimalInfo from './components/AnimalInfo';
19+
import VolunteerActivity from './components/VolunteerActivity';
20+
import VolunteerHistory from './components/VolunteerHistory';
2121

2222

2323
const customStyles = theme => ({
@@ -40,6 +40,9 @@ class View360 extends Component {
4040

4141
this.state = {
4242
participantData: {},
43+
animalData: {},
44+
adoptionEvents: {},
45+
fosterEvents: {},
4346
matchId: undefined,
4447
isDataBusy: false,
4548
}
@@ -49,13 +52,12 @@ class View360 extends Component {
4952
}
5053

5154
async componentDidMount() {
52-
this.setState({
55+
await this.setState({
5356
isDataBusy: true,
5457
showSearchBar: false,
5558
matchId: _.last(this.props.location.pathname.split('/'))
5659
});
5760

58-
await new Promise(resolve => setTimeout(resolve, 1000));
5961
let response = await fetch(`/api/360/${this.state.matchId}`,
6062
{
6163
method: 'GET',
@@ -66,13 +68,39 @@ class View360 extends Component {
6668
});
6769
response = await response.json();
6870

71+
let animalInfo = await fetch(`/api/person/${this.state.matchId}/animals`);
72+
animalInfo = await animalInfo.json()
73+
const animalIds = _.keys(animalInfo);
74+
75+
let adoptionEvents = {};
76+
let fosterEvents = {};
77+
78+
for (let id of animalIds) {
79+
let events = await this.getAnimalEvents(id, this.state.matchId);
80+
81+
adoptionEvents[id] = _.filter(events[id], function(e) {
82+
return e["Type"] && e["Type"].toLowerCase().includes("adopt");
83+
});
84+
fosterEvents[id] = _.filter(events[id], function(e) {
85+
return e["Type"] && e["Type"].toLowerCase().includes("foster");
86+
});
87+
}
88+
6989
this.setState({
7090
participantData: response.result,
91+
animalData: animalInfo,
92+
adoptionEvents: adoptionEvents,
93+
fosterEvents: fosterEvents,
7194
isDataBusy: false
7295
});
7396

7497
}
7598

99+
async getAnimalEvents(animalId, matchId) {
100+
let response = await fetch(`/api/person/${matchId}/animal/${animalId}/events`);
101+
return await response.json()
102+
}
103+
76104
extractVolunteerActivity() {
77105
const volgistics = _.find(this.state.participantData.contact_details, {"source_type": "volgistics"}) || {};
78106
let volunteerActivity = {"life_hours": 0, "ytd_hours": 0, "start_date": "N/A"}
@@ -127,14 +155,24 @@ class View360 extends Component {
127155
</Button>
128156
</Grid>
129157
</Grid>
158+
130159
</Grid>
131160
<Grid item xs={8} className={classes.tablesCol}>
132161
<Grid container direction="column" style={{"marginTop": "1em"}}>
133162
<Donations donations={_.get(this.state, 'participantData.donations')}/>
134-
<Adoptions adoptions={_.get(this.state, 'participantData.adoptions')}
135-
adoption_person_id={_.get(this.state, 'participantData.adoptions_person_id')}/>
136-
<Volunteer volunteer={this.extractVolunteerActivity()}
137-
volunteerShifts={_.get(this.state, 'participantData.shifts')}/>
163+
<AnimalInfo pets={_.get(this.state, 'animalData')}
164+
events={_.get(this.state, 'adoptionEvents')}
165+
headerText={"Adoption Records"}
166+
shelterluv_id={_.get(this.state, 'participantData.shelterluv_id')}
167+
168+
/>
169+
<AnimalInfo pets={_.get(this.state, 'animalData')}
170+
events={_.get(this.state, 'fosterEvents')}
171+
headerText={"Foster Records"}
172+
shelterluv_id={_.get(this.state, 'participantData.shelterluv_id')}
173+
/>
174+
<VolunteerActivity volunteer={this.extractVolunteerActivity()} />
175+
<VolunteerHistory volunteerShifts={_.get(this.state, 'participantData.shifts')} />
138176
</Grid>
139177
</Grid>
140178
</Grid>

src/client/src/pages/DataView360/View/components/Adoptions.js

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
1-
import React, {Component} from 'react';
1+
import React, { Component } from 'react';
22
import {
33
Paper,
44
Typography,
5-
Table,
6-
TableContainer,
7-
TableHead,
8-
TableBody,
9-
TableRow,
10-
TableCell,
115
Container,
126
IconButton
137
} from '@material-ui/core';
148
import LinkIcon from '@material-ui/icons/Link';
15-
import {withStyles} from '@material-ui/core/styles';
9+
import { withStyles } from '@material-ui/core/styles';
1610
import _ from 'lodash';
1711
import moment from "moment";
1812
import Grid from "@material-ui/core/Grid";
1913
import PetsIcon from "@material-ui/icons/Pets";
2014

15+
import CollapsibleTable from './CollapsibleTable';
16+
import DataTableHeader from './DataTableHeader';
17+
2118

2219
const customStyles = theme => ({
2320
spaceIcon: {
@@ -26,84 +23,47 @@ const customStyles = theme => ({
2623
},
2724
headerCell: {
2825
fontWeight: "bold",
26+
},
27+
paper: {
28+
position: 'absolute',
29+
width: 400,
30+
backgroundColor: theme.palette.background.paper,
31+
border: '2px solid #000',
32+
boxShadow: theme.shadows[5],
33+
padding: theme.spacing(2, 4, 3),
2934
}
3035
});
3136

32-
const PET_COUNT = 3;
37+
const PET_COUNT = 5;
3338

3439
class Adoptions extends Component {
3540

36-
getLatestPets(petList) {
37-
let retVal;
38-
39-
if (petList) {
40-
retVal = petList.slice(0, PET_COUNT);
41-
}
42-
43-
return retVal;
44-
}
45-
46-
getAnimalAge(epochTime) {
47-
let dateOfBirth = moment(epochTime * 1000);
48-
return moment().diff(dateOfBirth, 'years');
41+
getLatestPets(petObject) {
42+
return petObject;
4943
}
5044

5145
render() {
52-
const {classes} = this.props;
46+
const { classes } = this.props;
5347
const numOfPets = _.size(this.props.adoptions);
5448
const latestPets = this.getLatestPets(this.props.adoptions);
55-
const shelterLuvPersonURL = `https://www.shelterluv.com/phlp-p-${this.props.adoption_person_id}`
56-
57-
return (<Container component={Paper} style={{"marginTop": "1em"}}>
58-
<Typography variant='h5'>
59-
<Grid container style={{"margin": "0.5em"}} direction={'row'}>
60-
<Grid item className={classes.spaceIcon}>
61-
<PetsIcon color='primary' fontSize='inherit'/>
62-
</Grid>
63-
<Grid item>
64-
Adoption/Foster Records {(numOfPets > 3) && "(Showing 3 Pets out of " + numOfPets + ")"}
65-
</Grid>
66-
{
67-
this.props.adoption_person_id &&
68-
<Grid item>
69-
<IconButton style={{'padding': 0, 'paddingLeft': 5}} color="primary" aria-label="link" href={shelterLuvPersonURL}>
70-
<LinkIcon />
71-
</IconButton>
72-
</Grid>
73-
}
7449

50+
const events = this.props.events;
51+
const headerText = "Adoption Records"
52+
const headerAddition = (numOfPets > PET_COUNT) ? " (Showing " + PET_COUNT + " Pets out of " + numOfPets + ")" : ""
53+
54+
return (
55+
<Container component={Paper} style={{ "marginTop": "1em" }}>
56+
<DataTableHeader
57+
headerText={headerText + headerAddition}
58+
emojiIcon={<PetsIcon color='primary' fontSize='inherit' />}
59+
>
60+
<Grid item>
61+
<IconButton style={{ 'padding': 0, 'paddingLeft': 5 }} color="primary" aria-label="link" href={shelterLuvPersonURL}>
62+
<LinkIcon />
63+
</IconButton>
7564
</Grid>
76-
</Typography>
77-
78-
<TableContainer component={Paper} style={{"marginBottom": "1em"}} variant='outlined'>
79-
<Table>
80-
<TableHead>
81-
<TableRow>
82-
<TableCell className={classes.headerCell} align="center">Name</TableCell>
83-
<TableCell className={classes.headerCell} align="center">Animal Type</TableCell>
84-
<TableCell className={classes.headerCell} align="center">Breed</TableCell>
85-
<TableCell className={classes.headerCell} align="center">Age</TableCell>
86-
<TableCell className={classes.headerCell} align="center">Photo</TableCell>
87-
</TableRow>
88-
</TableHead>
89-
<TableBody>
90-
{_.map(latestPets, (adoptionInfo, index) => {
91-
92-
const photoLink = _.get(adoptionInfo, "Photos.[0]");
93-
const photo = <img src={photoLink} alt="animal" style={{"maxWidth": "100px"}}/>
94-
95-
return <TableRow key={index}>
96-
<TableCell align="center">{adoptionInfo["Name"]}</TableCell>
97-
<TableCell align="center">{adoptionInfo["Type"]}</TableCell>
98-
<TableCell align="center">{adoptionInfo["Breed"]}</TableCell>
99-
<TableCell
100-
align="center">{this.getAnimalAge(adoptionInfo["DOBUnixTime"])}</TableCell>
101-
<TableCell align="center">{photo}</TableCell>
102-
</TableRow>
103-
})}
104-
</TableBody>
105-
</Table>
106-
</TableContainer>
65+
</DataTableHeader>
66+
<CollapsibleTable data={latestPets} events={events} />
10767
</Container>
10868
);
10969
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React, { Component } from 'react';
2+
import {
3+
Paper,
4+
Container,
5+
IconButton
6+
} from '@material-ui/core';
7+
import LinkIcon from '@material-ui/icons/Link';
8+
import { withStyles } from '@material-ui/core/styles';
9+
import _ from 'lodash';
10+
import Grid from "@material-ui/core/Grid";
11+
import PetsIcon from "@material-ui/icons/Pets";
12+
13+
import CollapsibleTable from './CollapsibleTable';
14+
import DataTableHeader from './DataTableHeader';
15+
16+
17+
const customStyles = theme => ({
18+
spaceIcon: {
19+
marginTop: 3,
20+
marginRight: 3
21+
},
22+
headerCell: {
23+
fontWeight: "bold",
24+
},
25+
paper: {
26+
position: 'absolute',
27+
width: 400,
28+
backgroundColor: theme.palette.background.paper,
29+
border: '2px solid #000',
30+
boxShadow: theme.shadows[5],
31+
padding: theme.spacing(2, 4, 3),
32+
}
33+
});
34+
35+
const PET_COUNT = 5;
36+
37+
class AnimalInfo extends Component {
38+
39+
getLatestPets(petObject, events) {
40+
41+
function customizer(objValue, srcValue) {
42+
if (_.isObject(objValue) && _.isObject(srcValue)) {
43+
// sort according to date of most recent event
44+
return _.set(objValue, 'Events', _.orderBy(srcValue, ['Time'], ['desc']));
45+
}
46+
}
47+
48+
let result = _.mergeWith(petObject, events, customizer);
49+
let nonEmptyEvents = _.filter(result, function(pet) { return pet["Events"] && pet["Events"].length > 0 });
50+
result = [..._.orderBy(nonEmptyEvents, ['Events[0].Time'], ['desc'])]
51+
return result.slice(0, PET_COUNT);
52+
}
53+
54+
render() {
55+
const numOfPets = _.size(this.props.pets);
56+
const events = this.props.events;
57+
const latestPets = this.getLatestPets(this.props.pets, events);
58+
const headerText = this.props.headerText;
59+
const headerAddition = (numOfPets > PET_COUNT) ? " (Showing " + PET_COUNT + " Pets out of " + numOfPets + ")" : ""
60+
const shelterLuvPersonURL = `https://www.shelterluv.com/phlp-p-${this.props.shelterluv_id}`;
61+
62+
return (
63+
<Container component={Paper} style={{ "marginTop": "1em" }}>
64+
<DataTableHeader headerText={headerText + headerAddition}
65+
emojiIcon={<PetsIcon color='primary' fontSize='inherit'/>}
66+
>
67+
<Grid item>
68+
<IconButton style={{ 'padding': 0, 'paddingLeft': 5 }} color="primary" aria-label="link" href={shelterLuvPersonURL} target="_blank">
69+
<LinkIcon />
70+
</IconButton>
71+
</Grid>
72+
</DataTableHeader>
73+
<CollapsibleTable data={latestPets} events={events} />
74+
</Container>
75+
);
76+
}
77+
}
78+
79+
80+
export default withStyles(customStyles)(AnimalInfo);

0 commit comments

Comments
 (0)