CoolFace
Apppublic

KillerKing93/Transformers-TextEngine-OpenAPI

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
marketplace_demo.html615 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>AI Marketplace Demo - Qwen3-4B-Instruct</title>7    <style>8        * {9            margin: 0;10            padding: 0;11            box-sizing: border-box;12        }13 14        body {15            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;16            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);17            min-height: 100vh;18            padding: 20px;19        }20 21        .container {22            max-width: 1200px;23            margin: 0 auto;24            background: white;25            border-radius: 15px;26            box-shadow: 0 20px 60px rgba(0,0,0,0.3);27            padding: 30px;28        }29 30        h1 {31            color: #667eea;32            margin-bottom: 10px;33            font-size: 2.5em;34        }35 36        .subtitle {37            color: #666;38            margin-bottom: 30px;39            font-size: 1.1em;40        }41 42        .tabs {43            display: flex;44            gap: 10px;45            margin-bottom: 30px;46            border-bottom: 2px solid #e0e0e0;47        }48 49        .tab {50            padding: 12px 24px;51            cursor: pointer;52            border: none;53            background: none;54            font-size: 16px;55            color: #666;56            border-bottom: 3px solid transparent;57            transition: all 0.3s;58        }59 60        .tab:hover {61            color: #667eea;62        }63 64        .tab.active {65            color: #667eea;66            border-bottom-color: #667eea;67            font-weight: bold;68        }69 70        .tab-content {71            display: none;72        }73 74        .tab-content.active {75            display: block;76        }77 78        .form-group {79            margin-bottom: 20px;80        }81 82        label {83            display: block;84            margin-bottom: 8px;85            color: #333;86            font-weight: 600;87        }88 89        input, select, textarea {90            width: 100%;91            padding: 12px;92            border: 2px solid #e0e0e0;93            border-radius: 8px;94            font-size: 14px;95            transition: border-color 0.3s;96        }97 98        input:focus, select:focus, textarea:focus {99            outline: none;100            border-color: #667eea;101        }102 103        textarea {104            resize: vertical;105            min-height: 100px;106        }107 108        button {109            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);110            color: white;111            padding: 12px 30px;112            border: none;113            border-radius: 8px;114            font-size: 16px;115            font-weight: 600;116            cursor: pointer;117            transition: transform 0.2s, box-shadow 0.2s;118        }119 120        button:hover {121            transform: translateY(-2px);122            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);123        }124 125        button:active {126            transform: translateY(0);127        }128 129        .response {130            margin-top: 20px;131            padding: 20px;132            border-radius: 8px;133            background: #f8f9fa;134            border-left: 4px solid #667eea;135        }136 137        .response h3 {138            color: #667eea;139            margin-bottom: 10px;140        }141 142        .response pre {143            background: #2d2d2d;144            color: #f8f8f2;145            padding: 15px;146            border-radius: 5px;147            overflow-x: auto;148            font-size: 13px;149            line-height: 1.5;150        }151 152        .error {153            border-left-color: #e74c3c;154        }155 156        .error h3 {157            color: #e74c3c;158        }159 160        .product-card {161            background: white;162            border: 2px solid #e0e0e0;163            border-radius: 8px;164            padding: 15px;165            margin-bottom: 15px;166        }167 168        .product-card h4 {169            color: #667eea;170            margin-bottom: 10px;171        }172 173        .product-info {174            display: grid;175            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));176            gap: 10px;177            margin-top: 10px;178        }179 180        .info-item {181            color: #666;182            font-size: 14px;183        }184 185        .info-item strong {186            color: #333;187        }188 189        .loading {190            display: none;191            text-align: center;192            padding: 20px;193            color: #667eea;194        }195 196        .loading.active {197            display: block;198        }199 200        .spinner {201            border: 4px solid #f3f3f3;202            border-top: 4px solid #667eea;203            border-radius: 50%;204            width: 40px;205            height: 40px;206            animation: spin 1s linear infinite;207            margin: 0 auto 10px;208        }209 210        @keyframes spin {211            0% { transform: rotate(0deg); }212            100% { transform: rotate(360deg); }213        }214 215        .config {216            background: #fff3cd;217            padding: 15px;218            border-radius: 8px;219            margin-bottom: 20px;220            border-left: 4px solid #ffc107;221        }222 223        .config input {224            margin-top: 5px;225        }226    </style>227</head>228<body>229    <div class="container">230        <h1>๐Ÿค– AI Marketplace Demo</h1>231        <p class="subtitle">Test marketplace API endpoints with Qwen3-4B-Instruct</p>232 233        <div class="config">234            <label>API Base URL:</label>235            <input type="text" id="apiBase" value="http://localhost:3000" placeholder="http://localhost:3000">236        </div>237 238        <div class="tabs">239            <button class="tab active" onclick="switchTab('search')">AI Search</button>240            <button class="tab" onclick="switchTab('products')">Products</button>241            <button class="tab" onclick="switchTab('suppliers')">Suppliers</button>242            <button class="tab" onclick="switchTab('users')">Users</button>243        </div>244 245        <!-- AI Search Tab -->246        <div id="search" class="tab-content active">247            <h2>๐ŸŒŸ AI-Powered Product Search</h2>248            <p style="color: #666; margin-bottom: 20px;">Natural language product recommendations with location awareness</p>249 250            <div class="form-group">251                <label>User ID (must have AI access enabled):</label>252                <input type="number" id="searchUserId" value="1" placeholder="1">253            </div>254 255            <div class="form-group">256                <label>Query (in Indonesian or English):</label>257                <textarea id="searchQuery" placeholder="Saya butuh laptop gaming di Jakarta, budget 12 juta">laptop gaming Jakarta budget 12 juta</textarea>258            </div>259 260            <button onclick="aiSearch()">๐Ÿ” Search with AI</button>261 262            <div id="searchLoading" class="loading">263                <div class="spinner"></div>264                <p>AI is analyzing your query...</p>265            </div>266 267            <div id="searchResponse"></div>268        </div>269 270        <!-- Products Tab -->271        <div id="products" class="tab-content">272            <h2>๐Ÿ“ฆ Product Management</h2>273 274            <h3 style="margin-top: 30px; color: #667eea;">List Products</h3>275            <div class="form-group">276                <label>Category (optional):</label>277                <input type="text" id="listCategory" placeholder="laptop, smartphone, etc.">278            </div>279            <button onclick="listProducts()">List Products</button>280 281            <h3 style="margin-top: 30px; color: #667eea;">Search Products (Location-Aware)</h3>282            <div class="form-group">283                <label>Search Query:</label>284                <input type="text" id="productQuery" placeholder="gaming laptop" value="laptop">285            </div>286            <div class="form-group">287                <label>User Latitude (for distance sorting):</label>288                <input type="number" step="any" id="userLat" placeholder="-6.2088" value="-6.2088">289            </div>290            <div class="form-group">291                <label>User Longitude:</label>292                <input type="number" step="any" id="userLon" placeholder="106.8456" value="106.8456">293            </div>294            <button onclick="searchProducts()">Search Products</button>295 296            <div id="productsLoading" class="loading">297                <div class="spinner"></div>298                <p>Loading products...</p>299            </div>300 301            <div id="productsResponse"></div>302        </div>303 304        <!-- Suppliers Tab -->305        <div id="suppliers" class="tab-content">306            <h2>๐Ÿช Supplier Management</h2>307 308            <h3 style="margin-top: 30px; color: #667eea;">Register Supplier</h3>309            <div class="form-group">310                <label>Name:</label>311                <input type="text" id="supplierName" placeholder="John Doe">312            </div>313            <div class="form-group">314                <label>Business Name:</label>315                <input type="text" id="businessName" placeholder="Tech Store Jakarta">316            </div>317            <div class="form-group">318                <label>Email:</label>319                <input type="email" id="supplierEmail" placeholder="john@techstore.com">320            </div>321            <div class="form-group">322                <label>City:</label>323                <input type="text" id="supplierCity" placeholder="Jakarta">324            </div>325            <div class="form-group">326                <label>Latitude:</label>327                <input type="number" step="any" id="supplierLat" placeholder="-6.2088" value="-6.2088">328            </div>329            <div class="form-group">330                <label>Longitude:</label>331                <input type="number" step="any" id="supplierLon" placeholder="106.8456" value="106.8456">332            </div>333            <button onclick="registerSupplier()">Register Supplier</button>334 335            <h3 style="margin-top: 30px; color: #667eea;">List Suppliers</h3>336            <button onclick="listSuppliers()">List All Suppliers</button>337 338            <div id="suppliersLoading" class="loading">339                <div class="spinner"></div>340                <p>Loading suppliers...</p>341            </div>342 343            <div id="suppliersResponse"></div>344        </div>345 346        <!-- Users Tab -->347        <div id="users" class="tab-content">348            <h2>๐Ÿ‘ค User Management</h2>349 350            <h3 style="margin-top: 30px; color: #667eea;">Register User</h3>351            <div class="form-group">352                <label>Name:</label>353                <input type="text" id="userName" placeholder="Jane Smith">354            </div>355            <div class="form-group">356                <label>Email:</label>357                <input type="email" id="userEmail" placeholder="jane@email.com">358            </div>359            <div class="form-group">360                <label>City:</label>361                <input type="text" id="userCity" placeholder="Jakarta">362            </div>363            <div class="form-group">364                <label>Latitude:</label>365                <input type="number" step="any" id="userLatReg" placeholder="-6.2088" value="-6.2088">366            </div>367            <div class="form-group">368                <label>Longitude:</label>369                <input type="number" step="any" id="userLonReg" placeholder="106.8456" value="106.8456">370            </div>371            <div class="form-group">372                <label>373                    <input type="checkbox" id="aiAccess" checked style="width: auto; margin-right: 5px;">374                    Enable AI Access (Premium Feature)375                </label>376            </div>377            <button onclick="registerUser()">Register User</button>378 379            <div id="usersLoading" class="loading">380                <div class="spinner"></div>381                <p>Processing...</p>382            </div>383 384            <div id="usersResponse"></div>385        </div>386    </div>387 388    <script>389        const getApiBase = () => document.getElementById('apiBase').value;390 391        function switchTab(tabName) {392            // Hide all tabs393            document.querySelectorAll('.tab-content').forEach(content => {394                content.classList.remove('active');395            });396            document.querySelectorAll('.tab').forEach(tab => {397                tab.classList.remove('active');398            });399 400            // Show selected tab401            document.getElementById(tabName).classList.add('active');402            event.target.classList.add('active');403        }404 405        function showLoading(id) {406            document.getElementById(id).classList.add('active');407        }408 409        function hideLoading(id) {410            document.getElementById(id).classList.remove('active');411        }412 413        function showResponse(id, data, isError = false) {414            const responseDiv = document.getElementById(id);415            const className = isError ? 'response error' : 'response';416            responseDiv.innerHTML = `417                <div class="${className}">418                    <h3>${isError ? 'โŒ Error' : 'โœ… Success'}</h3>419                    <pre>${JSON.stringify(data, null, 2)}</pre>420                </div>421            `;422        }423 424        async function aiSearch() {425            const userId = document.getElementById('searchUserId').value;426            const query = document.getElementById('searchQuery').value;427 428            if (!userId || !query) {429                alert('Please fill in all fields');430                return;431            }432 433            showLoading('searchLoading');434            document.getElementById('searchResponse').innerHTML = '';435 436            try {437                const response = await fetch(`${getApiBase()}/api/chat/search`, {438                    method: 'POST',439                    headers: { 'Content-Type': 'application/json' },440                    body: JSON.stringify({ user_id: parseInt(userId), query })441                });442 443                const data = await response.json();444                hideLoading('searchLoading');445 446                if (response.ok) {447                    showResponse('searchResponse', data);448                } else {449                    showResponse('searchResponse', data, true);450                }451            } catch (error) {452                hideLoading('searchLoading');453                showResponse('searchResponse', { error: error.message }, true);454            }455        }456 457        async function listProducts() {458            const category = document.getElementById('listCategory').value;459            const url = category460                ? `${getApiBase()}/api/products?category=${encodeURIComponent(category)}`461                : `${getApiBase()}/api/products`;462 463            showLoading('productsLoading');464            document.getElementById('productsResponse').innerHTML = '';465 466            try {467                const response = await fetch(url);468                const data = await response.json();469                hideLoading('productsLoading');470 471                if (response.ok) {472                    showResponse('productsResponse', data);473                } else {474                    showResponse('productsResponse', data, true);475                }476            } catch (error) {477                hideLoading('productsLoading');478                showResponse('productsResponse', { error: error.message }, true);479            }480        }481 482        async function searchProducts() {483            const q = document.getElementById('productQuery').value;484            const lat = document.getElementById('userLat').value;485            const lon = document.getElementById('userLon').value;486 487            if (!q) {488                alert('Please enter a search query');489                return;490            }491 492            const params = new URLSearchParams({ q });493            if (lat) params.append('user_lat', lat);494            if (lon) params.append('user_lon', lon);495 496            showLoading('productsLoading');497            document.getElementById('productsResponse').innerHTML = '';498 499            try {500                const response = await fetch(`${getApiBase()}/api/products/search?${params}`);501                const data = await response.json();502                hideLoading('productsLoading');503 504                if (response.ok) {505                    showResponse('productsResponse', data);506                } else {507                    showResponse('productsResponse', data, true);508                }509            } catch (error) {510                hideLoading('productsLoading');511                showResponse('productsResponse', { error: error.message }, true);512            }513        }514 515        async function registerSupplier() {516            const data = {517                name: document.getElementById('supplierName').value,518                business_name: document.getElementById('businessName').value,519                email: document.getElementById('supplierEmail').value,520                city: document.getElementById('supplierCity').value,521                latitude: parseFloat(document.getElementById('supplierLat').value),522                longitude: parseFloat(document.getElementById('supplierLon').value)523            };524 525            if (!data.name || !data.business_name || !data.email || !data.city) {526                alert('Please fill in all required fields');527                return;528            }529 530            showLoading('suppliersLoading');531            document.getElementById('suppliersResponse').innerHTML = '';532 533            try {534                const response = await fetch(`${getApiBase()}/api/suppliers/register`, {535                    method: 'POST',536                    headers: { 'Content-Type': 'application/json' },537                    body: JSON.stringify(data)538                });539 540                const result = await response.json();541                hideLoading('suppliersLoading');542 543                if (response.ok) {544                    showResponse('suppliersResponse', result);545                } else {546                    showResponse('suppliersResponse', result, true);547                }548            } catch (error) {549                hideLoading('suppliersLoading');550                showResponse('suppliersResponse', { error: error.message }, true);551            }552        }553 554        async function listSuppliers() {555            showLoading('suppliersLoading');556            document.getElementById('suppliersResponse').innerHTML = '';557 558            try {559                const response = await fetch(`${getApiBase()}/api/suppliers`);560                const data = await response.json();561                hideLoading('suppliersLoading');562 563                if (response.ok) {564                    showResponse('suppliersResponse', data);565                } else {566                    showResponse('suppliersResponse', data, true);567                }568            } catch (error) {569                hideLoading('suppliersLoading');570                showResponse('suppliersResponse', { error: error.message }, true);571            }572        }573 574        async function registerUser() {575            const data = {576                name: document.getElementById('userName').value,577                email: document.getElementById('userEmail').value,578                city: document.getElementById('userCity').value,579                latitude: parseFloat(document.getElementById('userLatReg').value),580                longitude: parseFloat(document.getElementById('userLonReg').value),581                ai_access_enabled: document.getElementById('aiAccess').checked582            };583 584            if (!data.name || !data.email || !data.city) {585                alert('Please fill in all required fields');586                return;587            }588 589            showLoading('usersLoading');590            document.getElementById('usersResponse').innerHTML = '';591 592            try {593                const response = await fetch(`${getApiBase()}/api/users/register`, {594                    method: 'POST',595                    headers: { 'Content-Type': 'application/json' },596                    body: JSON.stringify(data)597                });598 599                const result = await response.json();600                hideLoading('usersLoading');601 602                if (response.ok) {603                    showResponse('usersResponse', result);604                } else {605                    showResponse('usersResponse', result, true);606                }607            } catch (error) {608                hideLoading('usersLoading');609                showResponse('usersResponse', { error: error.message }, true);610            }611        }612    </script>613</body>614</html>615