From 19ecca41d58dd2557b70c065f47790cf1e27b80f Mon Sep 17 00:00:00 2001 From: xarlizard Date: Thu, 24 Oct 2024 12:55:48 +0200 Subject: [PATCH] StreamHatchet Frontend Technical Test --- sites/streamhatchet_frontendtest/css/main.css | 62 +++++++++ sites/streamhatchet_frontendtest/img/logo.png | Bin 0 -> 33458 bytes sites/streamhatchet_frontendtest/index.html | 62 +++++++++ .../js/header-streamhatchet.js | 83 ++++++++++++ sites/streamhatchet_frontendtest/js/main.js | 120 ++++++++++++++++++ .../js/popupNotify.js | 82 ++++++++++++ sites/streamhatchet_frontendtest/readme.md | 20 +++ 7 files changed, 429 insertions(+) create mode 100644 sites/streamhatchet_frontendtest/css/main.css create mode 100644 sites/streamhatchet_frontendtest/img/logo.png create mode 100644 sites/streamhatchet_frontendtest/index.html create mode 100644 sites/streamhatchet_frontendtest/js/header-streamhatchet.js create mode 100644 sites/streamhatchet_frontendtest/js/main.js create mode 100644 sites/streamhatchet_frontendtest/js/popupNotify.js create mode 100644 sites/streamhatchet_frontendtest/readme.md diff --git a/sites/streamhatchet_frontendtest/css/main.css b/sites/streamhatchet_frontendtest/css/main.css new file mode 100644 index 0000000..4098c3d --- /dev/null +++ b/sites/streamhatchet_frontendtest/css/main.css @@ -0,0 +1,62 @@ +/*Responsive page, has two sizes for desktop or phone devices (just to show off how the streamhatchet header webcomponent resizes)*/ +body { + margin-top: 450px; + display: flex; + flex-direction: column; + font-family: 'Nunito', Arial; + font-size: 22px; +} +.container{ + margin: auto; + display: flex; + gap: 30px; + flex-direction: row; + justify-content: center; + width: 80%; + margin: auto; + height: 100%; +} + +.containerr { + width: 80%; + margin: 8em auto; +} + +.chart-container { + min-width: 300px; +} + +#myChart { + width: 100%; + max-width: 300px; + margin: 0 auto; +} + +#buttonContainer{ + transform: scale(0); + margin: auto; +} + +button{ + margin: auto 0; + height: 100px; +} + +button:hover{ + cursor: pointer; +} + +#getRequestContainer button{ + height: 20px; +} + +#buttonload { + display: none; +} + +/* Specifications for desktop screen size*/ +@media only screen and (min-width:800px) { + body { + margin-top: 80px; + } +} \ No newline at end of file diff --git a/sites/streamhatchet_frontendtest/img/logo.png b/sites/streamhatchet_frontendtest/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d17402ebda50bb2c0a51f8e38cbb5b794a38c82f GIT binary patch literal 33458 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 V;ho0TSq#X)uB+=@EmFG|_J4p^Lzn;n literal 0 HcmV?d00001 diff --git a/sites/streamhatchet_frontendtest/index.html b/sites/streamhatchet_frontendtest/index.html new file mode 100644 index 0000000..296c52e --- /dev/null +++ b/sites/streamhatchet_frontendtest/index.html @@ -0,0 +1,62 @@ + + + + + + Demo StreamHatchet + + + + + + + + + + +
+ + +
+ +
+

