Skip to content

Instantly share code, notes, and snippets.

@SH20RAJ
Created March 10, 2025 06:08
Show Gist options
  • Save SH20RAJ/776fd496fc0e16bb493b3f5d0ddeeafe to your computer and use it in GitHub Desktop.
Save SH20RAJ/776fd496fc0e16bb493b3f5d0ddeeafe to your computer and use it in GitHub Desktop.
Leetmatric
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Leetmatric</h1>
<p>Enter your username below:</p>
<div class="user-container">
<input type="text" placeholder="enter your username here"id="user-input">
<button id="search-btn">Search </button>
</div>
<div class="stats-container">
<div class="progress">
<div class="progress-item circle ">
<div class="easy-progress ">
<span id="easy-label"></span>
Easy
</div>
</div>
<div class="progress-item circle">
<div class="medium-progress ">
<span id="medium-label"></span>
Medium
</div>
</div>
<div class="progress-item circle">
<div class="hard-progress ">
<span id="hard-label"></span>
Hard
</div>
</div>
</div>
<div class="stat-card">
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
document.addEventListener("DOMContentLoaded",function(){
const searchButton = document.getElementById("search-btn");
const usernameInput =document.getElementById("user-input");
const statsContainer = document.querySelector(".stats-container");
const easyProgressCircle=document.querySelector(".easy-progress");
const mediumProgressCircle=document.querySelector(".mediumProgress");
const hardProgressCircle= document.querySelector(".hard-progress");
const easyLabel= document.getElementById("easy-label");
const mediumLabel = document.getElementById("medium-label");
const hardLabel = document.getElementById("hard-label");
const cardStatsContainer= document.querySelector(".stats-cards");
function validateUsername(username){
if(username.trim()===""){
alert("Username should not be empty");
return false;
}
const regex=/^[a-zA-Z0-9._-]{3,16}$/;
const isMatching= regex.test(username);
if(!isMatching){
alert("Invalid Username");
}
return isMatching;
}
async function fetchUserDetails(username){
try{
searchButton.textContent="Searching..";
searchButton.disabled=true;
const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
const targetUrl = 'https://leetcode.com/graphql';
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Origin", "https://leetcode.com");
myHeaders.append("Referer", "https://leetcode.com");
myHeaders.append("Access-Control-Allow-Origin", "*");
const graphql = JSON.stringify({
query: `
query getUserProfile($username: String!) {
matchedUser(username: $username) {
submitStats: submitStatsGlobal {
acSubmissionNum {
difficulty
count
}
}
}
}
`,
variables: { "username": username }
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: graphql,
mode: "cors",
credentials: "omit"
};
const response = await fetch(proxyUrl + targetUrl, requestOptions);
if(!response.ok){
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.errors) {
throw new Error(data.errors[0].message || "API Error");
}
updateUI(data.data);
}
catch(error){
console.error("Error:", error);
statsContainer.innerHTML = `<p>Error: ${error.message}</p>`;
}
finally{
searchButton.textContent = "Search";
searchButton.disabled = false;
}
}
function updateUI(data) {
if (!data || !data.matchedUser || !data.matchedUser.submitStats) {
throw new Error("Invalid data format");
}
const stats = data.matchedUser.submitStats.acSubmissionNum.reduce((acc, curr) => {
acc[curr.difficulty.toLowerCase()] = curr.count;
return acc;
}, {});
easyLabel.textContent = stats.easy || 0;
mediumLabel.textContent = stats.medium || 0;
hardLabel.textContent = stats.hard || 0;
}
searchButton.addEventListener('click', function(){
const username = usernameInput.value;
console.log("loggin username", username);
if(validateUsername(username)){
fetchUserDetails(username);
}
})
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
}
body {
background-color: #f5f5f5;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background-color: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
width: 90%;
max-width: 800px;
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 1rem;
}
p {
color: #666;
text-align: center;
margin-bottom: 2rem;
}
.user-container {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
}
#user-input {
flex: 1;
padding: 0.8rem;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 1rem;
transition: border-color 0.3s;
}
#user-input:focus {
outline: none;
border-color: #3498db;
}
#search-btn {
padding: 0.8rem 1.5rem;
background-color: #3498db;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
#search-btn:hover {
background-color: #2980b9;
}
#search-btn:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.stats-container {
margin-top: 2rem;
}
.progress {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 2rem;
}
.progress-item {
text-align: center;
}
.circle {
width: 150px;
height: 150px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: #f8f9fa;
}
.easy-progress, .medium-progress, .hard-progress {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #2c3e50;
}
.easy-progress span, .medium-progress span, .hard-progress span {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.easy-progress {
border: 8px solid #00b8a3;
border-radius: 50%;
}
.medium-progress {
border: 8px solid #ffc01e;
border-radius: 50%;
}
.hard-progress {
border: 8px solid #ff375f;
border-radius: 50%;
}
.stat-card {
margin-top: 2rem;
padding: 1rem;
background-color: #f8f9fa;
border-radius: 5px;
}
@media (max-width: 768px) {
.container {
padding: 1rem;
width: 95%;
}
.user-container {
flex-direction: column;
}
.circle {
width: 120px;
height: 120px;
}
.progress {
gap: 1rem;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment