273 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						||
  <div class="container">
 | 
						||
    <h1>Vinlottis highscore</h1>
 | 
						||
 | 
						||
    <div class="backdrop">
 | 
						||
      <a @click="navigateBack" @keydown.enter="navigateBack" tabindex="0">
 | 
						||
        ⬅ <span class="vin-link navigate-back">Tilbake til {{ previousRoute.name }}</span>
 | 
						||
      </a>
 | 
						||
 | 
						||
      <section v-if="winner">
 | 
						||
        <h2 class="name">{{ winner.name }}</h2>
 | 
						||
 | 
						||
        <p class="win-count el-spacing">{{ numberOfWins }} vinn</p>
 | 
						||
 | 
						||
        <h4 class="margin-bottom-0">Vinnende farger:</h4>
 | 
						||
        <div class="raffle-container el-spacing">
 | 
						||
          <div class="raffle-element" :class="color + `-raffle`" v-for="[color, occurences] in Object.entries(winningColors)" :key="color">
 | 
						||
            {{ occurences }}
 | 
						||
          </div>
 | 
						||
        </div>
 | 
						||
 | 
						||
        <h4 class="el-spacing">Flasker vunnet:</h4>
 | 
						||
 | 
						||
        <div v-for="win in winner.highscore" :key="win._id">
 | 
						||
          <router-link :to="winDateUrl(win.date)" class="days-ago">
 | 
						||
            {{ humanReadableDate(win.date) }} - {{ daysAgo(win.date) }} dager siden
 | 
						||
          </router-link>
 | 
						||
          
 | 
						||
          <div class="won-wine">
 | 
						||
            <img :src="smallerWineImage(win.wine.image)">
 | 
						||
 | 
						||
            <div class="won-wine-details">
 | 
						||
              <h3>{{ win.wine.name }}</h3>
 | 
						||
              <a :href="win.wine.vivinoLink" class="vin-link no-margin">
 | 
						||
                Les mer på vinmonopolet.no
 | 
						||
              </a>
 | 
						||
            </div>
 | 
						||
 | 
						||
            <div class="raffle-element small" :class="win.color + `-raffle`"></div>
 | 
						||
          </div>
 | 
						||
        </div>
 | 
						||
      </section>
 | 
						||
 | 
						||
      <h2 v-else-if="error" class="error">
 | 
						||
        {{ error }}
 | 
						||
      </h2>
 | 
						||
    </div>
 | 
						||
  </div>
 | 
						||
</template>
 | 
						||
 | 
						||
<script>
 | 
						||
import { getWinnerByName } from "@/api";
 | 
						||
import { humanReadableDate, daysAgo } from "@/utils";
 | 
						||
 | 
						||
export default {
 | 
						||
  data() {
 | 
						||
    return {
 | 
						||
      winner: undefined,
 | 
						||
      error: undefined,
 | 
						||
      previousRoute: {
 | 
						||
        default: true,
 | 
						||
        name: "topplisten",
 | 
						||
        path: "/highscore"
 | 
						||
      }
 | 
						||
    }
 | 
						||
  },
 | 
						||
  beforeRouteEnter(to, from, next) {
 | 
						||
    next(vm => {
 | 
						||
      if (from.name != null)
 | 
						||
        vm.previousRoute = from
 | 
						||
    })
 | 
						||
  },
 | 
						||
  computed: {
 | 
						||
    numberOfWins() {
 | 
						||
      return this.winner.highscore.length
 | 
						||
    }
 | 
						||
  },
 | 
						||
  created() {
 | 
						||
    const nameFromURL = this.$route.params.name;
 | 
						||
    getWinnerByName(nameFromURL)
 | 
						||
      .then(winner => this.setWinner(winner))
 | 
						||
      .catch(err => this.error = `Ingen med navn: "${nameFromURL}" funnet.`)
 | 
						||
  },
 | 
						||
  methods: {
 | 
						||
    setWinner(winner) {
 | 
						||
      this.winner = {
 | 
						||
        name: winner.name,
 | 
						||
        highscore: [],
 | 
						||
        ...winner
 | 
						||
      }
 | 
						||
      this.winningColors = this.findWinningColors()
 | 
						||
    },
 | 
						||
    smallerWineImage(image) {
 | 
						||
      if (image && image.includes(`515x515`))
 | 
						||
        return image.replace(`515x515`, `175x175`)
 | 
						||
      return image
 | 
						||
    },
 | 
						||
    findWinningColors() {
 | 
						||
      const colors = this.winner.highscore.map(win => win.color)
 | 
						||
      const colorOccurences = {}
 | 
						||
      colors.forEach(color => {
 | 
						||
        if (colorOccurences[color] == undefined) {
 | 
						||
          colorOccurences[color] = 1
 | 
						||
        } else {
 | 
						||
          colorOccurences[color] += 1
 | 
						||
        }
 | 
						||
      })
 | 
						||
      return colorOccurences
 | 
						||
    },
 | 
						||
    winDateUrl(date) {
 | 
						||
      const timestamp = new Date(date).getTime();
 | 
						||
      return `/history/${timestamp}`
 | 
						||
    },
 | 
						||
    navigateBack() {
 | 
						||
      if (this.previousRoute.default) {
 | 
						||
        this.$router.push({ path: this.previousRoute.path });
 | 
						||
      } else {
 | 
						||
        this.$router.go(-1);
 | 
						||
      }
 | 
						||
    },
 | 
						||
    humanReadableDate: humanReadableDate,
 | 
						||
    daysAgo: daysAgo
 | 
						||
  }
 | 
						||
}
 | 
						||
