@selfcommunity/react-ui 0.7.50-event.29 → 0.7.50-event.30

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 (50) hide show
  1. package/lib/cjs/components/Event/Event.d.ts +0 -6
  2. package/lib/cjs/components/Event/Event.js +4 -4
  3. package/lib/cjs/components/Event/Skeleton.d.ts +16 -2
  4. package/lib/cjs/components/Event/Skeleton.js +16 -8
  5. package/lib/cjs/components/Event/index.d.ts +2 -2
  6. package/lib/cjs/components/EventForm/EventForm.js +10 -10
  7. package/lib/cjs/components/EventInviteButton/EventInviteButton.d.ts +57 -0
  8. package/lib/cjs/components/EventInviteButton/EventInviteButton.js +284 -0
  9. package/lib/cjs/components/EventInviteButton/index.d.ts +3 -0
  10. package/lib/cjs/components/EventInviteButton/index.js +5 -0
  11. package/lib/cjs/components/Events/Events.d.ts +64 -0
  12. package/lib/cjs/components/Events/Events.js +230 -0
  13. package/lib/cjs/components/Events/Skeleton.d.ts +38 -0
  14. package/lib/cjs/components/Events/Skeleton.js +45 -0
  15. package/lib/cjs/components/Events/constants.d.ts +1 -0
  16. package/lib/cjs/components/Events/constants.js +4 -0
  17. package/lib/cjs/components/Events/index.d.ts +4 -0
  18. package/lib/cjs/components/Events/index.js +8 -0
  19. package/lib/cjs/components/Events/prefetchedEvents.d.ts +271 -0
  20. package/lib/cjs/components/Events/prefetchedEvents.js +275 -0
  21. package/lib/cjs/constants/PubSub.d.ts +4 -3
  22. package/lib/cjs/constants/PubSub.js +2 -1
  23. package/lib/cjs/index.d.ts +4 -2
  24. package/lib/cjs/index.js +7 -2
  25. package/lib/esm/components/Event/Event.d.ts +0 -6
  26. package/lib/esm/components/Event/Event.js +4 -4
  27. package/lib/esm/components/Event/Skeleton.d.ts +16 -2
  28. package/lib/esm/components/Event/Skeleton.js +17 -9
  29. package/lib/esm/components/Event/index.d.ts +2 -2
  30. package/lib/esm/components/EventForm/EventForm.js +10 -10
  31. package/lib/esm/components/EventInviteButton/EventInviteButton.d.ts +57 -0
  32. package/lib/esm/components/EventInviteButton/EventInviteButton.js +281 -0
  33. package/lib/esm/components/EventInviteButton/index.d.ts +3 -0
  34. package/lib/esm/components/EventInviteButton/index.js +2 -0
  35. package/lib/esm/components/Events/Events.d.ts +64 -0
  36. package/lib/esm/components/Events/Events.js +227 -0
  37. package/lib/esm/components/Events/Skeleton.d.ts +38 -0
  38. package/lib/esm/components/Events/Skeleton.js +42 -0
  39. package/lib/esm/components/Events/constants.d.ts +1 -0
  40. package/lib/esm/components/Events/constants.js +1 -0
  41. package/lib/esm/components/Events/index.d.ts +4 -0
  42. package/lib/esm/components/Events/index.js +4 -0
  43. package/lib/esm/components/Events/prefetchedEvents.d.ts +271 -0
  44. package/lib/esm/components/Events/prefetchedEvents.js +275 -0
  45. package/lib/esm/constants/PubSub.d.ts +4 -3
  46. package/lib/esm/constants/PubSub.js +2 -1
  47. package/lib/esm/index.d.ts +4 -2
  48. package/lib/esm/index.js +3 -1
  49. package/lib/umd/react-ui.js +1 -1
  50. package/package.json +6 -6
