pi-kiosk-shared 1.0.0

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,117 @@
1
+ // Centralized logging system with environment-aware configuration
2
+ import { getEnvironmentConfig, getCurrentEnvironment } from './environments';
3
+ class Logger {
4
+ constructor() {
5
+ this.config = getEnvironmentConfig();
6
+ this.sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
7
+ }
8
+ shouldLog(level) {
9
+ const levels = {
10
+ debug: 0,
11
+ info: 1,
12
+ warn: 2,
13
+ error: 3
14
+ };
15
+ // Default to 'info' level if not specified in config
16
+ const configLevel = this.config.showDebugInfo ? 'debug' : 'info';
17
+ return levels[level] >= levels[configLevel];
18
+ }
19
+ formatMessage(level, message, context, data) {
20
+ return {
21
+ level,
22
+ message,
23
+ context,
24
+ data,
25
+ timestamp: new Date().toISOString(),
26
+ environment: getCurrentEnvironment(),
27
+ sessionId: this.sessionId
28
+ };
29
+ }
30
+ log(level, message, context, data) {
31
+ if (!this.shouldLog(level))
32
+ return;
33
+ const logEntry = this.formatMessage(level, message, context, data);
34
+ // Console logging with appropriate method
35
+ const consoleMethod = level === 'debug' ? 'log' : level;
36
+ const prefix = `[${level.toUpperCase()}] ${logEntry.timestamp}`;
37
+ const contextStr = context ? ` [${context}]` : '';
38
+ console[consoleMethod](`${prefix}${contextStr}: ${message}`, data || '');
39
+ // Send to external logging service in production
40
+ if (!this.config.showDebugInfo && (level === 'error' || level === 'warn')) {
41
+ this.sendToExternalService(logEntry);
42
+ }
43
+ // Store in local storage for debugging (development only)
44
+ if (this.config.showDebugInfo) {
45
+ this.storeLogEntry(logEntry);
46
+ }
47
+ }
48
+ sendToExternalService(logEntry) {
49
+ // TODO: Integrate with Sentry, LogRocket, or other monitoring service
50
+ // For now, just log to console in production
51
+ console.warn('External logging not implemented yet:', logEntry);
52
+ }
53
+ storeLogEntry(logEntry) {
54
+ try {
55
+ const storageKey = 'kiosk-logs';
56
+ const existingLogs = JSON.parse(localStorage.getItem(storageKey) || '[]');
57
+ const updatedLogs = [...existingLogs.slice(-99), logEntry]; // Keep last 100 entries
58
+ localStorage.setItem(storageKey, JSON.stringify(updatedLogs));
59
+ }
60
+ catch (error) {
61
+ console.warn('Failed to store log entry:', error);
62
+ }
63
+ }
64
+ debug(message, context, data) {
65
+ this.log('debug', message, context, data);
66
+ }
67
+ info(message, context, data) {
68
+ this.log('info', message, context, data);
69
+ }
70
+ warn(message, context, data) {
71
+ this.log('warn', message, context, data);
72
+ }
73
+ error(message, context, data) {
74
+ this.log('error', message, context, data);
75
+ }
76
+ // Kiosk-specific logging methods
77
+ kioskAction(action, kioskId, data) {
78
+ this.info(`Kiosk action: ${action}`, `kiosk-${kioskId}`, data);
79
+ }
80
+ paymentEvent(event, paymentId, data) {
81
+ this.info(`Payment event: ${event}`, `payment-${paymentId}`, data);
82
+ }
83
+ apiCall(method, endpoint, duration, error) {
84
+ const message = `API ${method} ${endpoint}${duration ? ` (${duration}ms)` : ''}`;
85
+ if (error) {
86
+ this.error(message, 'api-client', { error: error.message, stack: error.stack });
87
+ }
88
+ else {
89
+ this.debug(message, 'api-client');
90
+ }
91
+ }
92
+ // Get logs for debugging
93
+ getLogs() {
94
+ try {
95
+ return JSON.parse(localStorage.getItem('kiosk-logs') || '[]');
96
+ }
97
+ catch {
98
+ return [];
99
+ }
100
+ }
101
+ // Clear stored logs
102
+ clearLogs() {
103
+ localStorage.removeItem('kiosk-logs');
104
+ }
105
+ }
106
+ // Export singleton instance
107
+ export const logger = new Logger();
108
+ // Export convenience functions
109
+ export const log = {
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),
117
+ };
@@ -0,0 +1,66 @@
1
+ export declare const APP_CONFIG: {
2
+ readonly DEFAULT_API_URL: "http://localhost:3015";
3
+ readonly DEFAULT_WS_URL: "ws://localhost:3015";
4
+ readonly API_TIMEOUT: 10000;
5
+ readonly RETRY_ATTEMPTS: 3;
6
+ readonly RETRY_DELAY: 1000;
7
+ readonly WS_RECONNECT_ATTEMPTS: 5;
8
+ readonly WS_RECONNECT_INTERVAL: 3000;
9
+ readonly WS_HEARTBEAT_INTERVAL: 30000;
10
+ readonly LOADING_DEBOUNCE: 300;
11
+ readonly ERROR_DISPLAY_DURATION: 5000;
12
+ readonly MIN_USERNAME_LENGTH: 3;
13
+ readonly MIN_PASSWORD_LENGTH: 6;
14
+ readonly MAX_PRODUCT_NAME_LENGTH: 100;
15
+ readonly MAX_DESCRIPTION_LENGTH: 500;
16
+ readonly DEFAULT_KIOSK_ID: 1;
17
+ readonly PAYMENT_POLLING_INTERVAL: 3000;
18
+ readonly PRODUCT_CACHE_TTL: 300000;
19
+ readonly PAYMENT_ACCOUNT_NUMBER: "1234567890";
20
+ readonly PAYMENT_CURRENCY: "CZK";
21
+ readonly QR_CODE_WIDTH: 300;
22
+ readonly QR_CODE_FORMAT: "SPD*1.0";
23
+ };
24
+ export declare const UI_MESSAGES: {
25
+ readonly LOADING_PRODUCTS: "Načítání produktů...";
26
+ readonly LOADING_PAYMENT: "Zpracovávám platbu...";
27
+ readonly GENERATING_QR: "Generuji QR kód...";
28
+ readonly PAYMENT_SUCCESS: "Platba byla úspěšně zpracována!";
29
+ readonly PRODUCT_SAVED: "Produkt byl úspěšně uložen!";
30
+ readonly NETWORK_ERROR: "Problém s připojením. Zkuste to znovu.";
31
+ readonly VALIDATION_ERROR: "Zkontrolujte zadané údaje.";
32
+ readonly UNKNOWN_ERROR: "Něco se pokazilo. Zkuste to znovu.";
33
+ readonly NO_PRODUCTS: "Žádné produkty nejsou k dispozici";
34
+ readonly NO_TRANSACTIONS: "Žádné transakce";
35
+ readonly COMING_SOON: "Připravujeme pro vás...";
36
+ readonly REQUIRED_FIELD: "Toto pole je povinné";
37
+ readonly INVALID_EMAIL: "Zadejte platnou emailovou adresu";
38
+ readonly INVALID_PRICE: "Cena musí být větší než 0";
39
+ };
40
+ export declare const CSS_CLASSES: {
41
+ readonly CONTAINER: "container";
42
+ readonly GRID: "grid";
43
+ readonly FLEX: "flex";
44
+ readonly LOADING: "loading";
45
+ readonly ERROR: "error";
46
+ readonly SUCCESS: "success";
47
+ readonly DISABLED: "disabled";
48
+ readonly ACTIVE: "active";
49
+ readonly BUTTON_PRIMARY: "btn-primary";
50
+ readonly BUTTON_SECONDARY: "btn-secondary";
51
+ readonly INPUT: "input";
52
+ readonly CARD: "card";
53
+ readonly ONLINE: "online";
54
+ readonly OFFLINE: "offline";
55
+ readonly CONNECTED: "connected";
56
+ readonly DISCONNECTED: "disconnected";
57
+ };
58
+ export declare const ROUTES: {
59
+ readonly KIOSK_HOME: "/";
60
+ readonly KIOSK_PAYMENT: "/payment";
61
+ readonly KIOSK_CONFIRMATION: "/confirmation";
62
+ readonly ADMIN_LOGIN: "/admin/login";
63
+ readonly ADMIN_DASHBOARD: "/admin";
64
+ readonly ADMIN_PRODUCTS: "/admin/products";
65
+ readonly ADMIN_KIOSKS: "/admin/kiosks";
66
+ };
@@ -0,0 +1,85 @@
1
+ // Shared constants across all packages
2
+ export const APP_CONFIG = {
3
+ // API Configuration
4
+ DEFAULT_API_URL: 'http://localhost:3015',
5
+ DEFAULT_WS_URL: 'ws://localhost:3015',
6
+ // Timeouts
7
+ API_TIMEOUT: 10000, // 10 seconds
8
+ RETRY_ATTEMPTS: 3,
9
+ RETRY_DELAY: 1000, // 1 second
10
+ // WebSocket
11
+ WS_RECONNECT_ATTEMPTS: 5,
12
+ WS_RECONNECT_INTERVAL: 3000,
13
+ WS_HEARTBEAT_INTERVAL: 30000,
14
+ // UI
15
+ LOADING_DEBOUNCE: 300,
16
+ ERROR_DISPLAY_DURATION: 5000,
17
+ // Validation
18
+ MIN_USERNAME_LENGTH: 3,
19
+ MIN_PASSWORD_LENGTH: 6,
20
+ MAX_PRODUCT_NAME_LENGTH: 100,
21
+ MAX_DESCRIPTION_LENGTH: 500,
22
+ // Business Rules
23
+ DEFAULT_KIOSK_ID: 1,
24
+ PAYMENT_POLLING_INTERVAL: 3000,
25
+ PRODUCT_CACHE_TTL: 300000, // 5 minutes
26
+ // Payment Configuration
27
+ PAYMENT_ACCOUNT_NUMBER: '1234567890',
28
+ PAYMENT_CURRENCY: 'CZK',
29
+ QR_CODE_WIDTH: 300,
30
+ QR_CODE_FORMAT: 'SPD*1.0', // Czech QR payment standard
31
+ };
32
+ export const UI_MESSAGES = {
33
+ // Loading states
34
+ LOADING_PRODUCTS: 'Načítání produktů...',
35
+ LOADING_PAYMENT: 'Zpracovávám platbu...',
36
+ GENERATING_QR: 'Generuji QR kód...',
37
+ // Success messages
38
+ PAYMENT_SUCCESS: 'Platba byla úspěšně zpracována!',
39
+ PRODUCT_SAVED: 'Produkt byl úspěšně uložen!',
40
+ // Error messages
41
+ NETWORK_ERROR: 'Problém s připojením. Zkuste to znovu.',
42
+ VALIDATION_ERROR: 'Zkontrolujte zadané údaje.',
43
+ UNKNOWN_ERROR: 'Něco se pokazilo. Zkuste to znovu.',
44
+ // Empty states
45
+ NO_PRODUCTS: 'Žádné produkty nejsou k dispozici',
46
+ NO_TRANSACTIONS: 'Žádné transakce',
47
+ COMING_SOON: 'Připravujeme pro vás...',
48
+ // Form validation
49
+ REQUIRED_FIELD: 'Toto pole je povinné',
50
+ INVALID_EMAIL: 'Zadejte platnou emailovou adresu',
51
+ INVALID_PRICE: 'Cena musí být větší než 0',
52
+ };
53
+ export const CSS_CLASSES = {
54
+ // Layout
55
+ CONTAINER: 'container',
56
+ GRID: 'grid',
57
+ FLEX: 'flex',
58
+ // States
59
+ LOADING: 'loading',
60
+ ERROR: 'error',
61
+ SUCCESS: 'success',
62
+ DISABLED: 'disabled',
63
+ ACTIVE: 'active',
64
+ // Components
65
+ BUTTON_PRIMARY: 'btn-primary',
66
+ BUTTON_SECONDARY: 'btn-secondary',
67
+ INPUT: 'input',
68
+ CARD: 'card',
69
+ // Status indicators
70
+ ONLINE: 'online',
71
+ OFFLINE: 'offline',
72
+ CONNECTED: 'connected',
73
+ DISCONNECTED: 'disconnected',
74
+ };
75
+ export const ROUTES = {
76
+ // Kiosk routes
77
+ KIOSK_HOME: '/',
78
+ KIOSK_PAYMENT: '/payment',
79
+ KIOSK_CONFIRMATION: '/confirmation',
80
+ // Admin routes
81
+ ADMIN_LOGIN: '/admin/login',
82
+ ADMIN_DASHBOARD: '/admin',
83
+ ADMIN_PRODUCTS: '/admin/products',
84
+ ADMIN_KIOSKS: '/admin/kiosks',
85
+ };
@@ -0,0 +1,29 @@
1
+ export declare class AppError extends Error {
2
+ readonly code: string;
3
+ readonly statusCode: number;
4
+ readonly isOperational: boolean;
5
+ constructor(message: string, code?: string, statusCode?: number, isOperational?: boolean);
6
+ }
7
+ export declare class ValidationError extends AppError {
8
+ constructor(message: string, _field?: string);
9
+ }
10
+ export declare class NetworkError extends AppError {
11
+ constructor(message?: string);
12
+ }
13
+ export declare class AuthenticationError extends AppError {
14
+ constructor(message?: string);
15
+ }
16
+ export declare class NotFoundError extends AppError {
17
+ constructor(resource?: string);
18
+ }
19
+ export interface ErrorResponse {
20
+ success: false;
21
+ error: {
22
+ code: string;
23
+ message: string;
24
+ timestamp: string;
25
+ details?: any;
26
+ };
27
+ }
28
+ export declare const formatError: (error: Error | AppError, details?: any) => ErrorResponse;
29
+ export declare const getErrorMessage: (error: Error | AppError) => string;
package/dist/errors.js ADDED
@@ -0,0 +1,73 @@
1
+ // Shared error handling system
2
+ export class AppError extends Error {
3
+ constructor(message, code = 'UNKNOWN_ERROR', statusCode = 500, isOperational = true) {
4
+ super(message);
5
+ this.name = 'AppError';
6
+ this.code = code;
7
+ this.statusCode = statusCode;
8
+ this.isOperational = isOperational;
9
+ // Ensure the stack trace is captured
10
+ Error.captureStackTrace(this, this.constructor);
11
+ }
12
+ }
13
+ // Predefined error types
14
+ export class ValidationError extends AppError {
15
+ constructor(message, _field) {
16
+ super(message, 'VALIDATION_ERROR', 400);
17
+ this.name = 'ValidationError';
18
+ }
19
+ }
20
+ export class NetworkError extends AppError {
21
+ constructor(message = 'Chyba připojení k serveru') {
22
+ super(message, 'NETWORK_ERROR', 503);
23
+ this.name = 'NetworkError';
24
+ }
25
+ }
26
+ export class AuthenticationError extends AppError {
27
+ constructor(message = 'Neplatné přihlašovací údaje') {
28
+ super(message, 'AUTH_ERROR', 401);
29
+ this.name = 'AuthenticationError';
30
+ }
31
+ }
32
+ export class NotFoundError extends AppError {
33
+ constructor(resource = 'Zdroj') {
34
+ super(`${resource} nebyl nalezen`, 'NOT_FOUND', 404);
35
+ this.name = 'NotFoundError';
36
+ }
37
+ }
38
+ export const formatError = (error, details) => {
39
+ const isAppError = error instanceof AppError;
40
+ return {
41
+ success: false,
42
+ error: {
43
+ code: isAppError ? error.code : 'UNKNOWN_ERROR',
44
+ message: error.message || 'Došlo k neočekávané chybě',
45
+ timestamp: new Date().toISOString(),
46
+ ...(details && { details })
47
+ }
48
+ };
49
+ };
50
+ // Error handler hook for React components
51
+ export const getErrorMessage = (error) => {
52
+ if (error instanceof NetworkError) {
53
+ return 'Problém s připojením. Zkuste to znovu.';
54
+ }
55
+ if (error instanceof ValidationError) {
56
+ return error.message;
57
+ }
58
+ if (error instanceof AuthenticationError) {
59
+ return 'Neplatné přihlašovací údaje.';
60
+ }
61
+ if (error instanceof NotFoundError) {
62
+ return error.message;
63
+ }
64
+ // Check for specific error messages
65
+ if (error.message.includes('Failed to fetch') || error.message.includes('fetch')) {
66
+ return 'Problém s připojením. Zkuste to znovu.';
67
+ }
68
+ if (error.message.includes('401') || error.message.includes('Unauthorized')) {
69
+ return 'Neplatné přihlašovací údaje.';
70
+ }
71
+ // Return original message if available, otherwise generic
72
+ return error.message || 'Něco se pokazilo. Zkuste to znovu.';
73
+ };
@@ -0,0 +1,20 @@
1
+ import { APIClient } from '../api';
2
+ export interface ApiState<T> {
3
+ data: T | null;
4
+ loading: boolean;
5
+ error: Error | null;
6
+ }
7
+ export declare function useApi<T = any>(_apiClient: APIClient): {
8
+ execute: (apiCall: () => Promise<T>, options?: {
9
+ onSuccess?: (data: T) => void;
10
+ onError?: (error: Error) => void;
11
+ skipLoading?: boolean;
12
+ }) => Promise<T>;
13
+ reset: () => void;
14
+ isLoading: boolean;
15
+ hasError: boolean;
16
+ hasData: boolean;
17
+ data: T | null;
18
+ loading: boolean;
19
+ error: Error | null;
20
+ };
@@ -0,0 +1,51 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { NetworkError, AppError } from '../errors';
3
+ export function useApi(_apiClient) {
4
+ const [state, setState] = useState({
5
+ data: null,
6
+ loading: false,
7
+ error: null
8
+ });
9
+ const execute = useCallback(async (apiCall, options) => {
10
+ try {
11
+ if (!options?.skipLoading) {
12
+ setState(prev => ({ ...prev, loading: true, error: null }));
13
+ }
14
+ const data = await apiCall();
15
+ setState({
16
+ data,
17
+ loading: false,
18
+ error: null
19
+ });
20
+ options?.onSuccess?.(data);
21
+ return data;
22
+ }
23
+ catch (error) {
24
+ const appError = error instanceof AppError
25
+ ? error
26
+ : new NetworkError('Chyba při komunikaci se serverem');
27
+ setState(prev => ({
28
+ ...prev,
29
+ loading: false,
30
+ error: appError
31
+ }));
32
+ options?.onError?.(appError);
33
+ throw appError;
34
+ }
35
+ }, []);
36
+ const reset = useCallback(() => {
37
+ setState({
38
+ data: null,
39
+ loading: false,
40
+ error: null
41
+ });
42
+ }, []);
43
+ return {
44
+ ...state,
45
+ execute,
46
+ reset,
47
+ isLoading: state.loading,
48
+ hasError: !!state.error,
49
+ hasData: !!state.data
50
+ };
51
+ }
@@ -0,0 +1,21 @@
1
+ interface UseAsyncOperationOptions<T> {
2
+ onSuccess?: (data: T) => void;
3
+ onError?: (error: Error) => void;
4
+ initialData?: T;
5
+ }
6
+ /**
7
+ * Consistent hook for handling async operations with loading states and error handling
8
+ */
9
+ export declare function useAsyncOperation<T = any>(options?: UseAsyncOperationOptions<T>): {
10
+ execute: (operation: () => Promise<T>, context?: string) => Promise<T | null>;
11
+ reset: () => void;
12
+ setData: (data: T) => void;
13
+ isLoading: boolean;
14
+ hasError: boolean;
15
+ hasData: boolean;
16
+ isIdle: boolean;
17
+ data: T | null;
18
+ loading: boolean;
19
+ error: Error | null;
20
+ };
21
+ export {};
@@ -0,0 +1,58 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { useErrorHandler } from './useErrorHandler';
3
+ /**
4
+ * Consistent hook for handling async operations with loading states and error handling
5
+ */
6
+ export function useAsyncOperation(options = {}) {
7
+ const [state, setState] = useState({
8
+ data: options.initialData || null,
9
+ loading: false,
10
+ error: null
11
+ });
12
+ const { handleError } = useErrorHandler();
13
+ const execute = useCallback(async (operation, context) => {
14
+ setState(prev => ({ ...prev, loading: true, error: null }));
15
+ try {
16
+ const result = await operation();
17
+ setState({
18
+ data: result,
19
+ loading: false,
20
+ error: null
21
+ });
22
+ options.onSuccess?.(result);
23
+ return result;
24
+ }
25
+ catch (error) {
26
+ const errorObj = error instanceof Error ? error : new Error(String(error));
27
+ setState(prev => ({
28
+ ...prev,
29
+ loading: false,
30
+ error: errorObj
31
+ }));
32
+ handleError(errorObj, context || 'useAsyncOperation');
33
+ options.onError?.(errorObj);
34
+ return null;
35
+ }
36
+ }, [handleError, options]);
37
+ const reset = useCallback(() => {
38
+ setState({
39
+ data: options.initialData || null,
40
+ loading: false,
41
+ error: null
42
+ });
43
+ }, [options.initialData]);
44
+ const setData = useCallback((data) => {
45
+ setState(prev => ({ ...prev, data }));
46
+ }, []);
47
+ return {
48
+ ...state,
49
+ execute,
50
+ reset,
51
+ setData,
52
+ // Computed properties
53
+ isLoading: state.loading,
54
+ hasError: !!state.error,
55
+ hasData: !!state.data,
56
+ isIdle: !state.loading && !state.error && !state.data
57
+ };
58
+ }
@@ -0,0 +1,14 @@
1
+ import { AppError } from '../errors';
2
+ export interface ErrorState {
3
+ error: AppError | Error | null;
4
+ message: string;
5
+ isVisible: boolean;
6
+ }
7
+ export declare function useErrorHandler(): {
8
+ error: Error | AppError | null;
9
+ errorMessage: string;
10
+ isErrorVisible: boolean;
11
+ handleError: (error: Error | AppError, context?: string) => void;
12
+ clearError: () => void;
13
+ retryAction: (action: () => Promise<void> | void) => void;
14
+ };
@@ -0,0 +1,54 @@
1
+ import { useCallback, useState } from 'react';
2
+ import { getErrorMessage, formatError } from '../errors';
3
+ export function useErrorHandler() {
4
+ const [errorState, setErrorState] = useState({
5
+ error: null,
6
+ message: '',
7
+ isVisible: false
8
+ });
9
+ const handleError = useCallback((error, context) => {
10
+ console.error(`Error in ${context || 'unknown context'}:`, error);
11
+ const userMessage = getErrorMessage(error);
12
+ setErrorState({
13
+ error,
14
+ message: userMessage,
15
+ isVisible: true
16
+ });
17
+ // Auto-hide error after 5 seconds
18
+ setTimeout(() => {
19
+ setErrorState(prev => ({ ...prev, isVisible: false }));
20
+ }, 5000);
21
+ // Send to monitoring service in production
22
+ if (process.env.NODE_ENV === 'production') {
23
+ // TODO: Integrate with monitoring service (Sentry, LogRocket, etc.)
24
+ console.warn('Production error logged:', formatError(error));
25
+ }
26
+ }, []);
27
+ const clearError = useCallback(() => {
28
+ setErrorState({
29
+ error: null,
30
+ message: '',
31
+ isVisible: false
32
+ });
33
+ }, []);
34
+ const retryAction = useCallback((action) => {
35
+ clearError();
36
+ try {
37
+ const result = action();
38
+ if (result instanceof Promise) {
39
+ result.catch(handleError);
40
+ }
41
+ }
42
+ catch (error) {
43
+ handleError(error);
44
+ }
45
+ }, [handleError, clearError]);
46
+ return {
47
+ error: errorState.error,
48
+ errorMessage: errorState.message,
49
+ isErrorVisible: errorState.isVisible,
50
+ handleError,
51
+ clearError,
52
+ retryAction
53
+ };
54
+ }
@@ -0,0 +1,13 @@
1
+ export * from './types';
2
+ export * from './api';
3
+ export * from './constants';
4
+ export * from './validation';
5
+ export * from './errors';
6
+ export * from './utils';
7
+ export * from './hooks/useErrorHandler';
8
+ export * from './hooks/useApi';
9
+ export * from './hooks/useAsyncOperation';
10
+ export * from './components/LoadingSpinner';
11
+ export * from './components/ErrorDisplay';
12
+ export * from './config/environments';
13
+ export * from './config/logger';
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // Shared package entry point
2
+ export * from './types';
3
+ export * from './api';
4
+ export * from './constants';
5
+ export * from './validation';
6
+ export * from './errors';
7
+ export * from './utils';
8
+ // Note: ./utils exports getErrorMessage which shadows the one from ./errors
9
+ export * from './hooks/useErrorHandler';
10
+ export * from './hooks/useApi';
11
+ export * from './hooks/useAsyncOperation';
12
+ export * from './components/LoadingSpinner';
13
+ export * from './components/ErrorDisplay';
14
+ export * from './config/environments';
15
+ export * from './config/logger';
@@ -0,0 +1,56 @@
1
+ export interface Product {
2
+ id: number;
3
+ name: string;
4
+ price: number;
5
+ description: string;
6
+ image?: string;
7
+ imageUrl?: string;
8
+ quantityInStock: number;
9
+ clickedOn: number;
10
+ numberOfPurchases: number;
11
+ }
12
+ export interface PaymentData {
13
+ productId: number;
14
+ productName: string;
15
+ amount: number;
16
+ customerEmail: string;
17
+ qrCode: string;
18
+ paymentId: string;
19
+ }
20
+ export interface AdminProduct {
21
+ id: number;
22
+ name: string;
23
+ price: number;
24
+ description: string;
25
+ image: string;
26
+ imageUrl?: string;
27
+ active: boolean;
28
+ clickedOn: number;
29
+ qrCodesGenerated: number;
30
+ numberOfPurchases: number;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ quantityInStock?: number;
34
+ }
35
+ export interface ApiResponse<T> {
36
+ success: boolean;
37
+ data?: T;
38
+ message?: string;
39
+ error?: string;
40
+ }
41
+ export interface KioskStatus {
42
+ id: number;
43
+ name: string;
44
+ location: string;
45
+ online: boolean;
46
+ lastSeen: Date;
47
+ salesToday: number;
48
+ }
49
+ export interface WebSocketMessage {
50
+ type: string;
51
+ updateType?: string;
52
+ data?: any;
53
+ kioskId?: number;
54
+ timestamp?: string;
55
+ }
56
+ export type ScreenType = 'products' | 'payment' | 'confirmation' | 'admin-login' | 'admin-dashboard';
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ // Shared types across all packages
2
+ export {};