gentelella
Version:
Gentelella Admin is a free to use Bootstrap admin template
1,666 lines • 168 kB
HTML
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-default.css">
<link rel="stylesheet" href="/gentelella/assets/css/just-the-docs-head-nav.css" id="jtd-head-nav-stylesheet">
<style id="jtd-nav-activation">
.site-nav > ul.nav-list:first-child > li:not(:nth-child(8)) > a,
.site-nav > ul.nav-list:first-child > li > ul > li a {
background-image: none;
}
.site-nav > ul.nav-list:not(:first-child) a,
.site-nav li.external a {
background-image: none;
}
.site-nav > ul.nav-list:first-child > li:nth-child(8) > a {
font-weight: 600;
text-decoration: none;
}.site-nav > ul.nav-list:first-child > li:nth-child(8) > button svg {
transform: rotate(-90deg);
}.site-nav > ul.nav-list:first-child > li.nav-list-item:nth-child(8) > ul.nav-list {
display: block;
}
</style>
<script src="/gentelella/assets/js/vendor/lunr.min.js"></script>
<script src="/gentelella/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/gentelella/favicon.ico" type="image/x-icon">
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>API Integration | Gentelella Admin Template</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="API Integration" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<meta property="og:description" content="Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations" />
<link rel="canonical" href="http://localhost:4000/gentelella/api-integration/" />
<meta property="og:url" content="http://localhost:4000/gentelella/api-integration/" />
<meta property="og:site_name" content="Gentelella Admin Template" />
<meta property="og:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg" />
<meta property="twitter:title" content="API Integration" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebPage","description":"Modern Bootstrap 5 Admin Dashboard Template with Performance Optimizations","headline":"API Integration","image":"http://localhost:4000/gentelella/assets/images/gentelella-preview.jpg","url":"http://localhost:4000/gentelella/api-integration/"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<a class="skip-to-main" href="#main-content">Skip to main content</a>
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="svg-link" viewBox="0 0 24 24">
<title>Link</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
</svg>
</symbol>
<symbol id="svg-menu" viewBox="0 0 24 24">
<title>Menu</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu">
<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</symbol>
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
<title>Expand</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</symbol>
<!-- Feather. MIT License: https://github.com/feathericons/feather/blob/master/LICENSE -->
<symbol id="svg-external-link" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link">
<title id="svg-external-link-title">(external link)</title>
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line>
</symbol>
<symbol id="svg-doc" viewBox="0 0 24 24">
<title>Document</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>
</svg>
</symbol>
<symbol id="svg-search" viewBox="0 0 24 24">
<title>Search</title>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</symbol>
<!-- Bootstrap Icons. MIT License: https://github.com/twbs/icons/blob/main/LICENSE.md -->
<symbol id="svg-copy" viewBox="0 0 16 16">
<title>Copy</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</svg>
</symbol>
<symbol id="svg-copied" viewBox="0 0 16 16">
<title>Copied</title>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check-fill" viewBox="0 0 16 16">
<path d="M6.5 0A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3Zm3 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3Z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1A2.5 2.5 0 0 1 9.5 5h-3A2.5 2.5 0 0 1 4 2.5v-1Zm6.854 7.354-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708.708Z"/>
</svg>
</symbol>
</svg>
<div class="side-bar">
<div class="site-header" role="banner">
<a href="/gentelella/" class="site-title lh-tight">
Gentelella Admin Template
</a>
<button id="menu-button" class="site-button btn-reset" aria-label="Toggle menu" aria-pressed="false">
<svg viewBox="0 0 24 24" class="icon" aria-hidden="true"><use xlink:href="#svg-menu"></use></svg>
</button>
</div>
<nav aria-label="Main" id="site-nav" class="site-nav">
<ul class="nav-list"><li class="nav-list-item"><a href="/gentelella/" class="nav-list-link">Gentelella Admin Template Documentation</a></li><li class="nav-list-item"><a href="/gentelella/installation/" class="nav-list-link">Installation Guide</a></li><li class="nav-list-item"><a href="/gentelella/configuration/" class="nav-list-link">Configuration</a></li><li class="nav-list-item"><a href="/gentelella/components/" class="nav-list-link">Components Guide</a></li><li class="nav-list-item"><a href="/gentelella/performance/" class="nav-list-link">Performance Guide</a></li><li class="nav-list-item"><a href="/gentelella/deployment/" class="nav-list-link">Deployment Guide</a></li><li class="nav-list-item"><a href="/gentelella/customization/" class="nav-list-link">Customization Guide</a></li><li class="nav-list-item"><a href="/gentelella/api-integration/" class="nav-list-link">API Integration</a></li></ul>
</nav>
<footer class="site-footer">
This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.
</footer>
</div>
<div class="main" id="top">
<div id="main-header" class="main-header">
<div class="search" role="search">
<div class="search-input-wrap">
<input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search Gentelella Admin Template" aria-label="Search Gentelella Admin Template" autocomplete="off">
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label>
</div>
<div id="search-results" class="search-results"></div>
</div>
<nav aria-label="Auxiliary" class="aux-nav">
<ul class="aux-nav-list">
<li class="aux-nav-list-item">
<a href="//github.com/puikinsh/gentelella" class="site-button"
>
Gentelella on GitHub
</a>
</li>
<li class="aux-nav-list-item">
<a href="//colorlib.com" class="site-button"
>
Colorlib
</a>
</li>
</ul>
</nav>
</div>
<div class="main-content-wrap">
<div id="main-content" class="main-content">
<main>
<h1 class="no_toc" id="api-integration-guide">
<a href="#api-integration-guide" class="anchor-heading" aria-labelledby="api-integration-guide"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> API Integration Guide
</h1>
<p class="fs-6 fw-300">Learn how to integrate Gentelella Admin Template with backend APIs and external services</p>
<h2 class="no_toc text-delta" id="table-of-contents">
<a href="#table-of-contents" class="anchor-heading" aria-labelledby="table-of-contents"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Table of contents
</h2>
<ol id="markdown-toc">
<li><a href="#rest-api-integration" id="markdown-toc-rest-api-integration">REST API Integration</a> <ol>
<li><a href="#http-client-setup" id="markdown-toc-http-client-setup">HTTP Client Setup</a> <ol>
<li><a href="#axios-configuration" id="markdown-toc-axios-configuration">Axios Configuration</a></li>
</ol>
</li>
<li><a href="#api-service-layer" id="markdown-toc-api-service-layer">API Service Layer</a> <ol>
<li><a href="#base-service-class" id="markdown-toc-base-service-class">Base Service Class</a></li>
<li><a href="#specific-service-classes" id="markdown-toc-specific-service-classes">Specific Service Classes</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#real-time-integration" id="markdown-toc-real-time-integration">Real-time Integration</a> <ol>
<li><a href="#websocket-connection" id="markdown-toc-websocket-connection">WebSocket Connection</a></li>
<li><a href="#real-time-dashboard-updates" id="markdown-toc-real-time-dashboard-updates">Real-time Dashboard Updates</a></li>
</ol>
</li>
<li><a href="#data-management" id="markdown-toc-data-management">Data Management</a> <ol>
<li><a href="#state-management" id="markdown-toc-state-management">State Management</a></li>
<li><a href="#data-caching" id="markdown-toc-data-caching">Data Caching</a></li>
</ol>
</li>
<li><a href="#authentication-integration" id="markdown-toc-authentication-integration">Authentication Integration</a> <ol>
<li><a href="#jwt-token-management" id="markdown-toc-jwt-token-management">JWT Token Management</a></li>
</ol>
</li>
<li><a href="#error-handling" id="markdown-toc-error-handling">Error Handling</a> <ol>
<li><a href="#global-error-handler" id="markdown-toc-global-error-handler">Global Error Handler</a></li>
</ol>
</li>
<li><a href="#performance-optimization" id="markdown-toc-performance-optimization">Performance Optimization</a> <ol>
<li><a href="#request-batching" id="markdown-toc-request-batching">Request Batching</a></li>
</ol>
</li>
<li><a href="#next-steps" id="markdown-toc-next-steps">Next Steps</a></li>
</ol><hr />
<h2 id="rest-api-integration">
<a href="#rest-api-integration" class="anchor-heading" aria-labelledby="rest-api-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> REST API Integration
</h2>
<h3 id="http-client-setup">
<a href="#http-client-setup" class="anchor-heading" aria-labelledby="http-client-setup"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> HTTP Client Setup
</h3>
<h4 id="axios-configuration">
<a href="#axios-configuration" class="anchor-heading" aria-labelledby="axios-configuration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Axios Configuration
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/http-client.js</span>
<span class="k">import</span> <span class="nx">axios</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">axios</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">HttpClient</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span> <span class="o">=</span> <span class="nx">axios</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="na">baseURL</span><span class="p">:</span> <span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">VITE_API_URL</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">http://localhost:8080/api</span><span class="dl">'</span><span class="p">,</span>
<span class="na">timeout</span><span class="p">:</span> <span class="mi">10000</span><span class="p">,</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Accept</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">application/json</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setupInterceptors</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">setupInterceptors</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Request interceptor - add auth token</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">interceptors</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
<span class="p">(</span><span class="nx">config</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">config</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">Authorization</span> <span class="o">=</span> <span class="s2">`Bearer </span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2">`</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">config</span><span class="p">;</span>
<span class="p">},</span>
<span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span>
<span class="p">);</span>
<span class="c1">// Response interceptor - handle errors</span>
<span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">interceptors</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span>
<span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="o">=></span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">?.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">401</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleUnauthorized</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">formatError</span><span class="p">(</span><span class="nx">error</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="nx">handleUnauthorized</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/login.html</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">formatError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">?.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">Server error</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Network error - please check your connection</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="mi">0</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">Unknown error occurred</span><span class="dl">'</span><span class="p">,</span>
<span class="na">status</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// HTTP methods</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">put</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">patch</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">patch</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">delete</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">config</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// File upload</span>
<span class="nx">upload</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span> <span class="o">=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">formData</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FormData</span><span class="p">();</span>
<span class="nx">formData</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="dl">'</span><span class="s1">file</span><span class="dl">'</span><span class="p">,</span> <span class="nx">file</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">client</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">formData</span><span class="p">,</span> <span class="p">{</span>
<span class="na">headers</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">multipart/form-data</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">onUploadProgress</span><span class="p">:</span> <span class="p">(</span><span class="nx">progressEvent</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">onProgress</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">progress</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span>
<span class="p">(</span><span class="nx">progressEvent</span><span class="p">.</span><span class="nx">loaded</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span> <span class="o">/</span> <span class="nx">progressEvent</span><span class="p">.</span><span class="nx">total</span>
<span class="p">);</span>
<span class="nx">onProgress</span><span class="p">(</span><span class="nx">progress</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">httpClient</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HttpClient</span><span class="p">();</span>
</code></pre></div></div>
<h3 id="api-service-layer">
<a href="#api-service-layer" class="anchor-heading" aria-labelledby="api-service-layer"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> API Service Layer
</h3>
<h4 id="base-service-class">
<a href="#base-service-class" class="anchor-heading" aria-labelledby="base-service-class"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Base Service Class
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/base-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">httpClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./http-client.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">export</span> <span class="kd">class</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span> <span class="o">=</span> <span class="nx">endpoint</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">http</span> <span class="o">=</span> <span class="nx">httpClient</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getAll</span><span class="p">(</span><span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">,</span> <span class="p">{</span> <span class="nx">params</span> <span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="na">meta</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">meta</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getById</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">create</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">update</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="k">delete</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">search</span><span class="p">(</span><span class="nx">query</span><span class="p">,</span> <span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/search`</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="na">q</span><span class="p">:</span> <span class="nx">query</span><span class="p">,</span> <span class="p">...</span><span class="nx">params</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
<span class="na">meta</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">meta</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span>
<span class="na">details</span><span class="p">:</span> <span class="nx">error</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="specific-service-classes">
<a href="#specific-service-classes" class="anchor-heading" aria-labelledby="specific-service-classes"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Specific Service Classes
</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/user-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">BaseService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./base-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">UserService</span> <span class="kd">extends</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="p">(</span><span class="dl">'</span><span class="s1">/users</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">authenticate</span><span class="p">(</span><span class="nx">credentials</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/login</span><span class="dl">'</span><span class="p">,</span> <span class="nx">credentials</span><span class="p">);</span>
<span class="c1">// Store auth token</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">user</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">logout</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/logout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="dl">'</span><span class="s1">Logout API call failed:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/login.html</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getCurrentUser</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/me</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">updateProfile</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/profile</span><span class="dl">'</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="c1">// Update stored user data</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">));</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">changePassword</span><span class="p">(</span><span class="nx">passwordData</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/change-password</span><span class="dl">'</span><span class="p">,</span> <span class="nx">passwordData</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">uploadAvatar</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="nx">upload</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/avatar</span><span class="dl">'</span><span class="p">,</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">onProgress</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">userService</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">UserService</span><span class="p">();</span>
<span class="c1">// src/js/api/dashboard-service.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">BaseService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./base-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">DashboardService</span> <span class="kd">extends</span> <span class="nx">BaseService</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getStats</span><span class="p">(</span><span class="nx">dateRange</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">30d</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard/stats</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="na">range</span><span class="p">:</span> <span class="nx">dateRange</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getChartData</span><span class="p">(</span><span class="nx">chartType</span><span class="p">,</span> <span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s2">`/dashboard/charts/</span><span class="p">${</span><span class="nx">chartType</span><span class="p">}</span><span class="s2">`</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">params</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">getRecentActivity</span><span class="p">(</span><span class="nx">limit</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="k">this</span><span class="p">.</span><span class="nx">http</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/dashboard/activity</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">params</span><span class="p">:</span> <span class="p">{</span> <span class="nx">limit</span> <span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">dashboardService</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DashboardService</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="real-time-integration">
<a href="#real-time-integration" class="anchor-heading" aria-labelledby="real-time-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Real-time Integration
</h2>
<h3 id="websocket-connection">
<a href="#websocket-connection" class="anchor-heading" aria-labelledby="websocket-connection"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> WebSocket Connection
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/websocket-client.js</span>
<span class="kd">class</span> <span class="nx">WebSocketClient</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">maxReconnectAttempts</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectDelay</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">connect</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">wsUrl</span> <span class="o">=</span> <span class="k">import</span><span class="p">.</span><span class="nx">meta</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">VITE_WS_URL</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">ws://localhost:8080/ws</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">wsUrl</span><span class="p">}</span><span class="s2">?token=</span><span class="p">${</span><span class="nx">token</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onopen</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket connected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">connected</span><span class="dl">'</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleMessage</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to parse WebSocket message:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onclose</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket disconnected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">disconnected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnect</span><span class="p">();</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket error:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">reconnect</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">>=</span> <span class="k">this</span><span class="p">.</span><span class="nx">maxReconnectAttempts</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Max reconnection attempts reached</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span><span class="o">++</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">delay</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">reconnectDelay</span> <span class="o">*</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`Reconnecting in </span><span class="p">${</span><span class="nx">delay</span><span class="p">}</span><span class="s2">ms (attempt </span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">reconnectAttempts</span><span class="p">}</span><span class="s2">)`</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span>
<span class="p">},</span> <span class="nx">delay</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">handleMessage</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">send</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="dl">'</span><span class="s1">WebSocket not connected</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">data</span> <span class="p">});</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">on</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="p">[]);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">).</span><span class="nx">push</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">off</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">callbacks</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">callbacks</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">callbacks</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">emit</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">event</span><span class="p">))</span> <span class="k">return</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">event</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">callback</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s2">`Error in WebSocket event handler for </span><span class="p">${</span><span class="nx">event</span><span class="p">}</span><span class="s2">:`</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">disconnect</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ws</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">isConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">wsClient</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocketClient</span><span class="p">();</span>
<span class="c1">// Auto-connect if user is authenticated</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="real-time-dashboard-updates">
<a href="#real-time-dashboard-updates" class="anchor-heading" aria-labelledby="real-time-dashboard-updates"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Real-time Dashboard Updates
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/dashboard/real-time-dashboard.js</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">wsClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../api/websocket-client.js</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">dashboardService</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../api/dashboard-service.js</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">RealTimeDashboard</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">charts</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">stats</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">init</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">init</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setupWebSocketListeners</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadInitialData</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">setupWebSocketListeners</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Listen for real-time stats updates</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">stats.update</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateStats</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for new chart data</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">chart.data</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateChart</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">chartId</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for new notifications</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">notification</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">showNotification</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Listen for user activity</span>
<span class="nx">wsClient</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">user.activity</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">updateActivityFeed</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">loadInitialData</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="c1">// Load dashboard stats</span>
<span class="kd">const</span> <span class="nx">statsResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getStats</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">statsResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderStats</span><span class="p">(</span><span class="nx">statsResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Load chart data</span>
<span class="kd">const</span> <span class="nx">chartTypes</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">sales</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">users</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">revenue</span><span class="dl">'</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">chartType</span> <span class="k">of</span> <span class="nx">chartTypes</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">chartResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getChartData</span><span class="p">(</span><span class="nx">chartType</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">chartResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderChart</span><span class="p">(</span><span class="nx">chartType</span><span class="p">,</span> <span class="nx">chartResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Load recent activity</span>
<span class="kd">const</span> <span class="nx">activityResult</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">dashboardService</span><span class="p">.</span><span class="nx">getRecentActivity</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">activityResult</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderActivity</span><span class="p">(</span><span class="nx">activityResult</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to load dashboard data:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateStats</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">entries</span><span class="p">(</span><span class="nx">data</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(([</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">])</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">element</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">`[data-stat="</span><span class="p">${</span><span class="nx">key</span><span class="p">}</span><span class="s2">"]`</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Animate value change</span>
<span class="k">this</span><span class="p">.</span><span class="nx">animateValue</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">animateValue</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span> <span class="nx">newValue</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">currentValue</span> <span class="o">=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[^</span><span class="sr">0-9.-</span><span class="se">]</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">))</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">difference</span> <span class="o">=</span> <span class="nx">newValue</span> <span class="o">-</span> <span class="nx">currentValue</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">steps</span> <span class="o">=</span> <span class="mi">30</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">stepValue</span> <span class="o">=</span> <span class="nx">difference</span> <span class="o">/</span> <span class="nx">steps</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">current</span> <span class="o">=</span> <span class="nx">currentValue</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">timer</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">current</span> <span class="o">+=</span> <span class="nx">stepValue</span><span class="p">;</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">formatValue</span><span class="p">(</span><span class="nx">current</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">format</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">--</span><span class="nx">steps</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearInterval</span><span class="p">(</span><span class="nx">timer</span><span class="p">);</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">formatValue</span><span class="p">(</span><span class="nx">newValue</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">format</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span> <span class="mi">16</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">formatValue</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">format</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">format</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">currency</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Intl</span><span class="p">.</span><span class="nx">NumberFormat</span><span class="p">(</span><span class="dl">'</span><span class="s1">en-US</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">style</span><span class="p">:</span> <span class="dl">'</span><span class="s1">currency</span><span class="dl">'</span><span class="p">,</span>
<span class="na">currency</span><span class="p">:</span> <span class="dl">'</span><span class="s1">USD</span><span class="dl">'</span>
<span class="p">}).</span><span class="nx">format</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">percentage</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">value</span><span class="p">.</span><span class="nx">toFixed</span><span class="p">(</span><span class="mi">1</span><span class="p">)}</span><span class="s2">%`</span><span class="p">;</span>
<span class="k">case</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">:</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Intl</span><span class="p">.</span><span class="nx">NumberFormat</span><span class="p">(</span><span class="dl">'</span><span class="s1">en-US</span><span class="dl">'</span><span class="p">).</span><span class="nx">format</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">round</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
<span class="nl">default</span><span class="p">:</span>
<span class="k">return</span> <span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateChart</span><span class="p">(</span><span class="nx">chartId</span><span class="p">,</span> <span class="nx">newData</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">chart</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">charts</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">chartId</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">chart</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="c1">// Update chart data</span>
<span class="nx">chart</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="nx">newData</span><span class="p">;</span>
<span class="nx">chart</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">active</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">showNotification</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Use notification plugin or create custom notification</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span> <span class="o">&&</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">notifications</span><span class="p">.</span><span class="nx">show</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">message</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">updateActivityFeed</span><span class="p">(</span><span class="nx">activity</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">feedContainer</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#activity-feed</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">feedContainer</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">activityItem</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">activityItem</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">activity-item</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">activityItem</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">`
<div class="activity-icon">
<i class="fa fa-</span><span class="p">${</span><span class="nx">activity</span><span class="p">.</span><span class="nx">icon</span><span class="p">}</span><span class="s2">"></i>
</div>
<div class="activity-content">
<div class="activity-text"></span><span class="p">${</span><span class="nx">activity</span><span class="p">.</span><span class="nx">message</span><span class="p">}</span><span class="s2"></div>
<div class="activity-time"></span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">formatTime</span><span class="p">(</span><span class="nx">activity</span><span class="p">.</span><span class="nx">timestamp</span><span class="p">)}</span><span class="s2"></div>
</div>
`</span><span class="p">;</span>
<span class="c1">// Add to top of feed</span>
<span class="nx">feedContainer</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">activityItem</span><span class="p">,</span> <span class="nx">feedContainer</span><span class="p">.</span><span class="nx">firstChild</span><span class="p">);</span>
<span class="c1">// Remove oldest items if feed is too long</span>
<span class="kd">const</span> <span class="nx">items</span> <span class="o">=</span> <span class="nx">feedContainer</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">.activity-item</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">items</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">remove</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">formatTime</span><span class="p">(</span><span class="nx">timestamp</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">date</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">timestamp</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">();</span>
<span class="kd">const</span> <span class="nx">diff</span> <span class="o">=</span> <span class="nx">now</span> <span class="o">-</span> <span class="nx">date</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">60000</span><span class="p">)</span> <span class="k">return</span> <span class="dl">'</span><span class="s1">Just now</span><span class="dl">'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">3600000</span><span class="p">)</span> <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">diff</span> <span class="o">/</span> <span class="mi">60000</span><span class="p">)}</span><span class="s2">m ago`</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">diff</span> <span class="o"><</span> <span class="mi">86400000</span><span class="p">)</span> <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">diff</span> <span class="o">/</span> <span class="mi">3600000</span><span class="p">)}</span><span class="s2">h ago`</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">date</span><span class="p">.</span><span class="nx">toLocaleDateString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Initialize real-time dashboard</span>
<span class="k">new</span> <span class="nx">RealTimeDashboard</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="data-management">
<a href="#data-management" class="anchor-heading" aria-labelledby="data-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Data Management
</h2>
<h3 id="state-management">
<a href="#state-management" class="anchor-heading" aria-labelledby="state-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> State Management
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/store/app-store.js</span>
<span class="kd">class</span> <span class="nx">AppStore</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">user</span><span class="p">:</span> <span class="kc">null</span><span class="p">,</span>
<span class="na">theme</span><span class="p">:</span> <span class="dl">'</span><span class="s1">light</span><span class="dl">'</span><span class="p">,</span>
<span class="na">sidebarCollapsed</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">notifications</span><span class="p">:</span> <span class="p">[],</span>
<span class="na">loading</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">loadFromStorage</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// Get current state</span>
<span class="nx">getState</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="p">};</span>
<span class="p">}</span>
<span class="c1">// Update state</span>
<span class="nx">setState</span><span class="p">(</span><span class="nx">updates</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">prevState</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">,</span> <span class="p">...</span><span class="nx">updates</span> <span class="p">};</span>
<span class="c1">// Notify listeners</span>
<span class="k">this</span><span class="p">.</span><span class="nx">notifyListeners</span><span class="p">(</span><span class="nx">prevState</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">);</span>
<span class="c1">// Persist certain state to localStorage</span>
<span class="k">this</span><span class="p">.</span><span class="nx">saveToStorage</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// Subscribe to state changes</span>
<span class="nx">subscribe</span><span class="p">(</span><span class="nx">listener</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">id</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span> <span class="nx">listener</span><span class="p">);</span>
<span class="c1">// Return unsubscribe function</span>
<span class="k">return</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">notifyListeners</span><span class="p">(</span><span class="nx">prevState</span><span class="p">,</span> <span class="nx">newState</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">listener</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">listener</span><span class="p">(</span><span class="nx">newState</span><span class="p">,</span> <span class="nx">prevState</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error in state listener:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">loadFromStorage</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">userData</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">userData</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">userData</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">theme</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">theme</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">theme</span> <span class="o">=</span> <span class="nx">theme</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">sidebarCollapsed</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">sidebar-collapsed</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">sidebarCollapsed</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span> <span class="o">=</span> <span class="nx">sidebarCollapsed</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">true</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to load state from storage:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">saveToStorage</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">user</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">theme</span><span class="dl">'</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">theme</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">sidebar-collapsed</span><span class="dl">'</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to save state to storage:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Action methods</span>
<span class="nx">setUser</span><span class="p">(</span><span class="nx">user</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">user</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">clearUser</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">user</span><span class="p">:</span> <span class="kc">null</span> <span class="p">});</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">removeItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">setTheme</span><span class="p">(</span><span class="nx">theme</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">theme</span> <span class="p">});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="dl">'</span><span class="s1">data-theme</span><span class="dl">'</span><span class="p">,</span> <span class="nx">theme</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">toggleSidebar</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">sidebarCollapsed</span><span class="p">:</span> <span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">sidebarCollapsed</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">addNotification</span><span class="p">(</span><span class="nx">notification</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="p">[...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">notifications</span><span class="p">,</span> <span class="p">{</span>
<span class="na">id</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span>
<span class="na">timestamp</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(),</span>
<span class="p">...</span><span class="nx">notification</span>
<span class="p">}];</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">notifications</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">removeNotification</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">notifications</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">n</span> <span class="o">=></span> <span class="nx">n</span><span class="p">.</span><span class="nx">id</span> <span class="o">!==</span> <span class="nx">id</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">notifications</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">setLoading</span><span class="p">(</span><span class="nx">loading</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">loading</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">setError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="nx">error</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">clearError</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">error</span><span class="p">:</span> <span class="kc">null</span> <span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">appStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AppStore</span><span class="p">();</span>
<span class="c1">// Helper hook for components</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">useStore</span><span class="p">(</span><span class="nx">selector</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">state</span> <span class="o">=</span> <span class="nx">appStore</span><span class="p">.</span><span class="nx">getState</span><span class="p">();</span>
<span class="k">return</span> <span class="nx">selector</span> <span class="p">?</span> <span class="nx">selector</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span> <span class="p">:</span> <span class="nx">state</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="data-caching">
<a href="#data-caching" class="anchor-heading" aria-labelledby="data-caching"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Data Caching
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/cache/data-cache.js</span>
<span class="kd">class</span> <span class="nx">DataCache</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">defaultTTL</span> <span class="o">=</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span> <span class="c1">// 5 minutes</span>
<span class="p">}</span>
<span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">ttl</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">defaultTTL</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">+</span> <span class="nx">ttl</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">expiryTime</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">></span> <span class="nx">expiryTime</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">has</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">clear</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">cleanup</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">now</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="p">[</span><span class="nx">key</span><span class="p">,</span> <span class="nx">expiryTime</span><span class="p">]</span> <span class="k">of</span> <span class="k">this</span><span class="p">.</span><span class="nx">expiry</span><span class="p">.</span><span class="nx">entries</span><span class="p">())</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">now</span> <span class="o">></span> <span class="nx">expiryTime</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">size</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">cache</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">dataCache</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DataCache</span><span class="p">();</span>
<span class="c1">// Auto cleanup every 5 minutes</span>
<span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">dataCache</span><span class="p">.</span><span class="nx">cleanup</span><span class="p">();</span>
<span class="p">},</span> <span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">);</span>
</code></pre></div></div><hr />
<h2 id="authentication-integration">
<a href="#authentication-integration" class="anchor-heading" aria-labelledby="authentication-integration"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Authentication Integration
</h2>
<h3 id="jwt-token-management">
<a href="#jwt-token-management" class="anchor-heading" aria-labelledby="jwt-token-management"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> JWT Token Management
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/auth/auth-manager.js</span>
<span class="kd">class</span> <span class="nx">AuthManager</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">init</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">init</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">scheduleTokenRefresh</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">login</span><span class="p">(</span><span class="nx">credentials</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">userService</span><span class="p">.</span><span class="nx">authenticate</span><span class="p">(</span><span class="nx">credentials</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">token</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">scheduleTokenRefresh</span><span class="p">();</span>
<span class="c1">// Update app state</span>
<span class="nx">appStore</span><span class="p">.</span><span class="nx">setUser</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">user</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">success</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="na">error</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">logout</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">clearTokenRefresh</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">// Clear app state</span>
<span class="nx">appStore</span><span class="p">.</span><span class="nx">clearUser</span><span class="p">();</span>
<span class="c1">// Call logout service</span>
<span class="nx">userService</span><span class="p">.</span><span class="nx">logout</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">isAuthenticated</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">!!</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">&&</span> <span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">isTokenExpired</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">isTokenExpired</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">atob</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">)[</span><span class="mi">1</span><span class="p">]));</span>
<span class="k">return</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">exp</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o"><</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">refreshToken</span><span class="p">()</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">httpClient</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/auth/refresh</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">token</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">token</span><span class="p">;</span>
<span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">auth_token</span><span class="dl">'</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">scheduleTokenRefresh</span><span class="p">();</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Token refresh failed:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">logout</span><span class="p">();</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">scheduleTokenRefresh</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">clearTokenRefresh</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">atob</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">)[</span><span class="mi">1</span><span class="p">]));</span>
<span class="kd">const</span> <span class="nx">expiryTime</span> <span class="o">=</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">exp</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">refreshTime</span> <span class="o">=</span> <span class="nx">expiryTime</span> <span class="o">-</span> <span class="p">(</span><span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">);</span> <span class="c1">// 5 minutes before expiry</span>
<span class="kd">const</span> <span class="nx">timeUntilRefresh</span> <span class="o">=</span> <span class="nx">refreshTime</span> <span class="o">-</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">timeUntilRefresh</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshToken</span><span class="p">();</span>
<span class="p">},</span> <span class="nx">timeUntilRefresh</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// Token expired or will expire soon</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshToken</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to schedule token refresh:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">clearTokenRefresh</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">refreshTimer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">getToken</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">token</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">getUser</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">userData</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="dl">'</span><span class="s1">user_data</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">userData</span> <span class="p">?</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">userData</span><span class="p">)</span> <span class="p">:</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Create singleton instance</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">authManager</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AuthManager</span><span class="p">();</span>
<span class="c1">// Route protection</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">requireAuth</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authManager</span><span class="p">.</span><span class="nx">isAuthenticated</span><span class="p">())</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/login.html</span><span class="dl">'</span><span class="p">;</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Auto-redirect if not authenticated (for protected pages)</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">[data-require-auth]</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">requireAuth</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div><hr />
<h2 id="error-handling">
<a href="#error-handling" class="anchor-heading" aria-labelledby="error-handling"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Error Handling
</h2>
<h3 id="global-error-handler">
<a href="#global-error-handler" class="anchor-heading" aria-labelledby="global-error-handler"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Global Error Handler
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/error/error-handler.js</span>
<span class="kd">class</span> <span class="nx">ErrorHandler</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setupGlobalHandlers</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">setupGlobalHandlers</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Handle unhandled promise rejections</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">unhandledrejection</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Unhandled promise rejection:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span><span class="p">.</span><span class="nx">reason</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleError</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">reason</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Promise Rejection</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
<span class="p">});</span>
<span class="c1">// Handle JavaScript errors</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript error:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleError</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">error</span><span class="p">,</span> <span class="dl">'</span><span class="s1">JavaScript Error</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// Handle API errors</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">api-error</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleApiError</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">detail</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">handleError</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">context</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Unknown</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">errorInfo</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">message</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">Unknown error</span><span class="dl">'</span><span class="p">,</span>
<span class="na">stack</span><span class="p">:</span> <span class="nx">error</span><span class="p">.</span><span class="nx">stack</span><span class="p">,</span>
<span class="nx">context</span><span class="p">,</span>
<span class="na">timestamp</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(),</span>
<span class="na">userAgent</span><span class="p">:</span> <span class="nb">navigator</span><span class="p">.</span><span class="nx">userAgent</span><span class="p">,</span>
<span class="na">url</span><span class="p">:</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span><span class="p">,</span>
<span class="na">user</span><span class="p">:</span> <span class="nx">authManager</span><span class="p">.</span><span class="nx">getUser</span><span class="p">()?.</span><span class="nx">id</span>
<span class="p">};</span>
<span class="c1">// Log to console</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error handled:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">errorInfo</span><span class="p">);</span>
<span class="c1">// Send to error tracking service</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reportError</span><span class="p">(</span><span class="nx">errorInfo</span><span class="p">);</span>
<span class="c1">// Show user-friendly notification</span>
<span class="k">this</span><span class="p">.</span><span class="nx">showErrorNotification</span><span class="p">(</span><span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">handleApiError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="mi">401</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">handleUnauthorized</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">status</span> <span class="o">>=</span> <span class="mi">500</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">showErrorNotification</span><span class="p">({</span>
<span class="na">message</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Server error occurred. Please try again later.</span><span class="dl">'</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">showErrorNotification</span><span class="p">(</span><span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">handleUnauthorized</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Clear auth data and redirect to login</span>
<span class="nx">authManager</span><span class="p">.</span><span class="nx">logout</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">showErrorNotification</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Use notification plugin if available</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span> <span class="o">&&</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">notifications</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">GentelellaPlugins</span><span class="p">.</span><span class="nx">getPlugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">notifications</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">notifications</span><span class="p">.</span><span class="nx">show</span><span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">An error occurred</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// Fallback to alert</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span> <span class="o">||</span> <span class="dl">'</span><span class="s1">An error occurred</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">reportError</span><span class="p">(</span><span class="nx">errorInfo</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="c1">// Send error to monitoring service</span>
<span class="k">await</span> <span class="nx">httpClient</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/errors/report</span><span class="dl">'</span><span class="p">,</span> <span class="nx">errorInfo</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">reportingError</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Failed to report error:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">reportingError</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Initialize global error handler</span>
<span class="k">new</span> <span class="nx">ErrorHandler</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="performance-optimization">
<a href="#performance-optimization" class="anchor-heading" aria-labelledby="performance-optimization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Performance Optimization
</h2>
<h3 id="request-batching">
<a href="#request-batching" class="anchor-heading" aria-labelledby="request-batching"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Request Batching
</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/js/api/request-batcher.js</span>
<span class="kd">class</span> <span class="nx">RequestBatcher</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">batches</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">batchDelay</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="c1">// ms</span>
<span class="p">}</span>
<span class="nx">batch</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">params</span> <span class="o">=</span> <span class="p">{})</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">batches</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">))</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">batches</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">,</span> <span class="p">{</span>
<span class="na">requests</span><span class="p">:</span> <span class="p">[],</span>
<span class="na">timer</span><span class="p">:</span> <span class="kc">null</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">batch</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">batches</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">);</span>
<span class="nx">batch</span><span class="p">.</span><span class="nx">requests</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">params</span><span class="p">,</span> <span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span> <span class="p">});</span>
<span class="c1">// Clear existing timer and set new one</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">batch</span><span class="p">.</span><span class="nx">timer</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">batch</span><span class="p">.</span><span class="nx">timer</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">batch</span><span class="p">.</span><span class="nx">timer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">executeBatch</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">);</span>
<span class="p">},</span> <span class="k">this</span><span class="p">.</span><span class="nx">batchDelay</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">async</span> <span class="nx">executeBatch</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">batch</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">batches</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">endpoint</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">batch</span> <span class="o">||</span> <span class="nx">batch</span><span class="p">.</span><span class="nx">requests</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">requests</span> <span class="o">=</span> <span class="nx">batch</span><span class="p">.</span><span class="nx">requests</span><span class="p">.</span><span class="nx">slice</span><span class="p">();</span>
<span class="nx">batch</span><span class="p">.</span><span class="nx">requests</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">batch</span><span class="p">.</span><span class="nx">timer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">ids</span> <span class="o">=</span> <span class="nx">requests</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">req</span> <span class="o">=></span> <span class="nx">req</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">httpClient</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">endpoint</span><span class="p">}</span><span class="s2">/batch`</span><span class="p">,</span> <span class="p">{</span> <span class="nx">ids</span> <span class="p">});</span>
<span class="c1">// Resolve individual requests</span>
<span class="nx">requests</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">request</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">item</span> <span class="o">=></span> <span class="nx">item</span><span class="p">.</span><span class="nx">id</span> <span class="o">===</span> <span class="nx">request</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Item not found in batch response</span><span class="dl">'</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Reject all requests</span>
<span class="nx">requests</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">request</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="nx">error</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">requestBatcher</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RequestBatcher</span><span class="p">();</span>
</code></pre></div></div><hr />
<h2 id="next-steps">
<a href="#next-steps" class="anchor-heading" aria-labelledby="next-steps"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Next Steps
</h2>
<ul>
<li><strong><a href="/gentelella/docs/security/">Security Guide</a></strong> - Implement security best practices</li>
<li><strong><a href="/gentelella/docs/testing/">Testing Guide</a></strong> - Test your API integrations</li>
<li><strong><a href="/gentelella/docs/monitoring/">Monitoring Guide</a></strong> - Monitor API performance</li>
</ul><hr />
<p class="highlight">💡 <strong>Pro Tip</strong>: Always implement proper error handling and retry logic for API calls. Use caching strategically to reduce API load and improve user experience.</p>
</main>
<hr>
<footer>
<p><a href="#top" id="back-to-top">Back to top</a></p>
<p class="text-small text-grey-dk-100 mb-0">Copyright © {{ 'now' | date: '%Y' }} Colorlib. Distributed under the <a href="https://github.com/puikinsh/gentelella/blob/master/LICENSE.txt">MIT license</a>.</p>
</footer>
</div>
</div>
<div class="search-overlay"></div>
</div>
</body>
</html>