pager-widget 0.2.1 → 0.2.3

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.
@@ -1,24 +1,126 @@
1
- import React, { useState } from "react";
1
+ import React, { useContext, useState } from "react";
2
2
  import { countries } from "country-codes-flags-phone-codes";
3
3
  import axios from "axios";
4
4
  import styled from "styled-components";
5
+ import Dropdown from "./Dropdown";
6
+ import { EndPointContext } from "./useEndpoint";
5
7
 
6
- console.log("country", countries);
8
+ const InputWrapper = styled.div`
9
+ position: relative;
10
+ width: 100%;
11
+
12
+ input {
13
+ border-radius: 8px;
14
+ border: 1px solid
15
+ ${({ error }) =>
16
+ error === "true" ? "var(--red-300, #FFA2A2)" : "var(--k300, #d0d5dd)"};
17
+ background: #fff;
18
+ outline: none;
19
+ height: 44px;
20
+ width: 100%;
21
+ text-indent: 12px;
22
+ padding-right: 40px; /* Space for icon */
23
+
24
+ ::placeholder {
25
+ color: #98a2b3;
26
+ font-size: 14px;
27
+ font-style: normal;
28
+ font-weight: 400;
29
+ line-height: normal;
30
+ }
31
+ }
32
+
33
+ /* Error icon */
34
+ svg {
35
+ position: absolute;
36
+ right: 12px;
37
+ top: 50%;
38
+ transform: translateY(-50%);
39
+ display: ${({ error }) =>
40
+ error === "true" ? "block" : "none"}; /* Show only if error exists */
41
+ }
42
+ `;
43
+
44
+ const Form = styled.form`
45
+ margin-top: 5px;
46
+ `;
47
+
48
+ Form.Field = styled.div`
49
+ margin-bottom: 10px;
50
+ `;
51
+
52
+ Form.Wrapper = styled.div`
53
+ padding: 3.5px;
54
+ maxwidth: "600px";
55
+ margin: 0 auto;
56
+ `;
57
+
58
+ const Label = styled.label`
59
+ display: block;
60
+ margin-bottom: 5px;
61
+ font-size: 14px;
62
+ font-weight: 400;
63
+ line-height: 20px;
64
+ color: #101828;
65
+ font-family: Inter, Open Sans;
66
+ `;
67
+
68
+ Label.Meta = styled.span`
69
+ color: #667085;
70
+ margin-left: 5px;
71
+ font-family: Inter, Open Sans;
72
+ `;
73
+
74
+ const ErrorMessage = styled.div`
75
+ color: red;
76
+ margin-bottom: 5px;
77
+ font-size: 12px;
78
+ font-weight: 400;
79
+ padding-left: 4px;
80
+ padding-top: 2px;
81
+ `;
7
82
 
8
- const InputWrapper = styled.input`
9
- border-radius: 8px;
10
- border: 1px solid var(--k300, #d0d5dd);
11
- background: #fff;
12
- outline: none;
13
- height: 52px;
83
+ Form.Field.DescriptionMessage = styled.div`
84
+ font-size: 12px;
85
+ padding-top: 8px;
86
+ padding-left: 4px;
87
+ `;
88
+
89
+ const TextArea = styled.div`
90
+ position: relative;
14
91
  width: 100%;