</script>
 | 
						||
 | 
						||
<style lang="scss" scoped>
 | 
						||
@import "@/styles/variables";
 | 
						||
@import "@/styles/media-queries";
 | 
						||
 | 
						||
$elementSpacing: 3rem;
 | 
						||
 | 
						||
.el-spacing {
 | 
						||
  margin-bottom: $elementSpacing;
 | 
						||
}
 | 
						||
 | 
						||
.navigate-back {
 | 
						||
  font-weight: normal;
 | 
						||
  font-size: 1.2rem;
 | 
						||
  border-width: 2px;
 | 
						||
  border-color: gray;
 | 
						||
}
 | 
						||
 | 
						||
.container {
 | 
						||
  width: 90vw;  
 | 
						||
  margin: 3rem auto;
 | 
						||
  margin-bottom: 0;
 | 
						||
  padding-bottom: 3rem;
 | 
						||
  max-width: 1200px;
 | 
						||
 | 
						||
  @include desktop {
 | 
						||
    width: 80vw;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
h1 {
 | 
						||
  font-size: 3rem;
 | 
						||
  font-family: "knowit";
 | 
						||
  font-weight: normal;
 | 
						||
}
 | 
						||
 | 
						||
.name {
 | 
						||
  text-transform: capitalize;
 | 
						||
  font-size: 3.5rem;
 | 
						||
  font-family: "knowit";
 | 
						||
  font-weight: normal;
 | 
						||
  margin: 2rem 0 1rem 0;
 | 
						||
}
 | 
						||
 | 
						||
.error {
 | 
						||
  font-size: 2.5rem;
 | 
						||
  font-weight: normal;
 | 
						||
}
 | 
						||
 | 
						||
.win-count {
 | 
						||
  font-size: 1.5rem;
 | 
						||
  margin-top: 0;
 | 
						||
}
 | 
						||
 | 
						||
.raffle-container {
 | 
						||
  display: flex;
 | 
						||
  margin-top: 1rem;
 | 
						||
 | 
						||
  div:not(:last-of-type) {
 | 
						||
    margin-right: 1.5rem;
 | 
						||
  }
 | 
						||
}
 | 
						||
.raffle-element {
 | 
						||
  width: 5rem;
 | 
						||
  height: 4rem;
 | 
						||
  display: flex;
 | 
						||
  justify-content: center;
 | 
						||
  align-items: center;
 | 
						||
  font-size: 1.5rem;
 | 
						||
  margin-top: 0;
 | 
						||
 | 
						||
  &.small {
 | 
						||
    height: 40px;
 | 
						||
    width: 40px;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.days-ago {
 | 
						||
  color: $matte-text-color;
 | 
						||
  border-bottom: 2px solid transparent;
 | 
						||
 | 
						||
  &:hover {
 | 
						||
    border-color: $link-color;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
.won-wine {
 | 
						||
  --spacing: 1rem;
 | 
						||
  background-color: white;
 | 
						||
  margin: var(--spacing) 0 3rem 0;
 | 
						||
  padding: var(--spacing);
 | 
						||
 | 
						||
  position: relative;
 | 
						||
 | 
						||
  @include desktop {
 | 
						||
    flex-direction: row;
 | 
						||
  }
 | 
						||
 | 
						||
  img {
 | 
						||
    margin: 0 3rem;
 | 
						||
    height: 160px;
 | 
						||
  }
 | 
						||
 | 
						||
  &-details {
 | 
						||
    vertical-align: top;
 | 
						||
    display: inline-block;
 | 
						||
 | 
						||
    @include tablet {
 | 
						||
      width: calc(100% - 160px - 80px);
 | 
						||
    }
 | 
						||
    
 | 
						||
    & > * {
 | 
						||
      width: 100%;
 | 
						||
    }
 | 
						||
 | 
						||
    h3 {
 | 
						||
      font-size: 1.5rem;
 | 
						||
      font-weight: normal;
 | 
						||
      color: $matte-text-color;
 | 
						||
    }
 | 
						||
 | 
						||
    a {
 | 
						||
      font-size: 1.2rem;
 | 
						||
      border-width: 2px;
 | 
						||
      font-weight: normal;
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  .raffle-element {
 | 
						||
    position: absolute;
 | 
						||
    top: calc(var(--spacing) * 2);
 | 
						||
    right: calc(var(--spacing) * 2);
 | 
						||
    margin: 0;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
.backdrop {
 | 
						||
  $background: rgb(244,244,244);
 | 
						||
  
 | 
						||
  --padding: 2rem;
 | 
						||
  @include desktop {
 | 
						||
    --padding: 5rem;
 | 
						||
  }
 | 
						||
  background-color: $background;
 | 
						||
  padding: var(--padding);
 | 
						||
}
 | 
						||
</style> |