claude-code-templates 1.8.0 → 1.8.1

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,312 @@
1
+ /**
2
+ * Main application entry point for the modular analytics dashboard
3
+ * This replaces the embedded JavaScript in index.html
4
+ */
5
+
6
+ /**
7
+ * AnalyticsDashboard - Main application class
8
+ * Orchestrates all services and components
9
+ */
10
+ class AnalyticsDashboard {
11
+ constructor() {
12
+ this.services = {};
13
+ this.components = {};
14
+ this.isInitialized = false;
15
+ }
16
+
17
+ /**
18
+ * Initialize the application
19
+ */
20
+ async initialize() {
21
+ try {
22
+ console.log('🚀 Initializing Analytics Dashboard...');
23
+
24
+ await this.initializeServices();
25
+ await this.initializeComponents();
26
+ await this.startApplication();
27
+
28
+ this.isInitialized = true;
29
+ console.log('✅ Analytics Dashboard initialized successfully');
30
+ } catch (error) {
31
+ console.error('❌ Failed to initialize Analytics Dashboard:', error);
32
+ this.showError('Failed to initialize dashboard: ' + error.message);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Initialize all services
38
+ */
39
+ async initializeServices() {
40
+ console.log('🔧 Initializing services...');
41
+
42
+ // Initialize DataService
43
+ this.services.data = new DataService();
44
+
45
+ // Initialize StateService
46
+ this.services.state = new StateService();
47
+
48
+ // Initialize Charts service (placeholder)
49
+ this.services.chart = new Charts(null, this.services.data, this.services.state);
50
+
51
+ // Start periodic data refresh
52
+ this.services.data.startPeriodicRefresh();
53
+
54
+ console.log('✅ Services initialized');
55
+ }
56
+
57
+ /**
58
+ * Initialize all components
59
+ */
60
+ async initializeComponents() {
61
+ console.log('🎨 Initializing components...');
62
+
63
+ // Get main container
64
+ const container = document.getElementById('app') || document.body;
65
+
66
+ // Initialize Dashboard component
67
+ this.components.dashboard = new Dashboard(container, this.services);
68
+ await this.components.dashboard.initialize();
69
+
70
+ console.log('✅ Components initialized');
71
+ }
72
+
73
+ /**
74
+ * Start the application
75
+ */
76
+ async startApplication() {
77
+ console.log('🎯 Starting application...');
78
+
79
+ // Setup global error handling
80
+ this.setupErrorHandling();
81
+
82
+ // Setup keyboard shortcuts
83
+ this.setupKeyboardShortcuts();
84
+
85
+ // Setup visibility change handling
86
+ this.setupVisibilityHandling();
87
+
88
+ console.log('✅ Application started');
89
+ }
90
+
91
+ /**
92
+ * Setup global error handling
93
+ */
94
+ setupErrorHandling() {
95
+ window.addEventListener('error', (event) => {
96
+ console.error('Global error:', event.error);
97
+ this.services.state.setError(`Application error: ${event.error.message}`);
98
+ });
99
+
100
+ window.addEventListener('unhandledrejection', (event) => {
101
+ console.error('Unhandled promise rejection:', event.reason);
102
+ this.services.state.setError(`Promise rejection: ${event.reason.message || event.reason}`);
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Setup keyboard shortcuts
108
+ */
109
+ setupKeyboardShortcuts() {
110
+ document.addEventListener('keydown', (event) => {
111
+ // Ctrl/Cmd + R - Refresh data
112
+ if ((event.ctrlKey || event.metaKey) && event.key === 'r') {
113
+ event.preventDefault();
114
+ this.refreshData();
115
+ }
116
+
117
+ // Ctrl/Cmd + E - Export data
118
+ if ((event.ctrlKey || event.metaKey) && event.key === 'e') {
119
+ event.preventDefault();
120
+ this.exportData();
121
+ }
122
+
123
+ // Escape - Clear errors
124
+ if (event.key === 'Escape') {
125
+ this.services.state.clearError();
126
+ }
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Setup visibility change handling
132
+ */
133
+ setupVisibilityHandling() {
134
+ document.addEventListener('visibilitychange', () => {
135
+ if (document.hidden) {
136
+ // Page is hidden - pause updates
137
+ this.services.data.stopPeriodicRefresh();
138
+ } else {
139
+ // Page is visible - resume updates
140
+ this.services.data.startPeriodicRefresh();
141
+ // Immediately refresh data
142
+ this.refreshData();
143
+ }
144
+ });
145
+ }
146
+
147
+ /**
148
+ * Refresh all data
149
+ */
150
+ async refreshData() {
151
+ console.log('🔄 Refreshing data...');
152
+ try {
153
+ this.services.data.clearCache();
154
+
155
+ const [conversationsData, statesData] = await Promise.all([
156
+ this.services.data.getConversations(),
157
+ this.services.data.getConversationStates()
158
+ ]);
159
+
160
+ this.services.state.updateConversations(conversationsData.conversations);
161
+ this.services.state.updateSummary(conversationsData.summary);
162
+ this.services.state.updateConversationStates(statesData);
163
+
164
+ console.log('✅ Data refreshed');
165
+ } catch (error) {
166
+ console.error('❌ Failed to refresh data:', error);
167
+ this.services.state.setError('Failed to refresh data: ' + error.message);
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Export data
173
+ */
174
+ exportData() {
175
+ if (this.components.dashboard) {
176
+ this.components.dashboard.exportData();
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Show error message
182
+ * @param {string} message - Error message
183
+ */
184
+ showError(message) {
185
+ // Create error display if components aren't ready
186
+ const errorDiv = document.createElement('div');
187
+ errorDiv.className = 'initialization-error';
188
+ errorDiv.style.cssText = `
189
+ position: fixed;
190
+ top: 20px;
191
+ right: 20px;
192
+ background: #f85149;
193
+ color: white;
194
+ padding: 15px 20px;
195
+ border-radius: 5px;
196
+ z-index: 10000;
197
+ max-width: 400px;
198
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
199
+ `;
200
+ errorDiv.innerHTML = `
201
+ <strong>Initialization Error</strong><br>
202
+ ${message}
203
+ <button onclick="this.parentElement.remove()" style="
204
+ background: none;
205
+ border: none;
206
+ color: white;
207
+ float: right;
208
+ cursor: pointer;
209
+ font-size: 16px;
210
+ margin-top: -5px;
211
+ ">×</button>
212
+ `;
213
+ document.body.appendChild(errorDiv);
214
+
215
+ // Auto-remove after 10 seconds
216
+ setTimeout(() => {
217
+ if (errorDiv.parentElement) {
218
+ errorDiv.remove();
219
+ }
220
+ }, 10000);
221
+ }
222
+
223
+ /**
224
+ * Cleanup and destroy application
225
+ */
226
+ destroy() {
227
+ console.log('🧹 Cleaning up application...');
228
+
229
+ // Stop services
230
+ if (this.services.data) {
231
+ this.services.data.stopPeriodicRefresh();
232
+ }
233
+
234
+ // Destroy components
235
+ Object.values(this.components).forEach(component => {
236
+ if (component.destroy) {
237
+ component.destroy();
238
+ }
239
+ });
240
+
241
+ // Clear references
242
+ this.services = {};
243
+ this.components = {};
244
+ this.isInitialized = false;
245
+
246
+ console.log('✅ Application cleaned up');
247
+ }
248
+
249
+ /**
250
+ * Get application statistics
251
+ */
252
+ getStats() {
253
+ return {
254
+ initialized: this.isInitialized,
255
+ services: Object.keys(this.services).length,
256
+ components: Object.keys(this.components).length,
257
+ dataServiceStats: this.services.data ? this.services.data.getCacheStats() : null,
258
+ stateServiceStats: this.services.state ? this.services.state.getStateStats() : null
259
+ };
260
+ }
261
+ }
262
+
263
+ // Global application instance
264
+ let analyticsApp = null;
265
+
266
+ /**
267
+ * Initialize the application when DOM is ready
268
+ */
269
+ document.addEventListener('DOMContentLoaded', async () => {
270
+ console.log('📱 DOM Content Loaded - Starting Analytics Dashboard');
271
+
272
+ try {
273
+ analyticsApp = new AnalyticsDashboard();
274
+ await analyticsApp.initialize();
275
+
276
+ // Make app available globally for debugging
277
+ window.analyticsApp = analyticsApp;
278
+
279
+ // Add development helpers
280
+ if (window.location.hostname === 'localhost') {
281
+ window.refreshDashboard = () => analyticsApp.refreshData();
282
+ window.getAppStats = () => analyticsApp.getStats();
283
+ console.log('🔧 Development helpers available: refreshDashboard(), getAppStats()');
284
+ }
285
+
286
+ } catch (error) {
287
+ console.error('❌ Failed to start Analytics Dashboard:', error);
288
+ }
289
+ });
290
+
291
+ /**
292
+ * Cleanup on page unload
293
+ */
294
+ window.addEventListener('beforeunload', () => {
295
+ if (analyticsApp) {
296
+ analyticsApp.destroy();
297
+ }
298
+ });
299
+
300
+ /**
301
+ * Handle browser back/forward navigation
302
+ */
303
+ window.addEventListener('popstate', () => {
304
+ if (analyticsApp) {
305
+ analyticsApp.refreshData();
306
+ }
307
+ });
308
+
309
+ // Export for module use
310
+ if (typeof module !== 'undefined' && module.exports) {
311
+ module.exports = AnalyticsDashboard;
312
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Charts - Handles chart display and management
3
+ * Part of the modular frontend architecture
4
+ */
5
+ class Charts {
6
+ constructor(container, dataService, stateService) {
7
+ this.container = container;
8
+ this.dataService = dataService;
9
+ this.stateService = stateService;
10
+ this.charts = {};
11
+
12
+ // Subscribe to state changes
13
+ this.unsubscribe = this.stateService.subscribe(this.handleStateChange.bind(this));
14
+ }
15
+
16
+ /**
17
+ * Initialize charts
18
+ */
19
+ async initialize() {
20
+ await this.loadChartData();
21
+ this.setupCharts();
22
+ }
23
+
24
+ /**
25
+ * Handle state changes from StateService
26
+ * @param {Object} state - New state
27
+ * @param {string} action - Action that caused the change
28
+ */
29
+ handleStateChange(state, action) {
30
+ if (action === 'update_chart_data') {
31
+ this.updateCharts(state.chartData);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Load chart data from API
37
+ */
38
+ async loadChartData() {
39
+ try {
40
+ const chartData = await this.dataService.getChartData();
41
+ this.stateService.updateChartData(chartData);
42
+ } catch (error) {
43
+ console.error('Error loading chart data:', error);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Setup chart instances
49
+ */
50
+ setupCharts() {
51
+ // This would be called from Dashboard component
52
+ // which already has Chart.js integration
53
+ }
54
+
55
+ /**
56
+ * Update charts with new data
57
+ * @param {Object} chartData - New chart data
58
+ */
59
+ updateCharts(chartData) {
60
+ // Update existing charts with new data
61
+ Object.keys(this.charts).forEach(chartId => {
62
+ const chart = this.charts[chartId];
63
+ if (chartData[chartId]) {
64
+ chart.data = chartData[chartId];
65
+ chart.update();
66
+ }
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Create a new chart
72
+ * @param {string} id - Chart ID
73
+ * @param {HTMLElement} canvas - Canvas element
74
+ * @param {Object} config - Chart configuration
75
+ */
76
+ createChart(id, canvas, config) {
77
+ if (typeof Chart === 'undefined') {
78
+ console.error('Chart.js not loaded');
79
+ return null;
80
+ }
81
+
82
+ this.charts[id] = new Chart(canvas, config);
83
+ return this.charts[id];
84
+ }
85
+
86
+ /**
87
+ * Destroy specific chart
88
+ * @param {string} id - Chart ID
89
+ */
90
+ destroyChart(id) {
91
+ if (this.charts[id]) {
92
+ this.charts[id].destroy();
93
+ delete this.charts[id];
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Cleanup all charts
99
+ */
100
+ destroy() {
101
+ Object.keys(this.charts).forEach(id => {
102
+ this.destroyChart(id);
103
+ });
104
+
105
+ if (this.unsubscribe) {
106
+ this.unsubscribe();
107
+ }
108
+ }
109
+ }
110
+
111
+ // Export for module use
112
+ if (typeof module !== 'undefined' && module.exports) {
113
+ module.exports = Charts;
114
+ }