@visns-studio/visns-components 5.5.5 → 5.5.7

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.
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+
3
+ import styles from './styles/ClientDashboard.module.scss';
4
+
5
+ /**
6
+ * ClientDashboard - Example dashboard component for client portal
7
+ *
8
+ * This is a simple example of a custom component that can be passed to GenericClientPortal
9
+ */
10
+ const ClientDashboard = ({ clientProfile }) => {
11
+ return (
12
+ <div className={styles.dashboardContainer}>
13
+ <h1 className={styles.sectionTitle}>Dashboard</h1>
14
+
15
+ <div className={styles.welcomeCard}>
16
+ <h2>Welcome to your Client Portal</h2>
17
+ <p>
18
+ Hello {clientProfile.name || clientProfile.email}! This is your personal dashboard
19
+ where you can access your documents, update your profile, and more.
20
+ </p>
21
+ </div>
22
+
23
+ <div className={styles.statsGrid}>
24
+ <div className={styles.statCard}>
25
+ <h3>Documents</h3>
26
+ <p className={styles.statNumber}>5</p>
27
+ <p className={styles.statDescription}>Available documents</p>
28
+ </div>
29
+ <div className={styles.statCard}>
30
+ <h3>Messages</h3>
31
+ <p className={styles.statNumber}>2</p>
32
+ <p className={styles.statDescription}>Unread messages</p>
33
+ </div>
34
+ <div className={styles.statCard}>
35
+ <h3>Tasks</h3>
36
+ <p className={styles.statNumber}>3</p>
37
+ <p className={styles.statDescription}>Pending tasks</p>
38
+ </div>
39
+ </div>
40
+
41
+ <div className={styles.recentActivity}>
42
+ <h2>Recent Activity</h2>
43
+ <ul className={styles.activityList}>
44
+ <li className={styles.activityItem}>
45
+ <span className={styles.activityDate}>Today</span>
46
+ <span className={styles.activityDescription}>Document "Tax Return 2023" was uploaded</span>
47
+ </li>
48
+ <li className={styles.activityItem}>
49
+ <span className={styles.activityDate}>Yesterday</span>
50
+ <span className={styles.activityDescription}>You received a new message</span>
51
+ </li>
52
+ <li className={styles.activityItem}>
53
+ <span className={styles.activityDate}>3 days ago</span>
54
+ <span className={styles.activityDescription}>Your profile was updated</span>
55
+ </li>
56
+ </ul>
57
+ </div>
58
+ </div>
59
+ );
60
+ };
61
+
62
+ export default ClientDashboard;
@@ -0,0 +1,158 @@
1
+ import React from 'react';
2
+ import { Routes, Route, Link } from 'react-router-dom';
3
+ import { toast } from 'react-toastify';
4
+
5
+ import CustomFetch from '../Fetch';
6
+
7
+ import styles from './styles/ClientPortal.module.scss';
8
+
9
+ const ClientPortal = ({ clientProfile, setClientProfile, setClientAuth, logo }) => {
10
+ const handleLogout = async () => {
11
+ try {
12
+ await CustomFetch('/client/logout', 'POST');
13
+ setClientProfile({});
14
+ setClientAuth(false);
15
+ toast.success('You have been logged out successfully');
16
+ } catch (error) {
17
+ toast.error('Error logging out. Please try again.');
18
+ }
19
+ };
20
+
21
+ return (
22
+ <div className={styles.portalContainer}>
23
+ <header className={styles.portalHeader}>
24
+ <div className={styles.logoContainer}>
25
+ <img src={logo} alt="Client Portal" className={styles.logo} />
26
+ </div>
27
+ <div className={styles.userInfo}>
28
+ <span className={styles.welcomeText}>
29
+ Welcome, <strong>{clientProfile.name || clientProfile.email}</strong>
30
+ </span>
31
+ <button onClick={handleLogout} className={styles.logoutButton}>
32
+ Logout
33
+ </button>
34
+ </div>
35
+ </header>
36
+
37
+ <main className={styles.portalContent}>
38
+ <div className={styles.sidebar}>
39
+ <nav className={styles.navigation}>
40
+ <ul>
41
+ <li>
42
+ <Link to="/client/portal" className={styles.navLink}>
43
+ Dashboard
44
+ </Link>
45
+ </li>
46
+ <li>
47
+ <Link to="/client/portal/profile" className={styles.navLink}>
48
+ My Profile
49
+ </Link>
50
+ </li>
51
+ <li>
52
+ <Link to="/client/portal/documents" className={styles.navLink}>
53
+ Documents
54
+ </Link>
55
+ </li>
56
+ </ul>
57
+ </nav>
58
+ </div>
59
+
60
+ <div className={styles.mainContent}>
61
+ <Routes>
62
+ <Route
63
+ path="/"
64
+ element={<Dashboard clientProfile={clientProfile} />}
65
+ />
66
+ <Route
67
+ path="/profile"
68
+ element={<Profile clientProfile={clientProfile} setClientProfile={setClientProfile} />}
69
+ />
70
+ <Route
71
+ path="/documents"
72
+ element={<Documents clientProfile={clientProfile} />}
73
+ />
74
+ </Routes>
75
+ </div>
76
+ </main>
77
+ </div>
78
+ );
79
+ };
80
+
81
+ // Simple Dashboard component
82
+ const Dashboard = ({ clientProfile }) => {
83
+ return (
84
+ <div className={styles.dashboardContainer}>
85
+ <h1>Dashboard</h1>
86
+ <div className={styles.welcomeCard}>
87
+ <h2>Welcome to your Client Portal</h2>
88
+ <p>
89
+ This is your personal dashboard where you can access your documents,
90
+ update your profile, and more.
91
+ </p>
92
+ </div>
93
+
94
+ <div className={styles.statsGrid}>
95
+ <div className={styles.statCard}>
96
+ <h3>Documents</h3>
97
+ <p className={styles.statNumber}>5</p>
98
+ </div>
99
+ <div className={styles.statCard}>
100
+ <h3>Messages</h3>
101
+ <p className={styles.statNumber}>2</p>
102
+ </div>
103
+ <div className={styles.statCard}>
104
+ <h3>Tasks</h3>
105
+ <p className={styles.statNumber}>3</p>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ );
110
+ };
111
+
112
+ // Simple Profile component
113
+ const Profile = ({ clientProfile, setClientProfile }) => {
114
+ return (
115
+ <div className={styles.profileContainer}>
116
+ <h1>My Profile</h1>
117
+ <div className={styles.profileCard}>
118
+ <div className={styles.profileField}>
119
+ <label>Name</label>
120
+ <p>{clientProfile.name || 'Not provided'}</p>
121
+ </div>
122
+ <div className={styles.profileField}>
123
+ <label>Email</label>
124
+ <p>{clientProfile.email}</p>
125
+ </div>
126
+ <div className={styles.profileField}>
127
+ <label>Phone</label>
128
+ <p>{clientProfile.phone || 'Not provided'}</p>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ );
133
+ };
134
+
135
+ // Simple Documents component
136
+ const Documents = ({ clientProfile }) => {
137
+ return (
138
+ <div className={styles.documentsContainer}>
139
+ <h1>Documents</h1>
140
+ <p>Your documents will appear here.</p>
141
+
142
+ <div className={styles.documentsList}>
143
+ <div className={styles.documentCard}>
144
+ <h3>Sample Document 1</h3>
145
+ <p>Uploaded on: 2023-05-15</p>
146
+ <button className={styles.viewButton}>View</button>
147
+ </div>
148
+ <div className={styles.documentCard}>
149
+ <h3>Sample Document 2</h3>
150
+ <p>Uploaded on: 2023-06-20</p>
151
+ <button className={styles.viewButton}>View</button>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ );
156
+ };
157
+
158
+ export default ClientPortal;
@@ -0,0 +1,133 @@
1
+ // Client Dashboard Styles
2
+ .dashboardContainer {
3
+ width: 100%;
4
+ }
5
+
6
+ .sectionTitle {
7
+ margin-top: 0;
8
+ margin-bottom: 1rem;
9
+ color: #333;
10
+ font-size: 1.5rem;
11
+ font-weight: 600;
12
+ }
13
+
14
+ .welcomeCard {
15
+ background-color: white;
16
+ border-radius: 6px;
17
+ padding: 1.25rem;
18
+ margin-bottom: 1.5rem;
19
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
20
+ border-left: 3px solid var(--primary-color, #0f4229);
21
+
22
+ h2 {
23
+ margin-top: 0;
24
+ color: var(--primary-color, #0f4229);
25
+ font-size: 1.25rem;
26
+ margin-bottom: 0.5rem;
27
+ }
28
+
29
+ p {
30
+ color: #666;
31
+ line-height: 1.5;
32
+ margin-bottom: 0;
33
+ font-size: 0.9rem;
34
+ }
35
+ }
36
+
37
+ .statsGrid {
38
+ display: grid;
39
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
40
+ gap: 1rem;
41
+ margin-bottom: 1.5rem;
42
+ }
43
+
44
+ .statCard {
45
+ background-color: white;
46
+ border-radius: 6px;
47
+ padding: 1.25rem;
48
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
49
+ text-align: center;
50
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
51
+
52
+ &:hover {
53
+ transform: translateY(-2px);
54
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08);
55
+ }
56
+
57
+ h3 {
58
+ margin-top: 0;
59
+ color: #555;
60
+ font-size: 0.9rem;
61
+ font-weight: 500;
62
+ }
63
+
64
+ .statNumber {
65
+ font-size: 2rem;
66
+ font-weight: 600;
67
+ color: var(--primary-color, #0f4229);
68
+ margin: 0.4rem 0;
69
+ }
70
+
71
+ .statDescription {
72
+ color: #777;
73
+ font-size: 0.8rem;
74
+ margin: 0;
75
+ }
76
+ }
77
+
78
+ .recentActivity {
79
+ background-color: white;
80
+ border-radius: 6px;
81
+ padding: 1.25rem;
82
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
83
+
84
+ h2 {
85
+ margin-top: 0;
86
+ margin-bottom: 0.75rem;
87
+ font-size: 1.1rem;
88
+ color: #333;
89
+ }
90
+ }
91
+
92
+ .activityList {
93
+ list-style: none;
94
+ padding: 0;
95
+ margin: 0;
96
+ }
97
+
98
+ .activityItem {
99
+ display: flex;
100
+ padding: 0.75rem 0;
101
+ border-bottom: 1px solid #eee;
102
+
103
+ &:last-child {
104
+ border-bottom: none;
105
+ }
106
+
107
+ .activityDate {
108
+ flex: 0 0 80px;
109
+ color: #777;
110
+ font-size: 0.8rem;
111
+ }
112
+
113
+ .activityDescription {
114
+ flex: 1;
115
+ color: #333;
116
+ font-size: 0.9rem;
117
+ }
118
+ }
119
+
120
+ // Responsive styles
121
+ @media (max-width: 768px) {
122
+ .statsGrid {
123
+ grid-template-columns: 1fr;
124
+ }
125
+
126
+ .activityItem {
127
+ flex-direction: column;
128
+
129
+ .activityDate {
130
+ margin-bottom: 0.5rem;
131
+ }
132
+ }
133
+ }
@@ -0,0 +1,240 @@
1
+ // Client Portal Styles
2
+ .portalContainer {
3
+ display: flex;
4
+ flex-direction: column;
5
+ min-height: 100vh;
6
+ background-color: #f8f9fa;
7
+ }
8
+
9
+ .portalHeader {
10
+ display: flex;
11
+ justify-content: space-between;
12
+ align-items: center;
13
+ padding: 1rem 2rem;
14
+ background-color: white;
15
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
16
+ }
17
+
18
+ .logoContainer {
19
+ display: flex;
20
+ align-items: center;
21
+ }
22
+
23
+ .logo {
24
+ height: 40px;
25
+ max-width: 180px;
26
+ object-fit: contain;
27
+ }
28
+
29
+ .userInfo {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 1.5rem;
33
+ }
34
+
35
+ .welcomeText {
36
+ font-size: 0.9rem;
37
+ color: #555;
38
+ }
39
+
40
+ .logoutButton {
41
+ padding: 0.5rem 1rem;
42
+ background-color: transparent;
43
+ border: 1px solid #ddd;
44
+ border-radius: 4px;
45
+ color: #555;
46
+ font-size: 0.9rem;
47
+ cursor: pointer;
48
+ transition: all 0.2s ease;
49
+
50
+ &:hover {
51
+ background-color: #f5f5f5;
52
+ border-color: #ccc;
53
+ }
54
+ }
55
+
56
+ .portalContent {
57
+ display: flex;
58
+ flex: 1;
59
+ }
60
+
61
+ .sidebar {
62
+ width: 250px;
63
+ background-color: white;
64
+ border-right: 1px solid #eee;
65
+ padding: 2rem 0;
66
+ }
67
+
68
+ .navigation {
69
+ ul {
70
+ list-style: none;
71
+ padding: 0;
72
+ margin: 0;
73
+ }
74
+
75
+ li {
76
+ margin-bottom: 0.5rem;
77
+ }
78
+ }
79
+
80
+ .navLink {
81
+ display: block;
82
+ padding: 0.75rem 2rem;
83
+ color: #555;
84
+ text-decoration: none;
85
+ transition: all 0.2s ease;
86
+
87
+ &:hover {
88
+ background-color: #f5f5f5;
89
+ color: var(--primary-color, #0f4229);
90
+ }
91
+
92
+ &.active {
93
+ background-color: rgba(15, 66, 41, 0.05);
94
+ color: var(--primary-color, #0f4229);
95
+ border-left: 3px solid var(--primary-color, #0f4229);
96
+ }
97
+ }
98
+
99
+ .mainContent {
100
+ flex: 1;
101
+ padding: 2rem;
102
+ overflow-y: auto;
103
+ }
104
+
105
+ // Dashboard styles
106
+ .dashboardContainer {
107
+ h1 {
108
+ margin-top: 0;
109
+ margin-bottom: 1.5rem;
110
+ color: #333;
111
+ }
112
+ }
113
+
114
+ .welcomeCard {
115
+ background-color: white;
116
+ border-radius: 8px;
117
+ padding: 1.5rem;
118
+ margin-bottom: 2rem;
119
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
120
+
121
+ h2 {
122
+ margin-top: 0;
123
+ color: var(--primary-color, #0f4229);
124
+ font-size: 1.5rem;
125
+ }
126
+
127
+ p {
128
+ color: #666;
129
+ line-height: 1.6;
130
+ }
131
+ }
132
+
133
+ .statsGrid {
134
+ display: grid;
135
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
136
+ gap: 1.5rem;
137
+ }
138
+
139
+ .statCard {
140
+ background-color: white;
141
+ border-radius: 8px;
142
+ padding: 1.5rem;
143
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
144
+ text-align: center;
145
+
146
+ h3 {
147
+ margin-top: 0;
148
+ color: #555;
149
+ font-size: 1rem;
150
+ font-weight: 500;
151
+ }
152
+
153
+ .statNumber {
154
+ font-size: 2.5rem;
155
+ font-weight: 600;
156
+ color: var(--primary-color, #0f4229);
157
+ margin: 0.5rem 0;
158
+ }
159
+ }
160
+
161
+ // Profile styles
162
+ .profileContainer {
163
+ h1 {
164
+ margin-top: 0;
165
+ margin-bottom: 1.5rem;
166
+ color: #333;
167
+ }
168
+ }
169
+
170
+ .profileCard {
171
+ background-color: white;
172
+ border-radius: 8px;
173
+ padding: 2rem;
174
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
175
+ }
176
+
177
+ .profileField {
178
+ margin-bottom: 1.5rem;
179
+
180
+ label {
181
+ display: block;
182
+ font-size: 0.9rem;
183
+ color: #777;
184
+ margin-bottom: 0.5rem;
185
+ }
186
+
187
+ p {
188
+ font-size: 1.1rem;
189
+ color: #333;
190
+ margin: 0;
191
+ }
192
+ }
193
+
194
+ // Documents styles
195
+ .documentsContainer {
196
+ h1 {
197
+ margin-top: 0;
198
+ margin-bottom: 1.5rem;
199
+ color: #333;
200
+ }
201
+ }
202
+
203
+ .documentsList {
204
+ display: grid;
205
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
206
+ gap: 1.5rem;
207
+ margin-top: 2rem;
208
+ }
209
+
210
+ .documentCard {
211
+ background-color: white;
212
+ border-radius: 8px;
213
+ padding: 1.5rem;
214
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
215
+
216
+ h3 {
217
+ margin-top: 0;
218
+ color: #333;
219
+ }
220
+
221
+ p {
222
+ color: #777;
223
+ font-size: 0.9rem;
224
+ }
225
+ }
226
+
227
+ .viewButton {
228
+ padding: 0.5rem 1rem;
229
+ background-color: var(--primary-color, #0f4229);
230
+ color: white;
231
+ border: none;
232
+ border-radius: 4px;
233
+ cursor: pointer;
234
+ font-size: 0.9rem;
235
+ transition: background-color 0.2s ease;
236
+
237
+ &:hover {
238
+ background-color: var(--secondary-color, #0a2e1c);
239
+ }
240
+ }