Feat/lottery endpoint #18
							
								
								
									
										118
									
								
								api/lottery.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								api/lottery.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
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 mustBeAuthenticated = require(path.join(
 | 
			
		||||
  __dirname + '/../middleware/mustBeAuthenticated'
 | 
			
		||||
));
 | 
			
		||||
const config = require(path.join(__dirname + '/../config/defaults/lottery'));
 | 
			
		||||
 | 
			
		||||
const Highscore = require(path.join(__dirname + '/../schemas/Highscore'));
 | 
			
		||||
const Wine = require(path.join(__dirname + '/../schemas/Wine'));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Utils
 | 
			
		||||
const epochToDateString = date => new Date(parseInt(date)).toDateString();
 | 
			
		||||
 | 
			
		||||
const getHighscoreByDates = highscore => {
 | 
			
		||||
  let groupedLotteries = {}
 | 
			
		||||
 | 
			
		||||
  highscore.forEach(user => {
 | 
			
		||||
    user.wins.map(win => {
 | 
			
		||||
      const epochDate = new Date(win.date).setHours(0,0,0,0);
 | 
			
		||||
      const obj = {
 | 
			
		||||
        name: user.name,
 | 
			
		||||
        color: win.color,
 | 
			
		||||
        wine: win.wine,
 | 
			
		||||
        date: epochDate
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      groupedLotteries[epochDate] ?
 | 
			
		||||
        groupedLotteries[epochDate].push(obj) : groupedLotteries[epochDate] = [obj];
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  return groupedLotteries
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const groupedHighscoreToSortedList = groupedLotteries => {
 | 
			
		||||
  return Object.keys(groupedLotteries).map(key => {
 | 
			
		||||
    const winners = groupedLotteries[key];
 | 
			
		||||
    return {
 | 
			
		||||
      date: parseInt(key),
 | 
			
		||||
      dateString: epochToDateString(key),
 | 
			
		||||
      winners
 | 
			
		||||
    }
 | 
			
		||||
  }).sort((a,b) => parseInt(a.date) > parseInt(b.date) ? 1 : -1) 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const resolveWineReferences = listWithWines => {
 | 
			
		||||
  return Promise.all(listWithWines.map(element =>
 | 
			
		||||
    Wine.findById(element.wine)
 | 
			
		||||
      .then(wine => {
 | 
			
		||||
        element.wine = wine
 | 
			
		||||
        return element
 | 
			
		||||
      })
 | 
			
		||||
  ))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Routes
 | 
			
		||||
router.route('/all').get((req, res) => {
 | 
			
		||||
  return Highscore.find()
 | 
			
		||||
    .then(highscore => getHighscoreByDates(highscore))
 | 
			
		||||
    .then(groupedLotteries => groupedHighscoreToSortedList(groupedLotteries))
 | 
			
		||||
    .then(lotteries => res.send({
 | 
			
		||||
      message: "Lotteries by date!",
 | 
			
		||||
      lotteries
 | 
			
		||||
    }))
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
router.route('/by-date/:date').get((req, res) => {
 | 
			
		||||
  const { date } = req.params;
 | 
			
		||||
  const dateString = epochToDateString(date);
 | 
			
		||||
 | 
			
		||||
  return Highscore.find()
 | 
			
		||||
    .then(highscore => getHighscoreByDates(highscore))
 | 
			
		||||
    .then(async (lotteries) => {
 | 
			
		||||
      const lottery = lotteries[date];
 | 
			
		||||
 | 
			
		||||
      if (lottery != null) {
 | 
			
		||||
        return res.send({
 | 
			
		||||
          message: `Lottery for date: ${dateString}`,
 | 
			
		||||
          lottery: await resolveWineReferences(lottery)
 | 
			
		||||
        })
 | 
			
		||||
      } else {
 | 
			
		||||
        return res.status(404).send({
 | 
			
		||||
          message: `No lottery found for date: ${dateString}`
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
router.route("/by-name").get((req, res) => {
 | 
			
		||||
  const { name } = req.query;
 | 
			
		||||
 | 
			
		||||
  return Highscore.find({ name })
 | 
			
		||||
    .then(async (highscore) => {
 | 
			
		||||
      highscore = highscore[0]
 | 
			
		||||
      if (highscore) {
 | 
			
		||||
        const highscoreWithResolvedWines = await resolveWineReferences(highscore.wins)
 | 
			
		||||
 | 
			
		||||
        return res.send({
 | 
			
		||||
          message: `Lottery winnings by name: ${name}`,
 | 
			
		||||
          highscore: highscoreWithResolvedWines
 | 
			
		||||
         })
 | 
			
		||||
      } else {
 | 
			
		||||
        return res.status(404).send({
 | 
			
		||||
          message: `Name: ${ name } not found in leaderboards.`
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
module.exports = router;
 | 
			
		||||
@@ -15,6 +15,7 @@ const virtualApi = require(path.join(__dirname + "/api/virtualLottery"));
 | 
			
		||||
const virtualRegistrationApi = require(path.join(
 | 
			
		||||
  __dirname + "/api/virtualRegistration"
 | 
			
		||||
));
 | 
			
		||||
const lottery = require(path.join(__dirname + "/api/lottery"));
 | 
			
		||||
 | 
			
		||||
//This is required for the chat to work
 | 
			
		||||
const chat = require(path.join(__dirname + "/api/chat"))(io);
 | 
			
		||||
@@ -94,6 +95,7 @@ app.use("/api/", updateApi);
 | 
			
		||||
app.use("/api/", retrieveApi);
 | 
			
		||||
app.use("/api/", wineinfoApi);
 | 
			
		||||
app.use("/api/", chatHistory);
 | 
			
		||||
app.use("/api/lottery", lottery);
 | 
			
		||||
app.use("/api/virtual/", virtualApi(io));
 | 
			
		||||
app.use("/api/virtual-registration/", virtualRegistrationApi);
 | 
			
		||||
app.use("/subscription", subscriptionApi);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								src/api.js
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/api.js
									
									
									
									
									
								
							@@ -245,6 +245,18 @@ const postWineChosen = (id, wineName) => {
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const historyAll = () => {
 | 
			
		||||
  const url = new URL(`/api/lottery/all`, BASE_URL);
 | 
			
		||||
 | 
			
		||||
  return fetch(url.href).then(resp => {
 | 
			
		||||
    if (resp.ok) {
 | 
			
		||||
      return resp.json();
 | 
			
		||||
    } else {
 | 
			
		||||
      return handleErrors(resp);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  statistics,
 | 
			
		||||
  colorStatistics,
 | 
			
		||||
@@ -270,5 +282,6 @@ export {
 | 
			
		||||
  getChatHistory,
 | 
			
		||||
  finishedDraw,
 | 
			
		||||
  getAmIWinner,
 | 
			
		||||
  postWineChosen
 | 
			
		||||
  postWineChosen,
 | 
			
		||||
  historyAll
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								src/components/HistoryPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/components/HistoryPage.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <h1>Historie fra tidligere lotteri</h1>
 | 
			
		||||
 | 
			
		||||
    <div v-if="lotteries.length" v-for="lottery in lotteries">
 | 
			
		||||
      <Winners :winners="lottery.winners" :title="`Vinnere fra ${lottery.dateString}`" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { historyAll } from '@/api'
 | 
			
		||||
import Winners from '@/ui/Winners'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'History page of prev lotteries',
 | 
			
		||||
  components: { Winners },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      lotteries: [],
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    historyAll()
 | 
			
		||||
      .then(history => this.lotteries = history.lotteries.reverse())
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
h1 {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -10,6 +10,7 @@ import AdminPage from "@/components/AdminPage";
 | 
			
		||||
 | 
			
		||||
import WinnerPage from "@/components/WinnerPage";
 | 
			
		||||
import LotteryPage from "@/components/LotteryPage";
 | 
			
		||||
import HistoryPage from "@/components/HistoryPage";
 | 
			
		||||
 | 
			
		||||
const routes = [
 | 
			
		||||
  {
 | 
			
		||||
@@ -47,6 +48,10 @@ const routes = [
 | 
			
		||||
  {
 | 
			
		||||
    path: "/winner/:id",
 | 
			
		||||
    component: WinnerPage
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: "/history",
 | 
			
		||||
    component: HistoryPage
 | 
			
		||||
  }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <h2 v-if="winners.length > 0">Vinnere</h2>
 | 
			
		||||
    <h2 v-if="winners.length > 0"> {{ title ? title : 'Vinnere' }}</h2>
 | 
			
		||||
    <div class="winners" v-if="winners.length > 0">
 | 
			
		||||
      <div class="winner" v-for="(winner, index) in winners" :key="index">
 | 
			
		||||
        <div :class="winner.color + '-ballot'" class="ballot-element">{{ winner.name }}</div>
 | 
			
		||||
@@ -14,6 +14,10 @@ export default {
 | 
			
		||||
  props: {
 | 
			
		||||
    winners: {
 | 
			
		||||
      type: Array
 | 
			
		||||
    },
 | 
			
		||||
    title: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      required: false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user