DEV Community

Cover image for Flatcoin Watchlist JS
Danny Rivera
Danny Rivera

Posted on

Flatcoin Watchlist JS

This App was develop as a Flatiron School JS project. I developed this app to help users create cryptocurrencies watchlists where they can see updated data from their favorite coins.

Back End Setup:

Note: You may refer to my previous Rails project for more detailed information on Rails, click the following link to find useful information about the API I'm using and more details FlatCoin on Rails.

I easily created my back end running:

rails new js_watchlist_backend --api
Enter fullscreen mode Exit fullscreen mode

I generated my models via scaffold:

rails generate scaffold coin coin_api_id name symbol
rails generate scaffold watchlist name description
rails generate scaffold watchlistCoin coin:references watchlist:references
Enter fullscreen mode Exit fullscreen mode

Check out my back end repository here on GitHub!

Front End:

This is a single page Application (SPA), so a basic front end JS setup will have an index.html, index.css and index.js.
Learning JS from scratch in one month was very challenging but after days of heavy debugging I realized that it's just a matter of understanding how to communicate with the backend API via fetch.

I started out by creating editing my index.js file.

let editMode = false
let addWatchlist = false

let divWatchlistCollection = document.querySelector('#watchlist_collection')
const flatcoinWatchlistAdapter = new FlatcoinWatchlistAdapter(`http://127.0.0.1:3000/`)
const flatcoinCoinAdapter = new FlatcoinCoinAdapter(`http://127.0.0.1:3000/`)
const watchlistForm = new WatchlistForm
const coinlistForm = new CoinForm

// Creating a global variable for coinFormContainer
const coinFormContainer = document.getElementById("coin_form_container")
//Creating a global variable for Back to watchlist btn
const backToWatchlistBtn = document.getElementById("back_watchlist_btn")
// Creating a global variable for Watchlist Collection
const watchlistCollection = document.getElementById("watchlist_collection")
// Creating a global variable for Watchlist Form container
const watchlistFormContainer = document.getElementById("watchlist_form_container")
// Creating a global variable for Coin Collection
const coinCollection = document.getElementById("coin_collection")
// Creating a global variable for New Watchlist Btn
const newWatchlistBtn = document.getElementById("new_watchlist_btn")
// Creating a global variable for Coin Container
const coinContainer = document.getElementById("coin_form_container")
// Creating a global varial for Watch list created Confirmation Container
const confirmationContainer = document.getElementById("watchlist_created_confirmation")
// Creating a global varial for Watch list deleted Confirmation Container
const confirmationDeleteContainer = document.getElementById("watchlist_deleted_confirmation")
// Creating a global varial for Watch list updated Confirmation Container
const confirmationUpdateContainer = document.getElementById("watchlist_updated_confirmation")
// Creating a global varial for Coin Delete Confirmation
const confirmationCoinDeleteContainer = document.getElementById("coin_deleted_confirmation")
coin_created_confirmation
// Creating a global varial for Coin Create Confirmation
const confirmationCoinCreateContainer = document.getElementById("coin_created_confirmation")

// DOM
document.addEventListener("DOMContentLoaded", () => {
    watchlistForm.addCreateForm()
    flatcoinWatchlistAdapter.getWatchlists()
    watchlistForm.listenViewEditDelete()
    displayWatchlistForm()
    displayCoinCollection()
    displayGoBackWatchlists()
    handleGoBackWatchlists()
})

// Display Watchlist NEW and UPDATE form
function displayWatchlistForm() {
    newWatchlistBtn.addEventListener("click", () => {
        addWatchlist = !addWatchlist
        if (addWatchlist) {
            newWatchlistBtn.innerText = "Never mind!"
            watchlistFormContainer.style.display = "block"
            editMode = false
            // watchlistForm.addCreateForm()
        } else {
            watchlistFormContainer.style.display = "none"
            newWatchlistBtn.innerText = "Create a new Watchlist!"
        }
    })
}

// Displaying Coin Collection
function displayCoinCollection() {
    coinCollection.style.display = "none"
}

// Displaying 'Go back to Watchilists!' btn
function displayGoBackWatchlists() {
    backToWatchlistBtn.style.display = "none"
}

// 
function handleGoBackWatchlists() {
    backToWatchlistBtn.addEventListener("click", () => {
        // console.log("Go back baby")
        // Displaying Create New Watchlist
        newWatchlistBtn.style.display = "block"
        // Displaying Watchlist Collection
        watchlistCollection.style.display = "block"
        //Hiding Back to Watchlists btn
        backToWatchlistBtn.style.display = "none"
        // 
        coinContainer.style.display = "none"
        // Displaying Coins
        coinCollection.style.display = "none"
        clearCoinCollectionAndForm()

    })
}

// Testing area
// confirmationContainer.hide()
// setTimeout(function(){confirmationContainer.style.display = "none"}, 1000)

function clearCoinCollectionAndForm() {
    while (coinCollection.firstChild) {
        coinCollection.removeChild(coinCollection.firstChild)
    }
    while (coinFormContainer.firstChild) {
        coinFormContainer.removeChild(coinFormContainer.firstChild)
    }
}
Enter fullscreen mode Exit fullscreen mode

