@imerss/inat-components 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +0 -0
  2. package/declaration.d.ts +2 -0
  3. package/dist/index.d.ts +214 -0
  4. package/dist/index.js +876 -0
  5. package/package.json +53 -0
  6. package/public/favicon.ico +0 -0
  7. package/public/index.html +20 -0
  8. package/public/logo192.png +0 -0
  9. package/public/logo512.png +0 -0
  10. package/public/manifest.json +25 -0
  11. package/public/robots.txt +3 -0
  12. package/rollup.config.js +36 -0
  13. package/src/__shared/api/common-taxa.ts +56 -0
  14. package/src/__shared/api/favourites.ts +61 -0
  15. package/src/__shared/api/index.ts +4 -0
  16. package/src/__shared/api/recent-observations.ts +43 -0
  17. package/src/__shared/api/summary.ts +84 -0
  18. package/src/__shared/constants.ts +4 -0
  19. package/src/__shared/index.ts +4 -0
  20. package/src/__shared/typings.ts +69 -0
  21. package/src/__shared/utils/configUtils.ts +21 -0
  22. package/src/__shared/utils/dateUtils.ts +14 -0
  23. package/src/__shared/utils/index.ts +3 -0
  24. package/src/__shared/utils/numberUtils.ts +1 -0
  25. package/src/components/common-taxa/__tests__/common-taxa.test.tsx +14 -0
  26. package/src/components/common-taxa/common-taxa.tsx +99 -0
  27. package/src/components/error/__tests__/error.test.tsx +9 -0
  28. package/src/components/error/error.module.scss +7 -0
  29. package/src/components/error/error.tsx +15 -0
  30. package/src/components/favourites/__tests__/favourites.test.tsx +13 -0
  31. package/src/components/favourites/favourites.tsx +98 -0
  32. package/src/components/hooks/hooks.tsx +24 -0
  33. package/src/components/loader/__tests__/loader.test.tsx +10 -0
  34. package/src/components/loader/loader.tsx +26 -0
  35. package/src/components/no-results/__tests__/no-results.test.tsx +9 -0
  36. package/src/components/no-results/no-results.tsx +9 -0
  37. package/src/components/observation/__tests__/observation.test.tsx +14 -0
  38. package/src/components/observation/observation.module.scss +20 -0
  39. package/src/components/observation/observation.tsx +29 -0
  40. package/src/components/recent-observations/__tests__/recent-observations.test.tsx +9 -0
  41. package/src/components/recent-observations/recent-observations.tsx +101 -0
  42. package/src/components/seasonality-graph/__tests__/seasonality-graph.test.tsx +9 -0
  43. package/src/components/seasonality-graph/seasonality-graph.module.scss +7 -0
  44. package/src/components/seasonality-graph/seasonality-graph.tsx +46 -0
  45. package/src/components/shared/css/general.module.scss +69 -0
  46. package/src/components/summary/ObserverList.tsx +18 -0
  47. package/src/components/summary/__tests__/summary.test.tsx +18 -0
  48. package/src/components/summary/summary.module.scss +88 -0
  49. package/src/components/summary/summary.tsx +83 -0
  50. package/src/components/tabs/__tests__/tabs.test.tsx +16 -0
  51. package/src/components/tabs/tabs.module.scss +28 -0
  52. package/src/components/tabs/tabs.tsx +44 -0
  53. package/src/components/taxon-panel/__tests__/taxon-panel.test.tsx +10 -0
  54. package/src/components/taxon-panel/taxon-panel.module.scss +7 -0
  55. package/src/components/taxon-panel/taxon-panel.tsx +104 -0
  56. package/src/components/year-dropdown/__tests__/year-dropdown.test.tsx +14 -0
  57. package/src/components/year-dropdown/year-dropdown.module.scss +3 -0
  58. package/src/components/year-dropdown/year-dropdown.tsx +33 -0
  59. package/src/index.ts +15 -0
  60. package/tsconfig.json +6 -0
