0

There is a small web application that implements voting for Champions League games. For each game, there are 3 available scores :), :| , :( . Inside the form there are three buttons for voting accordingly. How do I make sure that one user can vote only once? When voting, the data is sent to FireBase. According to the task condition, it is best to use the uuid, but I do not yet understand how?

import React from 'react'

import good_mark from '../img/iconsForRating/good_mark.jpg'
import satisfactory_mark from '../img/iconsForRating/satisfactory_mark.jpg'
import bad_mark from '../img/iconsForRating/bad_mark.png'

import styles from "./EvaluationLecture.module.css"
import  firebase from 'firebase';


const currentData = {
    idLecture: "421452",
    nameLecture: "Advansed React",
    numberGoodMarks: 42,
    numberSatisfactoryMarks: 356,
    numberBadMarks: 14
}

// idLecture: "fsdf3124",
//     nameLecture: "Basic React",
//     numberGoodMarks: 9,
//     numberSatisfactoryMarks: 32,
//     numberBadMarks: 6

class EvaluationLecture extends React.Component{
    constructor(props) {
        super(props)
        this.handleSubmit = this.handleSubmit.bind(this);
        this.state = {
            idLecture: currentData.idLecture,
            nameLecture: currentData.nameLecture,
            numberGoodMarks: currentData.numberGoodMarks,
            numberSatisfactoryMarks: currentData.numberSatisfactoryMarks,
            numberBadMarks: currentData.numberBadMarks
        }
      }
      handleSubmit = ({target: {id}}) => {
        console.log(id)
    };

    btnClick = (e) => {
        if(e.target.id === "good_mark"){
            this.setState({
                numberGoodMarks: ++this.state.numberGoodMarks
            })
        }
        if(e.target.id === "satisfactory_mark"){
                this.setState({
                    numberSatisfactoryMarks: ++this.state.numberSatisfactoryMarks
                })
        }
        if(e.target.id === "bad_mark") {
                this.setState({
                    numberBadMarks: ++this.state.numberBadMarks
                })
            }
        // console.log(this.state)
        // firebase.auth()
        //     .catch(error => console.log(error))
        firebase.database().ref('lectures/' + this.state.idLecture).set(this.state);
    };

    componentDidMount(){
        const database = firebase.database();
        // console.log(database);
    }

    render(){
        return(
            <div className = {styles.evaluation_lecture__form}>
                <h1 className = {styles.evaluation_lecture__name}>{this.state.nameLecture}</h1>
                
                 <div className = {styles.evaluation_lecture__buttons}>
                    <button id = "good_mark" className = {styles.button + " " + styles.good_mark}   onClick = {this.btnClick}></button>

                    <button id = "satisfactory_mark" className = {styles.button + " " + styles.satisfactory_mark} onClick = {this.btnClick}></button>

                    <button id = "bad_mark" className = {styles.button + " " + styles.bad_mark} onClick = {this.btnClick}></button>
                </div>
                
                
               


                <h2>Statistics</h2>
                <ul className = {styles.evaluation_lecture__statistics}>
                    <li className = "">
                        <img src = {good_mark} style = {{wight: "50px", height: "50px"}}></img>
                        <span>{this.state.numberGoodMarks}</span>
                    </li>

                    <li className = "">
                        <img src = {satisfactory_mark} style = {{wight: "50px", height: "50px"}}></img>
                        <span>{this.state.numberSatisfactoryMarks}</span>
                    </li>

                    <li className = "">
                        <img src = {bad_mark} style = {{wight: "50px", height: "50px"}}></img>
                        <span>{this.state.numberBadMarks}</span>
                    </li>
                </ul>
                
            </div>
        )
    }
}

export default EvaluationLecture;
  • I am not sure how the uuid thing works, but I guess you could persist a value that the user has voted with local storage or a cookie that you check before submitting. If you need more security, you would probably need to check IP address, or if you use user-login save votings to a db that you check before accepting a vote – Lolukok Apr 26 '21 at 12:45

1 Answers1

1

Any time you want something in Firebase to be unique, the best approach is to use that thing as the key. So if you want each user to be able to vote only once, use their UID as the key to store their vote.

votes: {
  "uid1": ":)",
  "uid2": ":|"
}

With a structure like this, it is guaranteed that each user can only cast a single vote.


If each user can only vote once per match, you'll want to store the votes for each match. The simplest way to do this is to add a level for the match above the JSON we just created:

votes: {
  "match1": {
    "uid1": ":)",
    "uid2": ":|"
  },
  "match2": {
    "uid1": ":(",
    "uid2": ":("
  },
}

This works great if you only ever want to access the votes for each match individually, which is the majority of the cases I have.


If you also may want to query across all matches, you will need to store all votes as a flat list. In that case, you can combine the match ID and the UID to create the keys:

votes: {
  "match1_uid1": { match: "match1", uid: "uid1", vote: ":)" },
  "match1_uid2": { match: "match1", uid: "uid2", vote: ":|" },
  "match2_uid1": { match: "match2", uid: "uid1", vote: ":(" },
  "match2_uid2": { match: "match2", uid: "uid2", vote: ":(" }
}

This structure still ensures that each user can only vote once per match. But now you can for example query across all votes to find matches "uid1" has votes on, or all ":)" votes.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807