groovinads-ui 1.2.60 → 1.2.61

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "groovinads-ui",
3
3
  "description": "Groovinads UI is a React component library designed exclusively for Groovinads applications. It provides ready-to-use UI elements styled according to Groovinads design guidelines to facilitate rapid development.",
4
- "version": "1.2.60",
4
+ "version": "1.2.61",
5
5
  "keywords": [
6
6
  "css",
7
7
  "sass",
@@ -0,0 +1,166 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ // COMPONENTS GROOVINADS
5
+ import Input from './Input';
6
+ import { Button } from '../Button';
7
+
8
+ import { ComponentsService } from '../../services';
9
+ import { Icon, Spinner } from '../Labels';
10
+
11
+ const InputEmail = ({
12
+ showModal = true,
13
+ titleList = 'Added emails',
14
+ label = 'Email addresses',
15
+ textButton = 'Add',
16
+ textError = 'You must enter a valid email address',
17
+ apiGetEmail,
18
+ apiPostEmail,
19
+ apiDeleteEmail,
20
+ }) => {
21
+ // STATE
22
+ const [notifications, setNotifications] = useState([]);
23
+ const [newEmail, setNewEmail] = useState('');
24
+
25
+ const [selectedButton, setSelectedButton] = useState([]);
26
+
27
+ const [emailInvalid, setEmailInvalid] = useState(false);
28
+
29
+ // VARIABLES
30
+ const validEmailPattern = /^\w+([.-_+]?\w+)*@\w+([.-]?\w+)*(\.\w{2,10})+$/;
31
+
32
+ // GET, Returns a list of emails
33
+ const fetchNotifications = async () => {
34
+ const resp = await ComponentsService.getInfo(apiGetEmail);
35
+ setNotifications(resp || []);
36
+ };
37
+
38
+ // POST, Receives a list of emails
39
+ const handleAddEmail = async () => {
40
+ const emails = newEmail
41
+ .split(/[;, ]+/)
42
+ .map((email) => email.trim())
43
+ .filter((email) => email.length > 0);
44
+
45
+ // Filter invalid emails
46
+ const invalidEmails = emails.filter(
47
+ (email) => !validEmailPattern.test(email),
48
+ );
49
+ const validEmails = emails.filter((email) => validEmailPattern.test(email));
50
+
51
+ if (invalidEmails.length) {
52
+ setNewEmail(invalidEmails.join(' ')); // if there are multiple invalid emails, they are joined in the array and separated by a space
53
+ setEmailInvalid(true);
54
+ setTimeout(() => {
55
+ setEmailInvalid(false);
56
+ }, 3000);
57
+ }
58
+
59
+ // update total list of emails validated
60
+ if (validEmails.length) {
61
+ const resp = await ComponentsService.postInfo(apiPostEmail, [
62
+ ...notifications,
63
+ ...validEmails,
64
+ ]);
65
+ setNotifications(resp);
66
+ }
67
+ setNewEmail(invalidEmails.join(' '));
68
+ };
69
+
70
+ const handleInputChange = (e) => {
71
+ const value = e.target.value.replace(/\. +/g, ' '); // removes the dot and space, replacing it with ' '
72
+ setNewEmail(value);
73
+
74
+ if (!value.trim() || validEmailPattern.test(value)) {
75
+ setEmailInvalid(false);
76
+ }
77
+ };
78
+
79
+ // DELETE, Receives a list of emails
80
+ const handleDeleteEmail = async (emailToDelete) => {
81
+ setSelectedButton([...selectedButton, emailToDelete]);
82
+ const resp = await ComponentsService.deleteEmails(
83
+ apiDeleteEmail,
84
+ emailToDelete,
85
+ );
86
+ setTimeout(() => {
87
+ setSelectedButton(
88
+ selectedButton.filter((email) => email !== emailToDelete),
89
+ );
90
+ setNotifications(resp);
91
+ }, 1000);
92
+ };
93
+
94
+ useEffect(() => {
95
+ if (showModal) fetchNotifications();
96
+ }, [showModal]);
97
+ return (
98
+ <>
99
+ {/* SECTIONS ADD EMAILS */}
100
+ <div className={'mb-3'}>
101
+ <div
102
+ className={`mb-3 input-group w-100 mb-4 ${
103
+ emailInvalid ? 'not-validated' : ''
104
+ }`}
105
+ data-error={textError}
106
+ >
107
+ <Input
108
+ label={label}
109
+ value={newEmail}
110
+ onChange={(e) => {
111
+ handleInputChange(e);
112
+ }}
113
+ />
114
+ {/* ADD BUTTON */}
115
+ <Button
116
+ onClick={handleAddEmail}
117
+ className={`${newEmail.trim() ? '' : 'disabled'}`}
118
+ >
119
+ {textButton}
120
+ </Button>
121
+ </div>
122
+ </div>
123
+ {/* SECTIONS LIST ADDED EMAILS */}
124
+ {notifications.length ? (
125
+ <div className='shared-users-list'>
126
+ <h3>{titleList}</h3>
127
+ {notifications.map((email, index) => (
128
+ <div key={`email${index}`} className='shared-user-item'>
129
+ <div className='shared-user'>
130
+ <Icon iconName='user-circle' scale={2} />
131
+ <span>{email}</span>
132
+ </div>
133
+ {selectedButton.some(
134
+ (selectedEmail) => selectedEmail === email,
135
+ ) ? (
136
+ <div className='spinner-wrapper'>
137
+ <Spinner scale={1} />
138
+ </div>
139
+ ) : (
140
+ <Button
141
+ variant='terciary'
142
+ style='danger'
143
+ icon='trash-can'
144
+ onClick={() => handleDeleteEmail(email)}
145
+ />
146
+ )}
147
+ </div>
148
+ ))}
149
+ </div>
150
+ ) : null}
151
+ </>
152
+ );
153
+ };
154
+
155
+ InputEmail.propTypes = {
156
+ showModal: PropTypes.bool,
157
+ apiGetEmail: PropTypes.string.isRequired,
158
+ apiPostEmail: PropTypes.string.isRequired,
159
+ apiDeleteEmail: PropTypes.string.isRequired,
160
+ titleList: PropTypes.string.isRequired,
161
+ label: PropTypes.string,
162
+ textButton: PropTypes.string,
163
+ textError: PropTypes.string,
164
+ };
165
+
166
+ export default InputEmail;
@@ -4,5 +4,6 @@ import Radio from './Radio';
4
4
  import Switch from './Switch';
5
5
  import Textarea from './Textarea';
6
6
  import InputChip from './InputChip';
7
+ import InputEmail from './InputEmail';
7
8
 
8
- export { Checkbox, Input, Radio, Switch, Textarea, InputChip };
9
+ export { Checkbox, Input, Radio, Switch, Textarea, InputChip, InputEmail };
@@ -41,7 +41,7 @@ const Sidebar = ({
41
41
  };
42
42
 
43
43
  const fetchData = async () => {
44
- const resp = await ComponentsService.getSidebarInfo(api);
44
+ const resp = await ComponentsService.getInfo(api);
45
45
  setSidebarLinks(resp);
46
46
  };
47
47
 
@@ -1,21 +1,29 @@
1
1
  import urlPath, { basePath } from './url.path';
2
2
  import { POST, GET, DELETE } from './helpers';
3
3
 
4
- export const authStatus = async () => await GET({ url: urlPath.authStatus });
4
+ // GETS
5
+ export const getInfo = async (apiGetInfo) => await GET({ url: `${basePath}${apiGetInfo}`}); // (Sidebar and InputEmail)
5
6
 
6
- export const authLogout = async () => await POST({ url: urlPath.authLogout });
7
+ export const authStatus = async () => await GET({ url: urlPath.authStatus });
7
8
 
8
9
  export const applications = async () => await GET({ url: urlPath.applications });
9
10
 
10
- export const favApplication = async (appToFav) => await POST({url: `${urlPath.favApps}/${appToFav}`, data: appToFav})
11
+ export const getClientsList = async () => await GET({ url: urlPath.clients });
11
12
 
12
- export const unfavApplication = async (appToUnfav) => await DELETE({url: `${urlPath.favApps}/${appToUnfav}`});
13
+ export const getCustomReportsList = async () => await GET(`${urlPath.customReports}/?sort=id_report.desc&offset=0&limit=100`);
13
14
 
14
- export const getClientsList = async () => await GET({ url: urlPath.clients });
15
+ // POSTS
16
+ export const postInfo = async (apiPostInfo, data) => await POST({ url: `${basePath}${apiPostInfo}`, data }); // update emails RETAIL MEDIA (notifications)
17
+
18
+ export const authLogout = async () => await POST({ url: urlPath.authLogout });
19
+
20
+ export const favApplication = async (appToFav) => await POST({url: `${urlPath.favApps}/${appToFav}`, data: appToFav})
15
21
 
16
22
  export const clientsLogin = async (clientId) => await POST({ url: urlPath.clientsLogin, data:{ id_client: clientId }});
17
23
 
18
- export const getSidebarInfo = async (api) => await GET({ url: basePath + api});
24
+ // DELETES
25
+ export const unfavApplication = async (appToUnfav) => await DELETE({url: `${urlPath.favApps}/${appToUnfav}`});
26
+
27
+ export const deleteEmails = async (apiDeleteEmail, email) => await DELETE({ url: `${basePath}${apiDeleteEmail}/${email}` }); // delete emails RETAIL MEDIA (notifications)
19
28
 
20
- export const getCustomReportsList = async () => await GET(`${urlPath.customReports}/?sort=id_report.desc&offset=0&limit=100`);
21
29
 
@@ -27,6 +27,6 @@ export const PUT = async ({ url, data }) => {
27
27
  export const DELETE = async ({ url }) => {
28
28
  return await axios
29
29
  .delete(url, urlPath.headers)
30
- .then((data) => data)
30
+ .then(({data}) => data)
31
31
  .catch((response) => Promise.reject(response || 'error en la url'));
32
32
  };
@@ -0,0 +1,28 @@
1
+ import React, { useState } from 'react';
2
+
3
+ // COMPONENTS
4
+ import { InputEmail } from '../components/Inputs';
5
+ import { Button } from '../components/Button';
6
+
7
+ export default {
8
+ title: 'Inputs/InputEmail',
9
+ component: InputEmail,
10
+ };
11
+
12
+ const Template = (args) => {
13
+ // const [showModal, setShowModal] = useState(false);
14
+ return (
15
+ <>
16
+ {/* <Button onClick={() => setShowModal(!showModal)}>Cambiar show</Button> */}
17
+ <InputEmail
18
+ {...args}
19
+ apiGetEmail={'v2/retail-media/retailers/settings/notifications'}
20
+ apiPostEmail={'v2/retail-media/retailers/settings/notifications'}
21
+ apiDeleteEmail={'v2/retail-media/retailers/settings/notifications'}
22
+ // showModal={showModal}
23
+ />
24
+ </>
25
+ );
26
+ };
27
+
28
+ export const Default = Template.bind({});