@visns-studio/visns-components 4.7.4 → 4.7.6

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
@@ -75,7 +75,7 @@
75
75
  "react-dom": "^17.0.0 || ^18.0.0"
76
76
  },
77
77
  "name": "@visns-studio/visns-components",
78
- "version": "4.7.4",
78
+ "version": "4.7.6",
79
79
  "description": "Various packages to assist in the development of our Custom Applications.",
80
80
  "main": "src/index.js",
81
81
  "files": [
@@ -43,6 +43,7 @@ import {
43
43
  } from 'akar-icons';
44
44
  import CustomFetch from './Fetch';
45
45
  import Notification from './Notification';
46
+ import SwitchAccount from './SwitchAccount';
46
47
  import styles from './styles/Navigation.module.scss';
47
48
 
48
49
  const SearchComponent = ({
@@ -249,6 +250,16 @@ function Navigation({
249
250
  <Notification setSystemAuth={setSystemAuth} />
250
251
  </li>
251
252
  );
253
+ } else if (n.id === 'switchAccount') {
254
+ return (
255
+ <li>
256
+ <SwitchAccount
257
+ setSystemAuth={setSystemAuth}
258
+ setting={n}
259
+ userProfile={userProfile}
260
+ />
261
+ </li>
262
+ );
252
263
  } else if (n.id === 'logout') {
253
264
  const IconComponent = iconComponents[n.icon];
254
265
  return (
@@ -0,0 +1,138 @@
1
+ import React, { useState, useEffect, useRef, useCallback } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { ArrowCycle, ChevronVertical } from 'akar-icons';
4
+ import CustomFetch from './Fetch';
5
+ import styles from './styles/SwitchAccount.module.scss';
6
+
7
+ function SwitchAccount({ setSystemAuth, setting, userProfile }) {
8
+ const navigate = useNavigate();
9
+ const wrapperRef = useRef(null);
10
+ const [data, setData] = useState([]);
11
+ const [show, setShow] = useState(false);
12
+ const [activeAccountId, setActiveAccountId] = useState(
13
+ localStorage.getItem('selectedAccountId') || null
14
+ );
15
+
16
+ const ucfirst = (str) => {
17
+ if (!str) return str; // Return the string if it's empty or not a string
18
+ return str.charAt(0).toUpperCase() + str.slice(1);
19
+ };
20
+
21
+ const pluralise = (str) => {
22
+ if (!str) return str; // Return the string if it's empty or not a string
23
+
24
+ // Convert the string to lowercase
25
+ let lowerStr = str.toLowerCase();
26
+
27
+ // Check if the string is pluralized
28
+ if (!lowerStr.endsWith('s')) {
29
+ return lowerStr + 's';
30
+ }
31
+
32
+ return lowerStr;
33
+ };
34
+
35
+ const handleSelectAccount = (id) => {
36
+ localStorage.setItem('selectedAccountId', id);
37
+ setActiveAccountId(id); // Update the state with the selected account
38
+ };
39
+
40
+ const handleClickOutside = useCallback((e) => {
41
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
42
+ setShow(false);
43
+ }
44
+ }, []);
45
+
46
+ const toggleNotification = useCallback(() => {
47
+ setShow((prevShow) => !prevShow);
48
+ }, []);
49
+
50
+ const fetchData = async () => {
51
+ try {
52
+ const res = await CustomFetch(
53
+ `/ajax/${pluralise(setting.model)}/table`,
54
+ 'POST',
55
+ {}
56
+ );
57
+
58
+ setData(res.data.data);
59
+ } catch (error) {
60
+ console.info(error);
61
+ }
62
+ };
63
+
64
+ useEffect(() => {
65
+ fetchData();
66
+
67
+ document.addEventListener('mousedown', handleClickOutside, false);
68
+
69
+ return () => {
70
+ document.removeEventListener(
71
+ 'mousedown',
72
+ handleClickOutside,
73
+ false
74
+ );
75
+ };
76
+ }, [handleClickOutside]);
77
+
78
+ return (
79
+ <div>
80
+ <a
81
+ href="#"
82
+ onClick={toggleNotification}
83
+ data-tooltip-id="system-tooltip"
84
+ data-tooltip-content={setting.label}
85
+ >
86
+ <ArrowCycle size={16} verticalAlign="middle" />
87
+ </a>
88
+
89
+ {show && (
90
+ <div ref={wrapperRef}>
91
+ {data.length > 0 ? (
92
+ <div className={styles.notibox}>
93
+ {data.map((item) => (
94
+ <div
95
+ className={styles['notibox-item']}
96
+ key={`item-${item.id}`}
97
+ >
98
+ {item[setting.labelKey]}
99
+ {parseInt(activeAccountId) ===
100
+ parseInt(item.id) ? (
101
+ <span className={styles.currentAccount}>
102
+ Current Active{' '}
103
+ {`${ucfirst(setting.model)} `}
104
+ </span>
105
+ ) : (
106
+ <span
107
+ className={styles.switchBtn}
108
+ onClick={(e) => {
109
+ e.preventDefault();
110
+
111
+ handleSelectAccount(item.id);
112
+ }}
113
+ >
114
+ Select{' '}
115
+ {`${ucfirst(setting.model)} `}
116
+ <ChevronVertical
117
+ size={16}
118
+ fill="#20004d"
119
+ />
120
+ </span>
121
+ )}
122
+ </div>
123
+ ))}
124
+ </div>
125
+ ) : (
126
+ <div className={styles.notibox}>
127
+ <div className={styles['notibox-item']}>
128
+ No {pluralise(setting.model)} available.
129
+ </div>
130
+ </div>
131
+ )}
132
+ </div>
133
+ )}
134
+ </div>
135
+ );
136
+ }
137
+
138
+ export default SwitchAccount;
@@ -25,38 +25,51 @@ select:not(:placeholder-shown) + .fi__span {
25
25
  align-items: flex-start;
26
26
  flex-wrap: nowrap;
27
27
  height: auto;
28
+ gap: 1rem;
28
29
  }
29
30
 
30
31
  .grid__full {
31
32
  width: 100%;
32
- background: white;
33
+ background: var(--item-color);
33
34
  border-radius: var(--br);
34
- border: 1px solid var(--border-color);
35
+ border: 1px solid rgba(var(--item-color-rgb), 1.15);
35
36
  box-sizing: border-box;
36
37
  overflow: visible;
37
38
  position: relative;
38
- padding: 0;
39
- margin: 5px;
39
+ padding: 2px;
40
+ margin: 8px 0;
41
+ box-shadow: 0 4px 0 rgba(var(--primary-color-rgb), 0.05);
40
42
  }
41
43
 
42
44
  .crmtitle {
43
45
  border: none;
44
46
  min-height: auto;
45
47
  padding: 10px 20px;
46
- margin: 5px;
47
- background: var(--item-color);
48
+ margin: 0;
49
+ background: var(--tertiary-color);
48
50
  border-radius: var(--br);
49
- border: 1px solid var(--border-color);
51
+ border: 1px solid rgba(var(--item-color-rgb), 1.15);
50
52
  position: relative;
51
53
  }
52
54
 
53
55
  .crmtitle h1 {
54
56
  font-weight: 700;
55
- font-size: 1.25em;
57
+ font-size: 1.45em;
56
58
  margin: 0;
57
- padding: 0.25rem 0;
58
- color: var(--paragraph-color);
59
- text-transform: capitalize;
59
+ padding: 0.65rem 0;
60
+ }
61
+
62
+ .crmtitle h1 a {
63
+ text-decoration: none;
64
+ color: rgba(var(--secondary-color-rgb), 1.1);
65
+ font-weight: 300;
66
+ }
67
+
68
+ .crmtitle h1 svg {
69
+ color: rgba(var(--primary-color-rgb), 0.25);
70
+ position: relative;
71
+ top: 2px;
72
+ margin: 0 0.25rem;
60
73
  }
61
74
 
62
75
  .grid__subrow {
@@ -54,10 +54,10 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
54
54
  : []),
55
55
  { value: 'dynamicdata', label: 'Dynamic Data' },
56
56
  { value: 'file', label: 'File' },
57
- { value: 'plaintextheading', label: 'Heading' },
58
57
  { value: 'image', label: 'Image' },
59
58
  { value: 'number', label: 'Number' },
60
59
  { value: 'plaintext', label: 'Plain Text' },
60
+ { value: 'plaintextheading', label: 'Heading' },
61
61
  { value: 'section', label: 'Section' },
62
62
  { value: 'signature', label: 'Signature' },
63
63
  { value: 'table_radio', label: 'Table (Radio)' },
@@ -1453,6 +1453,11 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1453
1453
  'checkbox',
1454
1454
  'dropdown',
1455
1455
  'dynamicdata',
1456
+ 'file',
1457
+ 'image',
1458
+ 'plaintext',
1459
+ 'plaintextheading',
1460
+ 'section',
1456
1461
  'signature',
1457
1462
  'table',
1458
1463
  ].some(
@@ -1576,6 +1581,11 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
1576
1581
  'checkbox',
1577
1582
  'dropdown',
1578
1583
  'dynamicdata',
1584
+ 'file',
1585
+ 'image',
1586
+ 'plaintext',
1587
+ 'plaintextheading',
1588
+ 'section',
1579
1589
  'signature',
1580
1590
  'table',
1581
1591
  ].some(
@@ -1,41 +1,41 @@
1
1
  import React from 'react';
2
2
  import Table from '../DataGrid';
3
+ import styles from './styles/NotificationList.module.scss';
3
4
 
4
5
  const NotificationList = () => {
5
- const ajaxSetting = {
6
- url: '/ajax/notifications/table',
7
- take: 25,
8
- sortBy: 'id',
9
- sort: 'desc',
10
- where: [],
11
- };
12
-
13
- const form = {
14
- primaryKey: 'id',
15
- url: '/ajax/notifications',
16
- create: {},
17
- update: {},
18
- fields: [],
19
- };
20
-
21
- const columns = [
22
- {
23
- id: 'data',
24
- jsonData: 'label',
25
- label: 'Label',
26
- type: 'json',
6
+ const setting = {
7
+ ajaxSetting: {
8
+ url: '/ajax/user/notifications/table',
9
+ take: 25,
10
+ sortBy: 'id',
11
+ sort: 'desc',
12
+ where: [],
27
13
  },
28
- {
29
- id: 'read_at',
30
- label: 'Read At',
31
- type: 'datetime',
32
- minWidth: 200,
33
- maxWidth: 200,
14
+ form: {
15
+ primaryKey: 'id',
16
+ url: '/ajax/user/notifications',
17
+ createDisable: true,
18
+ create: {},
19
+ update: {},
20
+ fields: [],
34
21
  },
35
- ];
36
-
37
- const settings = [];
38
-
22
+ columns: [
23
+ {
24
+ id: 'data',
25
+ jsonData: 'label',
26
+ label: 'Label',
27
+ type: 'json',
28
+ },
29
+ {
30
+ id: 'read_at',
31
+ label: 'Read At',
32
+ type: 'datetime',
33
+ minWidth: 200,
34
+ maxWidth: 200,
35
+ },
36
+ ],
37
+ settings: [],
38
+ };
39
39
  return (
40
40
  <div>
41
41
  <div className={styles.grid}>
@@ -49,10 +49,10 @@ const NotificationList = () => {
49
49
  <div className={styles.grid__row}>
50
50
  <div className={styles.grid__full}>
51
51
  <Table
52
- ajaxSetting={ajaxSetting}
53
- form={form}
54
- columns={columns}
55
- settings={settings}
52
+ ajaxSetting={setting.ajaxSetting}
53
+ form={setting.form}
54
+ columns={setting.columns}
55
+ settings={setting.settings}
56
56
  />
57
57
  </div>
58
58
  </div>
@@ -32,36 +32,30 @@
32
32
  .crmtitle {
33
33
  border: none;
34
34
  min-height: auto;
35
- padding: 5px 20px;
35
+ padding: 10px 20px;
36
36
  margin: 0;
37
- background: var(--primary-color);
37
+ background: var(--tertiary-color);
38
38
  border-radius: var(--br);
39
39
  border: 1px solid rgba(var(--item-color-rgb), 1.15);
40
40
  position: relative;
41
- display: flex;
42
- align-items: center;
41
+ }
43
42
 
44
- h1 {
45
- color: var(--background-color);
46
- font-weight: 700;
47
- font-size: 1.15em;
48
- margin: 0;
49
- padding: 0.65rem 0;
50
- display: flex;
51
- align-items: center;
52
- gap: 0.25rem;
43
+ .crmtitle h1 {
44
+ font-weight: 700;
45
+ font-size: 1.45em;
46
+ margin: 0;
47
+ padding: 0.65rem 0;
48
+ }
53
49
 
54
- a {
55
- text-decoration: none;
56
- color: var(--secondary-color);
57
- }
50
+ .crmtitle h1 a {
51
+ text-decoration: none;
52
+ color: rgba(var(--secondary-color-rgb), 1.1);
53
+ font-weight: 300;
54
+ }
58
55
 
59
- svg {
60
- color: rgba(var(--tertiary-color-rgb), 0.5);
61
- position: relative;
62
- top: 0;
63
- margin: 0 0.5rem;
64
- max-width: 15px;
65
- }
66
- }
56
+ .crmtitle h1 svg {
57
+ color: rgba(var(--primary-color-rgb), 0.25);
58
+ position: relative;
59
+ top: 2px;
60
+ margin: 0 0.25rem;
67
61
  }
@@ -0,0 +1,69 @@
1
+ .notibox {
2
+ background: #fff;
3
+ border: 1px solid var(--primary-color-lighter);
4
+ border-top-color: rgb(204, 204, 204);
5
+ border-right-color: rgb(204, 204, 204);
6
+ border-bottom-color: rgb(204, 204, 204);
7
+ border-left-color: rgb(204, 204, 204);
8
+ border-color: rgba(0, 0, 0, 0.2);
9
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
10
+ display: block;
11
+ opacity: 1;
12
+ outline: none;
13
+ overflow: hidden;
14
+ position: absolute;
15
+ padding: 6px;
16
+ border-radius: var(--br);
17
+ width: 550px;
18
+ overflow-y: scroll;
19
+ transform: translateX(-470px);
20
+ text-align: left;
21
+ color: var(--paragraph-color);
22
+ box-sizing: border-box;
23
+ transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
24
+ z-index: 999;
25
+ }
26
+
27
+ .notibox-item {
28
+ width: 100%;
29
+ display: block;
30
+ background: #f0f0f0;
31
+ border-radius: var(--br);
32
+ padding: 9px 36px 8px 6px;
33
+ box-sizing: border-box;
34
+ margin-bottom: 4px;
35
+ position: relative;
36
+
37
+ span {
38
+ color: var(--paragraph-color);
39
+ font-size: 80%;
40
+ }
41
+
42
+ > button {
43
+ position: absolute;
44
+ right: 6px;
45
+ top: 5px;
46
+ cursor: pointer;
47
+ padding: 0;
48
+ margin: 0;
49
+ outline: none;
50
+ background: none;
51
+ border: none;
52
+ }
53
+
54
+ .switchBtn {
55
+ float: right;
56
+ color: var(--paragraph-color);
57
+ cursor: pointer;
58
+ }
59
+
60
+ .currentAccount {
61
+ float: right;
62
+ color: darken(#f0f0f0, 25%);
63
+ line-height: 1.25;
64
+ }
65
+
66
+ .noti-read {
67
+ color: var(--primary-color);
68
+ }
69
+ }