Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>Finral - User Profile Search</title> | |
| <script src="https://telegram.org/js/telegram-web-app.js"></script> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| html, body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%); | |
| color: #e0e6ed; | |
| padding: 0; | |
| margin: 0; | |
| min-height: 100vh; | |
| position: relative; | |
| overflow-x: hidden; | |
| max-width: 100vw; | |
| } | |
| .header { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border-bottom: 2px solid #00bcd4; | |
| padding: 10px; | |
| text-align: center; | |
| box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3); | |
| position: relative; | |
| z-index: 100; | |
| } | |
| .header::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(0, 188, 212, 0.1) 50%, transparent 70%); | |
| animation: shimmer 3s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| .page-title { | |
| font-size: 1.6rem; | |
| font-weight: 900; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb, #ffffff, #00bcd4); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 3px; | |
| text-shadow: 0 0 30px rgba(0, 188, 212, 0.8); | |
| animation: gradientShift 4s ease-in-out infinite; | |
| letter-spacing: 1px; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .page-title::after { | |
| content: '🔍'; | |
| position: absolute; | |
| right: -25px; | |
| top: -3px; | |
| font-size: 1rem; | |
| animation: spark 2s infinite; | |
| } | |
| @keyframes gradientShift { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| } | |
| @keyframes spark { | |
| 0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.7; } | |
| 50% { transform: rotate(15deg) scale(1.2); opacity: 1; } | |
| } | |
| .creator { | |
| font-size: 0.7rem; | |
| background: linear-gradient(45deg, #87ceeb, #00bcd4); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 3px; | |
| font-weight: 600; | |
| letter-spacing: 0.5px; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .page-subtitle { | |
| font-size: 0.65rem; | |
| color: rgba(135, 206, 235, 0.8); | |
| margin-bottom: 0; | |
| font-style: italic; | |
| font-weight: 300; | |
| position: relative; | |
| z-index: 3; | |
| } | |
| .main-layout { | |
| display: flex; | |
| min-height: calc(100vh - 80px); | |
| } | |
| .sidebar { | |
| width: 280px; | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border-right: 2px solid #00bcd4; | |
| padding: 15px; | |
| position: fixed; | |
| left: 0; | |
| top: 80px; | |
| height: calc(100vh - 80px); | |
| overflow-y: auto; | |
| z-index: 50; | |
| box-shadow: 4px 0 20px rgba(0, 188, 212, 0.3); | |
| } | |
| .sidebar-toggle { | |
| display: none; | |
| position: fixed; | |
| top: 90px; | |
| left: 10px; | |
| z-index: 60; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border: none; | |
| border-radius: 50%; | |
| width: 40px; | |
| height: 40px; | |
| color: #0a0a0a; | |
| font-size: 1.2rem; | |
| cursor: pointer; | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.5); | |
| } | |
| .search-section { | |
| background: linear-gradient(135deg, #16213e 0%, #1a1a2e 100%); | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .search-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .search-section h3 { | |
| font-size: 1rem; | |
| color: #00bcd4; | |
| margin-bottom: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .search-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border-radius: 2px; | |
| } | |
| .search-input { | |
| padding: 10px 12px; | |
| font-size: 0.9rem; | |
| width: 100%; | |
| border: 2px solid #00bcd4; | |
| border-radius: 6px; | |
| margin-bottom: 10px; | |
| background: rgba(26, 26, 46, 0.8); | |
| color: #e0e6ed; | |
| transition: all 0.3s ease; | |
| } | |
| .search-input:focus { | |
| outline: none; | |
| border-color: #87ceeb; | |
| box-shadow: 0 0 10px rgba(0, 188, 212, 0.4); | |
| } | |
| .search-input::placeholder { | |
| color: #87ceeb; | |
| } | |
| .search-btn { | |
| padding: 10px 16px; | |
| font-size: 0.9rem; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| color: #0a0a0a; | |
| border: none; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-weight: bold; | |
| transition: all 0.3s ease; | |
| width: 100%; | |
| } | |
| .search-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.4); | |
| } | |
| .search-btn:disabled { | |
| background: #555; | |
| cursor: not-allowed; | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .search-result { | |
| margin-top: 10px; | |
| padding: 12px; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| font-size: 0.85rem; | |
| } | |
| .view-profile-btn { | |
| padding: 6px 12px; | |
| background: linear-gradient(45deg, #4caf50, #66bb6a); | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| margin-top: 8px; | |
| font-weight: bold; | |
| font-size: 0.8rem; | |
| transition: all 0.3s ease; | |
| width: 100%; | |
| } | |
| .view-profile-btn:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 3px 10px rgba(76, 175, 80, 0.4); | |
| } | |
| .content { | |
| flex: 1; | |
| margin-left: 280px; | |
| padding: 15px; | |
| overflow-x: auto; | |
| } | |
| .top-section { | |
| display: grid; | |
| grid-template-columns: 1fr 300px; | |
| gap: 15px; | |
| margin-bottom: 15px; | |
| min-height: 200px; | |
| } | |
| .banner-profile-container { | |
| position: relative; | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| } | |
| .banner-profile-container::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| z-index: 2; | |
| } | |
| #banner { | |
| width: 100%; | |
| height: 140px; | |
| object-fit: cover; | |
| border-radius: 0; | |
| } | |
| .banner-overlay { | |
| position: absolute; | |
| top: 2px; | |
| left: 0; | |
| right: 0; | |
| height: 138px; | |
| background: linear-gradient( | |
| to bottom, | |
| rgba(0, 0, 0, 0.1) 0%, | |
| rgba(0, 0, 0, 0.3) 50%, | |
| rgba(26, 26, 46, 0.8) 100% | |
| ); | |
| z-index: 2; | |
| } | |
| #pfp { | |
| position: absolute; | |
| bottom: 10px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 105px; | |
| height: 105px; | |
| object-fit: cover; | |
| border-radius: 5%; | |
| border: 3px solid #00bcd4; | |
| box-shadow: | |
| 0 0 20px rgba(0, 188, 212, 0.8), | |
| 0 0 40px rgba(0, 188, 212, 0.4); | |
| background: #1a1a2e; | |
| z-index: 4; | |
| } | |
| .profile-glow { | |
| position: absolute; | |
| bottom: -30px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 100px; | |
| height: 100px; | |
| border-radius: 50%; | |
| background: radial-gradient(circle, rgba(0, 188, 212, 0.4) 0%, rgba(0, 188, 212, 0.2) 50%, transparent 70%); | |
| z-index: 3; | |
| animation: profileGlow 3s ease-in-out infinite alternate; | |
| } | |
| @keyframes profileGlow { | |
| 0% { transform: translateX(-50%) scale(1); opacity: 0.6; } | |
| 100% { transform: translateX(-50%) scale(1.1); opacity: 0.9; } | |
| } | |
| .user-info-card { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| padding: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| } | |
| .user-info-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .welcome-title { | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| color: #e0e6ed; | |
| margin-bottom: 8px; | |
| background: linear-gradient(45deg, #e0e6ed, #87ceeb); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| text-align: center; | |
| } | |
| .chat-id { | |
| font-size: 1rem; | |
| font-weight: bold; | |
| color: #00bcd4; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| padding: 8px; | |
| text-align: center; | |
| margin-bottom: 10px; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 12px; | |
| margin-bottom: 15px; | |
| } | |
| .stats-section { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| padding: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .stats-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .stats-section h3 { | |
| font-size: 1.1rem; | |
| color: #00bcd4; | |
| margin-bottom: 12px; | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .stats-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border-radius: 2px; | |
| } | |
| .basic-stats-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 8px; | |
| } | |
| .stat-item { | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 6px; | |
| padding: 8px 6px; | |
| text-align: center; | |
| transition: all 0.3s ease; | |
| } | |
| .stat-item:hover { | |
| border-color: #00bcd4; | |
| box-shadow: 0 2px 8px rgba(0, 188, 212, 0.3); | |
| transform: translateY(-1px); | |
| } | |
| .stat-item strong { | |
| color: #87ceeb; | |
| font-size: 0.75rem; | |
| display: block; | |
| margin-bottom: 2px; | |
| } | |
| .stat-value { | |
| color: #00bcd4; | |
| font-weight: bold; | |
| font-size: 0.9rem; | |
| } | |
| .groups-container { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 12px; | |
| } | |
| .group-box { | |
| background: linear-gradient(135deg, #16213e 0%, #1a1a2e 100%); | |
| border: 1px solid rgba(0, 188, 212, 0.5); | |
| border-radius: 8px; | |
| padding: 12px; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .group-box::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 1px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .group-box:hover { | |
| border-color: #00bcd4; | |
| box-shadow: 0 4px 15px rgba(0, 188, 212, 0.3); | |
| transform: translateY(-2px); | |
| } | |
| .group-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 10px; | |
| } | |
| .group-pic { | |
| width: 50px; | |
| height: 50px; | |
| object-fit: cover; | |
| border-radius: 8px; | |
| border: 2px solid #00bcd4; | |
| flex-shrink: 0; | |
| } | |
| .group-info { | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .group-name { | |
| font-weight: bold; | |
| color: #00bcd4; | |
| font-size: 0.9rem; | |
| margin-bottom: 2px; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .group-id { | |
| font-size: 0.75rem; | |
| color: #87ceeb; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .group-stats { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 6px; | |
| margin-bottom: 8px; | |
| } | |
| .group-stat-item { | |
| background: rgba(0, 188, 212, 0.05); | |
| border: 1px solid rgba(0, 188, 212, 0.2); | |
| border-radius: 4px; | |
| padding: 4px 6px; | |
| text-align: center; | |
| } | |
| .group-stat-value { | |
| font-weight: bold; | |
| color: #00bcd4; | |
| font-size: 0.8rem; | |
| display: block; | |
| } | |
| .group-stat-label { | |
| font-size: 0.65rem; | |
| color: #87ceeb; | |
| } | |
| .group-admins { | |
| margin-top: 8px; | |
| font-size: 0.8rem; | |
| } | |
| .group-admins summary { | |
| color: #87ceeb; | |
| cursor: pointer; | |
| font-weight: bold; | |
| margin-bottom: 4px; | |
| } | |
| .admin-list { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 4px; | |
| margin-top: 4px; | |
| } | |
| .admin-tag { | |
| background: rgba(0, 188, 212, 0.2); | |
| border: 1px solid rgba(0, 188, 212, 0.4); | |
| border-radius: 12px; | |
| padding: 2px 6px; | |
| font-size: 0.7rem; | |
| color: #87ceeb; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .admin-tag:hover { | |
| background: rgba(0, 188, 212, 0.3); | |
| color: #00bcd4; | |
| } | |
| .error { | |
| color: #ff6b6b; | |
| font-style: italic; | |
| background: rgba(255, 107, 107, 0.1); | |
| border: 1px solid rgba(255, 107, 107, 0.3); | |
| border-radius: 4px; | |
| padding: 6px; | |
| margin: 6px 0; | |
| font-size: 0.8rem; | |
| } | |
| .loading { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| color: #87ceeb; | |
| font-size: 1rem; | |
| padding: 40px 20px; | |
| } | |
| .loading-spinner { | |
| width: 20px; | |
| height: 20px; | |
| border: 2px solid #87ceeb; | |
| border-top: 2px solid #00bcd4; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .loading-dots { | |
| display: inline-flex; | |
| gap: 4px; | |
| } | |
| .loading-dot { | |
| width: 6px; | |
| height: 6px; | |
| background: #00bcd4; | |
| border-radius: 50%; | |
| animation: loadingDots 1.4s infinite ease-in-out; | |
| } | |
| .loading-dot:nth-child(1) { animation-delay: -0.32s; } | |
| .loading-dot:nth-child(2) { animation-delay: -0.16s; } | |
| @keyframes loadingDots { | |
| 0%, 80%, 100% { transform: scale(0); opacity: 0.5; } | |
| 40% { transform: scale(1); opacity: 1; } | |
| } | |
| /* NFT Styles */ | |
| .nfts-section { | |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); | |
| border: 1px solid #00bcd4; | |
| border-radius: 10px; | |
| padding: 15px; | |
| margin-bottom: 15px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .nfts-section::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #00bcd4, transparent); | |
| } | |
| .nfts-section h3 { | |
| font-size: 1.1rem; | |
| color: #00bcd4; | |
| margin-bottom: 15px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .nfts-section h3::before { | |
| content: ''; | |
| width: 3px; | |
| height: 15px; | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| border-radius: 2px; | |
| } | |
| .nfts-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | |
| gap: 15px; | |
| margin-bottom: 15px; | |
| } | |
| .nft-card { | |
| border-radius: 12px; | |
| padding: 12px; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| cursor: pointer; | |
| } | |
| /* Basic Quality (0-20) */ | |
| .nft-card.basic { | |
| background: linear-gradient(135deg, #2a2a3e 0%, #1e1e32 100%); | |
| border: 1px solid #555; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); | |
| } | |
| .nft-card.basic:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 12px rgba(85, 85, 85, 0.4); | |
| } | |
| /* Better Quality (21-40) */ | |
| .nft-card.better { | |
| background: linear-gradient(135deg, #1a2e3e 0%, #16213e 100%); | |
| border: 1px solid #4caf50; | |
| box-shadow: 0 3px 10px rgba(76, 175, 80, 0.3); | |
| } | |
| .nft-card.better::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #4caf50, transparent); | |
| } | |
| .nft-card.better:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 6px 15px rgba(76, 175, 80, 0.5); | |
| } | |
| /* Even Better Quality (41-60) */ | |
| .nft-card.even-better { | |
| background: linear-gradient(135deg, #1a1e3e 0%, #2e1a3e 100%); | |
| border: 1px solid #9c27b0; | |
| box-shadow: 0 4px 12px rgba(156, 39, 176, 0.4); | |
| position: relative; | |
| } | |
| .nft-card.even-better::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, transparent, #9c27b0, #e91e63, transparent); | |
| } | |
| .nft-card.even-better::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(156, 39, 176, 0.1) 50%, transparent 70%); | |
| animation: shimmer 3s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.even-better:hover { | |
| transform: translateY(-4px); | |
| box-shadow: 0 8px 20px rgba(156, 39, 176, 0.6); | |
| } | |
| /* Way Better Quality (61-80) */ | |
| .nft-card.way-better { | |
| background: linear-gradient(135deg, #3e1a1a 0%, #3e2a1a 100%); | |
| border: 2px solid #ff9800; | |
| box-shadow: 0 5px 15px rgba(255, 152, 0, 0.5); | |
| position: relative; | |
| } | |
| .nft-card.way-better::before { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: -2px; | |
| right: -2px; | |
| bottom: -2px; | |
| background: linear-gradient(45deg, #ff9800, #ffc107, #ff5722, #ff9800); | |
| background-size: 300% 300%; | |
| border-radius: 12px; | |
| z-index: -1; | |
| animation: gradientShift 2s ease-in-out infinite; | |
| } | |
| .nft-card.way-better::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, transparent 30%, rgba(255, 152, 0, 0.2) 50%, transparent 70%); | |
| animation: shimmer 2s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.way-better:hover { | |
| transform: translateY(-5px) scale(1.02); | |
| box-shadow: 0 10px 25px rgba(255, 152, 0, 0.7); | |
| } | |
| /* Legendary Quality (81-100) */ | |
| .nft-card.legendary { | |
| background: linear-gradient(135deg, #3e1a3e 0%, #1a3e3e 100%); | |
| border: 3px solid #ffd700; | |
| box-shadow: | |
| 0 0 20px rgba(255, 215, 0, 0.6), | |
| 0 0 40px rgba(255, 215, 0, 0.4), | |
| 0 0 60px rgba(255, 215, 0, 0.2); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .nft-card.legendary::before { | |
| content: ''; | |
| position: absolute; | |
| top: -3px; | |
| left: -3px; | |
| right: -3px; | |
| bottom: -3px; | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b, #ff6f00, #ffd700); | |
| background-size: 400% 400%; | |
| border-radius: 12px; | |
| z-index: -1; | |
| animation: legendaryGlow 1.5s ease-in-out infinite; | |
| } | |
| .nft-card.legendary::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: | |
| radial-gradient(circle at 20% 20%, rgba(255, 215, 0, 0.3) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 80%, rgba(255, 235, 59, 0.3) 0%, transparent 50%), | |
| linear-gradient(45deg, transparent 30%, rgba(255, 215, 0, 0.1) 50%, transparent 70%); | |
| animation: legendaryShimmer 3s infinite; | |
| pointer-events: none; | |
| } | |
| .nft-card.legendary:hover { | |
| transform: translateY(-6px) scale(1.05); | |
| box-shadow: | |
| 0 0 30px rgba(255, 215, 0, 0.8), | |
| 0 0 60px rgba(255, 215, 0, 0.6), | |
| 0 0 90px rgba(255, 215, 0, 0.4); | |
| } | |
| @keyframes legendaryGlow { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| } | |
| @keyframes legendaryShimmer { | |
| 0% { transform: translateX(-100%) rotate(45deg); } | |
| 100% { transform: translateX(100%) rotate(45deg); } | |
| } | |
| .nft-image { | |
| width: 100%; | |
| aspect-ratio: 1; | |
| object-fit: cover; | |
| border-radius: 8px; | |
| margin-bottom: 12px; | |
| transition: all 0.3s ease; | |
| } | |
| .nft-card:hover .nft-image { | |
| transform: scale(1.05); | |
| } | |
| .nft-info { | |
| position: relative; | |
| z-index: 2; | |
| } | |
| .nft-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-start; | |
| margin-bottom: 8px; | |
| } | |
| .nft-name { | |
| font-weight: bold; | |
| font-size: 1rem; | |
| color: #e0e6ed; | |
| flex: 1; | |
| margin-right: 8px; | |
| line-height: 1.2; | |
| } | |
| .nft-id { | |
| font-size: 0.7rem; | |
| color: #87ceeb; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 4px; | |
| padding: 2px 6px; | |
| white-space: nowrap; | |
| } | |
| .nft-rarity { | |
| font-size: 0.8rem; | |
| padding: 3px 8px; | |
| border-radius: 12px; | |
| display: inline-block; | |
| margin-bottom: 8px; | |
| font-weight: bold; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .rarity-common { background: #666; color: #fff; } | |
| .rarity-uncommon { background: #4caf50; color: #fff; } | |
| .rarity-rare { background: #2196f3; color: #fff; } | |
| .rarity-epic { background: #9c27b0; color: #fff; } | |
| .rarity-legendary { background: #ff9800; color: #fff; } | |
| .rarity-mythic { background: #f44336; color: #fff; } | |
| .nft-details { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 6px; | |
| margin-bottom: 10px; | |
| } | |
| .nft-detail { | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.2); | |
| border-radius: 6px; | |
| padding: 6px 8px; | |
| text-align: center; | |
| transition: all 0.3s ease; | |
| } | |
| .nft-detail:hover { | |
| background: rgba(0, 188, 212, 0.15); | |
| border-color: rgba(0, 188, 212, 0.4); | |
| } | |
| .nft-detail-label { | |
| color: #87ceeb; | |
| display: block; | |
| font-size: 0.7rem; | |
| margin-bottom: 2px; | |
| font-weight: 500; | |
| } | |
| .nft-detail-value { | |
| color: #00bcd4; | |
| font-weight: bold; | |
| font-size: 0.85rem; | |
| display: block; | |
| } | |
| .nft-obtained { | |
| background: rgba(135, 206, 235, 0.1); | |
| border: 1px solid rgba(135, 206, 235, 0.3); | |
| border-radius: 6px; | |
| padding: 6px 8px; | |
| text-align: center; | |
| grid-column: 1 / -1; | |
| } | |
| .nft-obtained-label { | |
| color: #87ceeb; | |
| font-size: 0.7rem; | |
| margin-bottom: 2px; | |
| display: block; | |
| } | |
| .nft-obtained-value { | |
| color: #87ceeb; | |
| font-weight: bold; | |
| font-size: 0.8rem; | |
| } | |
| .quality-badge { | |
| position: absolute; | |
| top: 8px; | |
| right: 8px; | |
| padding: 4px 8px; | |
| border-radius: 12px; | |
| font-size: 0.75rem; | |
| font-weight: bold; | |
| z-index: 3; | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .quality-basic { | |
| background: linear-gradient(45deg, #666, #888); | |
| color: #fff; | |
| } | |
| .quality-better { | |
| background: linear-gradient(45deg, #4caf50, #66bb6a); | |
| color: #fff; | |
| } | |
| .quality-even-better { | |
| background: linear-gradient(45deg, #9c27b0, #ba68c8); | |
| color: #fff; | |
| } | |
| .quality-way-better { | |
| background: linear-gradient(45deg, #ff9800, #ffb74d); | |
| color: #fff; | |
| } | |
| .quality-legendary { | |
| background: linear-gradient(45deg, #ffd700, #ffeb3b); | |
| color: #000; | |
| box-shadow: 0 0 10px rgba(255, 215, 0, 0.5); | |
| } | |
| .quality-badge::before { | |
| content: '⭐'; | |
| font-size: 0.8rem; | |
| } | |
| .no-nfts { | |
| text-align: center; | |
| padding: 60px 20px; | |
| color: #87ceeb; | |
| font-style: italic; | |
| } | |
| .no-nfts-icon { | |
| font-size: 4rem; | |
| margin-bottom: 15px; | |
| opacity: 0.5; | |
| } | |
| .no-nfts h4 { | |
| font-size: 1.2rem; | |
| margin-bottom: 8px; | |
| color: #e0e6ed; | |
| } | |
| .no-nfts p { | |
| font-size: 0.9rem; | |
| margin-bottom: 5px; | |
| } | |
| .show-all-btn { | |
| background: linear-gradient(45deg, #00bcd4, #87ceeb); | |
| color: #0a0a0a; | |
| border: none; | |
| border-radius: 8px; | |
| padding: 12px 24px; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| display: block; | |
| margin: 0 auto; | |
| font-size: 0.9rem; | |
| } | |
| .show-all-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(0, 188, 212, 0.4); | |
| } | |
| .nft-loading { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| padding: 60px; | |
| color: #87ceeb; | |
| } | |
| .nft-stats { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 15px; | |
| padding: 10px 15px; | |
| background: rgba(0, 188, 212, 0.1); | |
| border: 1px solid rgba(0, 188, 212, 0.3); | |
| border-radius: 8px; | |
| } | |
| .nft-stat { | |
| text-align: center; | |
| } | |
| .nft-stat-value { | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| color: #00bcd4; | |
| display: block; | |
| } | |
| .nft-stat-label { | |
| font-size: 0.7rem; | |
| color: #87ceeb; | |
| margin-top: 2px; | |
| } | |
| /* Mobile Responsive */ | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| transform: translateX(-100%); | |
| transition: transform 0.3s ease; | |
| } | |
| .sidebar.open { | |
| transform: translateX(0); | |
| } | |
| .sidebar-toggle { | |
| display: block; | |
| } | |
| .content { | |
| margin-left: 0; | |
| padding: 10px; | |
| } | |
| .top-section { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .stats-grid { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .basic-stats-grid { | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 6px; | |
| } | |
| .groups-container { | |
| grid-template-columns: 1fr; | |
| gap: 10px; | |
| } | |
| .group-stats { | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 4px; | |
| } | |
| .group-stat-item { | |
| padding: 3px 4px; | |
| } | |
| .group-stat-value { | |
| font-size: 0.75rem; | |
| } | |
| .toggle-details { | |
| background: none; | |
| border: none; | |
| color: #007bff; | |
| cursor: pointer; | |
| font-weight: bold; | |
| margin-top: 5px; | |
| padding: 0; | |
| } | |
| .toggle-details:hover { | |
| text-decoration: underline; | |
| } | |
| .group-stat-label { | |
| font-size: 0.6rem; | |
| } | |
| .nfts-grid { | |
| grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); | |
| gap: 10px; | |
| } | |
| .nft-card { | |
| padding: 10px; | |
| } | |
| .nft-name { | |
| font-size: 0.9rem; | |
| } | |
| .nft-details { | |
| gap: 4px; | |
| } | |
| .nft-detail { | |
| padding: 4px 6px; | |
| } | |
| .nft-stats { | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .nft-stats > div { | |
| display: flex; | |
| justify-content: space-around; | |
| width: 100%; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .page-title { | |
| font-size: 1.4rem; | |
| } | |
| .page-title::after { | |
| right: -20px; | |
| font-size: 0.9rem; | |
| } | |
| .header { | |
| padding: 8px; | |
| } | |
| .content { | |
| padding: 8px; | |
| } | |
| .basic-stats-grid { | |
| grid-template-columns: 1fr 1fr; | |
| gap: 4px; | |
| } | |
| .stat-item { | |
| padding: 6px 4px; | |
| } | |
| .stat-item strong { | |
| font-size: 0.7rem; | |
| } | |
| .stat-value { | |
| font-size: 0.8rem; | |
| } | |
| .nfts-grid { | |
| grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); | |
| gap: 8px; | |
| } | |
| .nft-card { | |
| padding: 8px; | |
| } | |
| .nft-name { | |
| font-size: 0.8rem; | |
| } | |
| .nft-rarity { | |
| font-size: 0.7rem; | |
| padding: 2px 6px; | |
| } | |
| .nft-details { | |
| grid-template-columns: 1fr; | |
| gap: 3px; | |
| } | |
| .nft-detail { | |
| padding: 4px 6px; | |
| } | |
| .quality-badge { | |
| padding: 2px 6px; | |
| font-size: 0.7rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <div class="page-title">Finral Search</div> | |
| <div class="creator">✨ Crafted with Excellence by Saul ✨</div> | |
| <div class="page-subtitle">"Find Any Telegram User"</div> | |
| </div> | |
| <button class="sidebar-toggle" id="sidebarToggle">🔍</button> | |
| <div class="main-layout"> | |
| <div class="sidebar" id="sidebar"> | |
| <div class="search-section"> | |
| <h3>🔍 Search User</h3> | |
| <input type="text" id="searchInput" class="search-input" placeholder="Enter Chat/User ID"> | |
| <button id="searchBtn" class="search-btn"> | |
| <span class="btn-text">Search User</span> | |
| <div class="loading-dots" style="display: none;"> | |
| <div class="loading-dot"></div> | |
| <div class="loading-dot"></div> | |
| <div class="loading-dot"></div> | |
| </div> | |
| </button> | |
| <div id="searchResult" class="search-result" style="display:none;"></div> | |
| </div> | |
| </div> | |
| <div class="content"> | |
| <div class="top-section"> | |
| <div class="banner-profile-container" id="bannerContainer" style="display:none;"> | |
| <img id="banner" src="/placeholder.svg" alt="User Banner"> | |
| <div class="banner-overlay"></div> | |
| <div class="profile-glow"></div> | |
| <img id="pfp" src="/placeholder.svg" alt="Profile Picture"> | |
| </div> | |
| <div class="user-info-card"> | |
| <div class="welcome-title" id="welcomeTitle">Welcome to Finral</div> | |
| <div id="chatId" class="chat-id"> | |
| <div class="loading"> | |
| <div class="loading-spinner"></div> | |
| Loading... | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stats-grid" id="statsGrid" style="display:none;"> | |
| <div class="stats-section"> | |
| <h3>📊 Basic Stats</h3> | |
| <div class="basic-stats-grid"> | |
| <div class="stat-item"> | |
| <strong>Level</strong> | |
| <div class="stat-value" id="totalLevel">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Total XP</strong> | |
| <div class="stat-value" id="totalXP">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Royalties</strong> | |
| <div class="stat-value" id="totalRoyalties">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Daily Msgs</strong> | |
| <div class="stat-value" id="totalDailyMessages">-</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="stats-section"> | |
| <h3>👤 User Info</h3> | |
| <div class="basic-stats-grid"> | |
| <div class="stat-item"> | |
| <strong>Full Name</strong> | |
| <div class="stat-value" id="fullName">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Username</strong> | |
| <div class="stat-value" id="username">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Groups</strong> | |
| <div class="stat-value" id="groupCount">-</div> | |
| </div> | |
| <div class="stat-item"> | |
| <strong>Status</strong> | |
| <div class="stat-value">Active</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- NFT Section FIRST --> | |
| <div class="nfts-section" id="nftsSection" style="display:none;"> | |
| <h3>🎨 NFT Collection</h3> | |
| <div class="nft-stats" id="nftStats" style="display:none;"> | |
| <div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="totalNfts">0</span> | |
| <span class="nft-stat-label">Total NFTs</span> | |
| </div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="avgQuality">0</span> | |
| <span class="nft-stat-label">Avg Quality</span> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="rarestHolders">0</span> | |
| <span class="nft-stat-label">Rarest (Holders)</span> | |
| </div> | |
| <div class="nft-stat"> | |
| <span class="nft-stat-value" id="highestQuality">0</span> | |
| <span class="nft-stat-label">Highest Quality</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="nftsContainer"> | |
| <div class="nft-loading"> | |
| <div class="loading-spinner"></div> | |
| Loading NFTs... | |
| </div> | |
| </div> | |
| <button id="showAllNftsBtn" class="show-all-btn" style="display:none;"> | |
| Show All NFTs (<span id="remainingCount">0</span> more) | |
| </button> | |
| </div> | |
| <!-- Group Section SECOND --> | |
| <div class="stats-section" id="groupsSection" style="display:none;"> | |
| <h3>👥 Group Memberships</h3> | |
| <div class="groups-container" id="groupsContainer"></div> | |
| </div> | |
| <script> | |
| // Sidebar toggle functionality | |
| const sidebarToggle = document.getElementById('sidebarToggle'); | |
| const sidebar = document.getElementById('sidebar'); | |
| sidebarToggle.addEventListener('click', () => { | |
| sidebar.classList.toggle('open'); | |
| sidebarToggle.textContent = sidebar.classList.contains('open') ? '✕' : '🔍'; | |
| }); | |
| // Close sidebar when clicking outside on mobile | |
| document.addEventListener('click', (e) => { | |
| if (window.innerWidth <= 768 && | |
| !sidebar.contains(e.target) && | |
| !sidebarToggle.contains(e.target) && | |
| sidebar.classList.contains('open')) { | |
| sidebar.classList.remove('open'); | |
| sidebarToggle.textContent = '🔍'; | |
| } | |
| }); | |
| // Function to search user by chat ID | |
| async function searchUser(chatId) { | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const searchResult = document.getElementById('searchResult'); | |
| const btnText = searchBtn.querySelector('.btn-text'); | |
| const loadingDots = searchBtn.querySelector('.loading-dots'); | |
| searchBtn.disabled = true; | |
| btnText.style.display = 'none'; | |
| loadingDots.style.display = 'flex'; | |
| searchResult.style.display = 'none'; | |
| try { | |
| const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/info`); | |
| const data = await response.json(); | |
| if (data.status && data.groups && data.groups.length > 0) { | |
| const userInfo = data.groups[0]; | |
| searchResult.innerHTML = ` | |
| <p><strong>✅ Found User:</strong></p> | |
| <p><strong>Name:</strong> ${userInfo.fullName || 'N/A'}</p> | |
| <p><strong>Username:</strong> ${userInfo.username || 'N/A'}</p> | |
| <p><strong>ID:</strong> ${chatId}</p> | |
| <button class="view-profile-btn" onclick="window.open('https://t.me/finralxbot/info?startapp=${chatId}', '_blank')"> | |
| View Full Profile | |
| </button> | |
| `; | |
| searchResult.style.display = 'block'; | |
| } else { | |
| searchResult.innerHTML = '<p class="error">❌ User not found or no data available.</p>'; | |
| searchResult.style.display = 'block'; | |
| } | |
| } catch (error) { | |
| searchResult.innerHTML = '<p class="error">⚠️ Error searching for user. Please try again.</p>'; | |
| searchResult.style.display = 'block'; | |
| } | |
| searchBtn.disabled = false; | |
| btnText.style.display = 'block'; | |
| loadingDots.style.display = 'none'; | |
| } | |
| window.addEventListener('DOMContentLoaded', async () => { | |
| // Set up search functionality | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const searchInput = document.getElementById('searchInput'); | |
| searchBtn.addEventListener('click', () => { | |
| const chatId = searchInput.value.trim(); | |
| if (chatId) { | |
| searchUser(chatId); | |
| } | |
| }); | |
| searchInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| const chatId = searchInput.value.trim(); | |
| if (chatId) { | |
| searchUser(chatId); | |
| } | |
| } | |
| }); | |
| // Get userId from Telegram WebApp start parameter or current user | |
| let userId; | |
| let isViewingOther = false; | |
| const initData = Telegram.WebApp.initDataUnsafe; | |
| const startParam = initData.start_param; | |
| if (startParam) { | |
| userId = startParam; | |
| isViewingOther = true; | |
| document.getElementById('welcomeTitle').textContent = `Viewing Profile`; | |
| } else { | |
| const user = initData.user; | |
| if (user && user.id) { | |
| userId = user.id; | |
| document.getElementById('welcomeTitle').textContent = `Welcome to Finral`; | |
| } else { | |
| document.getElementById('chatId').innerHTML = '<div class="error">❌ Unable to fetch chat ID</div>'; | |
| return; | |
| } | |
| } | |
| document.getElementById('chatId').textContent = userId; | |
| try { | |
| // Fetch user banner with fallback | |
| try { | |
| const bannerRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/banner`); | |
| const bannerData = await bannerRes.json(); | |
| const bannerEl = document.getElementById('banner'); | |
| if (bannerData.status && bannerData.catboxUrl) { | |
| bannerEl.src = bannerData.catboxUrl; | |
| } else { | |
| bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg'; | |
| } | |
| document.getElementById('bannerContainer').style.display = 'block'; | |
| } catch (err) { | |
| const bannerEl = document.getElementById('banner'); | |
| bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg'; | |
| document.getElementById('bannerContainer').style.display = 'block'; | |
| } | |
| // Fetch user PFP | |
| const pfpRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/pfp`); | |
| const pfpData = await pfpRes.json(); | |
| const imgEl = document.getElementById('pfp'); | |
| if (pfpData.status && pfpData.catboxUrl) { | |
| imgEl.src = pfpData.catboxUrl; | |
| } else { | |
| imgEl.src = 'https://files.catbox.moe/hmicys.jpeg'; | |
| } | |
| // Fetch user info | |
| const infoRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`); | |
| const infoData = await infoRes.json(); | |
| if (infoData.status) { | |
| const userInfo = infoData.groups[0] || {}; | |
| // Display basic stats | |
| document.getElementById('fullName').textContent = userInfo.fullName || 'N/A'; | |
| document.getElementById('username').textContent = userInfo.username || 'N/A'; | |
| document.getElementById('totalXP').textContent = infoData.totalXP.toLocaleString(); | |
| document.getElementById('totalLevel').textContent = infoData.totalLevel; | |
| document.getElementById('totalRoyalties').textContent = infoData.totalRoyalties.toLocaleString(); | |
| document.getElementById('totalDailyMessages').textContent = infoData.totalDailyMessages; | |
| document.getElementById('groupCount').textContent = infoData.groups.length; | |
| // Show stats grid | |
| document.getElementById('statsGrid').style.display = 'grid'; | |
| // Group unique groups by groupId | |
| const uniqueGroups = {}; | |
| for (const group of infoData.groups) { | |
| const groupId = group.groupId || group.id; | |
| if (!uniqueGroups[groupId]) { | |
| uniqueGroups[groupId] = { | |
| groupId: groupId, | |
| fullName: group.fullName, | |
| username: group.username, | |
| totalLevel: 0, | |
| totalXP: 0, | |
| totalRoyalties: 0, | |
| totalDailyMessages: 0, | |
| entries: [] | |
| }; | |
| } | |
| uniqueGroups[groupId].totalLevel += group.level || 0; | |
| uniqueGroups[groupId].totalXP += group.xp || 0; | |
| uniqueGroups[groupId].totalRoyalties += group.royalties || 0; | |
| uniqueGroups[groupId].totalDailyMessages += group.dailyMessages || 0; | |
| uniqueGroups[groupId].entries.push({ | |
| level: group.level, | |
| xp: group.xp, | |
| royalties: group.royalties, | |
| dailyMessages: group.dailyMessages | |
| }); | |
| } | |
| // Display group stats | |
| const groupsContainer = document.getElementById('groupsContainer'); | |
| groupsContainer.innerHTML = ''; | |
| for (const groupId in uniqueGroups) { | |
| const group = uniqueGroups[groupId]; | |
| let groupMeta = null; | |
| let metaError = null; | |
| try { | |
| const groupMetaRes = await fetch(`https://reaperxxxx-testldb.hf.space/group/${groupId}/meta`); | |
| if (groupMetaRes.ok) { | |
| groupMeta = await groupMetaRes.json(); | |
| } else { | |
| const errorText = await groupMetaRes.text(); | |
| metaError = `API Error: ${groupMetaRes.status}`; | |
| } | |
| } catch (err) { | |
| metaError = `Fetch Error: ${err.message}`; | |
| } | |
| const div = document.createElement('div'); | |
| div.className = 'group-box'; | |
| const displayName = (groupMeta && groupMeta.status && groupMeta.groupName) | |
| ? groupMeta.groupName | |
| : group.fullName || 'Unknown Group'; | |
| const groupPic = (groupMeta && groupMeta.status && groupMeta.groupPic) | |
| ? groupMeta.groupPic | |
| : null; | |
| const admins = (groupMeta && groupMeta.status && groupMeta.admins) | |
| ? groupMeta.admins | |
| : null; | |
| div.innerHTML = ` | |
| <div class="group-header"> | |
| ${groupPic ? `<img class="group-pic" src="${groupPic}" alt="Group Picture">` : '<div class="group-pic" style="background: linear-gradient(45deg, #00bcd4, #87ceeb); display: flex; align-items: center; justify-content: center; color: #0a0a0a; font-weight: bold;">👥</div>'} | |
| <div class="group-info"> | |
| <div class="group-name">${displayName}</div> | |
| <div class="group-id">ID: ${groupId}</div> | |
| </div> | |
| </div> | |
| <div class="group-stats"> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalLevel}</span> | |
| <span class="group-stat-label">Level</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalXP.toLocaleString()}</span> | |
| <span class="group-stat-label">XP</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalRoyalties.toLocaleString()}</span> | |
| <span class="group-stat-label">Royalties</span> | |
| </div> | |
| <div class="group-stat-item"> | |
| <span class="group-stat-value">${group.totalDailyMessages}</span> | |
| <span class="group-stat-label">Daily</span> | |
| </div> | |
| </div> | |
| ${metaError ? `<div class="error">⚠️ ${metaError}</div>` : ''} | |
| ${admins && admins.length > 0 ? ` | |
| <div class="group-admins"> | |
| <details> | |
| <summary>👑 Admins (${admins.length})</summary> | |
| <div class="admin-list"> | |
| ${admins.slice(0, 5).map(a => `<span class="admin-tag" onclick="window.open('https://t.me/finralxbot/info?startapp=${a.id}', '_blank')">${a.name || 'Unknown'}</span>`).join('')} | |
| ${admins.length > 5 ? `<span class="admin-tag">+${admins.length - 5} more</span>` : ''} | |
| </div> | |
| </details> | |
| </div>` : ''} | |
| `; | |
| groupsContainer.appendChild(div); | |
| } | |
| document.getElementById('groupsSection').style.display = 'block'; | |
| } | |
| // Fetch and display user NFTs | |
| try { | |
| const nftsRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/nfts`); | |
| const nftsData = await nftsRes.json(); | |
| const nftsContainer = document.getElementById('nftsContainer'); | |
| const showAllBtn = document.getElementById('showAllNftsBtn'); | |
| const remainingCount = document.getElementById('remainingCount'); | |
| const nftStats = document.getElementById('nftStats'); | |
| if (nftsData.status && nftsData.nfts && nftsData.nfts.length > 0) { | |
| // Sort NFTs by holders (ascending) to show rarest first | |
| const sortedNfts = nftsData.nfts.sort((a, b) => a.holders - b.holders); | |
| // Calculate NFT statistics | |
| const totalNfts = sortedNfts.length; | |
| const avgQuality = Math.round(sortedNfts.reduce((sum, nft) => sum + nft.nftquality, 0) / totalNfts); | |
| const rarestHolders = Math.min(...sortedNfts.map(nft => nft.holders)); | |
| const highestQuality = Math.max(...sortedNfts.map(nft => nft.nftquality)); | |
| // Update NFT stats | |
| document.getElementById('totalNfts').textContent = totalNfts; | |
| document.getElementById('avgQuality').textContent = avgQuality; | |
| document.getElementById('rarestHolders').textContent = rarestHolders; | |
| document.getElementById('highestQuality').textContent = highestQuality; | |
| nftStats.style.display = 'block'; | |
| function getQualityClass(quality) { | |
| if (quality >= 81) return 'legendary'; | |
| if (quality >= 61) return 'way-better'; | |
| if (quality >= 41) return 'even-better'; | |
| if (quality >= 21) return 'better'; | |
| return 'basic'; | |
| } | |
| function getQualityBadgeClass(quality) { | |
| if (quality >= 81) return 'quality-legendary'; | |
| if (quality >= 61) return 'quality-way-better'; | |
| if (quality >= 41) return 'quality-even-better'; | |
| if (quality >= 21) return 'quality-better'; | |
| return 'quality-basic'; | |
| } | |
| function getRarityClass(rarity) { | |
| const rarityLower = rarity.toLowerCase(); | |
| if (rarityLower.includes('mythic')) return 'rarity-mythic'; | |
| if (rarityLower.includes('legendary')) return 'rarity-legendary'; | |
| if (rarityLower.includes('epic')) return 'rarity-epic'; | |
| if (rarityLower.includes('rare')) return 'rarity-rare'; | |
| if (rarityLower.includes('uncommon')) return 'rarity-uncommon'; | |
| return 'rarity-common'; | |
| } | |
| function formatDate(dateString) { | |
| const date = new Date(dateString); | |
| return date.toLocaleDateString('en-US', { | |
| month: 'short', | |
| day: 'numeric', | |
| year: 'numeric' | |
| }); | |
| } | |
| function formatDateTime(dateString) { | |
| const date = new Date(dateString); | |
| return date.toLocaleString('en-US', { | |
| month: 'short', | |
| day: 'numeric', | |
| year: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }); | |
| } | |
| function createNftCard(nft) { | |
| const qualityClass = getQualityClass(nft.nftquality); | |
| const qualityBadgeClass = getQualityBadgeClass(nft.nftquality); | |
| const rarityClass = getRarityClass(nft.rarity); | |
| const uniqueId = `details-${nft.nftid}`; | |
| return ` | |
| <div class="nft-card ${qualityClass}"> | |
| <div class="quality-badge ${qualityBadgeClass}">${nft.nftquality}</div> | |
| <img src="${nft.nftimage}" alt="${nft.name}" class="nft-image" loading="lazy"> | |
| <div class="nft-info"> | |
| <div class="nft-header"> | |
| <div class="nft-name" title="${nft.name}">${nft.name}</div> | |
| <div class="nft-id">#${nft.nftid}</div> | |
| </div> | |
| <div class="nft-rarity ${rarityClass}">${nft.rarity}</div> | |
| <button class="toggle-details" onclick="toggleDetails('${uniqueId}', this)">▼ Show Details</button> | |
| <div class="nft-details-wrapper" id="${uniqueId}" style="display: none;"> | |
| <div class="nft-details"> | |
| <div class="nft-detail"> | |
| <span class="nft-detail-label">Quality</span> | |
| <span class="nft-detail-value">${nft.nftquality}/100</span> | |
| </div> | |
| <div class="nft-detail"> | |
| <span class="nft-detail-label">Holders</span> | |
| <span class="nft-detail-value">${nft.holders}</span> | |
| </div> | |
| </div> | |
| <div class="nft-obtained"> | |
| <span class="nft-obtained-label">Obtained On</span> | |
| <span class="nft-obtained-value">${formatDateTime(nft.gotten_on)}</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| // Show first 5 NFTs initially | |
| const initialNfts = sortedNfts.slice(0, 5); | |
| const remainingNfts = sortedNfts.slice(5); | |
| nftsContainer.innerHTML = ` | |
| <div class="nfts-grid"> | |
| ${initialNfts.map(nft => createNftCard(nft)).join('')} | |
| </div> | |
| `; | |
| // Show "Show All" button if there are more NFTs | |
| if (remainingNfts.length > 0) { | |
| remainingCount.textContent = remainingNfts.length; | |
| showAllBtn.style.display = 'block'; | |
| let allShown = false; | |
| showAllBtn.addEventListener('click', () => { | |
| if (!allShown) { | |
| const nftsGrid = nftsContainer.querySelector('.nfts-grid'); | |
| nftsGrid.innerHTML += remainingNfts.map(nft => createNftCard(nft)).join(''); | |
| showAllBtn.textContent = 'Show Less'; | |
| allShown = true; | |
| } else { | |
| const nftsGrid = nftsContainer.querySelector('.nfts-grid'); | |
| nftsGrid.innerHTML = initialNfts.map(nft => createNftCard(nft)).join(''); | |
| showAllBtn.innerHTML = `Show All NFTs (<span id="remainingCount">${remainingNfts.length}</span> more)`; | |
| allShown = false; | |
| } | |
| }); | |
| } | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } else { | |
| // No NFTs found | |
| nftsContainer.innerHTML = ` | |
| <div class="no-nfts"> | |
| <div class="no-nfts-icon">🎨</div> | |
| <h4>No NFTs Found</h4> | |
| <p>This user hasn't collected any NFTs yet.</p> | |
| <p>Start your digital art journey today!</p> | |
| </div> | |
| `; | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } | |
| } catch (err) { | |
| console.error('Error fetching NFTs:', err); | |
| const nftsContainer = document.getElementById('nftsContainer'); | |
| nftsContainer.innerHTML = ` | |
| <div class="no-nfts"> | |
| <div class="no-nfts-icon">⚠️</div> | |
| <h4>Failed to Load NFTs</h4> | |
| <p>Unable to fetch NFT collection data.</p> | |
| <p>Please try again later.</p> | |
| </div> | |
| `; | |
| document.getElementById('nftsSection').style.display = 'block'; | |
| } | |
| } catch (err) { | |
| console.error('Error fetching user data:', err); | |
| document.getElementById('chatId').innerHTML = '<div class="error">❌ Failed to load user info</div>'; | |
| } | |
| }); | |
| </script> | |
| <script> | |
| function toggleDetails(id, button) { | |
| const details = document.getElementById(id); | |
| const isVisible = details.style.display === 'block'; | |
| details.style.display = isVisible ? 'none' : 'block'; | |
| button.textContent = isVisible ? '▼ Show Details' : '▲ Hide Details'; | |
| } | |
| </script> | |
| </body> | |
| </html> |