diff --git a/api/message.js b/api/message.js new file mode 100644 index 0000000..d4037de --- /dev/null +++ b/api/message.js @@ -0,0 +1,83 @@ +const request = require("request"); +const path = require("path"); +const config = require(path.join(__dirname + "/../config/defaults/lottery")); + +async function sendMessage(winnerObject) { + winnerObject.timestamp_sent = new Date().getTime(); + winnerObject.timestamp_limit = new Date().getTime() * 600000; + await winnerObject.save(); + + await sendMessageToUser( + winnerObject.phoneNumber, + `Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Her er linken for å velge hva slags vin du vil ha, du har 10 minutter på å velge ut noe før du blir lagt bakerst i køen. /#/winner/${winnerObject.id}` + ); + + return true; +} + +async function sendWonWineMessage(winnerObject, wineObject) { + console.log( + `User ${winnerObject.id} is only one left, chosing wine for him/her.` + ); + winnerObject.timestamp_sent = new Date().getTime(); + winnerObject.timestamp_limit = new Date().getTime(); + await winnerObject.save(); + + await sendMessageToUser( + winnerObject.phoneNumber, + `Gratulerer som heldig vinner av vinlotteriet ${winnerObject.name}! Du har vunnet vinen ${wineObject.name}, og vil få nærmere info om hvordan/hvor du kan hente vinen snarest. Ha en ellers fin helg!` + ); + + return true; +} + +async function sendMessageTooLate(winnerObject) { + await sendMessageToUser( + winnerObject.phoneNumber, + `Hei ${winnerObject.name}, du har dessverre brukt mer enn 10 minutter på å velge premie og blir derfor puttet bakerst i køen. Du vil få en ny SMS når det er din tur igjen.` + ); +} + +async function sendMessageToUser(phoneNumber, message) { + request.post( + { + url: `https://gatewayapi.com/rest/mtsms?token=${config.token}`, + json: true, + body: { + sender: "Vinlottis", + message: message, + recipients: [{ msisdn: `47${phoneNumber}` }] + } + }, + function(err, r, body) { + console.log(err ? err : body); + } + ); +} + +async function sendUpdate(winners) { + let numbers = []; + for (let i = 0; i < winners.length; i++) { + numbers.push({ msisdn: `47${winners[i].phoneNumber}` }); + } + request.post( + { + url: `https://gatewayapi.com/rest/mtsms?token=${config.token}`, + json: true, + body: { + sender: "Vinlottis", + message: + "Gratulerer som vinner av vinlottisen! Du vil snart få en SMS med oppdatering om hvordan gangen går!", + recipients: numbers + } + }, + function(err, r, body) { + console.log(err ? err : body); + } + ); +} + +module.exports.sendUpdate = sendUpdate; +module.exports.sendMessage = sendMessage; +module.exports.sendMessageTooLate = sendMessageTooLate; +module.exports.sendWonWineMessage = sendWonWineMessage; diff --git a/api/person.js b/api/person.js new file mode 100644 index 0000000..bfce82d --- /dev/null +++ b/api/person.js @@ -0,0 +1,35 @@ +const path = require("path"); +const Highscore = require(path.join(__dirname + "/../schemas/Highscore")); + +async function findSavePerson(foundWinner, wonWine) { + let person = await Highscore.findOne({ + name: foundWinner.name + }); + + if (person == undefined) { + let newPerson = new Highscore({ + name: foundWinner.name, + wins: [ + { + color: foundWinner.color, + date: date, + wine: wonWine + } + ] + }); + + await newPerson.save(); + } else { + person.wins.push({ + color: foundWinner.color, + date: date, + wine: wonWine + }); + person.markModified("wins"); + await person.save(); + } + + return person; +} + +module.exports.findSavePerson = findSavePerson; diff --git a/api/redis.js b/api/redis.js index 886bdf1..88c5d13 100644 --- a/api/redis.js +++ b/api/redis.js @@ -1,7 +1,7 @@ let client; try { const redis = require("redis"); - console.log("trying to create"); + console.log("trying to create redis"); client = redis.createClient(); client.on("error", function(err) { client.quit(); diff --git a/api/update.js b/api/update.js index 30a5e10..2aad063 100644 --- a/api/update.js +++ b/api/update.js @@ -11,16 +11,13 @@ const mustBeAuthenticated = require(path.join( __dirname + "/../middleware/mustBeAuthenticated" )); +const _wineFunctions = require(path.join(__dirname + "/../api/wine")); +const _personFunctions = require(path.join(__dirname + "/../api/person")); const Subscription = require(path.join(__dirname + "/../schemas/Subscription")); const Purchase = require(path.join(__dirname + "/../schemas/Purchase")); -const Wine = require(path.join(__dirname + "/../schemas/Wine")); const PreLotteryWine = require(path.join( __dirname + "/../schemas/PreLotteryWine" )); -const VirtualWinner = require(path.join( - __dirname + "/../schemas/VirtualWinner" -)); -const Highscore = require(path.join(__dirname + "/../schemas/Highscore")); router.use((req, res, next) => { next(); @@ -86,53 +83,10 @@ router.route("/log").post(mustBeAuthenticated, async (req, res) => { for (let i = 0; i < winnersBody.length; i++) { let currentWinner = winnersBody[i]; - let wonWine = await Wine.findOne({ name: currentWinner.wine.name }); - if (wonWine == undefined) { - let newWonWine = new Wine({ - name: currentWinner.wine.name, - vivinoLink: currentWinner.wine.vivinoLink, - rating: currentWinner.wine.rating, - occurences: 1, - image: currentWinner.wine.image, - id: currentWinner.wine.id - }); - await newWonWine.save(); - wonWine = newWonWine; - } else { - wonWine.occurences += 1; - wonWine.image = currentWinner.wine.image; - wonWine.id = currentWinner.wine.id; - await wonWine.save(); - } - + let wonWine = await _wineFunctions.findSaveWine(currentWinner); winesThisDate.push(wonWine); - const person = await Highscore.findOne({ - name: currentWinner.name - }); - - if (person == undefined) { - let newPerson = new Highscore({ - name: currentWinner.name, - wins: [ - { - color: currentWinner.color, - date: date, - wine: wonWine - } - ] - }); - - await newPerson.save(); - } else { - person.wins.push({ - color: currentWinner.color, - date: date, - wine: wonWine - }); - person.markModified("wins"); - await person.save(); - } + await _personFunctions.findSavePerson(currentWinner, wonWine); } let purchase = new Purchase({ diff --git a/api/virtualLottery.js b/api/virtualLottery.js index f2d30dc..966be95 100644 --- a/api/virtualLottery.js +++ b/api/virtualLottery.js @@ -1,6 +1,7 @@ const express = require("express"); const path = require("path"); const router = express.Router(); +const crypto = require("crypto"); const mongoose = require("mongoose"); mongoose.connect("mongodb://localhost:27017/vinlottis", { useNewUrlParser: true @@ -9,11 +10,13 @@ let io; const mustBeAuthenticated = require(path.join( __dirname + "/../middleware/mustBeAuthenticated" )); +const config = require(path.join(__dirname + "/../config/defaults/lottery")); const Attendee = require(path.join(__dirname + "/../schemas/Attendee")); const VirtualWinner = require(path.join( __dirname + "/../schemas/VirtualWinner" )); +const Message = require(path.join(__dirname + "/../api/message")); router.use((req, res, next) => { next(); @@ -133,7 +136,9 @@ router.route("/winner").get(mustBeAuthenticated, async (req, res) => { red: winner.red, blue: winner.blue, green: winner.green, - yellow: winner.yellow + yellow: winner.yellow, + id: sha512(winner.phoneNumber, genRandomString(10)), + timestamp_drawn: new Date().getTime() }); await Attendee.update( @@ -145,6 +150,56 @@ router.route("/winner").get(mustBeAuthenticated, async (req, res) => { res.json(winner); }); +const genRandomString = function(length) { + return crypto + .randomBytes(Math.ceil(length / 2)) + .toString("hex") /** convert to hexadecimal format */ + .slice(0, length); /** return required number of characters */ +}; + +const sha512 = function(password, salt) { + var hash = crypto.createHmac("md5", salt); /** Hashing algorithm sha512 */ + hash.update(password); + var value = hash.digest("hex"); + return value; +}; + +router.route("/finish").get(mustBeAuthenticated, async (req, res) => { + if (!config.token) { + res.json(false); + return; + } + let winners = await VirtualWinner.find({ timestamp_sent: undefined }).sort({ + timestamp_drawn: 1 + }); + + if (winners.length == 0) { + res.json(false); + return; + } + + let firstWinner = winners[0]; + messageSent = false; + try { + let messageSent = await Message.sendMessage(firstWinner); + Message.sendUpdate(winners.slice(1)); + if (!messageSent) { + res.json(false); + return; + } + } catch (e) { + res.json(false); + return; + } + + firstWinner.timestamp_sent = new Date().getTime(); + firstWinner.timestamp_limit = new Date().getTime() + 600000; + + await firstWinner.save(); + res.json(true); + return; +}); + router.route("/attendees").get(async (req, res) => { let attendees = await Attendee.find(); let attendeesRedacted = []; diff --git a/api/virtualRegistration.js b/api/virtualRegistration.js new file mode 100644 index 0000000..c6c033c --- /dev/null +++ b/api/virtualRegistration.js @@ -0,0 +1,148 @@ +const express = require("express"); +const path = require("path"); +const router = express.Router(); +const mongoose = require("mongoose"); + +mongoose.connect("mongodb://localhost:27017/vinlottis", { + useNewUrlParser: true +}); + +const _wineFunctions = require(path.join(__dirname + "/../api/wine")); +const _personFunctions = require(path.join(__dirname + "/../api/person")); +const Message = require(path.join(__dirname + "/../api/message")); +const VirtualWinner = require(path.join( + __dirname + "/../schemas/VirtualWinner" +)); +const PreLotteryWine = require(path.join( + __dirname + "/../schemas/PreLotteryWine" +)); + +router.use((req, res, next) => { + next(); +}); + +router.route("/winner/:id").get((req, res) => { + res.redirect(`/#/winner/${req.params.id}`); +}); + +router.route("/:id").get(async (req, res) => { + let id = req.params.id; + let foundWinner = await VirtualWinner.findOne({ id: id }); + + if (!foundWinner) { + res.json({ + existing: false, + turn: false + }); + return; + } + + let allWinners = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); + + if ( + allWinners[0].id != foundWinner.id || + foundWinner.timestamp_limit == undefined || + foundWinner.timestamp_sent == undefined + ) { + res.json({ existing: true, turn: false }); + return; + } + + res.json({ + existing: true, + turn: true, + name: foundWinner.name, + color: foundWinner.color + }); + return; +}); + +router.route("/:id").post(async (req, res) => { + let id = req.params.id; + let wineName = req.body.wineName; + let foundWinner = await VirtualWinner.findOne({ id: id }); + + if (!foundWinner) { + res.json(false); + return; + } + + if (foundWinner.timestamp_limit < new Date().getTime()) { + res.json({ + success: false, + limit: true + }); + return; + } + let date = new Date(); + date.setHours(5, 0, 0, 0); + + let prelotteryWine = await PreLotteryWine.findOne({ name: wineName }); + + if (!prelotteryWine) { + res.json({ + success: false, + wine: true + }); + } + + let wonWine = await _wineFunctions.findSaveWine(prelotteryWine); + await prelotteryWine.delete(); + await _personFunctions.findSavePerson(foundWinner, wonWine); + + await foundWinner.delete(); + + let nextWineBottle = await PreLotteryWine.find(); + let nextWinner = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); + if (nextWinner.length > 1 && nextWineBottle.length > 1) { + Message.sendMessage(nextWinner[0]); + startTimeout(id); + } else if (nextWinner.length == 1 && nextWineBottle.length == 1) { + chooseForUser(nextWinner[0], nextWineBottle[0]); + } + + res.json({ + success: true + }); + return; +}); + +async function chooseForUser(winner, prelotteryWine) { + let date = new Date(); + date.setHours(5, 0, 0, 0); + let wonWine = await _wineFunctions.findSaveWine(prelotteryWine); + await _personFunctions.findSavePerson(winner, wonWine); + + await prelotteryWine.delete(); + Message.sendWonWineMessage(winner, prelotteryWine); +} + +function startTimeout(id) { + console.log(`Starting timeout for user ${id}.`); + setTimeout(async () => { + let virtualWinner = await VirtualWinner.findOne({ id: id }); + if (!virtualWinner) { + console.log( + `Timeout done for user ${id}, but user has already sent data.` + ); + return; + } + console.log(`Timeout done for user ${id}, sending update to user.`); + + Message.sendMessageTooLate(virtualWinner); + + virtualWinner.timestamp_drawn = new Date().getTime(); + virtualWinner.timestamp_limit = null; + virtualWinner.timestamp_sent = null; + + await virtualWinner.save(); + + let prelotteryWine = await PreLotteryWine.find(); + let nextWinner = await VirtualWinner.find().sort({ timestamp_drawn: 1 }); + if (nextWinner.length == 1 && prelotteryWine.length == 1) { + chooseForUser(nextWinner[0], prelotteryWine[0]); + } + }, 600000); +} + +module.exports = router; diff --git a/api/wine.js b/api/wine.js new file mode 100644 index 0000000..e844867 --- /dev/null +++ b/api/wine.js @@ -0,0 +1,27 @@ +const path = require("path"); +const Wine = require(path.join(__dirname + "/../schemas/Wine")); + +async function findSaveWine(prelotteryWine) { + let wonWine = await Wine.findOne({ name: prelotteryWine.name }); + if (wonWine == undefined) { + let newWonWine = new Wine({ + name: prelotteryWine.name, + vivinoLink: prelotteryWine.vivinoLink, + rating: prelotteryWine.rating, + occurences: 1, + image: prelotteryWine.image, + id: prelotteryWine.id + }); + await newWonWine.save(); + wonWine = newWonWine; + } else { + wonWine.occurences += 1; + wonWine.image = prelotteryWine.image; + wonWine.id = prelotteryWine.id; + await wonWine.save(); + } + + return wonWine; +} + +module.exports.findSaveWine = findSaveWine; diff --git a/config/defaults/lottery.js b/config/defaults/lottery.js index b2ea380..f0a53f7 100644 --- a/config/defaults/lottery.js +++ b/config/defaults/lottery.js @@ -11,6 +11,7 @@ try { message: "INSERT MESSAGE", date: 5, hours: 15, - apiUrl: "https://lottis.vin" + apiUrl: "https://lottis.vin", + token: undefined }; } diff --git a/config/env/lottery.config.example.js b/config/env/lottery.config.example.js index cde3d8c..0243d7c 100644 --- a/config/env/lottery.config.example.js +++ b/config/env/lottery.config.example.js @@ -5,5 +5,6 @@ module.exports = { message: "VINLOTTERI", date: 5, hours: 15, - apiUrl: undefined + apiUrl: undefined, + token: undefined }; diff --git a/package-lock.json b/package-lock.json index e381712..5fad270 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9302,9 +9302,9 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "public-encrypt": { "version": "4.0.3", @@ -9356,7 +9356,8 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true }, "q": { "version": "1.5.1", @@ -9821,9 +9822,9 @@ } }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -9832,7 +9833,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -9842,7 +9843,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, @@ -11394,12 +11395,19 @@ "dev": true }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } } }, "trim-newlines": { diff --git a/package.json b/package.json index 81d6102..829b5cc 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "passport-local-mongoose": "^6.0.1", "qrcode": "^1.4.4", "referrer-policy": "^1.2.0", + "request": "^2.88.2", "socket.io": "^2.3.0", "socket.io-client": "^2.3.0", "vue": "~2.6", diff --git a/schemas/VirtualWinner.js b/schemas/VirtualWinner.js index a5d4a37..94f69d1 100644 --- a/schemas/VirtualWinner.js +++ b/schemas/VirtualWinner.js @@ -8,7 +8,11 @@ const VirtualWinner = new Schema({ green: Number, blue: Number, red: Number, - yellow: Number + yellow: Number, + id: String, + timestamp_drawn: Number, + timestamp_sent: Number, + timestamp_limit: Number }); module.exports = mongoose.model("VirtualWinner", VirtualWinner); diff --git a/server.js b/server.js index a1648df..ccbf4c5 100644 --- a/server.js +++ b/server.js @@ -12,6 +12,9 @@ const subscriptionApi = require(path.join(__dirname + "/api/subscriptions")); const loginApi = require(path.join(__dirname + "/api/login")); const wineinfoApi = require(path.join(__dirname + "/api/wineinfo")); const virtualApi = require(path.join(__dirname + "/api/virtualLottery")); +const virtualRegistrationApi = require(path.join( + __dirname + "/api/virtualRegistration" +)); //This is required for the chat to work const chat = require(path.join(__dirname + "/api/chat"))(io); @@ -92,6 +95,7 @@ app.use("/api/", retrieveApi); app.use("/api/", wineinfoApi); app.use("/api/", chatHistory); app.use("/api/virtual/", virtualApi(io)); +app.use("/api/virtual-registration/", virtualRegistrationApi); app.use("/subscription", subscriptionApi); app.get("/dagens", function(req, res) { diff --git a/src/api.js b/src/api.js index 0b02ef0..aa859fd 100644 --- a/src/api.js +++ b/src/api.js @@ -1,58 +1,49 @@ const BASE_URL = __APIURL__ || window.location.origin; const statistics = () => { - const url = new URL('/api/purchase/statistics', BASE_URL) + const url = new URL("/api/purchase/statistics", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; const colorStatistics = () => { - const url = new URL("/api/purchase/statistics/color", BASE_URL) + const url = new URL("/api/purchase/statistics/color", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; const highscoreStatistics = () => { - const url = new URL("/api/highscore/statistics", BASE_URL) + const url = new URL("/api/highscore/statistics", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; const overallWineStatistics = () => { - const url = new URL("/api/wines/statistics/overall", BASE_URL) - - return fetch(url.href) - .then(resp => resp.json()) -} + const url = new URL("/api/wines/statistics/overall", BASE_URL); + return fetch(url.href).then(resp => resp.json()); +}; const chartWinsByColor = () => { - const url = new URL("/api/purchase/statistics/color", BASE_URL) + const url = new URL("/api/purchase/statistics/color", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; const chartPurchaseByColor = () => { - const url = new URL("/api/purchase/statistics", BASE_URL) - - return fetch(url.href) - .then(resp => resp.json()) -} + const url = new URL("/api/purchase/statistics", BASE_URL); + return fetch(url.href).then(resp => resp.json()); +}; const prelottery = () => { - const url = new URL("/api/wines/prelottery", BASE_URL) + const url = new URL("/api/wines/prelottery", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; -const log = (sendObject) => { - const url = new URL("/api/log", BASE_URL) +const log = sendObject => { + const url = new URL("/api/log", BASE_URL); const options = { headers: { @@ -60,11 +51,10 @@ const log = (sendObject) => { }, method: "POST", body: JSON.stringify(sendObject) - } + }; - return fetch(url.href, options) - .then(resp => resp.json()) -} + return fetch(url.href, options).then(resp => resp.json()); +}; const addAttendee = sendObject => { const url = new URL("/api/virtual/attendee", BASE_URL); @@ -115,7 +105,7 @@ const deleteWinners = () => { }; return fetch(url.href, options).then(resp => resp.json()); -} +}; const deleteAttendees = () => { const url = new URL("/api/virtual/attendees", BASE_URL); @@ -134,10 +124,10 @@ const attendees = () => { const url = new URL("/api/virtual/attendees", BASE_URL); return fetch(url.href).then(resp => resp.json()); -} +}; -const logWines = (wines) => { - const url = new URL("/api/log/wines", BASE_URL) +const logWines = wines => { + const url = new URL("/api/log/wines", BASE_URL); const options = { headers: { @@ -145,95 +135,115 @@ const logWines = (wines) => { }, method: "POST", body: JSON.stringify(wines) - } + }; - return fetch(url.href, options) - .then(resp => resp.json()) -} + return fetch(url.href, options).then(resp => resp.json()); +}; const wineSchema = () => { - const url = new URL("/api/log/schema", BASE_URL) + const url = new URL("/api/log/schema", BASE_URL); - return fetch(url.href) - .then(resp => resp.json()) -} + return fetch(url.href).then(resp => resp.json()); +}; -const barcodeToVinmonopolet = (id) => { - const url = new URL("/api/wineinfo/" + id, BASE_URL) +const barcodeToVinmonopolet = id => { + const url = new URL("/api/wineinfo/" + id, BASE_URL); - return fetch(url.href) - .then(async (resp) => { - if (!resp.ok) { - if (resp.status == 404) { - throw await resp.json() - } - } else { - return resp.json() + return fetch(url.href).then(async resp => { + if (!resp.ok) { + if (resp.status == 404) { + throw await resp.json(); } - }) -} + } else { + return resp.json(); + } + }); +}; -const handleErrors = async (resp) => { +const handleErrors = async resp => { if ([400, 409].includes(resp.status)) { - throw await resp.json() + throw await resp.json(); } else { - console.error("Unexpected error occured when login/register user:", resp) - throw await resp.json() + console.error("Unexpected error occured when login/register user:", resp); + throw await resp.json(); } -} +}; const login = (username, password) => { - const url = new URL("/login", BASE_URL) + const url = new URL("/login", BASE_URL); const options = { headers: { "Content-Type": "application/json" }, method: "POST", body: JSON.stringify({ username, password }) - } + }; - return fetch(url.href, options) - .then(resp => { - if (resp.ok) { - return resp.json() - } else { - return handleErrors(resp) - } - }) -} + return fetch(url.href, options).then(resp => { + if (resp.ok) { + return resp.json(); + } else { + return handleErrors(resp); + } + }); +}; const register = (username, password) => { - const url = new URL("/register", BASE_URL) + const url = new URL("/register", BASE_URL); const options = { headers: { "Content-Type": "application/json" }, method: "POST", body: JSON.stringify({ username, password }) - } + }; - return fetch(url.href, options) - .then(resp => { - if (resp.ok) { - return resp.json() - } else { - return handleErrors(resp) - } - }) -} + return fetch(url.href, options).then(resp => { + if (resp.ok) { + return resp.json(); + } else { + return handleErrors(resp); + } + }); +}; - -const getChatHistory = (skip=null, take=null) => { +const getChatHistory = (skip = null, take = null) => { const url = new URL("/api/chat/history", BASE_URL); - if (!isNaN(skip)) - url.searchParams.append("skip", skip); - if (!isNaN(take)) - url.searchParams.append("take", take); + if (!isNaN(skip)) url.searchParams.append("skip", skip); + if (!isNaN(take)) url.searchParams.append("take", take); - return fetch(url.href) - .then(resp => resp.json()) + return fetch(url.href).then(resp => resp.json()); +}; -} +const finishedDraw = () => { + const url = new URL("/api/virtual/finish", BASE_URL); + + return fetch(url.href).then(resp => resp.json()); +}; + +const getAmIWinner = id => { + const url = new URL(`/api/virtual-registration/${id}`, BASE_URL); + return fetch(url.href).then(resp => resp.json()); +}; + +const postWineChosen = (id, wineName) => { + const url = new URL(`/api/virtual-registration/${id}`, BASE_URL); + const options = { + headers: { + "Content-Type": "application/json" + }, + method: "POST", + body: JSON.stringify({ wineName: wineName }) + }; + + return fetch(url.href, options).then(resp => { + if (resp.ok) { + return resp.json(); + } else { + return handleErrors(resp); + } + }); +}; export { statistics, @@ -257,5 +267,8 @@ export { winnersSecure, deleteWinners, deleteAttendees, - getChatHistory + getChatHistory, + finishedDraw, + getAmIWinner, + postWineChosen }; diff --git a/src/components/VirtualLotteryRegistrationPage.vue b/src/components/VirtualLotteryRegistrationPage.vue index 8777f7d..81526dc 100644 --- a/src/components/VirtualLotteryRegistrationPage.vue +++ b/src/components/VirtualLotteryRegistrationPage.vue @@ -118,7 +118,8 @@ import { attendees, winnersSecure, deleteWinners, - deleteAttendees + deleteAttendees, + finishedDraw } from "@/api"; import RaffleGenerator from "@/ui/RaffleGenerator"; @@ -165,6 +166,9 @@ export default { this.socket.on("new_attendee", async msg => { this.getAttendees(); }); + + window.finishedDraw = finishedDraw; + console.log("here"); }, methods: { setWithRandomColors(colors) { @@ -209,6 +213,7 @@ export default { this.countdown(); } else { this.drawingWinner = false; + finishedDraw(); } this.getWinners(); this.getAttendees(); diff --git a/src/components/WinnerPage.vue b/src/components/WinnerPage.vue new file mode 100644 index 0000000..988f608 --- /dev/null +++ b/src/components/WinnerPage.vue @@ -0,0 +1,102 @@ + + + + + \ No newline at end of file diff --git a/src/routes/vinlottisRouter.js b/src/routes/vinlottisRouter.js index 616a4e2..6c5f517 100644 --- a/src/routes/vinlottisRouter.js +++ b/src/routes/vinlottisRouter.js @@ -8,7 +8,7 @@ import CreatePage from "@/components/CreatePage"; import AdminPage from "@/components/AdminPage"; -import VirtualLotteryPage from "@/components/VirtualLotteryPage"; +import WinnerPage from "@/components/WinnerPage"; import LotteryPage from "@/components/LotteryPage"; const routes = [ @@ -43,6 +43,10 @@ const routes = [ { path: "/lottery/:tab", component: LotteryPage + }, + { + path: "/winner/:id", + component: WinnerPage } ]; diff --git a/src/ui/Wine.vue b/src/ui/Wine.vue index e85d578..fb472cc 100644 --- a/src/ui/Wine.vue +++ b/src/ui/Wine.vue @@ -1,17 +1,32 @@