vasuzex 2.1.17 → 2.1.19

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,10 +1,11 @@
1
- import { FiEye, FiEdit, FiTrash2 } from "react-icons/fi";
1
+ import { Eye, Edit2, Trash2 } from "lucide-react";
2
2
 
3
3
  /**
4
4
  * ActionDefaults - Production Ready
5
5
  *
6
6
  * Default configurations for common DataTable actions
7
7
  * Provides sensible defaults for edit, view, delete, and switch actions
8
+ * Uses lucide-react icons matching RowActionsCell design
8
9
  *
9
10
  * @module components/DataTable/ActionDefaults
10
11
  */
@@ -13,26 +14,26 @@ export const ACTION_DEFAULTS = {
13
14
  edit: {
14
15
  type: "link",
15
16
  label: "Edit",
16
- icon: FiEdit,
17
+ icon: Edit2,
17
18
  title: "Edit",
18
19
  extraClass:
19
- "rounded-lg p-2 text-brand-600 hover:bg-brand-50 dark:text-brand-400 dark:hover:bg-gray-700",
20
+ "p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30",
20
21
  },
21
22
  view: {
22
23
  type: "button",
23
24
  label: "View Details",
24
- icon: FiEye,
25
+ icon: Eye,
25
26
  title: "View Details",
26
27
  extraClass:
27
- "rounded-lg p-2 text-blue-600 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-gray-700",
28
+ "p-1.5 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-blue-400 dark:hover:bg-blue-950/30",
28
29
  },
29
30
  delete: {
30
31
  type: "button",
31
32
  label: "Delete",
32
- icon: FiTrash2,
33
+ icon: Trash2,
33
34
  title: "Delete",
34
35
  extraClass:
35
- "rounded-lg p-2 text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-gray-700",
36
+ "p-1.5 text-gray-600 hover:text-rose-600 hover:bg-rose-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-rose-400 dark:hover:bg-rose-950/30",
36
37
  },
37
38
  switch: {
38
39
  type: "button",
@@ -0,0 +1,60 @@
1
+ /**
2
+ * ApprovalStatusCell Component
3
+ *
4
+ * Reusable read-only status pill for approval workflows
5
+ * Displays status with icon and soft background colors
6
+ *
7
+ * @module components/DataTable/CellComponents
8
+ */
9
+
10
+ import React from 'react';
11
+ import PropTypes from 'prop-types';
12
+ import { CheckCircle, XCircle, Clock } from 'lucide-react';
13
+
14
+ const STATUS_CONFIG = {
15
+ pending: {
16
+ icon: Clock,
17
+ label: 'Pending',
18
+ bgClass: 'bg-amber-50 dark:bg-amber-950/30',
19
+ textClass: 'text-amber-700 dark:text-amber-400',
20
+ },
21
+ approved: {
22
+ icon: CheckCircle,
23
+ label: 'Approved',
24
+ bgClass: 'bg-emerald-50 dark:bg-emerald-950/30',
25
+ textClass: 'text-emerald-700 dark:text-emerald-400',
26
+ },
27
+ rejected: {
28
+ icon: XCircle,
29
+ label: 'Rejected',
30
+ bgClass: 'bg-rose-50 dark:bg-rose-950/30',
31
+ textClass: 'text-rose-700 dark:text-rose-400',
32
+ },
33
+ };
34
+
35
+ /**
36
+ * ApprovalStatusCell - Professional status indicator
37
+ *
38
+ * @param {Object} props
39
+ * @param {string} props.status - Approval status: 'pending'|'approved'|'rejected'
40
+ * @returns {JSX.Element}
41
+ */
42
+ export function ApprovalStatusCell({ status }) {
43
+ const config = STATUS_CONFIG[status] || STATUS_CONFIG.pending;
44
+ const Icon = config.icon;
45
+
46
+ return (
47
+ <span
48
+ className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-xs font-medium ${config.bgClass} ${config.textClass}`}
49
+ >
50
+ <Icon className="h-3.5 w-3.5" />
51
+ {config.label}
52
+ </span>
53
+ );
54
+ }
55
+
56
+ ApprovalStatusCell.propTypes = {
57
+ status: PropTypes.oneOf(['pending', 'approved', 'rejected']).isRequired,
58
+ };
59
+
60
+ export default ApprovalStatusCell;
@@ -0,0 +1,212 @@
1
+ /**
2
+ * RowActionsCell Component
3
+ *
4
+ * Reusable actions cell with primary icons + overflow menu pattern
5
+ * Follows modern admin dashboard design (Amazon Seller/Stripe/Blinkit)
6
+ *
7
+ * @module components/DataTable/CellComponents
8
+ */
9
+
10
+ import React, { useState, useRef, useEffect } from 'react';
11
+ import PropTypes from 'prop-types';
12
+ import { Eye, Edit2, MoreVertical, CheckCircle, XCircle, History, Power, Trash2 } from 'lucide-react';
13
+ import { Link } from 'react-router-dom';
14
+
15
+ /**
16
+ * RowActionsCell - Professional actions menu for data tables
17
+ *
18
+ * @param {Object} props
19
+ * @param {Object} props.row - Row data object
20
+ * @param {Function} props.onView - View action handler
21
+ * @param {Function} props.onEdit - Edit action handler (optional if editPath provided)
22
+ * @param {string} props.editPath - Edit page path (will be passed to Link)
23
+ * @param {Function} props.onToggle - Toggle status handler
24
+ * @param {Function} props.onDelete - Delete action handler
25
+ * @param {Function} props.onApprove - Approve action handler (approval workflows)
26
+ * @param {Function} props.onReject - Reject action handler (approval workflows)
27
+ * @param {Function} props.onViewHistory - View approval history handler
28
+ * @param {boolean} props.hasApproval - Whether to show approval actions (default: false)
29
+ * @returns {JSX.Element}
30
+ */
31
+ export function RowActionsCell({
32
+ row,
33
+ onView,
34
+ onEdit,
35
+ editPath,
36
+ onToggle,
37
+ onDelete,
38
+ onApprove,
39
+ onReject,
40
+ onViewHistory,
41
+ hasApproval = false,
42
+ }) {
43
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
44
+ const menuRef = useRef(null);
45
+ const isPending = hasApproval && row.approval_status === 'pending';
46
+
47
+ // Close menu when clicking outside
48
+ useEffect(() => {
49
+ const handleClickOutside = (event) => {
50
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
51
+ setIsMenuOpen(false);
52
+ }
53
+ };
54
+
55
+ if (isMenuOpen) {
56
+ document.addEventListener('mousedown', handleClickOutside);
57
+ return () => document.removeEventListener('mousedown', handleClickOutside);
58
+ }
59
+ }, [isMenuOpen]);
60
+
61
+ return (
62
+ <div className="flex items-center gap-2">
63
+ {/* Primary Actions - Always Visible */}
64
+ <button
65
+ onClick={() => onView(row)}
66
+ className="p-1.5 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-blue-400 dark:hover:bg-blue-950/30"
67
+ title="View Details"
68
+ aria-label="View Details"
69
+ >
70
+ <Eye className="h-4 w-4" />
71
+ </button>
72
+
73
+ {editPath ? (
74
+ <Link
75
+ to={editPath}
76
+ className="p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30"
77
+ title="Edit"
78
+ aria-label="Edit"
79
+ >
80
+ <Edit2 className="h-4 w-4" />
81
+ </Link>
82
+ ) : (
83
+ onEdit && (
84
+ <button
85
+ onClick={() => onEdit(row)}
86
+ className="p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30"
87
+ title="Edit"
88
+ aria-label="Edit"
89
+ >
90
+ <Edit2 className="h-4 w-4" />
91
+ </button>
92
+ )
93
+ )}
94
+
95
+ {/* Overflow Menu - Secondary & Destructive Actions */}
96
+ <div className="relative" ref={menuRef}>
97
+ <button
98
+ onClick={() => setIsMenuOpen(!isMenuOpen)}
99
+ className="p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-700"
100
+ title="More Actions"
101
+ aria-label="More Actions"
102
+ aria-expanded={isMenuOpen}
103
+ >
104
+ <MoreVertical className="h-4 w-4" />
105
+ </button>
106
+
107
+ {isMenuOpen && (
108
+ <div className="absolute right-0 mt-1 w-48 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 z-50 py-1">
109
+ {/* Approval Actions - Only show when pending */}
110
+ {hasApproval && isPending && (
111
+ <>
112
+ {onApprove && (
113
+ <button
114
+ onClick={() => {
115
+ onApprove(row);
116
+ setIsMenuOpen(false);
117
+ }}
118
+ className="w-full flex items-center gap-3 px-4 py-2 text-sm text-emerald-700 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/30"
119
+ >
120
+ <CheckCircle className="h-4 w-4" />
121
+ <span>Approve</span>
122
+ </button>
123
+ )}
124
+ {onReject && (
125
+ <button
126
+ onClick={() => {
127
+ onReject(row);
128
+ setIsMenuOpen(false);
129
+ }}
130
+ className="w-full flex items-center gap-3 px-4 py-2 text-sm text-rose-700 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950/30"
131
+ >
132
+ <XCircle className="h-4 w-4" />
133
+ <span>Reject</span>
134
+ </button>
135
+ )}
136
+ <div className="border-t border-gray-200 dark:border-gray-700 my-1" />
137
+ </>
138
+ )}
139
+
140
+ {/* View History */}
141
+ {hasApproval && onViewHistory && (
142
+ <>
143
+ <button
144
+ onClick={() => {
145
+ onViewHistory(row);
146
+ setIsMenuOpen(false);
147
+ }}
148
+ className="w-full flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-700"
149
+ >
150
+ <History className="h-4 w-4" />
151
+ <span>View History</span>
152
+ </button>
153
+ <div className="border-t border-gray-200 dark:border-gray-700 my-1" />
154
+ </>
155
+ )}
156
+
157
+ {/* Toggle Status */}
158
+ {onToggle && (
159
+ <button
160
+ onClick={() => {
161
+ onToggle(row);
162
+ setIsMenuOpen(false);
163
+ }}
164
+ className="w-full flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-700"
165
+ >
166
+ <Power className="h-4 w-4" />
167
+ <div className="flex flex-col items-start">
168
+ <span>Toggle Status</span>
169
+ <span className="text-xs text-gray-500 dark:text-gray-400">
170
+ {row.is_active ? 'Deactivate' : 'Activate'}
171
+ </span>
172
+ </div>
173
+ </button>
174
+ )}
175
+
176
+ {/* Delete - Always last, always red */}
177
+ {onDelete && (
178
+ <>
179
+ <div className="border-t border-gray-200 dark:border-gray-700 my-1" />
180
+ <button
181
+ onClick={() => {
182
+ onDelete(row);
183
+ setIsMenuOpen(false);
184
+ }}
185
+ className="w-full flex items-center gap-3 px-4 py-2 text-sm text-rose-700 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950/30"
186
+ >
187
+ <Trash2 className="h-4 w-4" />
188
+ <span>Delete</span>
189
+ </button>
190
+ </>
191
+ )}
192
+ </div>
193
+ )}
194
+ </div>
195
+ </div>
196
+ );
197
+ }
198
+
199
+ RowActionsCell.propTypes = {
200
+ row: PropTypes.object.isRequired,
201
+ onView: PropTypes.func,
202
+ onEdit: PropTypes.func,
203
+ editPath: PropTypes.string,
204
+ onToggle: PropTypes.func,
205
+ onDelete: PropTypes.func,
206
+ onApprove: PropTypes.func,
207
+ onReject: PropTypes.func,
208
+ onViewHistory: PropTypes.func,
209
+ hasApproval: PropTypes.bool,
210
+ };
211
+
212
+ export default RowActionsCell;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @vasuzex/react - DataTable Cell Components
3
+ * Reusable cell renderers for common patterns
4
+ */
5
+
6
+ export { ApprovalStatusCell } from './ApprovalStatusCell.jsx';
7
+ export { RowActionsCell } from './RowActionsCell.jsx';
8
+ export { default as ApprovalStatusCellDefault } from './ApprovalStatusCell.jsx';
9
+ export { default as RowActionsCellDefault } from './RowActionsCell.jsx';
@@ -75,7 +75,7 @@ export function TableBody({
75
75
 
76
76
  {/* Render Actions */}
77
77
  {actions && (
78
- <td className="px-6 py-4 text-right">
78
+ <td className="px-2 py-2 text-right">
79
79
  <div className="flex items-center justify-end gap-2">
80
80
  {actions.map((userAction, actionIdx) => {
81
81
  // Check visibility first
@@ -146,7 +146,7 @@ export function TableBody({
146
146
  const content = action.renderContent ? (
147
147
  action.renderContent(row)
148
148
  ) : Icon ? (
149
- <Icon className="h-5 w-5" />
149
+ <Icon className="h-4 w-4" />
150
150
  ) : (
151
151
  action.label
152
152
  );
@@ -16,3 +16,6 @@ export {
16
16
  createViewClickHandler,
17
17
  createDeleteClickHandler
18
18
  } from './ActionDefaults.jsx';
19
+
20
+ // Cell Components - Reusable cell renderers
21
+ export { ApprovalStatusCell, RowActionsCell } from './CellComponents/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vasuzex",
3
- "version": "2.1.17",
3
+ "version": "2.1.19",
4
4
  "description": "Laravel-inspired framework for Node.js monorepos - V2 with optimized dependencies",
5
5
  "type": "module",
6
6
  "main": "./framework/index.js",
@@ -48,6 +48,34 @@
48
48
  "#config": "./config/index.cjs",
49
49
  "#config/*": "./config/*"
50
50
  },
51
+ "scripts": {
52
+ "dev": "turbo run dev",
53
+ "build": "turbo run build",
54
+ "start": "turbo run start",
55
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
56
+ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
57
+ "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
58
+ "db:migrate": "npx vasuzex migrate",
59
+ "test:all": "NODE_OPTIONS=--experimental-vm-modules npx jest",
60
+ "test:unit": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/unit",
61
+ "test:integration": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/integration",
62
+ "test:e2e": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/e2e",
63
+ "scan:issues": "node deep-scan-issues.cjs",
64
+ "dev:pilot-test-api": "turbo run dev --filter=pilot-test-api",
65
+ "start:pilot-test-api": "turbo run start --filter=pilot-test-api",
66
+ "dev:pilot-test-web": "turbo run dev --filter=pilot-test-web",
67
+ "start:pilot-test-web": "turbo run start --filter=pilot-test-web",
68
+ "dev:integration-test-api": "turbo run dev --filter=integration-test-api",
69
+ "start:integration-test-api": "turbo run start --filter=integration-test-api",
70
+ "dev:test-gen-api-api": "turbo run dev --filter=test-gen-api-api",
71
+ "start:test-gen-api-api": "turbo run start --filter=test-gen-api-api",
72
+ "dev:cleanup-test-api": "turbo run dev --filter=cleanup-test-api",
73
+ "start:cleanup-test-api": "turbo run start --filter=cleanup-test-api",
74
+ "dev:auth-integration-test-api": "turbo run dev --filter=auth-integration-test-api",
75
+ "start:auth-integration-test-api": "turbo run start --filter=auth-integration-test-api",
76
+ "dev:e2e-test-api": "turbo run dev --filter=e2e-test-api",
77
+ "start:e2e-test-api": "turbo run start --filter=e2e-test-api"
78
+ },
51
79
  "keywords": [
52
80
  "framework",
53
81
  "laravel",
@@ -87,6 +115,7 @@
87
115
  "joi": "^17.13.3",
88
116
  "jose": "^6.1.3",
89
117
  "jsonwebtoken": "^9.0.3",
118
+ "lucide-react": "^0.553.0",
90
119
  "maxmind": "^5.0.1",
91
120
  "multer": "^2.0.2",
92
121
  "node-plop": "^0.32.3",
@@ -124,6 +153,13 @@
124
153
  "turbo": "^2.6.1",
125
154
  "vite": "^5.0.0"
126
155
  },
156
+ "pnpm": {
157
+ "overrides": {
158
+ "express": "^5.2.1",
159
+ "react": "^18.2.0",
160
+ "vue": "^3.4.0"
161
+ }
162
+ },
127
163
  "repository": {
128
164
  "type": "git",
129
165
  "url": "git+https://github.com/rishicool/vasuzex.git"
@@ -132,32 +168,5 @@
132
168
  "url": "https://github.com/rishicool/vasuzex/issues"
133
169
  },
134
170
  "homepage": "https://github.com/rishicool/vasuzex#readme",
135
- "scripts": {
136
- "dev": "turbo run dev",
137
- "build": "turbo run build",
138
- "start": "turbo run start",
139
- "test": "NODE_OPTIONS=--experimental-vm-modules jest",
140
- "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
141
- "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
142
- "db:migrate": "npx vasuzex migrate",
143
- "test:all": "NODE_OPTIONS=--experimental-vm-modules npx jest",
144
- "test:unit": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/unit",
145
- "test:integration": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/integration",
146
- "test:e2e": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/e2e",
147
- "scan:issues": "node deep-scan-issues.cjs",
148
- "dev:pilot-test-api": "turbo run dev --filter=pilot-test-api",
149
- "start:pilot-test-api": "turbo run start --filter=pilot-test-api",
150
- "dev:pilot-test-web": "turbo run dev --filter=pilot-test-web",
151
- "start:pilot-test-web": "turbo run start --filter=pilot-test-web",
152
- "dev:integration-test-api": "turbo run dev --filter=integration-test-api",
153
- "start:integration-test-api": "turbo run start --filter=integration-test-api",
154
- "dev:test-gen-api-api": "turbo run dev --filter=test-gen-api-api",
155
- "start:test-gen-api-api": "turbo run start --filter=test-gen-api-api",
156
- "dev:cleanup-test-api": "turbo run dev --filter=cleanup-test-api",
157
- "start:cleanup-test-api": "turbo run start --filter=cleanup-test-api",
158
- "dev:auth-integration-test-api": "turbo run dev --filter=auth-integration-test-api",
159
- "start:auth-integration-test-api": "turbo run start --filter=auth-integration-test-api",
160
- "dev:e2e-test-api": "turbo run dev --filter=e2e-test-api",
161
- "start:e2e-test-api": "turbo run start --filter=e2e-test-api"
162
- }
163
- }
171
+ "packageManager": "pnpm@10.0.0"
172
+ }
@@ -1,201 +0,0 @@
1
- # 🚨 STRICT LOGGING POLICY - MANDATORY
2
-
3
- ## ❌ FORBIDDEN - NEVER USE THESE
4
-
5
- ```javascript
6
- // ❌ STRICTLY FORBIDDEN - DO NOT USE!
7
- console.log()
8
- console.warn()
9
- console.error()
10
- console.info()
11
- console.debug()
12
- ```
13
-
14
- **VIOLATION OF THIS RULE WILL BE REJECTED IMMEDIATELY!**
15
-
16
- ---
17
-
18
- ## ✅ CORRECT LOGGING METHODS
19
-
20
- ### Backend (API) - Use Vasuzex Log Facade
21
-
22
- ```javascript
23
- import { Log } from 'vasuzex';
24
-
25
- // Info logging
26
- Log.info('User logged in', { userId: user.id });
27
-
28
- // Warning logging
29
- Log.warning('Rate limit approaching', { ip: req.ip, count: 95 });
30
-
31
- // Error logging
32
- Log.error('Database connection failed', { error: err.message });
33
-
34
- // Debug logging (development only)
35
- Log.debug('Processing order', { orderId: 123, items: 5 });
36
-
37
- // Critical errors
38
- Log.critical('Payment gateway down', { gateway: 'razorpay' });
39
-
40
- // Alerts (requires immediate action)
41
- Log.alert('Disk space critical', { available: '5%' });
42
- ```
43
-
44
- ### Frontend (Web) - Use Custom Logger Utility
45
-
46
- ```javascript
47
- import { logger } from '@/utils/logger';
48
-
49
- // Info logging (development only)
50
- logger.info('Config loaded', { apiUrl, mediaUrl });
51
-
52
- // Warning logging
53
- logger.warning('API rate limit warning', { remaining: 10 });
54
-
55
- // Error logging (always logged)
56
- logger.error('Failed to fetch data', error);
57
-
58
- // Debug logging (development only)
59
- logger.debug('Component mounted', { props });
60
- ```
61
-
62
- ---
63
-
64
- ## 📁 Logger Implementation
65
-
66
- ### Backend: Vasuzex Log Facade
67
-
68
- **Location:** `vasuzex-v2/framework/Support/Facades/Log.js`
69
-
70
- **Methods:**
71
- - `Log.emergency()` - System unusable
72
- - `Log.alert()` - Immediate action required
73
- - `Log.critical()` - Critical conditions
74
- - `Log.error()` - Runtime errors
75
- - `Log.warning()` - Exceptional but not errors
76
- - `Log.notice()` - Normal but significant
77
- - `Log.info()` - Interesting events
78
- - `Log.debug()` - Debug information
79
-
80
- **Configuration:** `config/logging.cjs`
81
-
82
- ### Frontend: Custom Logger Utility
83
-
84
- **Location:** `apps/customer/web/src/utils/logger.js`
85
-
86
- **Features:**
87
- - Automatic timestamp
88
- - Context serialization
89
- - Development-only info/debug logs
90
- - Always-on error logs
91
- - Prefix: `[neasto]`
92
-
93
- **Methods:**
94
- - `logger.info(message, context)` - Development only
95
- - `logger.warning(message, context)` - Development/Test
96
- - `logger.error(message, error)` - Always logged
97
- - `logger.debug(message, data)` - Development only
98
-
99
- ---
100
-
101
- ## 🔍 Examples
102
-
103
- ### ✅ CORRECT
104
-
105
- ```javascript
106
- // Backend
107
- import { Log } from 'vasuzex';
108
-
109
- async function sendOTP(phone) {
110
- Log.info(`OTP sent to ${phone}`);
111
- }
112
-
113
- async function processPayment(orderId) {
114
- try {
115
- // ... payment logic
116
- Log.info('Payment processed', { orderId, amount });
117
- } catch (error) {
118
- Log.error('Payment failed', { orderId, error: error.message });
119
- throw error;
120
- }
121
- }
122
-
123
- // Frontend
124
- import { logger } from '@/utils/logger';
125
-
126
- function LoginForm() {
127
- const handleLogin = async () => {
128
- try {
129
- logger.debug('Login attempt', { phone });
130
- const result = await authService.login(phone);
131
- logger.info('Login successful');
132
- } catch (error) {
133
- logger.error('Login failed', error);
134
- }
135
- };
136
- }
137
- ```
138
-
139
- ### ❌ WRONG
140
-
141
- ```javascript
142
- // ❌ NEVER DO THIS!
143
- console.log('User logged in');
144
- console.error('Failed to process');
145
- console.warn('Rate limit warning');
146
-
147
- // ❌ NEVER DO THIS IN PRODUCTION CODE!
148
- if (isDevelopment) {
149
- console.log('Debug info'); // Still wrong! Use logger
150
- }
151
- ```
152
-
153
- ---
154
-
155
- ## 📋 Migration Checklist
156
-
157
- When adding new code:
158
-
159
- - [ ] Import `Log` from `vasuzex` (backend)
160
- - [ ] Import `logger` from `@/utils/logger` (frontend)
161
- - [ ] NO direct console.* calls anywhere
162
- - [ ] Use appropriate log level (info/warning/error/debug)
163
- - [ ] Include context objects for debugging
164
- - [ ] Test logging in development mode
165
-
166
- ---
167
-
168
- ## 🔧 Current Status
169
-
170
- ### Backend Files Using Log Facade ✅
171
-
172
- - `apps/customer/api/src/services/AuthService.js`
173
- - `apps/customer/api/src/services/OrderModificationService.js`
174
-
175
- ### Frontend Files Using Logger ✅
176
-
177
- - `apps/customer/web/src/hooks/useAuth.js`
178
- - `apps/customer/web/src/components/auth/LoginForm.jsx`
179
- - `apps/customer/web/src/App.jsx`
180
- - `apps/customer/web/src/lib/AppConfigProvider.jsx`
181
-
182
- ### Cleaned Files (No Logging) ✅
183
-
184
- - `apps/customer/web/src/main.jsx`
185
- - `apps/customer/web/src/lib/api-client.js`
186
-
187
- ---
188
-
189
- ## ⚠️ REMEMBER
190
-
191
- **NEVER write `console.log`, `console.warn`, or `console.error` in any file!**
192
-
193
- **ALWAYS use:**
194
- - Backend: `Log.info()`, `Log.error()`, `Log.warning()`, `Log.debug()`
195
- - Frontend: `logger.info()`, `logger.error()`, `logger.warning()`, `logger.debug()`
196
-
197
- **This is not a suggestion - it's a strict requirement!**
198
-
199
- ---
200
-
201
- Last Updated: 2025-12-10