From 48b3aaf2474d2144de954e477804bba189cf41cb Mon Sep 17 00:00:00 2001 From: Mikiyas-STP Date: Sun, 30 Mar 2025 21:33:43 +0100 Subject: [PATCH 1/2] implementation for codewarfetchdata --- codewars-badge.js | 181 +++++++++++++++++++++++++++++++++++++++------- index.html | 8 +- 2 files changed, 159 insertions(+), 30 deletions(-) diff --git a/codewars-badge.js b/codewars-badge.js index 7c26060..d8e2805 100644 --- a/codewars-badge.js +++ b/codewars-badge.js @@ -1,51 +1,182 @@ // This native web component fetches data from the Codewars API and renders it as a badge // Here is some information about web component https://developer.mozilla.org/en-US/docs/Web/Web_Components // Here is the link to the Codewars API Docs: https://dev.codewars.com/#get-user - class CodeWarsBadge extends HTMLElement { constructor() { super(); - this.attachShadow({ mode: "open" }); - this.userName = "CodeYourFuture"; - this.userData = []; + this.attachShadow({ mode: "open" });// this creates an isolated DOM or shadow Dom for styling + this.userName = "Mikiyas-STP"; //this holds the codewar username + this.userData = []; //this is an array to store the userDatas } - connectedCallback() { this.fetchActivity() .then(() => { this.render(); }) .catch((error) => { - console.error(error); + console.error("Error fetching Codewars data:", error); + this.renderError(); //to render the error message if the API failed. }); } - // fetch the data from the Codewars API async fetchActivity() { - const response = await fetch( - `https://www.codewars.com/api/v1/users/${this.userName}` - ); - const data = await response.json(); - this.userData = data; // set the userData property with the fetched data + try{ + const response = await fetch(`https://www.codewars.com/api/v1/users/${this.userName}`); + if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`); + const data = await response.json(); + this.userData = data; // set the userData property with the fetched data + this.render(); + }catch (error){ + console.error("Failed to fetch data:", error); + this.userData = null; + this.renderError(); } - +} render() { + if(!this.userData) return; + const rankColor = this.userData.ranks?.overall?.color || "gray"; // Fallback if undefined + const leaderboard = this.userData.leaderboardPosition ? `#${this.userData.leaderboardPosition}` : "N/A"; this.shadowRoot.innerHTML = ` - - ${this.userData.ranks.overall.name} - `; +
+

Username:${this.userData.username}

+

Honor Points:${this.userData.honor}

+
+
+
+ +

Completed Challenges: ${ + this.userData.codeChallenges.totalCompleted + }

+

Leaderboard Rank: ${leaderboard}

+

Rank:${ + this.userData.ranks.overall.name + }

+
`; + } + renderError(){ + this.shadowRoot.innerHTML = ` +

Failed to load Codewars data. Please try again later.

`; } } - customElements.define("codewars-badge", CodeWarsBadge); +/* New functionality added for the stretch exercise which is displaying the recent challenges. */ +//creating a new class that extend html element to make the class a web component +class RecentChallenges extends HTMLElement{ + constructor(){ + super(); + this.attachShadow({mode:'open'}); + this.userName = 'Mikiyas-STP'; + this.challenges = [];// to store the fetched challenges + } + connectedCallback(){ + this.fetchChallenges() + .then(()=> this.render()) + .catch(error => { + console.error("Error fetching recent challenges:", error); + this.renderError(); + }); + } + async fetchChallenges(){ + try { + const res = await fetch( + `https://www.codewars.com/api/v1/users/${this.userName}/code-challenges/completed` + ); + if (!res.ok) + throw new Error(`HTTP error! Status: ${res.status}`); + const data = await res.json(); + this.challenges = data.data.slice(0, 5); // Get the latest 5 challenges + this.render(); + } catch (error) { + console.error("Failed to fetch challenges:", error); + this.challenges = null; + this.renderError(); + } + } + render() { + if (!this.challenges) return; + + this.shadowRoot.innerHTML = ` + +
+