package/dist/index.js ADDED
@@ -0,0 +1,876 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import React, { useCallback, useState, useEffect } from 'react';
3
+ import { format } from 'date-fns';
4
+ import LoadingSpinner from 'react-spinners/MoonLoader.js';
5
+ import { Chart } from 'react-charts';
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+
22
+ var __assign = function() {
23
+ __assign = Object.assign || function __assign(t) {
24
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
25
+ s = arguments[i];
26
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
27
+ }
28
+ return t;
29
+ };
30
+ return __assign.apply(this, arguments);
31
+ };
32
+
33
+ function __awaiter(thisArg, _arguments, P, generator) {
34
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
35
+ return new (P || (P = Promise))(function (resolve, reject) {
36
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
37
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
38
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
39
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
40
+ });
41
+ }
42
+
43
+ function __generator(thisArg, body) {
44
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
45
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
46
+ function verb(n) { return function (v) { return step([n, v]); }; }
47
+ function step(op) {
48
+ if (f) throw new TypeError("Generator is already executing.");
49
+ while (_) try {
50
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
51
+ if (y = 0, t) op = [op[0] & 2, t.value];
52
+ switch (op[0]) {
53
+ case 0: case 1: t = op; break;
54
+ case 4: _.label++; return { value: op[1], done: false };
55
+ case 5: _.label++; y = op[1]; op = [0]; continue;
56
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
57
+ default:
58
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
59
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
60
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
61
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
62
+ if (t[2]) _.ops.pop();
63
+ _.trys.pop(); continue;
64
+ }
65
+ op = body.call(thisArg, _);
66
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
67
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
68
+ }
69
+ }
70
+
71
+ var BASE_API_URL = 'https://api.inaturalist.org';
72
+ var PER_PAGE = 100;
73
+ var BASE_URL = "https://www.inaturalist.org"; // /people/name_here
74
+ var ERROR_LOG_FILENAME = "inat-components-error.log";
75
+
76
+ var constants = /*#__PURE__*/Object.freeze({
77
+ __proto__: null,
78
+ BASE_API_URL: BASE_API_URL,
79
+ PER_PAGE: PER_PAGE,
80
+ BASE_URL: BASE_URL,
81
+ ERROR_LOG_FILENAME: ERROR_LOG_FILENAME
82
+ });
83
+
84
+ var getCommonTaxa = function (_a) {
85
+ var year = _a.year, taxonId = _a.taxonId, placeId = _a.placeId, perPage = _a.perPage;
86
+ return __awaiter(void 0, void 0, void 0, function () {
87
+ var url, response, resp, sortedTaxa;
88
+ return __generator(this, function (_b) {
89
+ switch (_b.label) {
90
+ case 0:
91
+ url = "".concat(BASE_API_URL, "/v1/observations/species_counts?verifiable=true&spam=false&place_id=").concat(placeId, "&taxon_id=").concat(taxonId, "&locale=en-US&per_page=").concat(perPage);
92
+ if (year !== "all") {
93
+ url += "&d1=".concat(year, "-01-01&d2=").concat(year, "-12-31");
94
+ }
95
+ return [4 /*yield*/, fetch(url, {
96
+ method: 'GET',
97
+ headers: {
98
+ Accept: 'application/json'
99
+ }
100
+ })];
101
+ case 1:
102
+ response = _b.sent();
103
+ return [4 /*yield*/, response.json()];
104
+ case 2:
105
+ resp = _b.sent();
106
+ sortedTaxa = resp.results.sort(function (a, b) {
107
+ if (a.count > b.count) {
108
+ return -1;
109
+ }
110
+ else if (a.count < b.count) {
111
+ return 1;
112
+ }
113
+ return 0;
114
+ });
115
+ return [2 /*return*/, {
116
+ totalResults: resp.total_results,
117
+ results: sortedTaxa.map(function (row) {
118
+ var _a, _b;
119
+ return ({
120
+ id: row.taxon.id,
121
+ imageUrl: ((_b = (_a = row.taxon) === null || _a === void 0 ? void 0 : _a.default_photo) === null || _b === void 0 ? void 0 : _b.square_url) || "",
122
+ obsCount: row.count,
123
+ taxonName: row.taxon.name || "",
124
+ taxonCommonName: row.taxon.preferred_common_name
125
+ });
126
+ })
127
+ }];
128
+ }
129
+ });
130
+ });
131
+ };
132
+
133
+ var getFavourites = function (_a) {
134
+ var year = _a.year, taxonId = _a.taxonId, placeId = _a.placeId, perPage = _a.perPage;
135
+ return __awaiter(void 0, void 0, void 0, function () {
136
+ var url, response, resp, sortedTaxa;
137
+ return __generator(this, function (_b) {
138
+ switch (_b.label) {
139
+ case 0:
140
+ url = "".concat(BASE_API_URL, "/v1/observations?verifiable=true&order_by=votes&order=desc&page=1&spam=false&place_id=").concat(placeId, "&taxon_id=").concat(taxonId, "&locale=en-US&per_page=").concat(perPage);
141
+ if (year !== "all") {
142
+ url += "&d1=".concat(year, "-01-01&d2=").concat(year, "-12-31");
143
+ }
144
+ return [4 /*yield*/, fetch(url, {
145
+ // method: 'GET',
146
+ // headers: {
147
+ // Accept: 'application/json'
148
+ // }
149
+ })];
150
+ case 1:
151
+ response = _b.sent();
152
+ return [4 /*yield*/, response.json()];
153
+ case 2:
154
+ resp = _b.sent();
155
+ sortedTaxa = resp.results.filter(function (i) { return i.faves.length > 0; }).sort(function (a, b) {
156
+ if (a.faves.length > b.faves.length) {
157
+ return -1;
158
+ }
159
+ else if (a.faves.length < b.faves.length) {
160
+ return 1;
161
+ }
162
+ return 0;
163
+ });
164
+ return [2 /*return*/, {
165
+ totalResults: resp.total_results,
166
+ results: sortedTaxa.map(function (row) {
167
+ var _a, _b;
168
+ return ({
169
+ id: row.id,
170
+ imageUrl: ((_b = (_a = row.taxon) === null || _a === void 0 ? void 0 : _a.default_photo) === null || _b === void 0 ? void 0 : _b.square_url) || "",
171
+ obsDate: row.observed_on_string,
172
+ obsUrl: row.uri,
173
+ taxonName: row.taxon.name || "",
174
+ taxonCommonName: row.taxon.preferred_common_name,
175
+ numFaves: row.faves.length
176
+ });
177
+ })
178
+ }];
179
+ }
180
+ });
181
+ });
182
+ };
183
+
184
+ var getRecentObservations = function (_a) {
185
+ var taxonId = _a.taxonId, placeId = _a.placeId, perPage = _a.perPage;
186
+ return __awaiter(void 0, void 0, void 0, function () {
187
+ var url, response, obs;
188
+ return __generator(this, function (_b) {
189
+ switch (_b.label) {
190
+ case 0:
191
+ url = "".concat(BASE_API_URL, "/v1/observations?photos=true&per_page=").concat(perPage, "&taxon_id=").concat(taxonId, "&place_id=").concat(placeId, "&order=desc&order_by=observed_on");
192
+ return [4 /*yield*/, fetch(url)];
193
+ case 1:
194
+ response = _b.sent();
195
+ return [4 /*yield*/, response.json()];
196
+ case 2:
197
+ obs = _b.sent();
198
+ return [2 /*return*/, {
199
+ totalResults: obs.total_results,
200
+ results: obs.results.map(function (obs) {
201
+ var _a;
202
+ return {
203
+ id: obs.id,
204
+ imageUrl: obs.observation_photos[0].photo.url,
205
+ obsUrl: obs.uri,
206
+ obsDate: obs.observed_on_string,
207
+ taxonName: ((_a = obs === null || obs === void 0 ? void 0 : obs.taxon) === null || _a === void 0 ? void 0 : _a.name) || "",
208
+ taxonCommonName: obs === null || obs === void 0 ? void 0 : obs.taxon.preferred_common_name,
209
+ observerUsername: obs.user.login
210
+ };
211
+ })
212
+ }];
213
+ }
214
+ });
215
+ });
216
+ };
217
+
218
+ var getSummary = function (_a) {
219
+ var taxonId = _a.taxonId, placeId = _a.placeId, year = _a.year;
220
+ return __awaiter(void 0, void 0, void 0, function () {
221
+ var observers, observations, seasonalityData;
222
+ return __generator(this, function (_b) {
223
+ switch (_b.label) {
224
+ case 0: return [4 /*yield*/, getObserverSummary(taxonId, placeId, year)];
225
+ case 1:
226
+ observers = _b.sent();
227
+ return [4 /*yield*/, getObservationSummary(taxonId, placeId, year)];
228
+ case 2:
229
+ observations = _b.sent();
230
+ return [4 /*yield*/, getSeasonalityData(taxonId, placeId, year)];
231
+ case 3:
232
+ seasonalityData = _b.sent();
233
+ return [2 /*return*/, {
234
+ observers: observers,
235
+ observations: observations,
236
+ seasonalityData: seasonalityData
237
+ }];
238
+ }
239
+ });
240
+ });
241
+ };
242
+ var getObserverSummary = function (taxonId, placeId, year) { return __awaiter(void 0, void 0, void 0, function () {
243
+ var url, response, data;
244
+ return __generator(this, function (_a) {
245
+ switch (_a.label) {
246
+ case 0:
247
+ url = "".concat(BASE_API_URL, "/v1/observations/observers?verifiable=true&order_by=votes&order=desc&page=1&spam=false&place_id=").concat(placeId, "&taxon_id=").concat(taxonId, "&locale=en-US&per_page=10");
248
+ if (year !== "all") {
249
+ url += "&d1=".concat(year, "-01-01&d2=").concat(year, "-12-31");
250
+ }
251
+ return [4 /*yield*/, fetch(url)];
252
+ case 1:
253
+ response = _a.sent();
254
+ return [4 /*yield*/, response.json()];
255
+ case 2:
256
+ data = _a.sent();
257
+ return [2 /*return*/, {
258
+ totalCount: data.total_results,
259
+ top: data.results.map(function (result) { return ({
260
+ id: result.user.id,
261
+ userName: result.user.login,
262
+ numObservations: result.observation_count,
263
+ iconUrl: result.user.icon_url
264
+ }); })
265
+ }];
266
+ }
267
+ });
268
+ }); };
269
+ var getObservationSummary = function (taxonId, placeId, year) { return __awaiter(void 0, void 0, void 0, function () {
270
+ var url, response, data;
271
+ return __generator(this, function (_a) {
272
+ switch (_a.label) {
273
+ case 0:
274
+ url = "".concat(BASE_API_URL, "/v1/observations?photos=true&per_page=1&taxon_id=").concat(taxonId, "&place_id=").concat(placeId, "&order=desc&order_by=observed_on");
275
+ if (year !== "all") {
276
+ url += "&d1=".concat(year, "-01-01&d2=").concat(year, "-12-31");
277
+ }
278
+ return [4 /*yield*/, fetch(url)];
279
+ case 1:
280
+ response = _a.sent();
281
+ return [4 /*yield*/, response.json()];
282
+ case 2:
283
+ data = _a.sent();
284
+ return [2 /*return*/, {
285
+ totalCount: data.total_results
286
+ }];
287
+ }
288
+ });
289
+ }); };
290
+ var getSeasonalityData = function (taxonId, placeId, year) { return __awaiter(void 0, void 0, void 0, function () {
291
+ var url, response, resp;
292
+ return __generator(this, function (_a) {
293
+ switch (_a.label) {
294
+ case 0:
295
+ url = "".concat(BASE_API_URL, "/v1/observations/histogram?verifiable=true&taxon_id=").concat(taxonId, "&place_id=").concat(placeId, "&locale=en-US&date_field=observed&interval=month_of_year");
296
+ if (year !== "all") {
297
+ url += "&d1=".concat(year, "-01-01&d2=").concat(year, "-12-31");
298
+ }
299
+ return [4 /*yield*/, fetch(url)];
300
+ case 1:
301
+ response = _a.sent();
302
+ return [4 /*yield*/, response.json()];
303
+ case 2:
304
+ resp = _a.sent();
305
+ return [2 /*return*/, {
306
+ monthOfYear: resp.results.month_of_year
307
+ }];
308
+ }
309
+ });
310
+ }); };
311
+
312
+ var DataSource;
313
+ (function (DataSource) {
314
+ DataSource["autoLoad"] = "autoLoad";
315
+ DataSource["dataProp"] = "dataProp";
316
+ DataSource["url"] = "url";
317
+ })(DataSource || (DataSource = {}));
318
+ var Feature;
319
+ (function (Feature) {
320
+ Feature["commonTaxa"] = "commonTaxa";
321
+ Feature["favourites"] = "favourites";
322
+ Feature["recentObservations"] = "recentObservations";
323
+ Feature["stats"] = "stats";
324
+ })(Feature || (Feature = {}));
325
+ // I know this is duplicated, but it's very possible they could be different in future
326
+ var Tab;
327
+ (function (Tab) {
328
+ Tab["recent"] = "recent";
329
+ Tab["commonTaxa"] = "commonTaxa";
330
+ Tab["favourites"] = "favourites";
331
+ Tab["stats"] = "stats";
332
+ })(Tab || (Tab = {}));
333
+
334
+ /*
335
+ * Note that right now the source filenames aren't configurable.
336
+ */
337
+ var getSourceFile = function (api, taxonInfo, placeInfo, year) {
338
+ var yearStr = year === "all" ? "allyears" : year;
339
+ var filename = "";
340
+ if (api === Feature.recentObservations) {
341
+ filename = "".concat(taxonInfo.short, "-").concat(placeInfo.short, "-recent.json");
342
+ }
343
+ else if (api === Feature.commonTaxa) {
344
+ filename = "".concat(taxonInfo.short, "-").concat(placeInfo.short, "-").concat(yearStr, "-commonTaxa.json");
345
+ }
346
+ else if (api === Feature.favourites) {
347
+ filename = "".concat(taxonInfo.short, "-").concat(placeInfo.short, "-").concat(yearStr, "-favourites.json");
348
+ }
349
+ else if (api === Feature.stats) {
350
+ filename = "".concat(taxonInfo.short, "-").concat(placeInfo.short, "-").concat(yearStr, "-stats.json");
351
+ }
352
+ return filename;
353
+ };
354
+
355
+ var getCurrentYear = function () { return new Date().getFullYear(); };
356
+ // not 100% this shows the date in the right timezone, but it's fine for BC
357
+ var formatDate = function (date, dateFormat) {
358
+ if (dateFormat === void 0) { dateFormat = "MMM do, h:mm b"; }
359
+ var formattedDate = "";
360
+ try {
361
+ formattedDate = format(Date.parse(date), dateFormat);
362
+ }
363
+ catch (e) {
364
+ console.log("Failed to parse date: ", date);
365
+ }
366
+ return formattedDate;
367
+ };
368
+
369
+ var numberWithCommas = function (x) { return (x || 0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); };
370
+
371
+ function styleInject(css, ref) {
372
+ if ( ref === void 0 ) ref = {};
373
+ var insertAt = ref.insertAt;
374
+
375
+ if (!css || typeof document === 'undefined') { return; }
376
+
377
+ var head = document.head || document.getElementsByTagName('head')[0];
378
+ var style = document.createElement('style');
379
+ style.type = 'text/css';
380
+
381
+ if (insertAt === 'top') {
382
+ if (head.firstChild) {
383
+ head.insertBefore(style, head.firstChild);
384
+ } else {
385
+ head.appendChild(style);
386
+ }
387
+ } else {
388
+ head.appendChild(style);
389
+ }
390
+
391
+ if (style.styleSheet) {
392
+ style.styleSheet.cssText = css;
393
+ } else {
394
+ style.appendChild(document.createTextNode(css));
395
+ }
396
+ }
397
+
398
+ var css_248z$5 = ".observation-module_obs__-5hGT {\n cursor: pointer;\n border-radius: 8px;\n background-color: #f9f9f9;\n text-align: center;\n transition: all 0.15s ease-in-out; }\n .observation-module_obs__-5hGT:hover {\n background-color: #e1e1e1; }\n\n.observation-module_obs__-5hGT h3 {\n margin: 0; }\n\n.observation-module_image__BBTP8 {\n max-width: 100%;\n max-height: 100%; }\n";
399
+ var styles$5 = {"obs":"observation-module_obs__-5hGT","image":"observation-module_image__BBTP8"};
400
+ styleInject(css_248z$5);
401
+
402
+ var Observation = function (_a) {
403
+ var imageUrl = _a.imageUrl, linkUrl = _a.linkUrl, children = _a.children;
404
+ var gotoObservation = useCallback(function () {
405
+ window.open(linkUrl);
406
+ }, [linkUrl]);
407
+ return (jsxs("article", __assign({ className: styles$5.obs, onClick: gotoObservation }, { children: [jsx("div", { style: {
408
+ width: 200,
409
+ height: 200,
410
+ overflow: "hidden",
411
+ borderRadius: 5,
412
+ background: "url(".concat(imageUrl, ") 50% 50% no-repeat"),
413
+ margin: "0 auto",
414
+ backgroundSize: "cover"
415
+ } }), children] })));
416
+ };
417
+
418
+ var css_248z$4 = ".general-module_page__ziNB9 {\n padding: 80px 10px 10px;\n margin: 0 auto;\n max-width: 1100px; }\n .general-module_page__ziNB9 h1 {\n border-bottom: 1px solid #efefef;\n padding-bottom: 2px;\n margin-bottom: 25px; }\n\n.general-module_panel__WjWzy {\n position: relative; }\n\n.general-module_grid__VwNiL {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n width: 100%;\n grid-gap: 8px;\n text-align: center; }\n\n.general-module_obsLabel__9R-PO {\n padding: 10px 20px; }\n .general-module_obsLabel__9R-PO a {\n text-decoration: none;\n color: #336699; }\n .general-module_obsLabel__9R-PO a:hover {\n text-decoration: underline; }\n\n.general-module_loader__gBvfF {\n position: absolute;\n top: 50px;\n left: 0;\n right: 0;\n z-index: 1;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center; }\n\n.general-module_loaderBg__URuj7 {\n position: absolute;\n background-color: #cccccc;\n padding: 20px;\n width: 100px;\n border-radius: 10px;\n height: 100%;\n opacity: 0.8; }\n\n.general-module_count__Gnr8W {\n background-color: #efefef;\n color: #666666;\n padding: 2px 8px;\n margin-top: 6px;\n display: inline-block;\n border-radius: 3px;\n font-weight: bold;\n font-size: 18px; }\n";
419
+ var styles$4 = {"page":"general-module_page__ziNB9","panel":"general-module_panel__WjWzy","grid":"general-module_grid__VwNiL","obsLabel":"general-module_obsLabel__9R-PO","loader":"general-module_loader__gBvfF","loaderBg":"general-module_loaderBg__URuj7","count":"general-module_count__Gnr8W"};
420
+ styleInject(css_248z$4);
421
+
422
+ var Loader = function (_a) {
423
+ var loading = _a.loading;
424
+ var loaderClasses = styles$4.loader;
425
+ // if (loading) {
426
+ // loaderClasses += ` ${styles.loading}`;
427
+ // }
428
+ if (!loading) {
429
+ return null;
430
+ }
431
+ return (jsxs("div", __assign({ className: loaderClasses }, { children: [jsx("div", { className: styles$4.loaderBg }), jsx(LoadingSpinner, { color: "#000000" })] })));
432
+ };
433
+
434
+ var NoResults = function () {
435
+ return (jsx("p", { children: "No results found." }));
436
+ };
437
+
438
+ var RecentObservationLabel = function (obs) { return (jsxs("div", __assign({ className: styles$4.obsLabel }, { children: [jsx("h3", { children: obs.taxonCommonName || obs.taxonName }), jsx("div", { children: formatDate(obs.obsDate) }), jsx("div", { children: jsx("a", __assign({ href: "".concat(BASE_URL, "/people/").concat(obs.observerUsername), target: "_blank", rel: "noreferrer", onClick: function (e) { return e.stopPropagation(); } }, { children: obs.observerUsername })) })] }))); };
439
+ var RecentObservations = function (_a) {
440
+ var taxonId = _a.taxonId, placeId = _a.placeId, data = _a.data, dataUrl = _a.dataUrl, _b = _a.source, source = _b === void 0 ? DataSource.autoLoad : _b, _c = _a.perPage, perPage = _c === void 0 ? PER_PAGE : _c, components = _a.components, className = _a.className;
441
+ var _d = useState(false), loading = _d[0], setLoading = _d[1];
442
+ var _e = useState(function () { return (source === DataSource.dataProp) ? data : []; }), observations = _e[0], setObservations = _e[1];
443
+ useEffect(function () {
444
+ if (source !== DataSource.autoLoad) {
445
+ return;
446
+ }
447
+ if (!taxonId) {
448
+ console.error("Please supply a `taxonId` prop for the `autoLoad` source prop option.");
449
+ return;
450
+ }
451
+ if (!placeId) {
452
+ console.error("Please supply a `placeId` prop for the `autoLoad` source prop option.");
453
+ return;
454
+ }
455
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
456
+ var obs;
457
+ return __generator(this, function (_a) {
458
+ switch (_a.label) {
459
+ case 0:
460
+ setLoading(true);
461
+ return [4 /*yield*/, getRecentObservations({ taxonId: taxonId, placeId: placeId, perPage: perPage })];
462
+ case 1:
463
+ obs = _a.sent();
464
+ setObservations(obs.results);
465
+ setLoading(false);
466
+ return [2 /*return*/];
467
+ }
468
+ });
469
+ }); })();
470
+ }, [source, taxonId, placeId, perPage]);
471
+ useEffect(function () {
472
+ if (source !== DataSource.url) {
473
+ return;
474
+ }
475
+ if (!dataUrl) {
476
+ console.error("Please supply a `dataUrl` prop for the `url` source prop option.");
477
+ return;
478
+ }
479
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
480
+ var obs, json;
481
+ return __generator(this, function (_a) {
482
+ switch (_a.label) {
483
+ case 0:
484
+ setLoading(true);
485
+ return [4 /*yield*/, fetch(dataUrl)];
486
+ case 1:
487
+ obs = _a.sent();
488
+ return [4 /*yield*/, obs.json()];
489
+ case 2:
490
+ json = _a.sent();
491
+ setObservations(json.results);
492
+ setLoading(false);
493
+ return [2 /*return*/];
494
+ }
495
+ });
496
+ }); })();
497
+ }, [source, dataUrl]);
498
+ var Load = (components === null || components === void 0 ? void 0 : components.loader) ? components.loader : Loader;
499
+ var Label = (components === null || components === void 0 ? void 0 : components.label) ? components.label : RecentObservationLabel;
500
+ var classes = styles$4.panel;
501
+ if (className) {
502
+ classes += " ".concat(className);
503
+ }
504
+ return (jsxs("div", __assign({ className: classes }, { children: [jsx(Load, { loading: loading }), jsxs("div", __assign({ className: styles$4.grid }, { children: [!loading && observations.length === 0 && jsx(NoResults, {}), observations.map(function (obs) { return (jsx(Observation, __assign({ imageUrl: obs.imageUrl.replace(/square/, "medium"), linkUrl: obs.obsUrl }, { children: jsx(Label, __assign({}, obs)) }), obs.id)); })] }))] })));
505
+ };
506
+
507
+ var css_248z$3 = "/*\n * Replace this with your own classes\n *\n * e.g.\n * .container {\n * }\n*/\n";
508
+ var styles$3 = {};
509
+ styleInject(css_248z$3);
510
+
511
+ var Error = function (props) {
512
+ return (jsx("div", __assign({ className: styles$3['container'] }, { children: jsx("h1", { children: "Welcome to Error!" }) })));
513
+ };
514
+
515
+ var CommonTaxaLabel = function (data) { return (jsxs("div", __assign({ className: styles$4.obsLabel }, { children: [jsx("h3", { children: data.taxonCommonName || data.taxonName }), jsx("label", __assign({ className: styles$4.count }, { children: numberWithCommas(data.obsCount) }))] }))); };
516
+ var CommonTaxa = function (_a) {
517
+ var year = _a.year, source = _a.source, taxonId = _a.taxonId, placeId = _a.placeId, _b = _a.perPage, perPage = _b === void 0 ? PER_PAGE : _b, data = _a.data, dataUrl = _a.dataUrl, components = _a.components, className = _a.className;
518
+ var _c = useState(function () { return (source === DataSource.dataProp) ? data : []; }), taxa = _c[0], setTaxa = _c[1];
519
+ var _d = useState(false), loading = _d[0], setLoading = _d[1];
520
+ useEffect(function () {
521
+ if (source !== DataSource.autoLoad) {
522
+ return;
523
+ }
524
+ if (!taxonId) {
525
+ console.error("Please supply a `taxonId` prop for the `autoLoad` source prop option.");
526
+ return;
527
+ }
528
+ if (!placeId) {
529
+ console.error("Please supply a `placeId` prop for the `autoLoad` source prop option.");
530
+ return;
531
+ }
532
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
533
+ var resp;
534
+ return __generator(this, function (_a) {
535
+ switch (_a.label) {
536
+ case 0:
537
+ setLoading(true);
538
+ return [4 /*yield*/, getCommonTaxa({ taxonId: taxonId, placeId: placeId, year: year, perPage: perPage })];
539
+ case 1:
540
+ resp = _a.sent();
541
+ setTaxa(resp.results);
542
+ setLoading(false);
543
+ return [2 /*return*/];
544
+ }
545
+ });
546
+ }); })();
547
+ }, [source, year, placeId, taxonId, perPage]);
548
+ useEffect(function () {
549
+ if (source !== DataSource.url) {
550
+ return;
551
+ }
552
+ if (!dataUrl) {
553
+ console.error("Please supply a `dataUrl` prop for the `url` source prop option.");
554
+ return;
555
+ }
556
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
557
+ var obs, json;
558
+ return __generator(this, function (_a) {
559
+ switch (_a.label) {
560
+ case 0:
561
+ setLoading(true);
562
+ return [4 /*yield*/, fetch(dataUrl)];
563
+ case 1:
564
+ obs = _a.sent();
565
+ return [4 /*yield*/, obs.json()];
566
+ case 2:
567
+ json = _a.sent();
568
+ setTaxa(json.results);
569
+ setLoading(false);
570
+ return [2 /*return*/];
571
+ }
572
+ });
573
+ }); })();
574
+ }, [source, dataUrl]);
575
+ var Load = (components === null || components === void 0 ? void 0 : components.loader) ? components.loader : Loader;
576
+ var Label = (components === null || components === void 0 ? void 0 : components.label) ? components.label : CommonTaxaLabel;
577
+ (components === null || components === void 0 ? void 0 : components.error) ? components.error : Error;
578
+ var classes = styles$4.panel;
579
+ if (className) {
580
+ classes += " ".concat(className);
581
+ }
582
+ return (jsxs("div", __assign({ className: classes }, { children: [jsx(Load, { loading: loading }), !loading && taxa.length === 0 && jsx(NoResults, {}), jsx("div", __assign({ className: styles$4.grid }, { children: taxa.map(function (data) { return (jsx(Observation, __assign({ imageUrl: data.imageUrl.replace(/square/, "medium"), linkUrl: "".concat(BASE_URL, "/").concat(data.id) }, { children: jsx(Label, __assign({}, data)) }), data.id)); }) }))] })));
583
+ };
584
+
585
+ var FavouritesLabel = function (data) { return (jsxs("div", __assign({ className: styles$4.obsLabel }, { children: [jsx("h3", { children: data.taxonCommonName || data.taxonName }), jsx("div", { children: data.observerUsername }), jsx("div", { children: formatDate(data.obsDate) }), jsx("label", __assign({ className: styles$4.count }, { children: data.numFaves }))] }))); };
586
+ var Favourites = function (_a) {
587
+ var year = _a.year, source = _a.source, taxonId = _a.taxonId, placeId = _a.placeId, data = _a.data, dataUrl = _a.dataUrl, components = _a.components, className = _a.className, _b = _a.perPage, perPage = _b === void 0 ? PER_PAGE : _b;
588
+ var _c = useState(function () { return (source === DataSource.dataProp) ? data : []; }), observations = _c[0], setObservations = _c[1];
589
+ var _d = useState(false), loading = _d[0], setLoading = _d[1];
590
+ useEffect(function () {
591
+ if (source !== DataSource.autoLoad) {
592
+ return;
593
+ }
594
+ if (!taxonId) {
595
+ console.error("Please supply a `taxonId` prop for the `autoLoad` source prop option.");
596
+ return;
597
+ }
598
+ if (!placeId) {
599
+ console.error("Please supply a `placeId` prop for the `autoLoad` source prop option.");
600
+ return;
601
+ }
602
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
603
+ var resp;
604
+ return __generator(this, function (_a) {
605
+ switch (_a.label) {
606
+ case 0:
607
+ setLoading(true);
608
+ return [4 /*yield*/, getFavourites({ taxonId: taxonId, placeId: placeId, year: year, perPage: perPage })];
609
+ case 1:
610
+ resp = _a.sent();
611
+ setObservations(resp.results);
612
+ setLoading(false);
613
+ return [2 /*return*/];
614
+ }
615
+ });
616
+ }); })();
617
+ }, [source, year, placeId, taxonId, perPage]);
618
+ useEffect(function () {
619
+ if (source !== DataSource.url) {
620
+ return;
621
+ }
622
+ if (!dataUrl) {
623
+ console.error("Please supply a `dataUrl` prop for the `url` source prop option.");
624
+ return;
625
+ }
626
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
627
+ var obs, json;
628
+ return __generator(this, function (_a) {
629
+ switch (_a.label) {
630
+ case 0:
631
+ setLoading(true);
632
+ return [4 /*yield*/, fetch(dataUrl)];
633
+ case 1:
634
+ obs = _a.sent();
635
+ return [4 /*yield*/, obs.json()];
636
+ case 2:
637
+ json = _a.sent();
638
+ setObservations(json.results);
639
+ setLoading(false);
640
+ return [2 /*return*/];
641
+ }
642
+ });
643
+ }); })();
644
+ }, [source, dataUrl]);
645
+ var Load = (components === null || components === void 0 ? void 0 : components.loader) ? components.loader : Loader;
646
+ var Label = (components === null || components === void 0 ? void 0 : components.label) ? components.label : FavouritesLabel;
647
+ var classes = styles$4.panel;
648
+ if (className) {
649
+ classes += " ".concat(className);
650
+ }
651
+ return (jsxs("div", __assign({ className: classes }, { children: [jsx(Load, { loading: loading }), !loading && observations.length === 0 && jsx(NoResults, {}), jsx("div", __assign({ className: styles$4.grid }, { children: observations.map(function (obs) { return (jsx(Observation, __assign({ imageUrl: obs.imageUrl.replace(/square/, "medium"), linkUrl: obs.obsUrl }, { children: jsx(Label, __assign({}, obs)) }), obs.id)); }) }))] })));
652
+ };
653
+
654
+ var css_248z$2 = ".summary-module_summaryPage__NMmsj {\n position: relative; }\n .summary-module_summaryPage__NMmsj section {\n display: flex; }\n\n.summary-module_top__TKW0j {\n list-style-type: none;\n margin: 0;\n padding: 0; }\n .summary-module_top__TKW0j .summary-module_avatar__16ZeD, .summary-module_top__TKW0j .summary-module_noAvatar__OsMWn {\n margin-right: 10px;\n border-radius: 20px;\n width: 40px;\n height: 40px; }\n .summary-module_top__TKW0j .summary-module_noAvatar__OsMWn {\n display: inline-block;\n background-color: #efefef; }\n .summary-module_top__TKW0j h3 {\n flex: 1;\n color: black; }\n .summary-module_top__TKW0j label {\n flex: 0;\n background-color: #efefef;\n color: #666666;\n padding: 2px 8px;\n margin-top: 6px;\n border-radius: 3px;\n font-weight: bold;\n font-size: 16px; }\n .summary-module_top__TKW0j li {\n border-radius: 3px; }\n .summary-module_top__TKW0j li a {\n display: flex;\n align-items: center;\n text-decoration: none; }\n .summary-module_top__TKW0j li:hover {\n background-color: #efefef; }\n\n.summary-module_countSummary__Xc2Kd {\n list-style-type: none;\n line-height: 28px;\n font-size: 16px;\n padding: 0;\n margin: 0 0 30px; }\n\n.summary-module_seasonalityBlock__BL8L- {\n flex: 3; }\n\n.summary-module_observersBlock__0wnbm {\n flex: 1;\n margin-left: 40px;\n margin-bottom: -40px; }\n\n@media screen and (max-width: 800px) {\n .summary-module_summaryPage__NMmsj section {\n display: block; }\n .summary-module_seasonalityBlock__BL8L- {\n height: 250px;\n margin-bottom: 80px; }\n .summary-module_observersBlock__0wnbm {\n margin-left: 0; } }\n";
655
+ var styles$2 = {"summaryPage":"summary-module_summaryPage__NMmsj","top":"summary-module_top__TKW0j","avatar":"summary-module_avatar__16ZeD","noAvatar":"summary-module_noAvatar__OsMWn","countSummary":"summary-module_countSummary__Xc2Kd","seasonalityBlock":"summary-module_seasonalityBlock__BL8L-","observersBlock":"summary-module_observersBlock__0wnbm"};
656
+ styleInject(css_248z$2);
657
+
658
+ var ObserverList = function (_a) {
659
+ var observers = _a.observers;
660
+ return (jsx("ul", __assign({ className: styles$2.top }, { children: observers.map(function (obs) { return (jsx("li", { children: jsxs("a", __assign({ href: "".concat(BASE_URL, "/people/").concat(obs.userName), target: "_blank", rel: "noreferrer" }, { children: [obs.iconUrl ? jsx("img", { src: obs.iconUrl || "", className: styles$2.avatar, alt: "User icon" }) :
661
+ jsx("div", { className: styles$2.noAvatar }), jsx("h3", { children: obs.userName }), jsx("label", { children: numberWithCommas(obs.numObservations) })] })) }, obs.id)); }) })));
662
+ };
663
+
664
+ var SeasonalityGraph = function (_a) {
665
+ var data = _a.data;
666
+ var primaryAxis = React.useMemo(function () { return ({
667
+ getValue: function (datum) { return datum.primary; }
668
+ }); }, []);
669
+ var secondaryAxes = React.useMemo(function () { return [
670
+ {
671
+ getValue: function (datum) { return datum.secondary; },
672
+ elementType: "area"
673
+ }
674
+ ]; }, []);
675
+ var formattedData = [
676
+ {
677
+ label: "Observations",
678
+ data: Object.keys(data).map(function (monthNum) { return ({
679
+ primary: format(new Date(2000, parseInt(monthNum, 10) - 1, 1), 'MMMM'),
680
+ secondary: data[monthNum]
681
+ }); })
682
+ }
683
+ ];
684
+ return (jsx(Chart, { options: {
685
+ data: formattedData,
686
+ primaryAxis: primaryAxis,
687
+ secondaryAxes: secondaryAxes
688
+ } }));
689
+ };
690
+
691
+ var Summary = function (_a) {
692
+ var _b, _c, _d;
693
+ var source = _a.source; _a.data; var dataUrl = _a.dataUrl, taxonId = _a.taxonId, placeId = _a.placeId, year = _a.year;
694
+ var _e = useState({}), summaryData = _e[0], setSummaryData = _e[1];
695
+ var _f = useState(false), loading = _f[0], setLoading = _f[1];
696
+ useEffect(function () {
697
+ if (source !== DataSource.autoLoad) {
698
+ return;
699
+ }
700
+ if (!taxonId) {
701
+ console.error("Please supply a `taxonId` prop for the `autoLoad` source prop option.");
702
+ return;
703
+ }
704
+ if (!placeId) {
705
+ console.error("Please supply a `placeId` prop for the `autoLoad` source prop option.");
706
+ return;
707
+ }
708
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
709
+ var data;
710
+ return __generator(this, function (_a) {
711
+ switch (_a.label) {
712
+ case 0:
713
+ setLoading(true);
714
+ return [4 /*yield*/, getSummary({ taxonId: taxonId, placeId: placeId, year: year })];
715
+ case 1:
716
+ data = _a.sent();
717
+ setSummaryData(data);
718
+ setLoading(false);
719
+ return [2 /*return*/];
720
+ }
721
+ });
722
+ }); })();
723
+ }, [source, year, placeId, taxonId]);
724
+ useEffect(function () {
725
+ if (source !== DataSource.url) {
726
+ return;
727
+ }
728
+ if (!dataUrl) {
729
+ console.error("Please supply a `dataUrl` prop for the `url` source prop option.");
730
+ return;
731
+ }
732
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
733
+ var obs, json;
734
+ return __generator(this, function (_a) {
735
+ switch (_a.label) {
736
+ case 0:
737
+ setLoading(true);
738
+ return [4 /*yield*/, fetch(dataUrl)];
739
+ case 1:
740
+ obs = _a.sent();
741
+ return [4 /*yield*/, obs.json()];
742
+ case 2:
743
+ json = _a.sent();
744
+ setSummaryData(json);
745
+ setLoading(false);
746
+ return [2 /*return*/];
747
+ }
748
+ });
749
+ }); })();
750
+ }, [source, dataUrl]);
751
+ return (jsxs("div", __assign({ className: styles$2.summaryPage }, { children: [jsx(Loader, { loading: loading }), jsxs("ul", __assign({ className: styles$2.countSummary }, { children: [jsxs("li", { children: ["Total number of observers: ", jsx("b", { children: ((_b = summaryData.observers) === null || _b === void 0 ? void 0 : _b.totalCount) ? numberWithCommas(summaryData.observers.totalCount) : "" })] }), jsxs("li", { children: ["Total number of observations: ", jsx("b", { children: ((_c = summaryData.observations) === null || _c === void 0 ? void 0 : _c.totalCount) ? numberWithCommas(summaryData.observations.totalCount) : "" })] })] })), jsxs("section", { children: [jsxs("div", __assign({ className: styles$2.seasonalityBlock }, { children: [jsx("h1", { children: "Seasonality" }), summaryData.seasonalityData && jsx(SeasonalityGraph, { data: summaryData.seasonalityData.monthOfYear })] })), jsxs("div", __assign({ className: styles$2.observersBlock }, { children: [jsx("h1", { children: "Top observers" }), ((_d = summaryData.observers) === null || _d === void 0 ? void 0 : _d.top) && jsx(ObserverList, { observers: summaryData.observers.top })] }))] })] })));
752
+ };
753
+
754
+ var css_248z$1 = ".year-dropdown-module_dropdown__iD9sj {\n font-size: 18px; }\n";
755
+ var styles$1 = {"dropdown":"year-dropdown-module_dropdown__iD9sj"};
756
+ styleInject(css_248z$1);
757
+
758
+ var Years = function (_a) {
759
+ var value = _a.value, onChange = _a.onChange, className = _a.className;
760
+ var years = useState(function () {
761
+ var currentYear = getCurrentYear();
762
+ var years = [];
763
+ for (var i = currentYear; i >= currentYear - 10; i--) {
764
+ years.push(i);
765
+ }
766
+ return years;
767
+ })[0];
768
+ var classes = styles$1.dropdown;
769
+ if (className) {
770
+ classes += " ".concat(className);
771
+ }
772
+ return (jsxs("select", __assign({ className: classes, onChange: function (e) { return onChange(e.target.value); }, defaultValue: value }, { children: [jsx("option", __assign({ value: "all" }, { children: "All years" })), years.map(function (year) { return jsx("option", __assign({ value: year }, { children: year }), year); })] })));
773
+ };
774
+
775
+ var css_248z = ".tabs-module_tabs__UMeM9 {\n display: flex;\n flex-direction: row;\n list-style: none;\n font-size: 18px;\n padding: 0;\n margin-bottom: 30px; }\n .tabs-module_tabs__UMeM9 li {\n margin: 0 20px;\n padding: 4px 20px;\n cursor: pointer;\n color: #999999;\n transition: all 0.2s ease-in-out; }\n .tabs-module_tabs__UMeM9 li.tabs-module_selected__SVr0E, .tabs-module_tabs__UMeM9 li:hover {\n border-bottom: 5px solid #0099cc;\n color: black; }\n\n@media screen and (max-width: 600px) {\n .tabs-module_tabs__UMeM9 li {\n margin: 0 5px;\n padding: 4px 6px; } }\n";
776
+ var styles = {"tabs":"tabs-module_tabs__UMeM9","selected":"tabs-module_selected__SVr0E"};
777
+ styleInject(css_248z);
778
+
779
+ var _a;
780
+ var defaultTitles = (_a = {},
781
+ _a[Tab.recent] = "Recent",
782
+ _a[Tab.commonTaxa] = "Most common",
783
+ _a[Tab.favourites] = "Most favourited",
784
+ _a[Tab.stats] = "General stats",
785
+ _a);
786
+ var useFeatureTitles = function (features) {
787
+ var _a = useState(defaultTitles), titles = _a[0], setTitles = _a[1];
788
+ useEffect(function () {
789
+ var _a;
790
+ var _b, _c, _d, _e;
791
+ setTitles((_a = {},
792
+ _a[Tab.recent] = ((_b = features.recentObservations) === null || _b === void 0 ? void 0 : _b.label) || defaultTitles[Tab.recent],
793
+ _a[Tab.commonTaxa] = ((_c = features.commonTaxa) === null || _c === void 0 ? void 0 : _c.label) || defaultTitles[Tab.commonTaxa],
794
+ _a[Tab.favourites] = ((_d = features.favourites) === null || _d === void 0 ? void 0 : _d.label) || defaultTitles[Tab.favourites],
795
+ _a[Tab.stats] = ((_e = features.stats) === null || _e === void 0 ? void 0 : _e.label) || defaultTitles[Tab.stats],
796
+ _a));
797
+ }, [features]);
798
+ return titles;
799
+ };
800
+
801
+ var Tabs = function (_a) {
802
+ var selectedTab = _a.selectedTab, onChangeTab = _a.onChangeTab, features = _a.features;
803
+ var titles = useFeatureTitles(features);
804
+ return (jsxs("ul", __assign({ className: styles.tabs }, { children: [features.recentObservations && (jsx("li", __assign({ onClick: function () { return onChangeTab(Tab.recent); }, className: selectedTab === Tab.recent ? styles.selected : "" }, { children: titles[Tab.recent] }))), features.commonTaxa && (jsx("li", __assign({ onClick: function () { return onChangeTab(Tab.commonTaxa); }, className: selectedTab === Tab.commonTaxa ? styles.selected : "" }, { children: titles[Tab.commonTaxa] }))), features.favourites && (jsx("li", __assign({ onClick: function () { return onChangeTab(Tab.favourites); }, className: selectedTab === Tab.favourites ? styles.selected : "" }, { children: titles[Tab.favourites] }))), features.stats && (jsx("li", __assign({ onClick: function () { return onChangeTab(Tab.stats); }, className: selectedTab === Tab.stats ? styles.selected : "" }, { children: titles[Tab.stats] })))] })));
805
+ };
806
+
807
+ var TaxonPanel = function (_a) {
808
+ var taxonId = _a.taxonId, placeId = _a.placeId, dataSource = _a.dataSource, config = _a.config, baseURL = _a.baseURL;
809
+ var _b = useState(Tab.recent), tab = _b[0], setTab = _b[1];
810
+ var _c = useState("all"), year = _c[0], setYear = _c[1];
811
+ var titles = useFeatureTitles(config.features);
812
+ var _d = useState(function () { return config.taxa.find(function (i) { return i.taxonId === taxonId; }); }), taxonInfo = _d[0]; _d[1];
813
+ var _e = useState(function () { return config.places.find(function (i) { return i.placeId === placeId; }); }), placeInfo = _e[0]; _e[1];
814
+ var getCurrentTab = function () {
815
+ switch (tab) {
816
+ case Tab.recent: {
817
+ var props = {
818
+ source: dataSource
819
+ };
820
+ if (dataSource === DataSource.url) {
821
+ props.dataUrl = baseURL + '/' + getSourceFile(Feature.recentObservations, taxonInfo, placeInfo);
822
+ }
823
+ else {
824
+ props.placeId = placeId;
825
+ props.taxonId = taxonId;
826
+ }
827
+ return (jsx(RecentObservations, __assign({}, props)));
828
+ }
829
+ case Tab.commonTaxa: {
830
+ var props = {
831
+ source: dataSource,
832
+ year: year
833
+ };
834
+ if (dataSource === DataSource.url) {
835
+ props.dataUrl = baseURL + '/' + getSourceFile(Feature.commonTaxa, taxonInfo, placeInfo, year);
836
+ }
837
+ else {
838
+ props.placeId = placeId;
839
+ props.taxonId = taxonId;
840
+ }
841
+ return (jsx(CommonTaxa, __assign({}, props)));
842
+ }
843
+ case Tab.favourites: {
844
+ var props = {
845
+ source: dataSource,
846
+ year: year
847
+ };
848
+ if (dataSource === DataSource.url) {
849
+ props.dataUrl = baseURL + '/' + getSourceFile(Feature.favourites, taxonInfo, placeInfo, year);
850
+ }
851
+ else {
852
+ props.placeId = placeId;
853
+ props.taxonId = taxonId;
854
+ }
855
+ return (jsx(Favourites, __assign({}, props)));
856
+ }
857
+ case Tab.stats: {
858
+ var props = {
859
+ source: dataSource,
860
+ year: year
861
+ };
862
+ if (dataSource === DataSource.url) {
863
+ props.dataUrl = baseURL + '/' + getSourceFile(Feature.stats, taxonInfo, placeInfo, year);
864
+ }
865
+ else {
866
+ props.placeId = placeId;
867
+ props.taxonId = taxonId;
868
+ }
869
+ return jsx(Summary, __assign({}, props));
870
+ }
871
+ }
872
+ };
873
+ return (jsxs("div", __assign({ className: styles$4.page }, { children: [jsx(Tabs, { selectedTab: tab, onChangeTab: setTab, features: config.features }), jsxs("div", { children: [tab !== Tab.recent && (jsx("div", __assign({ style: { float: "right" } }, { children: jsx(Years, { value: year, onChange: setYear }) }))), jsx("h1", { children: titles[tab] })] }), getCurrentTab()] })));
874
+ };
875
+
876
+ export { constants as C, CommonTaxa, CommonTaxaLabel, DataSource, Favourites, FavouritesLabel, Feature, Observation, RecentObservationLabel, RecentObservations, SeasonalityGraph, Summary, Tab, TaxonPanel as default, formatDate, getCommonTaxa, getCurrentYear, getFavourites, getObservationSummary, getObserverSummary, getRecentObservations, getSeasonalityData, getSourceFile, getSummary, numberWithCommas };