Kodenshare


This web app allows users to create code problems for students/interviewees


https://kodenshare.site/creation.pnghttps://kodenshare.site/instructions.pnghttps://kodenshare.site/devices.png

How Kodenshare got started

Kodenshare started as a completely different project. Now called Projare, Kodenshare started as a progressive web app that allows users to share their projects, what they used to create their projects, and the status of their projects. However, unknown to me, there was a web app called codeshare (fun fact, Kodenshare used to be called codeshare at one point until I discovered that there was already a web app called codeshare) that allows users to share their code with others. Realizing that the name Codeshare matches the description, I realized that the name Kodenshare might seem a bit misleading. With that in mind, I decided to rename it; however, I still owned the domain name kodenshare.site. Not wanting this to go to waste, I decided to make use of it. Inspired by Codenshare's ability to share code and Kahoot's ability to allow a teacher to see his/her student's responses, I decided to mix the two to create a new Kodenshare.

UI and UX

I knew that my UI and UX skills needed to be improved, so at the start of the project I decided to revamp my designs. I started to use Figma once again to create mockups of what I wanted Kodenshare to be.

Main page and about page mockup

Admin session mockup

User session mockup

I then used that as a basis for designing the actual app. I also made the navbar responsive by moving it to the bottom and making it horizontal when the screen size becomes smaller and for mobile users.

Sending answers

This was the hardest part of development. At first, I tried to use SocketIO. This was difficult for me because I had not used web sockets before. After struggling, I was able to get the local server to keep track of answers and to send them to the admin on command. However, after three answers, the web app would become sluggish and would disconnect from the socketio server. I wondered if this was just a problem with the local environment, so I deployed it on Vercel to see if there would be any changes. However, to my frustration, I discovered that Vercel does not support Web Sockets. Thankfully, Vercel has a list of alternatives that helped me to discover Pusher. I was able to use this to accomplish the same thing.

I found out that deployed servers cannot keep track of the answers given, so I decided to keep track of everything within the front end. At first, I had trouble because I thought that I could accomplish this by using useState to create an array and then add to that array every time a user makes an answer by doing the following:


    const [messages, setMessages] = useState([])

    channel.bind('answerIt', function(data) {
        if(data && data.message.url === pageTitle) {
            console.log(JSON.stringify(data))
            setMessages(currentValues => {return [...currentValues, data]})
        } 
    });

Sadly, that created an infinite loop and created endless duplicates of answers. I solved it by

  1. creating an array outside the main function
  2. converted messages from an array into an object
  3. Pushing the answer into the array later on in the main function but outside the channel bind.
  4. Filter out any duplicates (not the infinite ones) that decided to appear.

It looked like the following:


    Pusher.logToConsole = true
    var pusher = new Pusher('not going to show', {
        cluster: 'us2'
      });

      var channel = pusher.subscribe('answer');

      var listOfMessages = []

export default function Problem() {
const [messages, setMessages] = useState({})

    channel.bind('answerIt', function(data) {
        if(data && data.message.url === pageTitle) {
            console.log(JSON.stringify(data))
            setMessages(data.message)
        } 
    )}

    if(messages && messages.url) {
        listOfMessages.map(answer => answer.user === messages.user ? answer.message = messages.message : console.log(answer.user + "'s answer has not been updated" ))
        listOfMessages.push(messages)
    }
    

    listOfMessages.map((answer, index) => {
        let currentPosition = listOfMessages.indexOf(answer)
        listOfMessages[index] === answer && index !== currentPosition && listOfMessages.splice(index, 1)
        console.log("listOfMessages", listOfMessages)
        
    })

}