Recent Challenges

+ ${this.challenges + .map( + challenge => ` +
+

Name: ${challenge.name}

+

Completed At: ${new Date(challenge.completedAt).toLocaleDateString()}

+

View Kata

+
` + ) + .join("")} +
`; + } + renderError() { + this.shadowRoot.innerHTML = ` + +

Failed to load recent challenges. Please try again later.

`; + } +} +customElements.define("codewars-recent-challenges", RecentChallenges); + diff --git a/index.html b/index.html index bbb3149..a89df8d 100644 --- a/index.html +++ b/index.html @@ -3,15 +3,13 @@ - Codewars Badge - + Codewars Information Board + + From 9b1be1cf4ec804c62d165b1dbb38d0d3819c504d Mon Sep 17 00:00:00 2001 From: Mikiyas-STP Date: Sun, 30 Mar 2025 22:44:07 +0100 Subject: [PATCH 2/2] added functionality for the search by name --- codewars-badge.js | 130 +++++++++++++++++++++++++++++++++++++++------- index.html | 1 + 2 files changed, 112 insertions(+), 19 deletions(-) diff --git a/codewars-badge.js b/codewars-badge.js index d8e2805..650bcf7 100644 --- a/codewars-badge.js +++ b/codewars-badge.js @@ -1,12 +1,81 @@ // This native web component fetches data from the Codewars API and renders it as a badge // Here is some information about web component https://developer.mozilla.org/en-US/docs/Web/Web_Components // Here is the link to the Codewars API Docs: https://dev.codewars.com/#get-user +//the first section is for the searchsection implementation +class CodewarsSearch extends HTMLElement{ + constructor(){ + super(); + this.attachShadow({mode:"open"}); //for isolated styling and structure + } + + connectedCallback(){ + this.render(); //this is the initial render + } + handlingTheSearch(){ + const input = this.shadowRoot.querySelector("#usernameInput"); + const username = input.value.trim(); //input the username and clean it + if(!username) return; //this prevents empty input + //find the badge and change its username + const badge = document.querySelector("codewars-badge"); + if(badge){ + badge.userName = username; //updating the username if the badge exists. + badge.fetchActivity(); //by using badge fetch. + } + const challenges = document.querySelector("codewars-recent-challenges"); + if(challenges){ + challenges.setAttribute("username", username); + } + + } + render(){ + this.shadowRoot.innerHTML = ` + +
+ + +
+ `; + //event listener + this.shadowRoot.querySelector("#searchBtn").addEventListener("click", () => this.handlingTheSearch()); + } + } +//defining the new search component +customElements.define("codewars-search", CodewarsSearch); + + +//this implementation is for the codewarsbadge class CodeWarsBadge extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" });// this creates an isolated DOM or shadow Dom for styling this.userName = "Mikiyas-STP"; //this holds the codewar username - this.userData = []; //this is an array to store the userDatas + this.userData = null; //this is set to null to check for empty data } connectedCallback() { this.fetchActivity() @@ -41,6 +110,9 @@ class CodeWarsBadge extends HTMLElement { :host { font: 600 1rem system-ui, sans-serif; } + #main-cont{ + margin:30px; + } .badge{ display: inline-block; color: black; @@ -52,7 +124,7 @@ class CodeWarsBadge extends HTMLElement { background: green; } p{ - margin: 5px 0; + margin: 5px 0px; line-height: 1.4; } .progress-bar{ @@ -69,13 +141,15 @@ class CodeWarsBadge extends HTMLElement { transition: width 0.5s ease-in-out; } +

Username:${this.userData.username}

Honor Points:${this.userData.honor}

-
- + +
+

Completed Challenges: ${ this.userData.codeChallenges.totalCompleted }

@@ -83,7 +157,9 @@ class CodeWarsBadge extends HTMLElement {

Rank:${ this.userData.ranks.overall.name }

-
`; +
+ ` + ; } renderError(){ this.shadowRoot.innerHTML = `