Compare commits

...

17 Commits

6 changed files with 142 additions and 34 deletions

Binary file not shown.

View File

@@ -16,7 +16,6 @@
height: 85%; height: 85%;
width: 100%; width: 100%;
padding: 5%; padding: 5%;
overflow: auto;
} }
#menu { #menu {
@@ -40,4 +39,25 @@
#taskButton { #taskButton {
padding-left: 0; padding-left: 0;
}
#historyContent {
height: 75%;
overflow: scroll;
width: 100%;
}
#stats {
height: 25%;
width: 100%;
}
#tasks {
overflow: scroll;
}
pre {
padding: 0;
background: white;
border-radius: 0;
} }

View File

@@ -29,7 +29,17 @@
<div id="mainPage" style="display: none;"> <div id="mainPage" style="display: none;">
<div id="content"> <div id="content">
<div id="tasks" class="screen flex two demo" style=""></div> <div id="tasks" class="screen flex two demo" style=""></div>
<div id="history" class="screen" style="display: none;"></div> <div id="history" class="screen" style="display: none;">
<div id="stats">
<article class="card">
<header>
<h1>Stats</h1>
<pre id="statData"></pre>
</header>
</article>
</div>
<div id="historyContent"></div>
</div>
<div id="addTask" class="screen" style="display: none;">Add Task</div> <div id="addTask" class="screen" style="display: none;">Add Task</div>
</div> </div>
<div id="menu" class="flex three demo"> <div id="menu" class="flex three demo">

View File

