UniversityOffers.jsx 5.31 KB
Newer Older
1
/* eslint-disable indent */
2
import React, { useState } from "react";
3
4
5
6
7
import PropTypes from "prop-types";
import compose from "recompose/compose";
import Close from "@material-ui/icons/Close";
import DoneAll from "@material-ui/icons/DoneAll";
import Paper from "@material-ui/core/Paper";
8
import { makeStyles } from "@material-ui/styles";
9
10
import Typography from "@material-ui/core/Typography";
import Chip from "@material-ui/core/Chip";
Florent Chehab's avatar
Florent Chehab committed
11
import withUnivInfo from "../../../hoc/withUnivInfo";
Florent Chehab's avatar
Florent Chehab committed
12
import RequestParams from "../../../utils/api/RequestParams";
13
import PaginatedData from "../../common/PaginatedData";
14
15
16
import withNetworkWrapper, {
  NetWrapParam
} from "../../../hoc/withNetworkWrapper";
17

18
const useStyles = makeStyles(theme => ({
19
  paper: {
20
    padding: theme.spacing(1)
21
22
23
24
25
26
27
  },
  chip: {
    margin: theme.spacing(0.5)
  },
  inlineIcon: {
    fontSize: "1em",
    position: "relative",
28
    top: ".125em"
29
30
31
  },
  itemRoot: {
    marginTop: theme.spacing(1),
32
    marginBottom: theme.spacing(1)
33
  }
34
}));
35
36

function Item(props) {
37
  const { majors, semester, seats, comment, master, doubleDegree } = props;
38
  const classes = useStyles();
39
40
41
42

  return (
    <div className={classes.itemRoot}>
      <div>
43
44
45
46
47
48
49
50
51
        <Chip label={semester} color="primary" className={classes.chip} />
        {majors.map(spe => (
          <Chip
            key={spe}
            label={<b>{spe}</b>}
            className={classes.chip}
            color="secondary"
          />
        ))}
52
53
      </div>
      <div>
54
55
56
57
58
59
60
        {seats ? (
          <>
            <Typography display="inline">Au total,&nbsp;</Typography>
            <Typography color="primary" display="inline">
              {seats}
              &nbsp; place
              {seats > 1 ? "s" : ""}
61
            </Typography>
62
63
64
65
66
67
68
69
70
71
72
            <Typography display="inline">
              &nbsp;
              {seats > 1 ? "étaient/sont disponibles" : "est/disponible"}.
            </Typography>
          </>
        ) : (
          <Typography variant="caption">
            Aucune information n'est disponible concernant le nombre de places
            disponibles.
          </Typography>
        )}
73
74
        <div>
          <Typography>
75
            Master&nbsp;
76
77
78
79
80
            {master ? (
              <DoneAll className={classes.inlineIcon} color="primary" />
            ) : (
              <Close className={classes.inlineIcon} color="error" />
            )}
81
82
          </Typography>
          <Typography>
83
            Double diplome&nbsp;
84
85
86
87
88
            {doubleDegree ? (
              <DoneAll className={classes.inlineIcon} color="primary" />
            ) : (
              <Close className={classes.inlineIcon} color="error" />
            )}
89
90
91
          </Typography>
        </div>
        <div>
92
          {comment && (
93
            <>
94
              <Typography variant="caption">Commentaire de la DRI :</Typography>
95
96
97
98
99
              <Typography>
                <em>{comment}</em>
              </Typography>
            </>
          )}
100
101
102
103
104
105
106
107
108
109
        </div>
      </div>
    </div>
  );
}

Item.propTypes = {
  doubleDegree: PropTypes.bool.isRequired,
  master: PropTypes.bool.isRequired,
  semester: PropTypes.string.isRequired,
Florent Chehab's avatar
Florent Chehab committed
110
  majors: PropTypes.arrayOf(PropTypes.string).isRequired,
111
  comment: PropTypes.string,
112
  seats: PropTypes.number
113
114
};

115
116
117
118
119
Item.defaultProps = {
  comment: "",
  seats: null
};

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
function renderEl(dataEl) {
  const {
    comment,
    double_degree: doubleDegree,
    is_master_offered: master,
    semester,
    year,
    majors,
    id,
    nb_seats_offered: seats
  } = dataEl;

  const p = {
    seats,
    id,
    doubleDegree,
    comment,
    master,
    majors: typeof majors === "string" ? majors.split(",") : [],
    semester: `${semester}${year}`
140
141
  };

142
143
  return <Item key={p.id} {...p} />;
}
144

145
function UniversityOffers({ offers, goToPage }) {
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  const classes = useStyles();

  return (
    <Paper className={classes.paper}>
      <Typography variant="h4">Possibilité(s) d'échanges</Typography>
      <Typography variant="caption">
        REX-DRI s'efforce d'être à jour avec l'ENT. Toutefois, seul l'ENT fait
        foi à 100% concernant les possibilités passées et actuelles d'échanges.
      </Typography>

      <PaginatedData
        data={offers}
        goToPage={goToPage}
        render={renderEl}
        stepperOnBottom
        stepperOnTop={false}
        EmptyMessageComponent={
          <Typography>
            <em>
              Aucune possibilité (passée ou présente) n'a été enregistrée à ce
              jour.
            </em>
          </Typography>
        }
      />
    </Paper>
  );
173
174
175
}

UniversityOffers.propTypes = {
176
177
  offers: PropTypes.object.isRequired,
  goToPage: PropTypes.func.isRequired
178
179
};

180
181
182
183
184
185
const buildParams = (univId, page) =>
  RequestParams.Builder.withQueryParam("university", univId)
    .withQueryParam("page", page)
    .withQueryParam("page_size", 3)
    .build();

186
const ConnectedComponent = compose(
187
  withUnivInfo(),
188
  withNetworkWrapper([
189
    new NetWrapParam("offers", "all", {
190
      addDataToProp: "offers",
191
192
193
194
195
196
      params: props => buildParams(props.univId, props.page),
      propTypes: {
        univId: PropTypes.number.isRequired,
        page: PropTypes.number.isRequired
      }
    })
197
  ])
198
)(UniversityOffers);
199
200
201
202
203
204
205

export default () => {
  // Lifting state up to work around NetworkWrapper limitations
  const [page, goToPage] = useState(1);

  return <ConnectedComponent page={page} goToPage={goToPage} />;
};