pi-kiosk-shared 1.0.0 → 1.0.2
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/dist/api.js +8 -3
- package/dist/components/ErrorDisplay.js +9 -6
- package/dist/components/LoadingSpinner.js +7 -4
- package/dist/config/deployment.js +14 -11
- package/dist/config/environments.js +14 -7
- package/dist/config/logger.js +15 -12
- package/dist/constants.js +7 -4
- package/dist/errors.js +17 -7
- package/dist/hooks/useApi.js +11 -8
- package/dist/hooks/useAsyncOperation.js +11 -8
- package/dist/hooks/useErrorHandler.js +12 -9
- package/dist/index.js +29 -13
- package/dist/types.js +2 -1
- package/dist/utils.js +17 -7
- package/dist/validation.d.ts +1 -1
- package/dist/validation.js +27 -23
- package/package.json +9 -1
package/dist/api.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared API utilities
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createAPIClient = exports.APIClient = exports.API_ENDPOINTS = void 0;
|
|
5
|
+
exports.API_ENDPOINTS = {
|
|
3
6
|
PRODUCTS: '/api/products',
|
|
4
7
|
PRODUCT_CLICK: '/api/products/:id/click',
|
|
5
8
|
ADMIN_LOGIN: '/admin/login',
|
|
@@ -8,7 +11,7 @@ export const API_ENDPOINTS = {
|
|
|
8
11
|
HEALTH: '/health',
|
|
9
12
|
CHECK_TRANSACTIONS: '/api/check-new-transactions'
|
|
10
13
|
};
|
|
11
|
-
|
|
14
|
+
class APIClient {
|
|
12
15
|
constructor(baseUrl, kioskSecret) {
|
|
13
16
|
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
14
17
|
this.kioskSecret = kioskSecret;
|
|
@@ -51,7 +54,9 @@ export class APIClient {
|
|
|
51
54
|
return this.request(endpoint, { method: 'DELETE' });
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
|
-
|
|
57
|
+
exports.APIClient = APIClient;
|
|
58
|
+
const createAPIClient = (baseUrl, kioskSecret) => {
|
|
55
59
|
const url = baseUrl || process.env.REACT_APP_API_URL || 'http://localhost:3015';
|
|
56
60
|
return new APIClient(url, kioskSecret);
|
|
57
61
|
};
|
|
62
|
+
exports.createAPIClient = createAPIClient;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorDisplay = ErrorDisplay;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
7
|
+
function ErrorDisplay({ error, onRetry, onDismiss, className = '', showDetails = false, retryLabel = 'Zkusit znovu', dismissLabel = 'Zavřít' }) {
|
|
8
|
+
const userMessage = (0, errors_1.getErrorMessage)(error);
|
|
6
9
|
const isNetworkError = error.name === 'NetworkError';
|
|
7
|
-
return (
|
|
10
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `error-display ${constants_1.CSS_CLASSES.ERROR} ${className}`, role: "alert", "aria-live": "assertive", children: (0, jsx_runtime_1.jsxs)("div", { className: "error-content", children: [(0, jsx_runtime_1.jsx)("div", { className: "error-icon", "aria-hidden": "true", children: isNetworkError ? '🌐' : '❌' }), (0, jsx_runtime_1.jsxs)("div", { className: "error-text", children: [(0, jsx_runtime_1.jsx)("h3", { className: "error-title", children: isNetworkError ? 'Problém s připojením' : 'Došlo k chybě' }), (0, jsx_runtime_1.jsx)("p", { className: "error-message", children: userMessage })] }), showDetails && process.env.NODE_ENV === 'development' && ((0, jsx_runtime_1.jsxs)("details", { className: "error-details", children: [(0, jsx_runtime_1.jsx)("summary", { children: "Technick\u00E9 detaily" }), (0, jsx_runtime_1.jsx)("pre", { className: "error-stack", children: (0, jsx_runtime_1.jsx)("code", { children: error.stack || error.message }) })] })), (0, jsx_runtime_1.jsxs)("div", { className: "error-actions", children: [onRetry && ((0, jsx_runtime_1.jsxs)("button", { onClick: onRetry, className: `retry-btn ${constants_1.CSS_CLASSES.BUTTON_PRIMARY}`, type: "button", children: ["\uD83D\uDD04 ", retryLabel] })), onDismiss && ((0, jsx_runtime_1.jsxs)("button", { onClick: onDismiss, className: `dismiss-btn ${constants_1.CSS_CLASSES.BUTTON_SECONDARY}`, type: "button", children: ["\u2715 ", dismissLabel] }))] })] }) }));
|
|
8
11
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LoadingSpinner = LoadingSpinner;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
function LoadingSpinner({ size = 'medium', message, className = '', 'aria-label': ariaLabel = 'Loading' }) {
|
|
4
7
|
const sizeClass = {
|
|
5
8
|
small: 'spinner-small',
|
|
6
9
|
medium: 'spinner-medium',
|
|
7
10
|
large: 'spinner-large'
|
|
8
11
|
}[size];
|
|
9
|
-
return (
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `loading-container ${constants_1.CSS_CLASSES.LOADING} ${className}`, children: [(0, jsx_runtime_1.jsx)("div", { className: `spinner ${sizeClass}`, role: "status", "aria-label": ariaLabel, children: (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: ariaLabel }) }), message && ((0, jsx_runtime_1.jsx)("p", { className: "loading-message", "aria-live": "polite", children: message }))] }));
|
|
10
13
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Deployment configuration for different modes and platforms
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.railwayConfigs = exports.deploymentConfig = void 0;
|
|
5
|
+
exports.deploymentConfig = {
|
|
3
6
|
railway: {
|
|
4
7
|
testService: 'kiosk-test',
|
|
5
8
|
stagingService: 'kiosk-staging',
|
|
@@ -46,7 +49,7 @@ export const deploymentConfig = {
|
|
|
46
49
|
}
|
|
47
50
|
};
|
|
48
51
|
// Railway deployment configuration files
|
|
49
|
-
|
|
52
|
+
exports.railwayConfigs = {
|
|
50
53
|
test: {
|
|
51
54
|
build: {
|
|
52
55
|
builder: 'NIXPACKS'
|
|
@@ -61,7 +64,7 @@ export const railwayConfigs = {
|
|
|
61
64
|
name: 'kiosk-backend-test',
|
|
62
65
|
source: './packages/backend',
|
|
63
66
|
env: {
|
|
64
|
-
...deploymentConfig.environmentVariables.test,
|
|
67
|
+
...exports.deploymentConfig.environmentVariables.test,
|
|
65
68
|
PORT: '3000',
|
|
66
69
|
FIO_API_MODE: 'test'
|
|
67
70
|
}
|
|
@@ -71,14 +74,14 @@ export const railwayConfigs = {
|
|
|
71
74
|
source: './packages/kiosk-app',
|
|
72
75
|
buildCommand: 'npm run build',
|
|
73
76
|
startCommand: 'npx serve -s dist -l 5173',
|
|
74
|
-
env: deploymentConfig.environmentVariables.test
|
|
77
|
+
env: exports.deploymentConfig.environmentVariables.test
|
|
75
78
|
},
|
|
76
79
|
{
|
|
77
80
|
name: 'admin-frontend-test',
|
|
78
81
|
source: './packages/admin-app',
|
|
79
82
|
buildCommand: 'npm run build',
|
|
80
83
|
startCommand: 'npx serve -s dist -l 5174',
|
|
81
|
-
env: deploymentConfig.environmentVariables.test
|
|
84
|
+
env: exports.deploymentConfig.environmentVariables.test
|
|
82
85
|
}
|
|
83
86
|
]
|
|
84
87
|
},
|
|
@@ -96,7 +99,7 @@ export const railwayConfigs = {
|
|
|
96
99
|
name: 'kiosk-backend-staging',
|
|
97
100
|
source: './packages/backend',
|
|
98
101
|
env: {
|
|
99
|
-
...deploymentConfig.environmentVariables.staging,
|
|
102
|
+
...exports.deploymentConfig.environmentVariables.staging,
|
|
100
103
|
PORT: '3000'
|
|
101
104
|
}
|
|
102
105
|
},
|
|
@@ -105,14 +108,14 @@ export const railwayConfigs = {
|
|
|
105
108
|
source: './packages/kiosk-app',
|
|
106
109
|
buildCommand: 'npm run build',
|
|
107
110
|
startCommand: 'npx serve -s dist -l 5173',
|
|
108
|
-
env: deploymentConfig.environmentVariables.staging
|
|
111
|
+
env: exports.deploymentConfig.environmentVariables.staging
|
|
109
112
|
},
|
|
110
113
|
{
|
|
111
114
|
name: 'admin-frontend-staging',
|
|
112
115
|
source: './packages/admin-app',
|
|
113
116
|
buildCommand: 'npm run build',
|
|
114
117
|
startCommand: 'npx serve -s dist -l 5174',
|
|
115
|
-
env: deploymentConfig.environmentVariables.staging
|
|
118
|
+
env: exports.deploymentConfig.environmentVariables.staging
|
|
116
119
|
}
|
|
117
120
|
]
|
|
118
121
|
},
|
|
@@ -130,7 +133,7 @@ export const railwayConfigs = {
|
|
|
130
133
|
name: 'kiosk-backend-prod',
|
|
131
134
|
source: './packages/backend',
|
|
132
135
|
env: {
|
|
133
|
-
...deploymentConfig.environmentVariables.production,
|
|
136
|
+
...exports.deploymentConfig.environmentVariables.production,
|
|
134
137
|
PORT: '3000'
|
|
135
138
|
}
|
|
136
139
|
},
|
|
@@ -139,14 +142,14 @@ export const railwayConfigs = {
|
|
|
139
142
|
source: './packages/kiosk-app',
|
|
140
143
|
buildCommand: 'npm run build',
|
|
141
144
|
startCommand: 'npx serve -s dist -l 5173',
|
|
142
|
-
env: deploymentConfig.environmentVariables.production
|
|
145
|
+
env: exports.deploymentConfig.environmentVariables.production
|
|
143
146
|
},
|
|
144
147
|
{
|
|
145
148
|
name: 'admin-frontend-prod',
|
|
146
149
|
source: './packages/admin-app',
|
|
147
150
|
buildCommand: 'npm run build',
|
|
148
151
|
startCommand: 'npx serve -s dist -l 5174',
|
|
149
|
-
env: deploymentConfig.environmentVariables.production
|
|
152
|
+
env: exports.deploymentConfig.environmentVariables.production
|
|
150
153
|
}
|
|
151
154
|
]
|
|
152
155
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Simple environment configuration
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.isProduction = exports.isDevelopment = exports.getEnvironmentConfig = exports.getCurrentEnvironment = exports.environments = void 0;
|
|
5
|
+
exports.environments = {
|
|
3
6
|
development: {
|
|
4
7
|
apiUrl: 'http://localhost:3015',
|
|
5
8
|
wsUrl: 'ws://localhost:3015',
|
|
@@ -16,14 +19,18 @@ export const environments = {
|
|
|
16
19
|
}
|
|
17
20
|
};
|
|
18
21
|
// Simple environment detection
|
|
19
|
-
|
|
22
|
+
const getCurrentEnvironment = () => {
|
|
20
23
|
return process.env.NODE_ENV === 'production' ? 'production' : 'development';
|
|
21
24
|
};
|
|
25
|
+
exports.getCurrentEnvironment = getCurrentEnvironment;
|
|
22
26
|
// Get current environment configuration
|
|
23
|
-
|
|
24
|
-
const env = getCurrentEnvironment();
|
|
25
|
-
return environments[env];
|
|
27
|
+
const getEnvironmentConfig = () => {
|
|
28
|
+
const env = (0, exports.getCurrentEnvironment)();
|
|
29
|
+
return exports.environments[env];
|
|
26
30
|
};
|
|
31
|
+
exports.getEnvironmentConfig = getEnvironmentConfig;
|
|
27
32
|
// Simple environment checks
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
const isDevelopment = () => (0, exports.getCurrentEnvironment)() === 'development';
|
|
34
|
+
exports.isDevelopment = isDevelopment;
|
|
35
|
+
const isProduction = () => (0, exports.getCurrentEnvironment)() === 'production';
|
|
36
|
+
exports.isProduction = isProduction;
|
package/dist/config/logger.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Centralized logging system with environment-aware configuration
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.log = exports.logger = void 0;
|
|
5
|
+
const environments_1 = require("./environments");
|
|
3
6
|
class Logger {
|
|
4
7
|
constructor() {
|
|
5
|
-
this.config = getEnvironmentConfig();
|
|
8
|
+
this.config = (0, environments_1.getEnvironmentConfig)();
|
|
6
9
|
this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
7
10
|
}
|
|
8
11
|
shouldLog(level) {
|
|
@@ -23,7 +26,7 @@ class Logger {
|
|
|
23
26
|
context,
|
|
24
27
|
data,
|
|
25
28
|
timestamp: new Date().toISOString(),
|
|
26
|
-
environment: getCurrentEnvironment(),
|
|
29
|
+
environment: (0, environments_1.getCurrentEnvironment)(),
|
|
27
30
|
sessionId: this.sessionId
|
|
28
31
|
};
|
|
29
32
|
}
|
|
@@ -104,14 +107,14 @@ class Logger {
|
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
// Export singleton instance
|
|
107
|
-
|
|
110
|
+
exports.logger = new Logger();
|
|
108
111
|
// Export convenience functions
|
|
109
|
-
|
|
110
|
-
debug: (message, context, data) => logger.debug(message, context, data),
|
|
111
|
-
info: (message, context, data) => logger.info(message, context, data),
|
|
112
|
-
warn: (message, context, data) => logger.warn(message, context, data),
|
|
113
|
-
error: (message, context, data) => logger.error(message, context, data),
|
|
114
|
-
kioskAction: (action, kioskId, data) => logger.kioskAction(action, kioskId, data),
|
|
115
|
-
paymentEvent: (event, paymentId, data) => logger.paymentEvent(event, paymentId, data),
|
|
116
|
-
apiCall: (method, endpoint, duration, error) => logger.apiCall(method, endpoint, duration, error),
|
|
112
|
+
exports.log = {
|
|
113
|
+
debug: (message, context, data) => exports.logger.debug(message, context, data),
|
|
114
|
+
info: (message, context, data) => exports.logger.info(message, context, data),
|
|
115
|
+
warn: (message, context, data) => exports.logger.warn(message, context, data),
|
|
116
|
+
error: (message, context, data) => exports.logger.error(message, context, data),
|
|
117
|
+
kioskAction: (action, kioskId, data) => exports.logger.kioskAction(action, kioskId, data),
|
|
118
|
+
paymentEvent: (event, paymentId, data) => exports.logger.paymentEvent(event, paymentId, data),
|
|
119
|
+
apiCall: (method, endpoint, duration, error) => exports.logger.apiCall(method, endpoint, duration, error),
|
|
117
120
|
};
|
package/dist/constants.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared constants across all packages
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.ROUTES = exports.CSS_CLASSES = exports.UI_MESSAGES = exports.APP_CONFIG = void 0;
|
|
5
|
+
exports.APP_CONFIG = {
|
|
3
6
|
// API Configuration
|
|
4
7
|
DEFAULT_API_URL: 'http://localhost:3015',
|
|
5
8
|
DEFAULT_WS_URL: 'ws://localhost:3015',
|
|
@@ -29,7 +32,7 @@ export const APP_CONFIG = {
|
|
|
29
32
|
QR_CODE_WIDTH: 300,
|
|
30
33
|
QR_CODE_FORMAT: 'SPD*1.0', // Czech QR payment standard
|
|
31
34
|
};
|
|
32
|
-
|
|
35
|
+
exports.UI_MESSAGES = {
|
|
33
36
|
// Loading states
|
|
34
37
|
LOADING_PRODUCTS: 'Načítání produktů...',
|
|
35
38
|
LOADING_PAYMENT: 'Zpracovávám platbu...',
|
|
@@ -50,7 +53,7 @@ export const UI_MESSAGES = {
|
|
|
50
53
|
INVALID_EMAIL: 'Zadejte platnou emailovou adresu',
|
|
51
54
|
INVALID_PRICE: 'Cena musí být větší než 0',
|
|
52
55
|
};
|
|
53
|
-
|
|
56
|
+
exports.CSS_CLASSES = {
|
|
54
57
|
// Layout
|
|
55
58
|
CONTAINER: 'container',
|
|
56
59
|
GRID: 'grid',
|
|
@@ -72,7 +75,7 @@ export const CSS_CLASSES = {
|
|
|
72
75
|
CONNECTED: 'connected',
|
|
73
76
|
DISCONNECTED: 'disconnected',
|
|
74
77
|
};
|
|
75
|
-
|
|
78
|
+
exports.ROUTES = {
|
|
76
79
|
// Kiosk routes
|
|
77
80
|
KIOSK_HOME: '/',
|
|
78
81
|
KIOSK_PAYMENT: '/payment',
|
package/dist/errors.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared error handling system
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getErrorMessage = exports.formatError = exports.NotFoundError = exports.AuthenticationError = exports.NetworkError = exports.ValidationError = exports.AppError = void 0;
|
|
5
|
+
class AppError extends Error {
|
|
3
6
|
constructor(message, code = 'UNKNOWN_ERROR', statusCode = 500, isOperational = true) {
|
|
4
7
|
super(message);
|
|
5
8
|
this.name = 'AppError';
|
|
@@ -10,32 +13,37 @@ export class AppError extends Error {
|
|
|
10
13
|
Error.captureStackTrace(this, this.constructor);
|
|
11
14
|
}
|
|
12
15
|
}
|
|
16
|
+
exports.AppError = AppError;
|
|
13
17
|
// Predefined error types
|
|
14
|
-
|
|
18
|
+
class ValidationError extends AppError {
|
|
15
19
|
constructor(message, _field) {
|
|
16
20
|
super(message, 'VALIDATION_ERROR', 400);
|
|
17
21
|
this.name = 'ValidationError';
|
|
18
22
|
}
|
|
19
23
|
}
|
|
20
|
-
|
|
24
|
+
exports.ValidationError = ValidationError;
|
|
25
|
+
class NetworkError extends AppError {
|
|
21
26
|
constructor(message = 'Chyba připojení k serveru') {
|
|
22
27
|
super(message, 'NETWORK_ERROR', 503);
|
|
23
28
|
this.name = 'NetworkError';
|
|
24
29
|
}
|
|
25
30
|
}
|
|
26
|
-
|
|
31
|
+
exports.NetworkError = NetworkError;
|
|
32
|
+
class AuthenticationError extends AppError {
|
|
27
33
|
constructor(message = 'Neplatné přihlašovací údaje') {
|
|
28
34
|
super(message, 'AUTH_ERROR', 401);
|
|
29
35
|
this.name = 'AuthenticationError';
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
|
-
|
|
38
|
+
exports.AuthenticationError = AuthenticationError;
|
|
39
|
+
class NotFoundError extends AppError {
|
|
33
40
|
constructor(resource = 'Zdroj') {
|
|
34
41
|
super(`${resource} nebyl nalezen`, 'NOT_FOUND', 404);
|
|
35
42
|
this.name = 'NotFoundError';
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
|
-
|
|
45
|
+
exports.NotFoundError = NotFoundError;
|
|
46
|
+
const formatError = (error, details) => {
|
|
39
47
|
const isAppError = error instanceof AppError;
|
|
40
48
|
return {
|
|
41
49
|
success: false,
|
|
@@ -47,8 +55,9 @@ export const formatError = (error, details) => {
|
|
|
47
55
|
}
|
|
48
56
|
};
|
|
49
57
|
};
|
|
58
|
+
exports.formatError = formatError;
|
|
50
59
|
// Error handler hook for React components
|
|
51
|
-
|
|
60
|
+
const getErrorMessage = (error) => {
|
|
52
61
|
if (error instanceof NetworkError) {
|
|
53
62
|
return 'Problém s připojením. Zkuste to znovu.';
|
|
54
63
|
}
|
|
@@ -71,3 +80,4 @@ export const getErrorMessage = (error) => {
|
|
|
71
80
|
// Return original message if available, otherwise generic
|
|
72
81
|
return error.message || 'Něco se pokazilo. Zkuste to znovu.';
|
|
73
82
|
};
|
|
83
|
+
exports.getErrorMessage = getErrorMessage;
|
package/dist/hooks/useApi.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useApi = useApi;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
function useApi(_apiClient) {
|
|
7
|
+
const [state, setState] = (0, react_1.useState)({
|
|
5
8
|
data: null,
|
|
6
9
|
loading: false,
|
|
7
10
|
error: null
|
|
8
11
|
});
|
|
9
|
-
const execute = useCallback(async (apiCall, options) => {
|
|
12
|
+
const execute = (0, react_1.useCallback)(async (apiCall, options) => {
|
|
10
13
|
try {
|
|
11
14
|
if (!options?.skipLoading) {
|
|
12
15
|
setState(prev => ({ ...prev, loading: true, error: null }));
|
|
@@ -21,9 +24,9 @@ export function useApi(_apiClient) {
|
|
|
21
24
|
return data;
|
|
22
25
|
}
|
|
23
26
|
catch (error) {
|
|
24
|
-
const appError = error instanceof AppError
|
|
27
|
+
const appError = error instanceof errors_1.AppError
|
|
25
28
|
? error
|
|
26
|
-
: new NetworkError('Chyba při komunikaci se serverem');
|
|
29
|
+
: new errors_1.NetworkError('Chyba při komunikaci se serverem');
|
|
27
30
|
setState(prev => ({
|
|
28
31
|
...prev,
|
|
29
32
|
loading: false,
|
|
@@ -33,7 +36,7 @@ export function useApi(_apiClient) {
|
|
|
33
36
|
throw appError;
|
|
34
37
|
}
|
|
35
38
|
}, []);
|
|
36
|
-
const reset = useCallback(() => {
|
|
39
|
+
const reset = (0, react_1.useCallback)(() => {
|
|
37
40
|
setState({
|
|
38
41
|
data: null,
|
|
39
42
|
loading: false,
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAsyncOperation = useAsyncOperation;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const useErrorHandler_1 = require("./useErrorHandler");
|
|
3
6
|
/**
|
|
4
7
|
* Consistent hook for handling async operations with loading states and error handling
|
|
5
8
|
*/
|
|
6
|
-
|
|
7
|
-
const [state, setState] = useState({
|
|
9
|
+
function useAsyncOperation(options = {}) {
|
|
10
|
+
const [state, setState] = (0, react_1.useState)({
|
|
8
11
|
data: options.initialData || null,
|
|
9
12
|
loading: false,
|
|
10
13
|
error: null
|
|
11
14
|
});
|
|
12
|
-
const { handleError } = useErrorHandler();
|
|
13
|
-
const execute = useCallback(async (operation, context) => {
|
|
15
|
+
const { handleError } = (0, useErrorHandler_1.useErrorHandler)();
|
|
16
|
+
const execute = (0, react_1.useCallback)(async (operation, context) => {
|
|
14
17
|
setState(prev => ({ ...prev, loading: true, error: null }));
|
|
15
18
|
try {
|
|
16
19
|
const result = await operation();
|
|
@@ -34,14 +37,14 @@ export function useAsyncOperation(options = {}) {
|
|
|
34
37
|
return null;
|
|
35
38
|
}
|
|
36
39
|
}, [handleError, options]);
|
|
37
|
-
const reset = useCallback(() => {
|
|
40
|
+
const reset = (0, react_1.useCallback)(() => {
|
|
38
41
|
setState({
|
|
39
42
|
data: options.initialData || null,
|
|
40
43
|
loading: false,
|
|
41
44
|
error: null
|
|
42
45
|
});
|
|
43
46
|
}, [options.initialData]);
|
|
44
|
-
const setData = useCallback((data) => {
|
|
47
|
+
const setData = (0, react_1.useCallback)((data) => {
|
|
45
48
|
setState(prev => ({ ...prev, data }));
|
|
46
49
|
}, []);
|
|
47
50
|
return {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useErrorHandler = useErrorHandler;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
function useErrorHandler() {
|
|
7
|
+
const [errorState, setErrorState] = (0, react_1.useState)({
|
|
5
8
|
error: null,
|
|
6
9
|
message: '',
|
|
7
10
|
isVisible: false
|
|
8
11
|
});
|
|
9
|
-
const handleError = useCallback((error, context) => {
|
|
12
|
+
const handleError = (0, react_1.useCallback)((error, context) => {
|
|
10
13
|
console.error(`Error in ${context || 'unknown context'}:`, error);
|
|
11
|
-
const userMessage = getErrorMessage(error);
|
|
14
|
+
const userMessage = (0, errors_1.getErrorMessage)(error);
|
|
12
15
|
setErrorState({
|
|
13
16
|
error,
|
|
14
17
|
message: userMessage,
|
|
@@ -21,17 +24,17 @@ export function useErrorHandler() {
|
|
|
21
24
|
// Send to monitoring service in production
|
|
22
25
|
if (process.env.NODE_ENV === 'production') {
|
|
23
26
|
// TODO: Integrate with monitoring service (Sentry, LogRocket, etc.)
|
|
24
|
-
console.warn('Production error logged:', formatError(error));
|
|
27
|
+
console.warn('Production error logged:', (0, errors_1.formatError)(error));
|
|
25
28
|
}
|
|
26
29
|
}, []);
|
|
27
|
-
const clearError = useCallback(() => {
|
|
30
|
+
const clearError = (0, react_1.useCallback)(() => {
|
|
28
31
|
setErrorState({
|
|
29
32
|
error: null,
|
|
30
33
|
message: '',
|
|
31
34
|
isVisible: false
|
|
32
35
|
});
|
|
33
36
|
}, []);
|
|
34
|
-
const retryAction = useCallback((action) => {
|
|
37
|
+
const retryAction = (0, react_1.useCallback)((action) => {
|
|
35
38
|
clearError();
|
|
36
39
|
try {
|
|
37
40
|
const result = action();
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared package entry point
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./api"), exports);
|
|
20
|
+
__exportStar(require("./constants"), exports);
|
|
21
|
+
__exportStar(require("./validation"), exports);
|
|
22
|
+
__exportStar(require("./errors"), exports);
|
|
23
|
+
__exportStar(require("./utils"), exports);
|
|
8
24
|
// Note: ./utils exports getErrorMessage which shadows the one from ./errors
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
__exportStar(require("./hooks/useErrorHandler"), exports);
|
|
26
|
+
__exportStar(require("./hooks/useApi"), exports);
|
|
27
|
+
__exportStar(require("./hooks/useAsyncOperation"), exports);
|
|
28
|
+
__exportStar(require("./components/LoadingSpinner"), exports);
|
|
29
|
+
__exportStar(require("./components/ErrorDisplay"), exports);
|
|
30
|
+
__exportStar(require("./config/environments"), exports);
|
|
31
|
+
__exportStar(require("./config/logger"), exports);
|
package/dist/types.js
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared utility functions - consolidated from utils/simple.ts
|
|
2
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.generatePaymentId = exports.debounce = exports.formatDate = exports.getKioskSecretFromUrl = exports.getKioskIdFromUrl = exports.formatPrice = exports.validateEmail = void 0;
|
|
5
|
+
const validateEmail = (email) => {
|
|
3
6
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
4
7
|
// Additional check for consecutive dots which are invalid
|
|
5
8
|
if (email.includes('..'))
|
|
6
9
|
return false;
|
|
7
10
|
return emailRegex.test(email);
|
|
8
11
|
};
|
|
9
|
-
|
|
12
|
+
exports.validateEmail = validateEmail;
|
|
13
|
+
const formatPrice = (price) => {
|
|
10
14
|
return `${price} Kč`;
|
|
11
15
|
};
|
|
12
|
-
|
|
16
|
+
exports.formatPrice = formatPrice;
|
|
17
|
+
const getKioskIdFromUrl = () => {
|
|
13
18
|
const urlParams = new URLSearchParams(window.location.search);
|
|
14
19
|
return parseInt(urlParams.get('kioskId') || '1');
|
|
15
20
|
};
|
|
16
|
-
|
|
21
|
+
exports.getKioskIdFromUrl = getKioskIdFromUrl;
|
|
22
|
+
const getKioskSecretFromUrl = () => {
|
|
17
23
|
const urlParams = new URLSearchParams(window.location.search);
|
|
18
24
|
return urlParams.get('secret') || undefined;
|
|
19
25
|
};
|
|
20
|
-
|
|
26
|
+
exports.getKioskSecretFromUrl = getKioskSecretFromUrl;
|
|
27
|
+
const formatDate = (date) => {
|
|
21
28
|
const d = typeof date === 'string' ? new Date(date) : date;
|
|
22
29
|
return d.toLocaleDateString('cs-CZ', {
|
|
23
30
|
year: 'numeric',
|
|
@@ -27,14 +34,17 @@ export const formatDate = (date) => {
|
|
|
27
34
|
minute: '2-digit'
|
|
28
35
|
});
|
|
29
36
|
};
|
|
30
|
-
|
|
37
|
+
exports.formatDate = formatDate;
|
|
38
|
+
const debounce = (func, delay) => {
|
|
31
39
|
let timeoutId;
|
|
32
40
|
return (...args) => {
|
|
33
41
|
clearTimeout(timeoutId);
|
|
34
42
|
timeoutId = setTimeout(() => func(...args), delay);
|
|
35
43
|
};
|
|
36
44
|
};
|
|
37
|
-
|
|
45
|
+
exports.debounce = debounce;
|
|
46
|
+
const generatePaymentId = () => {
|
|
38
47
|
return `pay-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
39
48
|
};
|
|
49
|
+
exports.generatePaymentId = generatePaymentId;
|
|
40
50
|
// Note: getErrorMessage is now exported from ./errors.ts instead
|
package/dist/validation.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface ValidationResult {
|
|
|
3
3
|
errors: Record<string, string>;
|
|
4
4
|
}
|
|
5
5
|
export declare const validators: {
|
|
6
|
-
required: (value: any
|
|
6
|
+
required: (value: any) => string | null;
|
|
7
7
|
email: (value: string) => string | null;
|
|
8
8
|
minLength: (value: string, min: number, fieldName: string) => string | null;
|
|
9
9
|
maxLength: (value: string, max: number, fieldName: string) => string | null;
|
package/dist/validation.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// Shared validation utilities
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.validationSchemas = exports.validateSchema = exports.validators = void 0;
|
|
2
5
|
// ValidationError is imported but not used directly in this file
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
required: (value
|
|
6
|
+
const constants_1 = require("./constants");
|
|
7
|
+
exports.validators = {
|
|
8
|
+
required: (value) => {
|
|
6
9
|
if (value === null || value === undefined || value === '') {
|
|
7
|
-
return
|
|
10
|
+
return constants_1.UI_MESSAGES.REQUIRED_FIELD;
|
|
8
11
|
}
|
|
9
12
|
return null;
|
|
10
13
|
},
|
|
@@ -13,7 +16,7 @@ export const validators = {
|
|
|
13
16
|
return null; // Let required validator handle empty values
|
|
14
17
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
15
18
|
if (!emailRegex.test(value)) {
|
|
16
|
-
return UI_MESSAGES.INVALID_EMAIL;
|
|
19
|
+
return constants_1.UI_MESSAGES.INVALID_EMAIL;
|
|
17
20
|
}
|
|
18
21
|
return null;
|
|
19
22
|
},
|
|
@@ -44,8 +47,8 @@ export const validators = {
|
|
|
44
47
|
username: (value) => {
|
|
45
48
|
if (!value)
|
|
46
49
|
return null;
|
|
47
|
-
if (value.length < APP_CONFIG.MIN_USERNAME_LENGTH) {
|
|
48
|
-
return `Uživatelské jméno musí mít alespoň ${APP_CONFIG.MIN_USERNAME_LENGTH} znaky`;
|
|
50
|
+
if (value.length < constants_1.APP_CONFIG.MIN_USERNAME_LENGTH) {
|
|
51
|
+
return `Uživatelské jméno musí mít alespoň ${constants_1.APP_CONFIG.MIN_USERNAME_LENGTH} znaky`;
|
|
49
52
|
}
|
|
50
53
|
if (!/^[a-zA-Z0-9_]+$/.test(value)) {
|
|
51
54
|
return 'Uživatelské jméno může obsahovat pouze písmena, číslice a podtržítka';
|
|
@@ -55,13 +58,13 @@ export const validators = {
|
|
|
55
58
|
password: (value) => {
|
|
56
59
|
if (!value)
|
|
57
60
|
return null;
|
|
58
|
-
if (value.length < APP_CONFIG.MIN_PASSWORD_LENGTH) {
|
|
59
|
-
return `Heslo musí mít alespoň ${APP_CONFIG.MIN_PASSWORD_LENGTH} znaků`;
|
|
61
|
+
if (value.length < constants_1.APP_CONFIG.MIN_PASSWORD_LENGTH) {
|
|
62
|
+
return `Heslo musí mít alespoň ${constants_1.APP_CONFIG.MIN_PASSWORD_LENGTH} znaků`;
|
|
60
63
|
}
|
|
61
64
|
return null;
|
|
62
65
|
}
|
|
63
66
|
};
|
|
64
|
-
|
|
67
|
+
const validateSchema = (data, schema) => {
|
|
65
68
|
const errors = {};
|
|
66
69
|
for (const [field, validatorFunctions] of Object.entries(schema)) {
|
|
67
70
|
const value = data[field];
|
|
@@ -78,36 +81,37 @@ export const validateSchema = (data, schema) => {
|
|
|
78
81
|
errors
|
|
79
82
|
};
|
|
80
83
|
};
|
|
84
|
+
exports.validateSchema = validateSchema;
|
|
81
85
|
// Common validation schemas
|
|
82
|
-
|
|
86
|
+
exports.validationSchemas = {
|
|
83
87
|
login: {
|
|
84
88
|
username: [
|
|
85
|
-
(value) => validators.required(value
|
|
86
|
-
validators.username
|
|
89
|
+
(value) => exports.validators.required(value),
|
|
90
|
+
exports.validators.username
|
|
87
91
|
],
|
|
88
92
|
password: [
|
|
89
|
-
(value) => validators.required(value
|
|
90
|
-
validators.password
|
|
93
|
+
(value) => exports.validators.required(value),
|
|
94
|
+
exports.validators.password
|
|
91
95
|
]
|
|
92
96
|
},
|
|
93
97
|
customerEmail: {
|
|
94
98
|
email: [
|
|
95
|
-
(value) => validators.required(value
|
|
96
|
-
validators.email
|
|
99
|
+
(value) => exports.validators.required(value),
|
|
100
|
+
exports.validators.email
|
|
97
101
|
]
|
|
98
102
|
},
|
|
99
103
|
product: {
|
|
100
104
|
name: [
|
|
101
|
-
(value) => validators.required(value
|
|
102
|
-
(value) => validators.minLength(value, 2, 'Název produktu'),
|
|
103
|
-
(value) => validators.maxLength(value, APP_CONFIG.MAX_PRODUCT_NAME_LENGTH, 'Název produktu')
|
|
105
|
+
(value) => exports.validators.required(value),
|
|
106
|
+
(value) => exports.validators.minLength(value, 2, 'Název produktu'),
|
|
107
|
+
(value) => exports.validators.maxLength(value, constants_1.APP_CONFIG.MAX_PRODUCT_NAME_LENGTH, 'Název produktu')
|
|
104
108
|
],
|
|
105
109
|
price: [
|
|
106
|
-
(value) => validators.required(value
|
|
107
|
-
(value) => validators.positiveNumber(value, 'Cena')
|
|
110
|
+
(value) => exports.validators.required(value),
|
|
111
|
+
(value) => exports.validators.positiveNumber(value, 'Cena')
|
|
108
112
|
],
|
|
109
113
|
description: [
|
|
110
|
-
(value) => validators.maxLength(value, APP_CONFIG.MAX_DESCRIPTION_LENGTH, 'Popis')
|
|
114
|
+
(value) => exports.validators.maxLength(value, constants_1.APP_CONFIG.MAX_DESCRIPTION_LENGTH, 'Popis')
|
|
111
115
|
]
|
|
112
116
|
}
|
|
113
117
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-kiosk-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared components and utilities for Pi Kiosk system",
|
|
6
6
|
"keywords": ["kiosk", "react", "typescript", "components"],
|
|
@@ -11,7 +11,15 @@
|
|
|
11
11
|
"url": "https://github.com/tehacko/pi-kiosk-shared"
|
|
12
12
|
},
|
|
13
13
|
"main": "dist/index.js",
|
|
14
|
+
"module": "dist/index.js",
|
|
14
15
|
"types": "dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"require": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
15
23
|
"scripts": {
|
|
16
24
|
"build": "tsc",
|
|
17
25
|
"dev": "tsc --watch",
|