15
- text-indent: 12px;
16
- ::placeholder {
17
- color: #98a2b3;
18
- font-size: 14px;
19
- font-style: normal;
20
- font-weight: 400;
21
- line-height: normal;
92
+
93
+ textarea {
94
+ border-radius: 8px;
95
+ border: 1px solid
96
+ ${({ error }) =>
97
+ error === "true" ? "var(--red-300, #FFA2A2)" : "var(--k300, #d0d5dd)"};
98
+ background: #fff;
99
+ outline: none;
100
+ height: 130px;
101
+ width: 100%;
102
+ text-indent: 12px;
103
+ resize: none;
104
+
105
+ :: placeholder {
106
+ color: #98a2b3;
107
+ font-size: 14px;
108
+ font-style: normal;
109
+ font-weight: 400;
110
+ line-height: normal;
111
+ padding-top: 5px;
112
+ font-family: Inter, Open Sans;
113
+ }
114
+ }
115
+
116
+ /* Error icon */
117
+ svg {
118
+ position: absolute;
119
+ right: 12px;
120
+ top: 50%;
121
+ transform: translateY(-50%);
122
+ display: ${({ error }) =>
123
+ error === "true" ? "block" : "none"}; /* Show only if error exists */
22
124
  }
23
125
  `;
24
126
 
@@ -37,20 +139,90 @@ font-weight: 400;
37
139
  line-height: normal;
38
140
  }
39
141
  option {
40
- padding: 16px; height: 40px; font-size: 16px; background-color: #ffffff; color: #333333; &:hover { background-color: #e0e0e0; } &:selected { background-color: #007bff; color: white; }
142
+ padding: 16px; height: 40px;
143
+ font-size: 16px;
144
+ background-color: #ffffff;
145
+ color: #333333;
146
+ &:hover { background-color: #e0e0e0; }
147
+ &:selected { background-color: #007bff; color: white; }
148
+ `;
149
+
150
+ const InfoIcon = styled.span`
151
+ position: relative;
152
+ display: inline-flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ width: 18px;
156
+ height: 18px;
157
+ font-size: 12px;
158
+ font-weight: bold;
159
+ color: #667085;
160
+ background-color: #f3f4f6;
161
+ border-radius: 50%;
162
+ cursor: pointer;
41
163
 
164
+ &:hover {
165
+ background-color: #e5e7eb;
166
+ }
167
+
168
+ // Tooltip container
169
+ &::after {
170
+ content: attr(data-tooltip); /* Display description */
171
+ position: absolute;
172
+ bottom: 150%;
173
+ left: 150%;
174
+ transform: translateX(-50%);
175
+ background-color: #181d27;
176
+ font-family: "Inter", "Open Sans";
177
+ font-weight: 400;
178
+ text-align: center;
179
+ white-space: normal;
180
+ word-wrap: break-word;
181
+ // max-width: 250px; /* ✅ Ensures proper width */
182
+ width: 250px;
183
+
184
+ color: #fff;
185
+ font-size: 12px;
186
+ padding: 6px 10px;
187
+ border-radius: 8px;
188
+ opacity: 0;
189
+ visibility: hidden;
190
+ transition: opacity 0.2s ease-in-out;
191
+ z-index: 10;
192
+ }
193
+
194
+ // Tooltip Arrow
195
+ &::before {
196
+ content: "";
197
+ position: absolute;
198
+ bottom: 140%;
199
+ left: 50%;
200
+ transform: translateX(-50%);
201
+ border-width: 6px;
202
+ border-style: solid;
203
+ border-color: #181d27 transparent transparent transparent; /* Creates the arrow */
204
+ opacity: 0;
205
+ visibility: hidden;
206
+ transition: opacity 0.2s ease-in-out;
207
+ }
208
+
209
+ &:hover::after,
210
+ &:hover::before {
211
+ opacity: 1;
212
+ visibility: visible;
213
+ }
42
214
  `;
43
215
 
44
216
  const InputConverter = ({
45
217
  formData,
46
218
  conversationId,
47
219
  workspace,
48
- widgetId,
220
+ widget,
49
221
  setFormSubmit,
50
222
  setSourceState,
51
223
  }) => {
52
224
  const [errors, setErrors] = useState({});
53
-
225
+ const endpoint = useContext(EndPointContext)
54
226
  // State to hold form data
55
227
  const [formValues, setFormValues] = useState(
56
228
  Object.fromEntries(
@@ -58,15 +230,6 @@ const InputConverter = ({
58
230
  )
59
231
  );
60
232
 
61
-
62
- const [selectedCountry, setSelectedCountry] = useState({
63
- flag: null,
64
- country: "select a country",
65
- });
66
- const [isDropDownOpen, setIsDropDownOpen] = useState(false);
67
- const [hoveredCountry, setHoveredCountry] = useState(null);
68
- const [searchQuery, setSearchQuery] = useState("");
69
- // Handle input changes
70
233
  const handleChange = (e) => {
71
234
  const { id, value } = e.target;
72
235
  setFormValues((prev) => ({
@@ -75,20 +238,22 @@ const InputConverter = ({
75
238
  }));
76
239
  };
77
240
 
78
-
79
-
80
- console.log("errors obj", Object.values(errors));
81
-
241
+ const handleDropChange = (id) => (value) => {
242
+ setFormValues((prev) => ({
243
+ ...prev,
244
+ [id]: value,
245
+ }));
246
+ };
82
247
 
83
248
  const handleSubmit = (e) => {
84
249
  e.preventDefault();
85
-
250
+
86
251
  const newErrors = {};
87
-
252
+
88
253
  formData.form_data.form_template.forEach((field) => {
89
- if (field.is_mandatory) {
254
+ if (field.is_mandatory) {
90
255
  if (field.field_type === "country") {
91
- if (selectedCountry.country === "select a country") {
256
+ if (formValues.SYS_country === "") {
92
257
  newErrors[field.field_id] = `${field.name} is required`;
93
258
  }
94
259
  } else if (!formValues[field.field_id]?.trim()) {
@@ -96,19 +261,22 @@ const InputConverter = ({
96
261
  }
97
262
  }
98
263
  });
99
-
264
+
100
265
  if (Object.keys(newErrors).length > 0) {
101
266
  setErrors(newErrors);
102
267
  return;
103
268
  }
104
-
269
+
105
270
  setErrors({});
106
-
271
+
107
272
  const submittedValues = formData.form_data.form_template.map((field) => ({
108
273
  ...field,
109
- value: field.field_type === "country" ? selectedCountry.country : formValues[field.field_id],
274
+ value:
275
+ field.field_type === "country"
276
+ ? formValues.SYS_country
277
+ : formValues[field.field_id],
110
278
  }));
111
-
279
+
112
280
  const submittedData = {
113
281
  form_id: formData.form_data.form_id,
114
282
  conversation_id: conversationId,
@@ -120,11 +288,15 @@ const InputConverter = ({
120
288
  },
121
289
  type: "lead",
122
290
  };
123
-
291
+
124
292
  axios
125
- .post(`https://dev.pagergpt.ai/wgt-hook/${workspace}/${widgetId}/lead`, submittedData, {
126
- withCredentials: true,
127
- })
293
+ .post(
294
+ `${endpoint}/${workspace}/${widget?.id}/lead`,
295
+ submittedData,
296
+ {
297
+ withCredentials: true,
298
+ }
299
+ )
128
300
  .then((res) => {
129
301
  setSourceState(res.data.source_id);
130
302
  })
@@ -133,223 +305,170 @@ const InputConverter = ({
133
305
  });
134
306
  };
135
307
 
308
+ const updateFieldValue = (field, value) => {
309
+ setFormValues((prev) => ({
310
+ ...prev,
311
+ [field]: value,
312
+ }));
313
+ };
136
314
 
137
- const filteredCountries = countries.filter((country) =>
138
- country.name.toLowerCase().includes(searchQuery.toLowerCase())
139
- );
140
-
141
- const handleSelectDropdown = (flag, country) => {
142
- setSelectedCountry({ flag, country });
143
- setIsDropDownOpen(false);
144
-
145
- // Update formValues with the selected country
146
- setFormValues((prev) => ({
147
- ...prev,
148
- SYS_country: country, // Adjust this based on your actual field_id
149
- }));
150
- };
151
315
  return (
152
- <div style={{ padding: "20px", maxWidth: "600px", margin: "0 auto" }}>
153
- <form onSubmit={handleSubmit} style={{marginTop: "5px"}}>
316
+ <Form.Wrapper
317
+ style={{ padding: "3.5px", maxWidth: "600px", margin: "0 auto" }}
318
+ >
319
+ <Form onSubmit={handleSubmit} style={{ marginTop: "5px" }}>
154
320
  {formData.form_data.form_template.map((field) => (
155
- <div key={field.id} style={{ marginBottom: "10px" }}>
156
-
157
- <label
158
- htmlFor={field.field_id}
159
- style={{ display: "block", marginBottom: "5px", fontSize: "14px", fontWeight: "500", lineHeight:"20px" }}
321
+ <Form.Field key={field.id} style={{ marginBottom: "10px" }}>
322
+ <div
323
+ style={{
324
+ display: "flex",
325
+ flexDirection: "row",
326
+ gap: "10px",
327
+ }}
160
328
  >
161
-
162
- {field.dispaly_name ? field.dispaly_name : field?.name}
163
- {field.is_mandatory && (
164
- <span style={{ color: "red", marginLeft: "5px" }}>*</span>
329
+ <Label htmlFor={field.field_id}>
330
+ {field.dispaly_name ? field.dispaly_name : field?.name}
331
+ {!field.is_mandatory ? (
332
+ <Label.Meta>(Optional)</Label.Meta>
333
+ ) : null}
334
+ </Label>
335
+ {field.description && (
336
+ <InfoIcon data-tooltip={field.description}>
337
+ <svg
338
+ xmlns="
339
+ http://www.w3.org/2000/svg"
340
+ viewBox="0 0 24 24"
341
+ fill="none"
342
+ >
343
+ <path
344
+ d="M12 11.9999V15.9999M12 8.6249V8.62378M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
345
+ stroke="currentColor"
346
+ strokeWidth="1.7"
347
+ strokeLinecap="round"
348
+ strokeLinejoin="round"
349
+ />
350
+ </svg>
351
+ </InfoIcon>
165
352
  )}
166
- </label>
167
- {errors[field.field_id] && (
168
- <div style={{ color: "red", marginBottom: "5px" }}>
169
- {errors[field.field_id]}
170
- </div>
171
- )}
353
+ </div>
354
+
172
355
  {field.field_type === "long_text" ? (
173
- <textarea
174
- id={field.field_id}
175
- placeholder={field.placeholder}
176
- value={formValues[field.field_id]}
177
- onChange={handleChange}
178
- style={{
179
- borderRadius: "8px",
180
- border: "1px solid var(--k300, #D0D5DD)",
181
- background: "#FFF",
182
- outline: "none",
183
- height: "130px",
184
- width: "100%",
185
- }}
186
- ></textarea>
187
- ) : field.field_type === "country" ? (
188
- // <SelectWrapper
189
- // id={field.field_id}
190
- // // required={field.is_mandatory}
191
- // value={formValues[field.field_id]}
192
- // onChange={handleChange}
193
- // style={{
194
- // width: "100%",
195
- // padding: "8px",
196
- // border: "1px solid #ccc",
197
- // borderRadius: "4px",
198
- // }}
199
- // >
200
- // <option value="">Select a country</option>
201
- // {countries.map((country) => (
202
- // <option style={{height: "40px"}} key={country.name} value={country.name}>
203
- // {country.flag} {country.name}
204
- // </option>
205
- // ))}
206
- // </SelectWrapper>
207
- <div
208
- style={{
209
- width: "100%",
210
- position: "relative",
211
- }}
212
- >
213
- <span
214
- style={{
215
- borderRadius: "8px",
216
- border: "1px solid var(--k300, #D0D5DD)",
217
- background: "#FFF",
218
- padding: "10px 35px 10px 2px",
219
- cursor: "pointer",
220
- width: "91%",
221
- height: "15px",
222
- display: "flex",
223
- justifyContent: "space-between",
224
- alignItems: "center",
225
- }}
226
- onClick={() => setIsDropDownOpen(!isDropDownOpen)}
227
- >
228
- {selectedCountry.flag && selectedCountry.flag} &nbsp;{" "}
229
- {selectedCountry.country}{" "}
230
- <span style={{ rotate: isDropDownOpen ? "180deg" : "0deg" }}>
231
- <svg
232
- xmlns="http://www.w3.org/2000/svg"
233
- width="28"
234
- height="28"
235
- viewBox="0 0 20 20"
236
- fill="none"
237
- >
356
+ <>
357
+ <TextArea error={errors[field.field_id] ? "true" : "false"}>
358
+ <textarea
359
+ id={field.field_id}
360
+ placeholder={field.placeholder}
361
+ value={formValues[field.field_id]}
362
+ onChange={handleChange}
363
+ />
364
+ <svg
365
+ xmlns="http://www.w3.org/2000/svg"
366
+ width="16"
367
+ height="16"
368
+ viewBox="0 0 16 16"
369
+ fill="none"
370
+ >
371
+ <g clipPath="url(#clip0_679_4913)">
238
372
  <path
239
- d="M6.66675 8.45312C7.5518 9.67136 8.58931 10.7625 9.75185 11.6983C9.89789 11.8158 10.1023 11.8158 10.2483 11.6983C11.4109 10.7625 12.4484 9.67136 13.3334 8.45312"
240
- stroke="#344054"
241
- stroke-width="1.4"
242
- stroke-linecap="round"
243
- stroke-linejoin="round"
373
+ d="M7.99967 5.33337V8.00004M7.99967 10.6667H8.00634M14.6663 8.00004C14.6663 11.6819 11.6816 14.6667 7.99967 14.6667C4.31778 14.6667 1.33301 11.6819 1.33301 8.00004C1.33301 4.31814 4.31778 1.33337 7.99967 1.33337C11.6816 1.33337 14.6663 4.31814 14.6663 8.00004Z"
374
+ stroke="#FB2C36"
375
+ strokeWidth="1.33333"
376
+ strokeLinecap="round"
377
+ strokeLinejoin="round"
244
378
  />
245
- </svg>
246
- </span>
247
- </span>
248
- {isDropDownOpen && (
249
- <div
250
- style={{
251
- display: "flex",
252
- flexDirection: "column",
253
- gap: "8px",
254
- border: "1px solid #cbc8c8fa",
255
- padding: "12px 6px",
256
- position: "absolute",
257
- width: "96%",
258
- top: "38px",
259
- background: "white",
260
- borderRadius: "12px",
261
- left: "0px",
262
- height: "200px",
263
- overflowY: "scroll",
264
- }}
379
+ </g>
380
+ <defs>
381
+ <clipPath id="clip0_679_4913">
382
+ <rect width="16" height="16" fill="white" />
383
+ </clipPath>
384
+ </defs>
385
+ </svg>
386
+ </TextArea>
387
+ {errors[field.field_id] ? (
388
+ <ErrorMessage>{errors[field.field_id]}</ErrorMessage>
389
+ ) : null}
390
+ </>
391
+ ) : field.field_type === "country" ? (
392
+ <>
393
+ <Dropdown
394
+ error={errors[field.field_id] ? "true" : "false"}
395
+ updateFieldValue={updateFieldValue}
396
+ fieldId={"SYS_country"}
397
+ />
398
+ {errors[field.field_id] ? (
399
+ <ErrorMessage>{errors[field.field_id]}</ErrorMessage>
400
+ ) : null}
401
+ </>
402
+ ) : (
403
+ <>
404
+ <InputWrapper error={errors[field.field_id] ? "true" : "false"}>
405
+ <input
406
+ id={field.field_id}
407
+ type={
408
+ field.field_type === "short_text"
409
+ ? "text"
410
+ : field.field_type
411
+ }
412
+ placeholder={field.placeholder}
413
+ value={formValues[field.field_id]}
414
+ onChange={handleChange}
415
+ />
416
+ <svg
417
+ xmlns="http://www.w3.org/2000/svg"
418
+ width="16"
419
+ height="16"
420
+ viewBox="0 0 16 16"
421
+ fill="none"
265
422
  >
266
- {/* Search input inside dropdown */}
267
- <input
268
- type="text"
269
- placeholder="Search country..."
270
- value={searchQuery}
271
- onChange={(e) => setSearchQuery(e.target.value)}
272
- style={{
273
- width: "95%",
274
- padding: "8px",
275
- marginBottom: "8px",
276
- border: "1px solid #D0D5DD",
277
- borderRadius: "8px",
278
- outline: "none",
279
- }}
280
- />
423
+ <g clipPath="url(#clip0_679_4913)">
424
+ <path
425
+ d="M7.99967 5.33337V8.00004M7.99967 10.6667H8.00634M14.6663 8.00004C14.6663 11.6819 11.6816 14.6667 7.99967 14.6667C4.31778 14.6667 1.33301 11.6819 1.33301 8.00004C1.33301 4.31814 4.31778 1.33337 7.99967 1.33337C11.6816 1.33337 14.6663 4.31814 14.6663 8.00004Z"
426
+ stroke="#FB2C36"
427
+ strokeWidth="1.33333"
428
+ strokeLinecap="round"
429
+ strokeLinejoin="round"
430
+ />
431
+ </g>
432
+ <defs>
433
+ <clipPath id="clip0_679_4913">
434
+ <rect width="16" height="16" fill="white" />
435
+ </clipPath>
436
+ </defs>
437
+ </svg>
438
+ </InputWrapper>
281
439
 
282
- {filteredCountries.length > 0 ? (
283
- filteredCountries.map((country, index) => (
284
- <span
285
- key={country.name}
286
- style={{
287
- padding: "8px 8px",
288
- borderRadius: "8px",
289
- cursor: "pointer",
290
- background:
291
- hoveredCountry === index ? "#e9e5e5" : "white",
292
- }}
293
- onClick={() =>
294
- handleSelectDropdown(country.flag, country.name)
295
- }
296
- onMouseOver={() => setHoveredCountry(index)}
297
- onMouseLeave={() => setHoveredCountry(null)}
298
- >
299
- {country.flag} &nbsp; {country.name}
300
- </span>
301
- ))
302
- ) : (
303
- <span style={{ padding: "10px", textAlign: "center" }}>
304
- No results found
305
- </span>
306
- )}
307
- </div>
308
- )}
309
- </div>
310
- ) :
311
- (
312
- <InputWrapper
313
- id={field.field_id}
314
- type={
315
- field.field_type === "short_text" ? "text" : field.field_type
316
- }
317
- placeholder={field.placeholder}
318
- // required={field.is_mandatory}
319
- value={formValues[field.field_id]}
320
- onChange={handleChange}
321
- style={{
322
- borderRadius: "8px",
323
- border: "1px solid var(--k300, #D0D5DD)",
324
- background: "#FFF",
325
- outline: "none",
326
- height: "40px",
327
- width: "100%",
328
- }}
329
- />
330
- )
331
- }
332
- </div>
440
+ {errors[field.field_id] ? (
441
+ <ErrorMessage>{errors[field.field_id]}</ErrorMessage>
442
+ ) : null}
443
+ </>
444
+ )}
445
+ </Form.Field>
333
446
  ))}
334
- <button
335
- type="submit"
447
+
448
+ <div
336
449
  style={{
337
- padding: "10px 20px",
338
- backgroundColor: "#007BFF",
339
- color: "#fff",
340
- border: "none",
341
- borderRadius: "4px",
342
- cursor: "pointer",
343
- width: "100%"
450
+ paddingTop: "16px",
451
+ borderTop: "1px solid var(--k300, #D0D5DD)",
344
452
  }}
345
453
  >
346
- Submit
347
- </button>
348
- </form>
349
- </div>
454
+ <button
455
+ type="submit"
456
+ style={{
457
+ padding: "12px 20px",
458
+ backgroundColor: widget?.accent_color,
459
+ color: "#fff",
460
+ border: "none",
461
+ borderRadius: "8px",
462
+ cursor: "pointer",
463
+ width: "100%",
464
+ }}
465
+ >
466
+ Submit
467
+ </button>
468
+ </div>
469
+ </Form>
470
+ </Form.Wrapper>
350
471
  );
351
472
  };
352
473
 
353
474
  export default InputConverter;
354
-
355
-