API Key: + + + + -Input your 30-characters API_KEY +
+ (Used for GET server request through Axios method, doesn't get stored) +
+
+ + + + +

+
+
+ +
+ +
+
+ + +
+ + + + +
+ + + + + + + + \ No newline at end of file diff --git a/sites/streamhatchet_frontendtest/js/header-streamhatchet.js b/sites/streamhatchet_frontendtest/js/header-streamhatchet.js new file mode 100644 index 0000000..6ef00b5 --- /dev/null +++ b/sites/streamhatchet_frontendtest/js/header-streamhatchet.js @@ -0,0 +1,83 @@ +//const template = document.createElement("template"); //If more webcomponents use this, remove it and add it to the main js file ONCE. +template.innerHTML = ` + + + +`; + +class HeaderStreamHatchet extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this.shadowRoot.appendChild(template.content.cloneNode(true)); + } + + + //function to change between header titles/pages + headerSelect() { + const headerItem = this.shadowRoot.querySelector('.header-item'); + return true; + } + + connectedCallback() { + this.shadowRoot.querySelector('.header-item').addEventListener('click', () => { + this.headerSelect() + }) + } +} + +window.customElements.define("header-streamhatchet", HeaderStreamHatchet); diff --git a/sites/streamhatchet_frontendtest/js/main.js b/sites/streamhatchet_frontendtest/js/main.js new file mode 100644 index 0000000..4f6eb3a --- /dev/null +++ b/sites/streamhatchet_frontendtest/js/main.js @@ -0,0 +1,120 @@ +//We initialize all the variables needed later on server GET Request +let API_KEY = ""; //API will be provided by user input, we don't store API's on our client-side app's. +let {game1, game2, game3, game4, game5} = {}; //Variables to initialize empty chart to later be populated by server response.data +const template = document.createElement("template"); //We load the template that will be used by the WEB-COMPONENTS (for now we have 2, a custom HeaderStreamHatchet and a popupNotify for user interaction) + +//Buttons that dynamically change the chart data +airtimeHours.addEventListener("click", () => { + chart1.data.datasets[0].label = 'Airtime-hours'; + chart1.data.datasets[0].data = [game1.airtime_hours, game2.airtime_hours, game3.airtime_hours, game4.airtime_hours, game5.airtime_hours, ] + chart1.update(); +}); + +maxRank.addEventListener("click", () => { + chart1.data.datasets[0].label = 'Max_rank'; + chart1.data.datasets[0].data = [game1.max_rank, game2.max_rank, game3.max_rank, game4.max_rank, game5.max_rank, ] + chart1.update(); +}); + +averageViewers.addEventListener("click", () => { + chart1.data.datasets[0].label = 'Average_viewers'; + chart1.data.datasets[0].data = [game1.average_viewers, game2.average_viewers, game3.average_viewers, game4.average_viewers, game5.average_viewers, ] + chart1.update(); +}); + +averageChannels.addEventListener("click", () => { + chart1.data.datasets[0].label = 'Average_channels'; + chart1.data.datasets[0].data = [game1.average_channels, game2.average_channels, game3.average_channels, game4.average_channels, game5.average_channels] + chart1.update(); +}); + +//Chart creation with chart.js library -> TODO: Make it a standalone webcomponent as we did with custom header-streamhatchet, this way a constructor() could be setted for future charts. +//first we fetch de document element for the chart, a canvas inside a div with id #myChart +const ctx = document.getElementById('myChart'); +//Then we prepare the data set that is going to get passedd to the chart constructor +const data = { + //Instead of using generic labels we put the basic instructions for the user to read + labels: [ + 'You need to input a valid api', + 'to get this working, anyways chart', + 'animations do work meanwhile, you', + 'just need to click on {here} or even', + '<---{here} if you want to see it.' + ], + datasets: [{ + //Label showed on-hover + label: 'Input a valid API', + //dummy-data for first page load + data: [1, 1, 1, 1, 1], + backgroundColor: [ + 'rgb(255, 99, 132)', + 'rgb(54, 162, 235)', + 'rgb(255, 205, 86)', + 'rgb(255, 205, 0)', + 'rgb(255, 0, 86)' + ], + hoverOffset: 4, + //this is the doughnut circumference, we want only half for this chart + circumference: 180, + //by default the half-doughnut is rotated vertically, we need to adjust it by 90degrees increments (270 in this case) + rotation: 270 + }] +}; +//We load the initial chart (Axios hasnt fetched data from server, dummy/demo datasets should be provided as goodpractices) +const chart1 = new Chart(ctx, { + type: 'doughnut', + data: data, + options: { + aspectRatio: 1, + plugins: { + tooltip: {enabled:true}, + legend: {display: true} + } + } +}); + +//Server Requests +//fetch that loads when providing an API through the screen input field + button +fetchServer.addEventListener("click", () => { + + //Store the user + API_KEY = document.getElementById("apiInput").value; + document.getElementById("apiInput").value = ""; + + //Only when API provided by user has accepted length we fetch/call the server + if ( API_KEY.length == 30 ) { + //When the API is valid, we disable GET button and show a button animation + document.getElementById("fetchServer").style.display = "none"; + document.getElementById("buttonload").style.display = "inline-flex"; + + axios + .get(`https://api.streamhatchet.com/discovery/games/month/2024-01?token=${API_KEY}&sort_by=average_viewers&order=desc&limit=50&offset=0`) + .then((response) => { + //First things first, after server request is successful we disable API Input element's display + document.getElementById("getRequestContainer").style.display = "none"; + //We store the server response on games const, if we ever want to change the displayed games with a future button + const games = response.data.games; + game1 = games[0]; + game2 = games[1]; + game3 = games[2]; + game4 = games[3]; + game5 = games[4]; + + //initial data population for the first server load + chart1.data.labels = [game1.game, game2.game, game3.game, game4.game, game5.game] + chart1.data.datasets[0].label = 'Airtime-hours'; + chart1.data.datasets[0].data = [game1.airtime_hours, game2.airtime_hours, game3.airtime_hours, game4.airtime_hours, game5.airtime_hours, ] + chart1.update(); + buttonContainer.style.transform = 'scale(1)'; + }) + .catch((error) => { + console.log(error); + //When the API_KEY is not valid, we enable GET button again + document.getElementById("fetchServer").style.display = "inline-flex"; + document.getElementById("buttonload").style.display = "none"; + }); + }else{ + //Promp a warning indicating wrong input length/type + + } +}); diff --git a/sites/streamhatchet_frontendtest/js/popupNotify.js b/sites/streamhatchet_frontendtest/js/popupNotify.js new file mode 100644 index 0000000..26cadb5 --- /dev/null +++ b/sites/streamhatchet_frontendtest/js/popupNotify.js @@ -0,0 +1,82 @@ +//const template = document.createElement("template"); //If more webcomponents use this, remove it and add it to the main js file ONCE. +template.innerHTML = ` + + +
+ + + + + + + + + +
+ +
+
+`; + +class PopupNotify extends HTMLElement { + constructor() { + super(); + this.attachShadow({mode: 'open'}); + this.shadowRoot.appendChild(template.content.cloneNode(true)); + } + + tooltip(expandState) { + const tooltip = this.shadowRoot.querySelector('.notify-container') + const alert = this.shadowRoot.querySelector('.alert') + const cancel = this.shadowRoot.querySelector('.cancel') + + if(expandState == true) { + tooltip.style.transform = 'scale(1)'; + alert.style.display = 'none'; + cancel.style.display = 'block'; + expandState = false; + } else{ + tooltip.style.transform = 'scale(0)'; + alert.style.display = 'block'; + cancel.style.display = 'none'; + } + } + + connectedCallback() { + this.shadowRoot.querySelector('.alert').addEventListener('click', () => { + this.tooltip(true) + }) + this.shadowRoot.querySelector('.cancel').addEventListener('click', () => { + this.tooltip(false) + }) + } +} + +window.customElements.define('popup-notify', PopupNotify) \ No newline at end of file diff --git a/sites/streamhatchet_frontendtest/readme.md b/sites/streamhatchet_frontendtest/readme.md new file mode 100644 index 0000000..9e5349a --- /dev/null +++ b/sites/streamhatchet_frontendtest/readme.md @@ -0,0 +1,20 @@ +This repository folder contains the frontend project that I've submitted to the 45 minutes long technical test / interview for the role FrontEnd & UI/UX Developer. + + You can see it here: https://www.charlie.icu/sites/streamhatchet_frontendtest/index.html + +Languages used: Javascript, CSS, HTML + +Libraries used: + -Chart.js, Chart.css: For chart creation and display + -Axios: For server requests + -Ajax: For button loading animations + +Featured: Custom Webcomponents for "HeaderStreamHatchet" and for "popupInfo" (reusable and UI/UX friendly) + +In order to use it, simply load the index.html file and provide the input field with a valid API. + +If you dont have a valid API, demo chart is displayed to interact with it. + +Lead engineers interviewing me: Pere & Adrian +Date: 23/10/2024 +Interview status: ? \ No newline at end of file