I took a shoot at writing a Github contribution clone using Vuej, tippy.js and tailwindcss.
My working clone looks like this:
It is not an exact look-a-like but I'm getting there. I have received some feedback on using the librarydate-fns to generate year, months and days; it seems that the data generation is scattered across the application.
At the moment I think my code is pretty readable but performance wise, I don't have a clue - I haven't tested it with a larger amount of data.
Here is the working example (and astackblitz fiddle):
<template> <div id="app"> <div v-for="(month, index) in all_months" v-bind:key="month"> <h1>{{ month }}, {{ getDaysInMonth(index) }}</h1> <div class="flex"> <div v-for="day in getDaysInMonth(index)" v-bind:key="day" class="flex flex-col"> <div class="flex flex-row"> <div class="mr-1"></div> <div class="w-4 h-4 rounded-sm mt-1 bg-gray-300 shadow" :class="{'bg-green-300': test[whatDate(index, day, true)]}" :data-tippy-content='`${whatDate(index, day)}`'></div> </div> </div> </div> </div> <br> whatDate: {{ whatDate(1, 22, true)}} </div> </template> <script> import tippy from 'tippy.js'; import 'tippy.js/dist/tippy.css'; // optional for styling export default { mounted(){ tippy('[data-tippy-content]') }, // props: ['answers', 'correct_answer_count', 'wrong_answer_count'], data(){ return{ days: [], answers: { "06-Nov-22": { "total":24, "correct":17, "wrong":7}, "14-Jul-22": { "total":26, "correct":24, "wrong":2}, "13-Jul-22": { "total":21, "correct":14, "wrong":7}, "09-Jul-22": { "total":30, "correct":23, "wrong":7}, "06-Jul-22": { "total":4, "correct":3, "wrong":1}, "05-Jul-22": { "total":13, "correct":11, "wrong":2}, "04-Jul-22": { "total":164, "correct":148, "wrong":16}, "03-Jul-22": { "total":7, "correct":4, "wrong":3}, "27-Jun-22": { "total":1, "correct":1, "wrong":0}, "22-Jun-22": { "total":10, "correct":9, "wrong":1} }, } }, computed:{ test(){ const tempArray = {} const answers = this.answers Object.keys(this.answers).forEach(function(element, key) { tempArray[new Date(element).toLocaleDateString()] = answers[element] }) return tempArray }, all_months(){ const month = Array.from({length: 12}, (e,i) => { return new Date(2022, i + 1, null).toLocaleDateString("sv", {month: 'long'}) }) return month } }, methods:{ getDaysInMonth(index){ return new Date(2022, index + 1, 0).getDate(); }, whatDay(index, day){ switch (new Date(2022, index , day).getDay()){ case 0: day = "Sunday"; break; case 1: day = "Monday"; break; case 2: day = "Tuesday"; break; case 3: day = "Wednesday"; break; case 4: day = "Thursday"; break; case 5: day = "Friday"; break; case 6: day = "Saturday"; } return day }, whatDate(index, day, standardDate = false){ if(!standardDate){ return new Date(2022, index, day).toLocaleDateString("sv", {weekday: "long", year: "numeric", month: "long", day: "numeric"}) //.toDateString() } return new Date(2022, index, day).toLocaleDateString() } }, } </script>1 Answer1
General Feedback
It is interesting that Date methods liketoLocaleDateString() are used in methodwhatDate() as well as for computed properties yet the methodwhatDay() simply has aswitch statement to return string literals for the days of the week. One could replace theswitch statement with an array and fetch the day from the array based on the index, or use thetoLocaleDateString() method.
If performance does become an issue then one may want to consider converting functional loops (e.g. calling.forEach()) tofor loops.
Suggestions
Attribute binding syntax can be more consistent
There are several elements in the markup usingv-bind: - e.g.
<div v-for="(month, index) in all_months" v-bind:key="month">
and
<div v-for="day in getDaysInMonth(index)" v-bind:key="day" class="flex flex-col">
Yet others simply use thev-bind shorthand - e.g.:class and:data-tippy-content
:class="{'bg-green-300': test[whatDate(index, day, true)]}" :data-tippy-content='`${whatDate(index, day)}`'
Arrow function can be used to eliminate local variable
The callback passed to theforEach used in thetest() method can be switched to an arrow function, like that of the map function passed as the second argument toArray.from() within theall_months() computed function. Since arrow functions don't have their ownbindings tothis1 the callback function can referencethis.answers instead ofanswers and then that variable can be eliminated.
Variable name could be misleading
In the function for computed propertyall_months the array is stored in a variable calledmonth. A more appropriate name would bemonths, since it stores multiple months.
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.