@@ -0,0 +1,281 @@
1
+ import { __rest } from "tslib";
2
+ import React, { useContext, useEffect, useMemo, useState } from 'react';
3
+ import { useThemeProps } from '@mui/system';
4
+ import { styled } from '@mui/material/styles';
5
+ import { Avatar, Box, Button, Chip, Icon, IconButton, InputAdornment, TextField, Typography } from '@mui/material';
6
+ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
7
+ import { SCUserContext, useSCFetchEvent } from '@selfcommunity/react-core';
8
+ import classNames from 'classnames';
9
+ import BaseDialog from '../../shared/BaseDialog';
10
+ import { LoadingButton } from '@mui/lab';
11
+ import { EventService } from '@selfcommunity/api-services';
12
+ import Autocomplete from '@mui/material/Autocomplete';
13
+ import User from '../User';
14
+ import { SCOPE_SC_UI } from '../../constants/Errors';
15
+ import { Logger } from '@selfcommunity/utils';
16
+ import { SCGroupEventType, SCTopicType } from '../../constants/PubSub';
17
+ import PubSub from 'pubsub-js';
18
+ const messages = defineMessages({
19
+ placeholder: {
20
+ id: 'ui.eventInviteButton.searchBar.placeholder',
21
+ defaultMessage: 'ui.eventInviteButton.searchBar.placeholder'
22
+ }
23
+ });
24
+ const PREFIX = 'SCEventInviteButton';
25
+ const classes = {
26
+ root: `${PREFIX}-root`,
27
+ dialogRoot: `${PREFIX}-dialog-root`,
28
+ dialogTitle: `${PREFIX}-dialog-title`,
29
+ dialogContent: `${PREFIX}-dialog-content`,
30
+ autocomplete: `${PREFIX}-autocomplete`,
31
+ icon: `${PREFIX}-icon`,
32
+ input: `${PREFIX}-input`,
33
+ clear: `${PREFIX}-clear`,
34
+ invitedBox: `${PREFIX}-invited-box`,
35
+ suggested: `${PREFIX}-suggested`
36
+ };
37
+ const Root = styled(Button, {
38
+ name: PREFIX,
39
+ slot: 'Root',
40
+ overridesResolver: (props, styles) => styles.root
41
+ })(({ theme }) => ({}));
42
+ const DialogRoot = styled(BaseDialog, {
43
+ name: PREFIX,
44
+ slot: 'Root',
45
+ overridesResolver: (props, styles) => styles.dialogRoot
46
+ })(({ theme }) => ({}));
47
+ /**
48
+ *> API documentation for the Community-JS Event Invite Button component. Learn about the available props and the CSS API.
49
+ *
50
+ #### Import
51
+ ```jsx
52
+ import {SCEventInviteButton} from '@selfcommunity/react-ui';
53
+ ```
54
+
55
+ #### Component Name
56
+ The name `SCEventInviteButton` can be used when providing style overrides in the theme.
57
+
58
+ #### CSS
59
+
60
+ |Rule Name|Global class|Description|
61
+ |---|---|---|
62
+ |root|.SCEventInviteButton-root|Styles applied to the root element.|
63
+ |dialogRoot|.SCEventInviteButton-dialog-root|Styles applied to the dialog root.|
64
+ |dialogTitle|.SCEventInviteButton-dialog-title|Styles applied to the dialog title element.|
65
+ |dialogContent|.SCEventInviteButton-dialog-content|Styles applied to the dialog content.|
66
+ |autocomplete|.SCEventInviteButton-autocomplete|Styles applied to the autocomplete element.|
67
+ |icon|.SCEventInviteButton-icon|Styles applied to the autocomplete icon element.|
68
+ |input|.SCEventInviteButton-input|Styles applied to the autocomplete input element.|
69
+ |clear|.SCEventInviteButton-clear|Styles applied to the autocomplete clear icon element.|
70
+ |invitedBox|.SCEventInviteButton-invited-box|Styles applied to the invited users box.|
71
+ |suggested|.SCEventInviteButton-suggested|Styles applied to the suggested users box.|
72
+
73
+ * @param inProps
74
+ */
75
+ export default function EventInviteButton(inProps) {
76
+ var _a;
77
+ //PROPS
78
+ const props = useThemeProps({
79
+ props: inProps,
80
+ name: PREFIX
81
+ });
82
+ const { className, event, eventId, handleInvitations = null } = props, rest = __rest(props, ["className", "event", "eventId", "handleInvitations"]);
83
+ // CONTEXT
84
+ const scUserContext = useContext(SCUserContext);
85
+ // STATE
86
+ const [open, setOpen] = useState(false);
87
+ const [isSending, setIsSending] = useState(false);
88
+ const [value, setValue] = useState('');
89
+ const [suggested, setSuggested] = useState([]);
90
+ const [list, setList] = useState([]);
91
+ const [loading, setLoading] = useState(false);
92
+ const [invited, setInvited] = useState([]);
93
+ /**
94
+ * Notify UI when a member is invited to a event
95
+ * @param event
96
+ * @param usersInvited
97
+ */
98
+ function notifyChanges(event, usersInvited) {
99
+ if (event && usersInvited) {
100
+ PubSub.publish(`${SCTopicType.EVENT}.${SCGroupEventType.INVITE_MEMBER}`, usersInvited);
101
+ }
102
+ }
103
+ function convertToInvitedUsersObject(data) {
104
+ const invite_users = {};
105
+ data.forEach((user, index) => {
106
+ invite_users[`invite_users[${index}]`] = user.id;
107
+ });
108
+ return invite_users;
109
+ }
110
+ /**
111
+ * Memoized users invited ids
112
+ */
113
+ const ids = useMemo(() => {
114
+ if (invited) {
115
+ return invited.map((u) => {
116
+ return parseInt(u.id, 10);
117
+ });
118
+ }
119
+ return [invited];
120
+ }, [invited]);
121
+ // HOOKS
122
+ const { scEvent } = useSCFetchEvent({ id: eventId, event });
123
+ const isEventAdmin = useMemo(() => { var _a; return scUserContext.user && ((_a = scEvent === null || scEvent === void 0 ? void 0 : scEvent.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scEvent === null || scEvent === void 0 ? void 0 : scEvent.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
124
+ // INTL
125
+ const intl = useIntl();
126
+ function fetchResults() {
127
+ setLoading(true);
128
+ EventService.getEventSuggestedUsers(scEvent === null || scEvent === void 0 ? void 0 : scEvent.id, value)
129
+ .then((data) => {
130
+ setLoading(false);
131
+ setSuggested(data.results);
132
+ })
133
+ .catch((error) => {
134
+ setLoading(false);
135
+ Logger.error(SCOPE_SC_UI, error);
136
+ });
137
+ }
138
+ function fetchGeneralResults() {
139
+ setLoading(true);
140
+ EventService.getEventsSuggestedUsers(value)
141
+ .then((data) => {
142
+ setLoading(false);
143
+ setSuggested(data.results);
144
+ })
145
+ .catch((error) => {
146
+ setLoading(false);
147
+ Logger.error(SCOPE_SC_UI, error);
148
+ });
149
+ }
150
+ useEffect(() => {
151
+ if (scEvent === null || scEvent === void 0 ? void 0 : scEvent.id) {
152
+ EventService.getEventSuggestedUsers(scEvent === null || scEvent === void 0 ? void 0 : scEvent.id, value).then((data) => {
153
+ setLoading(false);
154
+ setList(data.results);
155
+ });
156
+ }
157
+ else {
158
+ EventService.getEventsSuggestedUsers(value).then((data) => {
159
+ setLoading(false);
160
+ setList(data.results);
161
+ });
162
+ }
163
+ }, [scEvent === null || scEvent === void 0 ? void 0 : scEvent.id]);
164
+ /**
165
+ * If a value is entered in new message field, it fetches user suggested
166
+ */
167
+ useEffect(() => {
168
+ if (scEvent) {
169
+ fetchResults();
170
+ }
171
+ else {
172
+ fetchGeneralResults();
173
+ }
174
+ }, [value, scEvent]);
175
+ /**
176
+ * Handles dialog close
177
+ */
178
+ const handleClose = () => {
179
+ setOpen((p) => !p);
180
+ };
181
+ /**
182
+ * Handles invitation sending
183
+ */
184
+ const handleSendInvitations = () => {
185
+ if (handleInvitations) {
186
+ handleInvitations(convertToInvitedUsersObject(invited));
187
+ setOpen(false);
188
+ }
189
+ else {
190
+ const data = { users: ids };
191
+ setIsSending(true);
192
+ EventService.inviteOrAcceptEventRequest(scEvent.id, data)
193
+ .then(() => {
194
+ setIsSending(false);
195
+ setOpen(false);
196
+ setInvited([]);
197
+ notifyChanges(scEvent, invited);
198
+ })
199
+ .catch((error) => {
200
+ setOpen(false);
201
+ setLoading(false);
202
+ Logger.error(SCOPE_SC_UI, error);
203
+ });
204
+ }
205
+ };
206
+ // Autocomplete Handlers
207
+ const handleInputChange = (event, value, reason) => {
208
+ switch (reason) {
209
+ case 'input':
210
+ setValue(value);
211
+ !value && setSuggested([]);
212
+ break;
213
+ case 'reset':
214
+ setValue(value);
215
+ break;
216
+ }
217
+ };
218
+ const handleChange = (event, value, reason, details) => {
219
+ event.preventDefault();
220
+ event.stopPropagation();
221
+ switch (reason) {
222
+ case 'selectOption':
223
+ setInvited(value);
224
+ setList((prev) => prev.filter((u) => u.id !== details.option.id));
225
+ break;
226
+ case 'removeOption':
227
+ setInvited(value);
228
+ setList((prev) => [...prev, details.option]);
229
+ break;
230
+ }
231
+ return false;
232
+ };
233
+ const handleUserInvite = (user) => {
234
+ setInvited((prev) => [...prev, user]);
235
+ setList((prev) => prev.filter((u) => u.id !== user.id));
236
+ };
237
+ const handleDelete = (option) => {
238
+ setInvited(invited.filter((v) => v !== option));
239
+ setList((prev) => [...prev, option]);
240
+ };
241
+ const filterOptions = (options, { inputValue }) => {
242
+ return options.filter((option) => {
243
+ const usernameMatch = option.username.toLowerCase().includes(inputValue.toLowerCase());
244
+ const nameMatch = option.real_name.toLowerCase().includes(inputValue.toLowerCase());
245
+ return usernameMatch || nameMatch;
246
+ });
247
+ };
248
+ /**
249
+ * If in event edit mode and logged-in user is not also the event manager, the component is hidden.
250
+ // */
251
+ if (event && !isEventAdmin) {
252
+ return null;
253
+ }
254
+ /**
255
+ * Renders root object
256
+ */
257
+ return (React.createElement(React.Fragment, null,
258
+ React.createElement(Root, Object.assign({ className: classNames(classes.root, className), onClick: handleClose, variant: scEvent ? 'contained' : 'outlined', color: scEvent ? 'secondary' : 'inherit', startIcon: React.createElement(Icon, null, "add") }, rest),
259
+ React.createElement(FormattedMessage, { id: "ui.eventInviteButton", defaultMessage: "ui.eventInviteButton" })),
260
+ open && (React.createElement(DialogRoot, { DialogContentProps: { dividers: false }, open: true, className: classes.dialogRoot, title: React.createElement(React.Fragment, null,
261
+ React.createElement(IconButton, { onClick: handleClose },
262
+ React.createElement(Icon, null, "arrow_back")),
263
+ React.createElement(Typography, { className: classes.dialogTitle },
264
+ React.createElement(FormattedMessage, { id: "ui.eventInviteButton.dialog.title", defaultMessage: "ui.eventInviteButton.dialog.title" })),
265
+ React.createElement(LoadingButton, { size: "small", color: "secondary", variant: "contained", onClick: handleSendInvitations, loading: isSending, disabled: !invited.length },
266
+ React.createElement(FormattedMessage, { id: "ui.eventInviteButton.dialog.button.end", defaultMessage: "ui.eventInviteButton.dialog.button.end" }))) },
267
+ React.createElement(Box, { className: classes.dialogContent },
268
+ React.createElement(Autocomplete, { className: classes.autocomplete, loading: loading, size: "small", multiple: true, freeSolo: true, disableClearable: true, options: suggested, onChange: handleChange, onInputChange: handleInputChange, inputValue: value, filterOptions: filterOptions, value: invited, getOptionLabel: (option) => (option ? option.username : '...'), isOptionEqualToValue: (option, value) => (option ? value.id === option.id : false), renderTags: () => null, renderOption: (props, option) => (React.createElement(Box, Object.assign({ component: "li" }, props),
269
+ React.createElement(Avatar, { alt: option.username, src: option.avatar }),
270
+ React.createElement(Typography, { ml: 1 }, option.username))), renderInput: (params) => (React.createElement(TextField, Object.assign({}, params, { variant: "outlined", placeholder: `${intl.formatMessage(messages.placeholder)}`, InputProps: Object.assign(Object.assign({}, params.InputProps), { className: classes.input, startAdornment: (React.createElement(React.Fragment, null,
271
+ React.createElement(InputAdornment, { position: "start" },
272
+ React.createElement(Icon, { className: classes.icon }, "search")),
273
+ params.InputProps.startAdornment)) }) }))) }),
274
+ React.createElement(Box, { className: classes.invitedBox }, invited.map((option, index) => (React.createElement(Chip, { key: index, avatar: React.createElement(Avatar, { alt: option.username, src: option.avatar }), label: option.username, onDelete: () => {
275
+ handleDelete(option);
276
+ }, style: { marginRight: 8 } })))),
277
+ React.createElement(Box, { className: classes.suggested },
278
+ list.length !== 0 && (React.createElement(Typography, { variant: "h4", fontWeight: "bold" },
279
+ React.createElement(FormattedMessage, { id: "ui.eventInviteButton.dialog.content.list", defaultMessage: "ui.eventInviteButton.dialog.content.list" }))),
280
+ list.slice(0, 5).map((user, index) => (React.createElement(User, { elevation: 0, actions: React.createElement(React.Fragment, null), user: user, userId: user.id, key: index, buttonProps: { onClick: () => handleUserInvite(user) } })))))))));
281
+ }
@@ -0,0 +1,3 @@
1
+ import EventInviteButton, { EventInviteButtonProps } from './EventInviteButton';
2
+ export default EventInviteButton;
3
+ export { EventInviteButtonProps };
@@ -0,0 +1,2 @@
1
+ import EventInviteButton from './EventInviteButton';
2
+ export default EventInviteButton;
@@ -0,0 +1,64 @@
1
+ import { EventProps } from '../Event';
2
+ export interface EventsProps {
3
+ /**
4
+ * Overrides or extends the styles applied to the component.
5
+ * @default null
6
+ */
7
+ className?: string;
8
+ /**
9
+ * Feed API Query Params
10
+ * @default [{'limit': 20, 'offset': 0}]
11
+ */
12
+ endpointQueryParams?: Record<string, string | number>;
13
+ /**
14
+ * Props to spread to single event object
15
+ * @default {}
16
+ */
17
+ EventComponentProps?: EventProps;
18
+ /**
19
+ * Show/Hide filters
20
+ * @default true
21
+ */
22
+ showFilters?: boolean;
23
+ /**
24
+ * Filters component
25
+ * @param props
26
+ */
27
+ filters?: JSX.Element;
28
+ /** If true, it means that the endpoint fetches all events available
29
+ * @default true
30
+ */
31
+ general?: boolean;
32
+ /**
33
+ * Other props
34
+ */
35
+ [p: string]: any;
36
+ }
37
+ /**
38
+ * > API documentation for the Community-JS Events component. Learn about the available props and the CSS API.
39
+ *
40
+ *
41
+ * The Events component renders the list of all available events.
42
+ * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Events)
43
+
44
+ #### Import
45
+ ```jsx
46
+ import {Events} from '@selfcommunity/react-ui';
47
+ ```
48
+ #### Component Name
49
+ The name `SCEvents` can be used when providing style overrides in the theme.
50
+
51
+ #### CSS
52
+
53
+ |Rule Name|Global class|Description|
54
+ |---|---|---|
55
+ |root|.SCEvents-root|Styles applied to the root element.|
56
+ |filters|.SCEvents-filters|Styles applied to the title element.|
57
+ |events|.SCEvents-events|Styles applied to the title element.|
58
+ |item|.SCEvents-item|Styles applied to the title element.|
59
+ |noResults|.SCEvents-no-results|Styles applied to no results section.|
60
+ |showMore|.SCEvents-show-more|Styles applied to show more button element.|
61
+
62
+ * @param inProps
63
+ */
64
+ export default function Events(inProps: EventsProps): JSX.Element;
@@ -0,0 +1,227 @@
1
+ import { __rest } from "tslib";
2
+ import React, { useContext, useEffect, useMemo, useState } from 'react';
3
+ import { styled } from '@mui/material/styles';
4
+ import { Box, Button, Chip, FormControl, Grid, Icon, InputLabel, MenuItem, Radio, Select, TextField, Typography } from '@mui/material';
5
+ import { Endpoints, EventService, http } from '@selfcommunity/api-services';
6
+ import { SCPreferences, SCPreferencesContext, SCUserContext, UserUtils } from '@selfcommunity/react-core';
7
+ import { SCEventDateFilterType } from '@selfcommunity/types';
8
+ import Event, { EventSkeleton } from '../Event';
9
+ import { FormattedMessage } from 'react-intl';
10
+ import classNames from 'classnames';
11
+ import { useThemeProps } from '@mui/system';
12
+ import { SCOPE_SC_UI } from '../../constants/Errors';
13
+ import { Logger, sortByAttr } from '@selfcommunity/utils';
14
+ import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
15
+ import { PREFIX } from './constants';
16
+ import Skeleton from '../Events/Skeleton';
17
+ import { DEFAULT_PAGINATION_OFFSET } from '../../constants/Pagination';
18
+ import CreateEventButton from '../CreateEventButton';
19
+ const classes = {
20
+ root: `${PREFIX}-root`,
21
+ filters: `${PREFIX}-filters`,
22
+ events: `${PREFIX}-events`,
23
+ item: `${PREFIX}-item`,
24
+ itemSkeleton: `${PREFIX}-item-skeleton`,
25
+ noResults: `${PREFIX}-no-results`,
26
+ showMore: `${PREFIX}-show-more`
27
+ };
28
+ const options = [
29
+ { value: SCEventDateFilterType.ANY, label: React.createElement(FormattedMessage, { id: "ui.events.select.any", defaultMessage: "ui.events.select.any" }) },
30
+ { value: SCEventDateFilterType.TODAY, label: React.createElement(FormattedMessage, { id: "ui.events.select.today", defaultMessage: "ui.events.select.today" }) },
31
+ { value: SCEventDateFilterType.TOMORROW, label: React.createElement(FormattedMessage, { id: "ui.events.select.tomorrow", defaultMessage: "ui.events.select.tomorrow" }) },
32
+ { value: SCEventDateFilterType.THIS_WEEK, label: React.createElement(FormattedMessage, { id: "ui.events.select.thisWeek", defaultMessage: "ui.events.select.thisWeek" }) },
33
+ { value: SCEventDateFilterType.NEXT_WEEK, label: React.createElement(FormattedMessage, { id: "ui.events.select.nextWeek", defaultMessage: "ui.events.select.nextWeek" }) },
34
+ { value: SCEventDateFilterType.THIS_MONTH, label: React.createElement(FormattedMessage, { id: "ui.events.select.thisMonth", defaultMessage: "ui.events.select.thisMonth" }) }
35
+ ];
36
+ const Root = styled(Box, {
37
+ name: PREFIX,
38
+ slot: 'Root'
39
+ })(() => ({}));
40
+ const ChipRoot = styled(Chip, {
41
+ name: PREFIX,
42
+ slot: 'ChipRoot'
43
+ })(() => ({}));
44
+ /**
45
+ * > API documentation for the Community-JS Events component. Learn about the available props and the CSS API.
46
+ *
47
+ *
48
+ * The Events component renders the list of all available events.
49
+ * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Events)
50
+
51
+ #### Import
52
+ ```jsx
53
+ import {Events} from '@selfcommunity/react-ui';
54
+ ```
55
+ #### Component Name
56
+ The name `SCEvents` can be used when providing style overrides in the theme.
57
+
58
+ #### CSS
59
+
60
+ |Rule Name|Global class|Description|
61
+ |---|---|---|
62
+ |root|.SCEvents-root|Styles applied to the root element.|
63
+ |filters|.SCEvents-filters|Styles applied to the title element.|
64
+ |events|.SCEvents-events|Styles applied to the title element.|
65
+ |item|.SCEvents-item|Styles applied to the title element.|
66
+ |noResults|.SCEvents-no-results|Styles applied to no results section.|
67
+ |showMore|.SCEvents-show-more|Styles applied to show more button element.|
68
+
69
+ * @param inProps
70
+ */
71
+ export default function Events(inProps) {
72
+ // PROPS
73
+ const props = useThemeProps({
74
+ props: inProps,
75
+ name: PREFIX
76
+ });
77
+ const { endpointQueryParams = { limit: 8, offset: DEFAULT_PAGINATION_OFFSET }, className, EventComponentProps = {}, showFilters = false, filters, general = true } = props, rest = __rest(props, ["endpointQueryParams", "className", "EventComponentProps", "showFilters", "filters", "general"]);
78
+ // STATE
79
+ const [events, setEvents] = useState([]);
80
+ const [loading, setLoading] = useState(true);
81
+ const [next, setNext] = useState(null);
82
+ const [search, setSearch] = useState('');
83
+ const [dateSearch, setDateSearch] = useState(options[0].value);
84
+ const [selected, setSelected] = useState(false);
85
+ // CONTEXT
86
+ const scUserContext = useContext(SCUserContext);
87
+ const scPreferencesContext = useContext(SCPreferencesContext);
88
+ const onlyStaffEnabled = useMemo(() => scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_EVENTS_ONLY_STAFF_ENABLED].value, [scPreferencesContext.preferences]);
89
+ // MEMO
90
+ const contentAvailability = SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY in scPreferencesContext.preferences &&
91
+ scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value;
92
+ // CONST
93
+ const authUserId = scUserContext.user ? scUserContext.user.id : null;
94
+ // HANDLERS
95
+ const handleChipClick = () => {
96
+ setSelected(!selected);
97
+ };
98
+ const handleDeleteClick = () => {
99
+ setSelected(false);
100
+ };
101
+ /**
102
+ * Fetches events list
103
+ */
104
+ const fetchEvents = () => {
105
+ let eventService;
106
+ if (general) {
107
+ eventService = EventService.searchEvents(Object.assign(Object.assign(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })), (dateSearch !== SCEventDateFilterType.ANY && { date_filter: dateSearch })), (selected && { follows: selected })));
108
+ }
109
+ else {
110
+ eventService = EventService.getUserEvents(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })));
111
+ }
112
+ eventService
113
+ .then((res) => {
114
+ setEvents(res.results);
115
+ setNext(res.next);
116
+ setLoading(false);
117
+ })
118
+ .catch((error) => {
119
+ Logger.error(SCOPE_SC_UI, error);
120
+ });
121
+ };
122
+ /**
123
+ * On mount, fetches events list
124
+ */
125
+ useEffect(() => {
126
+ if (!contentAvailability && !authUserId) {
127
+ return;
128
+ }
129
+ else {
130
+ fetchEvents();
131
+ }
132
+ }, [contentAvailability, authUserId, search, dateSearch, selected]);
133
+ const handleNext = useMemo(() => () => {
134
+ if (!next) {
135
+ return;
136
+ }
137
+ return http
138
+ .request({
139
+ url: next,
140
+ method: general ? Endpoints.SearchEvents.method : Endpoints.GetUserEvents.method
141
+ })
142
+ .then((res) => {
143
+ setEvents([...events, ...res.data.results]);
144
+ setNext(res.data.next);
145
+ })
146
+ .catch((error) => console.log(error))
147
+ .then(() => setLoading(false));
148
+ }, [next]);
149
+ /**
150
+ * Get events filtered
151
+ */
152
+ const getFilteredEvents = () => {
153
+ if (search) {
154
+ return events.filter((g) => g.name.toLowerCase().includes(search.toLowerCase()));
155
+ }
156
+ return events;
157
+ };
158
+ /**
159
+ * Handle change filter name
160
+ * @param event
161
+ */
162
+ const handleOnChangeFilterName = (event) => {
163
+ setSearch(event.target.value);
164
+ };
165
+ /**
166
+ * Handle change time frame
167
+ * @param event
168
+ */
169
+ const handleOnChangeTimeFrame = (event) => {
170
+ setDateSearch(event.target.value);
171
+ };
172
+ /**
173
+ * Renders events list
174
+ */
175
+ const filteredEvents = sortByAttr(getFilteredEvents(), 'order');
176
+ const c = (React.createElement(React.Fragment, null,
177
+ showFilters && (React.createElement(Grid, { container: true, className: classes.filters, gap: 2 }, filters ? (filters) : (React.createElement(React.Fragment, null,
178
+ React.createElement(Grid, { item: true, xs: 12, md: 4 },
179
+ React.createElement(TextField, { size: 'small', fullWidth: true, value: search, label: React.createElement(FormattedMessage, { id: "ui.events.filterByName", defaultMessage: "ui.events.filterByName" }), variant: "outlined", onChange: handleOnChangeFilterName, disabled: loading })),
180
+ React.createElement(Grid, { item: true, xs: 12, md: 2 },
181
+ React.createElement(FormControl, { fullWidth: true },
182
+ React.createElement(InputLabel, null,
183
+ React.createElement(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" })),
184
+ React.createElement(Select, { size: 'small', label: React.createElement(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" }), value: dateSearch, onChange: handleOnChangeTimeFrame, renderValue: (selected) => options.find((option) => option.value === selected).label }, options.map((option) => (React.createElement(MenuItem, { key: option.value, value: option.value },
185
+ React.createElement(Radio, { checked: dateSearch === option.value, value: option.value, name: "radio-button-select", inputProps: { 'aria-label': option.label } }),
186
+ option.label)))))),
187
+ React.createElement(Grid, { item: true, xs: 12, md: 2 },
188
+ React.createElement(ChipRoot
189
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
190
+ // @ts-ignore
191
+ , {
192
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
193
+ // @ts-ignore
194
+ color: selected ? 'secondary' : 'default',
195
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
196
+ // @ts-ignore
197
+ variant: selected ? 'filled' : 'outlined', label: React.createElement(FormattedMessage, { id: "ui.events.filterByFollowedInterest", defaultMessage: "ui.events.filterByFollowedInterest" }), onClick: handleChipClick,
198
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
199
+ // @ts-ignore
200
+ selected: selected, deleteIcon: selected ? React.createElement(Icon, null, "close") : null, onDelete: selected ? handleDeleteClick : null })))))),
201
+ React.createElement(React.Fragment, null, !events.length ? (React.createElement(Box, { className: classes.noResults }, (onlyStaffEnabled && !UserUtils.isStaff(scUserContext.user)) ||
202
+ (onlyStaffEnabled && UserUtils.isStaff(scUserContext.user) && general) ? (React.createElement(React.Fragment, null,
203
+ React.createElement(EventSkeleton, null),
204
+ React.createElement(Typography, { variant: "body1" },
205
+ React.createElement(FormattedMessage, { id: "ui.events.noEvents.title", defaultMessage: "ui.events.noEvents.title" })))) : (React.createElement(React.Fragment, null,
206
+ React.createElement(EventSkeleton, { action: React.createElement(CreateEventButton, null) }),
207
+ React.createElement(Typography, { variant: "body1" },
208
+ React.createElement(FormattedMessage, { id: "ui.events.noEvents.title.onlyStaff", defaultMessage: "ui.events.noEvents.title.onlyStaff" })))))) : (React.createElement(React.Fragment, null,
209
+ React.createElement(Grid, { container: true, spacing: { xs: 2 }, className: classes.events },
210
+ React.createElement(React.Fragment, null,
211
+ filteredEvents.map((event) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: event.id, className: classes.item },
212
+ React.createElement(Event, Object.assign({ event: event, eventId: event.id }, EventComponentProps))))),
213
+ filteredEvents.length <= 3 && (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: 'skeleton-item', className: classes.itemSkeleton },
214
+ React.createElement(EventSkeleton, { action: React.createElement(CreateEventButton, null) }))))),
215
+ Boolean(next) && (React.createElement(Button, { color: "secondary", variant: "text", onClick: handleNext, className: classes.showMore },
216
+ React.createElement(FormattedMessage, { id: "ui.events.button.seeMore", defaultMessage: "ui.events.button.seeMore" }))))))));
217
+ /**
218
+ * Renders root object (if content availability community option is false and user is anonymous, component is hidden)
219
+ */
220
+ if (!contentAvailability && !scUserContext.user) {
221
+ return React.createElement(HiddenPlaceholder, null);
222
+ }
223
+ if (loading) {
224
+ return React.createElement(Skeleton, null);
225
+ }
226
+ return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), c));
227
+ }
@@ -0,0 +1,38 @@
1
+ export interface EventsSkeletonProps {
2
+ /**
3
+ * Overrides or extends the styles applied to the component.
4
+ * @default null
5
+ */
6
+ className?: string;
7
+ /**
8
+ * Overrides or extends the styles applied to the component.
9
+ * @default null
10
+ */
11
+ EventSkeletonProps?: any;
12
+ /**
13
+ * @default 20
14
+ */
15
+ eventsNumber?: number;
16
+ }
17
+ /**
18
+ * > API documentation for the Community-JS Groups Skeleton component. Learn about the available props and the CSS API.
19
+
20
+ #### Import
21
+
22
+ ```jsx
23
+ import {EventsSkeleton} from '@selfcommunity/react-ui';
24
+ ```
25
+
26
+ #### Component Name
27
+
28
+ The name `SCEvents-skeleton-root` can be used when providing style overrides in the theme.
29
+
30
+ #### CSS
31
+
32
+ |Rule Name|Global class|Description|
33
+ |---|---|---|
34
+ |root|.SCEvents-skeleton-root|Styles applied to the root element.|
35
+ |events|.SCEvents-skeleton-events|Styles applied to the group elements.|
36
+ *
37
+ */
38
+ export default function EventsSkeleton(inProps: EventsSkeletonProps): JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { __rest } from "tslib";
2
+ import React from 'react';
3
+ import { styled } from '@mui/material/styles';
4
+ import { PREFIX } from './constants';
5
+ import { Box, Grid } from '@mui/material';
6
+ import classNames from 'classnames';
7
+ import { EventSkeleton } from '../Event';
8
+ const classes = {
9
+ root: `${PREFIX}-skeleton-root`,
10
+ events: `${PREFIX}-events`
11
+ };
12
+ const Root = styled(Box, {
13
+ name: PREFIX,
14
+ slot: 'SkeletonRoot'
15
+ })(() => ({}));
16
+ /**
17
+ * > API documentation for the Community-JS Groups Skeleton component. Learn about the available props and the CSS API.
18
+
19
+ #### Import
20
+
21
+ ```jsx
22
+ import {EventsSkeleton} from '@selfcommunity/react-ui';
23
+ ```
24
+
25
+ #### Component Name
26
+
27
+ The name `SCEvents-skeleton-root` can be used when providing style overrides in the theme.
28
+
29
+ #### CSS
30
+
31
+ |Rule Name|Global class|Description|
32
+ |---|---|---|
33
+ |root|.SCEvents-skeleton-root|Styles applied to the root element.|
34
+ |events|.SCEvents-skeleton-events|Styles applied to the group elements.|
35
+ *
36
+ */
37
+ export default function EventsSkeleton(inProps) {
38
+ const { className, EventSkeletonProps = {}, eventsNumber = 8 } = inProps, rest = __rest(inProps, ["className", "EventSkeletonProps", "eventsNumber"]);
39
+ return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest),
40
+ React.createElement(Grid, { container: true, spacing: { xs: 3 }, className: classes.events }, [...Array(eventsNumber)].map((event, index) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: index },
41
+ React.createElement(EventSkeleton, Object.assign({}, EventSkeletonProps))))))));
42
+ }
@@ -0,0 +1 @@
1
+ export declare const PREFIX = "SCEvents";
@@ -0,0 +1 @@
1
+ export const PREFIX = 'SCEvents';
@@ -0,0 +1,4 @@
1
+ import Events, { EventsProps } from './Events';
2
+ import EventsSkeleton, { EventsSkeletonProps } from './Skeleton';
3
+ export default Events;
4
+ export { EventsProps, EventsSkeleton, EventsSkeletonProps };