@@ -54,22 +54,43 @@ async function populateScreen() {
let tasks = tasksRaw.tasks; let tasks = tasksRaw.tasks;
// get historical data // get historical data
let historyPage = document.getElementById("history"); let historyPage = document.getElementById("historyContent");
historyPage.innerHTML = ""; historyPage.innerHTML = "";
response = await fetch("/getHistory"); response = await fetch("/getHistory");
let historyRaw = await response.json(); let historyRaw = await response.json();
let history = historyRaw.history; let history = historyRaw.history;
// get points data
let statsPage = document.getElementById("statData");
statsPage.innerText = "";
response = await fetch("/getUserPoints");
let statsRaw = await response.json();
let stats = statsRaw.userPoints;
for (let i = 0; i < tasks.length; i++) { // if it is a user make the tasks add points
taskPage.innerHTML += ` // or if admin make it do nothing
<div id="${tasks[i].tid}" class="half" style="height: fit-content"> if (sessionStorage.getItem("role") === "user") {
<div class="button" onclick="completeTask(${tasks[i].tid})"> for (let i = 0; i < tasks.length; i++) {
<p id="taskName">${tasks[i].name}</p> taskPage.innerHTML += `
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p> <div id="${tasks[i].tid}" class="half" style="height: fit-content">
</div> <div class="button" onclick="completeTask(${tasks[i].tid})">
</div>` <p id="taskName">${tasks[i].name}</p>
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p>
</div>
</div>`
}
} else if (sessionStorage.getItem("role") === "admin") {
for (let i = 0; i < tasks.length; i++) {
taskPage.innerHTML += `
<div id="${tasks[i].tid}" class="half" style="height: fit-content">
<div class="button" disabled data-tooltip="Admins can't get points">
<p id="taskName">${tasks[i].name}</p>
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p>
</div>
</div>`
}
} }
for (let i = (history.length -1); i >= 0; i-=1) { for (let i = (history.length -1); i >= 0; i-=1) {
historyPage.innerHTML += ` historyPage.innerHTML += `
<div class="full"> <div class="full">
@@ -83,13 +104,17 @@ async function populateScreen() {
</article> </article>
</div>` </div>`
} }
for (let i = 0; i < stats.length; i++) {
// put user points in box
statsPage.innerText += `${stats[i].name}: ${stats[i].points} \n`
}
} }
async function completeTask(taskID) { async function completeTask(taskID) {
let points = document.getElementById(`${taskID}-p`).innerText; let points = document.getElementById(`${taskID}-p`).innerText.split(" ")[0];
let time = new Date().toISOString().split(".")[0]; let time = new Date().toISOString().split(".")[0];
let uid = sessionStorage.getItem("uid"); let uid = sessionStorage.getItem("uid");
let response = await fetch("/completeTask", { await fetch("/completeTask", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

BIN
main

Binary file not shown.

95
main.go
View File

@@ -2,6 +2,7 @@ package main
import ( import (
"database/sql" "database/sql"
"flag"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"net/http" "net/http"
@@ -17,11 +18,12 @@ type loginInput struct {
Password string `json:"password"` Password string `json:"password"`
} }
type loginOutput struct { type userData struct {
UID int `json:"uid"` UID int `json:"uid"`
Name string `json:"name"` Name string `json:"name"`
Password string `json:"password"` Password string `json:"password"`
Role string `json:"role"` Role string `json:"role"`
Points int `json:"points"`
} }
type task struct { type task struct {
@@ -34,14 +36,14 @@ type taskArray struct {
Tasks []task `json:"tasks"` Tasks []task `json:"tasks"`
} }
type historyReqData struct { type newHistoryData struct {
UID int `json:"uid"` UID int `json:"uid"`
TID int `json:"tid"` TID int `json:"tid"`
Time string `json:"time"` Time string `json:"time"`
PointsGained int `json:"pointsGained"` PointsGained int `json:"pointsGained"`
} }
type historyResData struct { type historyData struct {
User string `json:"user"` User string `json:"user"`
Task string `json:"task"` Task string `json:"task"`
Time string `json:"time"` Time string `json:"time"`
@@ -49,32 +51,41 @@ type historyResData struct {
} }
type historyArray struct { type historyArray struct {
History []historyResData `json:"history"` History []historyData `json:"history"`
}
type userPointsData struct {
Name string `json:"name"`
Points int `json:"points"`
}
type userPointsArray struct {
UserPoints []userPointsData `json:"userPoints"`
} }
// log the user into their account // log the user into their account
func login(c *gin.Context) { func login(c *gin.Context) {
// get the username and password from the request // get the username and password from the request
var userData loginInput var requestedUser loginInput
if err := c.BindJSON(&userData); err != nil { if err := c.BindJSON(&requestedUser); err != nil {
c.IndentedJSON(http.StatusBadRequest, userData) c.IndentedJSON(http.StatusBadRequest, requestedUser)
return return
} }
// check for user using given credentials // check for user using given credentials
stmt, err := db.Prepare("SELECT * FROM users WHERE name=?") stmt, err := db.Prepare("SELECT * FROM users WHERE name=?")
checkErr(err) checkErr(err)
defer stmt.Close() defer stmt.Close()
var user loginOutput var user userData
err = stmt.QueryRow(userData.Name).Scan(&user.UID, &user.Name, &user.Password, &user.Role) err = stmt.QueryRow(requestedUser.Name).Scan(&user.UID, &user.Name, &user.Password, &user.Role, &user.Points)
if err != nil { if err != nil {
// search failed user not real // search failed user not real
c.IndentedJSON(http.StatusNotFound, userData) c.IndentedJSON(http.StatusNotFound, requestedUser)
panic(err) panic(err)
return return
} }
if user.Password != userData.Password { if user.Password != requestedUser.Password {
// user not real // user not real
c.IndentedJSON(http.StatusNotFound, userData) c.IndentedJSON(http.StatusNotFound, requestedUser)
panic(err) panic(err)
return return
} else { } else {
@@ -107,7 +118,7 @@ func getTasks(c *gin.Context) {
func completeTask(c *gin.Context) { func completeTask(c *gin.Context) {
// get the task data from the request // get the task data from the request
var completedTask historyReqData var completedTask newHistoryData
if err := c.BindJSON(&completedTask); err != nil { if err := c.BindJSON(&completedTask); err != nil {
c.IndentedJSON(http.StatusBadRequest, completedTask) c.IndentedJSON(http.StatusBadRequest, completedTask)
return return
@@ -123,17 +134,30 @@ func completeTask(c *gin.Context) {
c.IndentedJSON(http.StatusNotModified, completedTask) c.IndentedJSON(http.StatusNotModified, completedTask)
return return
} }
// add points to user table
stmt, err = db.Prepare("UPDATE users SET points = points + ? WHERE uid=?")
if err != nil {
c.IndentedJSON(http.StatusNotModified, completedTask)
return
}
_, err = stmt.Exec(completedTask.PointsGained, completedTask.UID)
if err != nil {
c.IndentedJSON(http.StatusNotModified, completedTask)
return
}
c.IndentedJSON(http.StatusOK, completedTask) c.IndentedJSON(http.StatusOK, completedTask)
} }
func getHistory(c *gin.Context) { func getHistory(c *gin.Context) {
// get the log of past points gained // get the log of past points gained
var history []historyReqData var history []newHistoryData
// get array of all historyReqData // get array of all history Data
rows, err := db.Query("SELECT * FROM history") rows, err := db.Query("SELECT * FROM history")
checkErr(err) checkErr(err)
for rows.Next() { for rows.Next() {
var tempHistoryData historyReqData var tempHistoryData newHistoryData
err = rows.Scan(&tempHistoryData.UID, &tempHistoryData.TID, &tempHistoryData.Time, &tempHistoryData.PointsGained) err = rows.Scan(&tempHistoryData.UID, &tempHistoryData.TID, &tempHistoryData.Time, &tempHistoryData.PointsGained)
if err != nil { if err != nil {
c.IndentedJSON(http.StatusNotFound, history) c.IndentedJSON(http.StatusNotFound, history)
@@ -143,15 +167,15 @@ func getHistory(c *gin.Context) {
} }
rows.Close() rows.Close()
var historyRes []historyResData var historyRes []historyData
// make the data human-readable // make the data human-readable
for i := 0; i < len(history); i++ { for i := 0; i < len(history); i++ {
var tempHistory historyResData var tempHistory historyData
// get the username // get the username
var tempUser loginOutput var tempUser userData
stmt, err := db.Prepare("SELECT * FROM users WHERE uid=?") stmt, err := db.Prepare("SELECT * FROM users WHERE uid=?")
checkErr(err) checkErr(err)
err = stmt.QueryRow(history[i].UID).Scan(&tempUser.UID, &tempUser.Name, &tempUser.Password, &tempUser.Role) err = stmt.QueryRow(history[i].UID).Scan(&tempUser.UID, &tempUser.Name, &tempUser.Password, &tempUser.Role, &tempUser.Points)
checkErr(err) checkErr(err)
tempHistory.User = tempUser.Name tempHistory.User = tempUser.Name
stmt.Close() stmt.Close()
@@ -197,7 +221,35 @@ func addTask(c *gin.Context) {
c.IndentedJSON(http.StatusOK, newTask) c.IndentedJSON(http.StatusOK, newTask)
} }
func getUserPoints(c *gin.Context) {
// get the names of all users
var allUsers []userPointsData
rows, err := db.Query("SELECT name, points FROM users WHERE role='user'")
checkErr(err)
// put them in an array of users
for rows.Next() {
var tempUser userPointsData
err = rows.Scan(&tempUser.Name, &tempUser.Points)
if err != nil {
c.IndentedJSON(http.StatusNotFound, allUsers)
return
}
allUsers = append(allUsers, tempUser)
}
rows.Close()
// return to the requester
var jsonUserPoints userPointsArray
jsonUserPoints.UserPoints = allUsers
c.IndentedJSON(http.StatusOK, jsonUserPoints)
}
func main() { func main() {
var port string
flag.StringVar(&port, "port", "localhost:8080", "define the port you want the program to use to serve")
flag.Parse()
//release mode //release mode
//gin.SetMode(gin.ReleaseMode) //gin.SetMode(gin.ReleaseMode)
router := gin.Default() router := gin.Default()
@@ -208,6 +260,7 @@ func main() {
router.POST("/addTask", addTask) router.POST("/addTask", addTask)
router.GET("/getTasks", getTasks) router.GET("/getTasks", getTasks)
router.GET("/getHistory", getHistory) router.GET("/getHistory", getHistory)
router.GET("/getUserPoints", getUserPoints)
// page routes // page routes
router.LoadHTMLGlob("frontend/*") router.LoadHTMLGlob("frontend/*")
@@ -216,7 +269,7 @@ func main() {
}) })
router.Static("/frontend", "./frontend") router.Static("/frontend", "./frontend")
router.Run("localhost:8080") router.Run(port)
} }
func checkErr(err error) { func checkErr(err error) {