Then I created an Adapter class for Watchlists, this handles all fetch requests.

class FlatcoinWatchlistAdapter {

    constructor(baseURL) {
        this.baseURL = baseURL
    }

    // Fetch Watchlist Function
    getWatchlists() {
        fetch(this.baseURL + `watchlists`)
        .then(res => res.json())
        .then(watchlists => {
            watchlists.forEach(watchlist => {
                // console.log(watchlist)
                const w = new Watchlist(watchlist)
                //console.log(w)
                w.addToDom()
            })
        })    
    }
    // Create new Watchlist
    createWatchlist(nameInput, descriptionInput) {
        fetch(this.baseURL + `watchlists`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
            body: JSON.stringify({
                name: nameInput.value,
                description: descriptionInput.value
            }) 
        })
        .then(resp => {
            console.log(resp)
            return resp.json()
        })
        .then(data => {
            console.log(data.message)
            if (data.status === 201) {
                const s = new Watchlist(data.watchlist)
                s.addToDom()
                // alert(data.message)
            } else {
                alert(data.errors)
            }
            nameInput.value = ""
            descriptionInput.value = ""
            newWatchlistBtn.click()
            confirmationContainer.style.display = "block"           
            setTimeout(function(){confirmationContainer.style.display = "none"}, 1500)
        })
        .catch(err => console.error(err)) 
    }
}
Enter fullscreen mode Exit fullscreen mode

Then a Watchlist Class.

class Watchlist {
    static all = []

    constructor({id, name, description, created_at}) {
        this.id = id
        this.name = name
        this.description = description
        this.created_at = created_at
        Watchlist.all.push(this)    
    }

    render() {
        return(`<div class="box" id="watchlist-${this.id}" data-id=${this.id}>
                <h2>${this.name}</h2>
                <p>${this.description}</p>
                <p>${this.created_at}</p>
                <button data-action='view'>View</button>
                <button data-action='edit'>Edit</button> 
                <button data-action='delete'>Delete</button>
            </div>`
        )
    }

    addToDom() {
        divWatchlistCollection.innerHTML += this.render()
    }


}
Enter fullscreen mode Exit fullscreen mode

And finally a WatchlistForm Class.

class WatchlistForm {
    constructor(){
        this.handleSubmit = this.handleSubmit.bind(this)
        this.handleViewEditDelete = this.handleViewEditDelete.bind(this)
    }

    addCreateForm() {
        const watchlistFormContainer = document.getElementById("watchlist_form_container")
        const form = document.createElement('form')
        form.innerHTML = `<input id="name_input" placeholder='Name' type='text'/><br>
        <input id="description_input" placeholder='Description' type='text'/><br>
        <input id="watchlist_submit" value="Create Watchlist!" type="submit"/>`
        watchlistFormContainer.append(form)

        form.addEventListener("submit", this.handleSubmit)
    }

    handleSubmit(event) {
        event.preventDefault()
        const nameInput = event.target[0]
        const descriptionInput = event.target[1]
        if (editMode){
            flatcoinWatchlistAdapter.editWatchlist(editMode, nameInput, descriptionInput)
        } else {
            flatcoinWatchlistAdapter.createWatchlist(nameInput, descriptionInput)
        }    
    }

    listenViewEditDelete() {
        const watchlistCollection = document.getElementById("watchlist_collection")
        watchlistCollection.addEventListener("click", this.handleViewEditDelete)
    }

    handleViewEditDelete(event) {
        const div = event.target.parentElement
        console.log(div)
        const action = event.target.dataset.action
        console.log(action)
        switch (action) {
            case "delete":
                flatcoinWatchlistAdapter.deleteWatchlist(div)
                break
            case "edit":
                editMode = div
                watchlistFormContainer.style.display = "block"
                newWatchlistBtn.style.display = "none"
                // const watchiListSubmitBtn = document.getElementById("watchlist_submit")
                // watchiListSubmitBtn.value = "Update"
                document.getElementById("watchlist_submit").value = "Update"
                // Populate input
                document.getElementById('name_input').value = div.children[0].innerText
                document.getElementById('description_input').value = div.children[1].innerText
                break
            case "view":
                // Hidding Create New Watchlist
                newWatchlistBtn.style.display = "none"
                // Hidding Watchlist Collection
                watchlistCollection.style.display = "none"
                //Displaying Back to Watchlists btn
                backToWatchlistBtn.style.display = "block"
                // Displaying Coin Form
                // const coinlistForm = new CoinForm
                coinlistForm.addCreateForm(div.children[0].innerText, div.dataset.id)
                // const coinContainer = document.getElementById("coin_form_container")
                coinContainer.style.display = "block"
                // Displaying Coins
                coinCollection.style.display = "block"
                console.log(div)
                // const flatcoinCoinAdapter = new FlatcoinCoinAdapter(`http://127.0.0.1:3000/`)
                flatcoinCoinAdapter.getCoinlist(div)
                // Adding an event listener for delete
                coinlistForm.listenDelete()
            default:
                break
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The logic for Coin object is the same as the watchlist, you may check out my front end repository here on GitHub for the full code.
Check out a quick YouTube video of my application.

Top comments (0)