Hides elements so we always show filled filled rows. The wine compoennt does not load images before they are in the viewport, so it should not decrease performance.
		
			
				
	
	
		
			201 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						|
  <div v-if="wines.length > 0" class="wines-main-container">
 | 
						|
    <div class="info-and-link">
 | 
						|
      <h3>
 | 
						|
        Topp viner
 | 
						|
      </h3>
 | 
						|
      <router-link to="viner">
 | 
						|
        <span class="vin-link">Se alle viner </span>
 | 
						|
      </router-link>
 | 
						|
    </div>
 | 
						|
    <div class="wines-container">
 | 
						|
      <Wine v-for="wine in wines" :key="wine" :wine="wine">
 | 
						|
        <template v-slot:top>
 | 
						|
          <div class="flex justify-end">
 | 
						|
            <div class="requested-count cursor-pointer">
 | 
						|
              <span> {{ wine.occurences }} </span>
 | 
						|
              <i class="icon icon--heart" />
 | 
						|
            </div>
 | 
						|
          </div>
 | 
						|
        </template>
 | 
						|
      </Wine>
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import Wine from "@/ui/Wine";
 | 
						|
import { overallWineStatistics } from "@/api";
 | 
						|
 | 
						|
export default {
 | 
						|
  components: {
 | 
						|
    Wine
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      wines: [],
 | 
						|
      clickedWine: null,
 | 
						|
      limit: 18
 | 
						|
    };
 | 
						|
  },
 | 
						|
  async mounted() {
 | 
						|
    this.getAllWines();
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    getAllWines() {
 | 
						|
      return fetch(`/api/wines?limit=${this.limit}`)
 | 
						|
        .then(resp => resp.json())
 | 
						|
        .then(response => {
 | 
						|
          let { wines, success } = response;
 | 
						|
 | 
						|
          this.wines = wines.sort(
 | 
						|
            this.predicate(
 | 
						|
              {
 | 
						|
                name: "occurences",
 | 
						|
                reverse: true
 | 
						|
              },
 | 
						|
              {
 | 
						|
                name: "rating",
 | 
						|
                reverse: true
 | 
						|
              }
 | 
						|
            )
 | 
						|
          );
 | 
						|
        });
 | 
						|
    },
 | 
						|
    predicate: function() {
 | 
						|
      var fields = [],
 | 
						|
        n_fields = arguments.length,
 | 
						|
        field,
 | 
						|
        name,
 | 
						|
        cmp;
 | 
						|
 | 
						|
      var default_cmp = function(a, b) {
 | 
						|
          if (a == undefined) a = 0;
 | 
						|
          if (b == undefined) b = 0;
 | 
						|
          if (a === b) return 0;
 | 
						|
          return a < b ? -1 : 1;
 | 
						|
        },
 | 
						|
        getCmpFunc = function(primer, reverse) {
 | 
						|
          var dfc = default_cmp,
 | 
						|
            // closer in scope
 | 
						|
            cmp = default_cmp;
 | 
						|
          if (primer) {
 | 
						|
            cmp = function(a, b) {
 | 
						|
              return dfc(primer(a), primer(b));
 | 
						|
            };
 | 
						|
          }
 | 
						|
          if (reverse) {
 | 
						|
            return function(a, b) {
 | 
						|
              return -1 * cmp(a, b);
 | 
						|
            };
 | 
						|
          }
 | 
						|
          return cmp;
 | 
						|
        };
 | 
						|
 | 
						|
      // preprocess sorting options
 | 
						|
      for (var i = 0; i < n_fields; i++) {
 | 
						|
        field = arguments[i];
 | 
						|
        if (typeof field === "string") {
 | 
						|
          name = field;
 | 
						|
          cmp = default_cmp;
 | 
						|
        } else {
 | 
						|
          name = field.name;
 | 
						|
          cmp = getCmpFunc(field.primer, field.reverse);
 | 
						|
        }
 | 
						|
        fields.push({
 | 
						|
          name: name,
 | 
						|
          cmp: cmp
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      // final comparison function
 | 
						|
      return function(A, B) {
 | 
						|
        var name, result;
 | 
						|
        for (var i = 0; i < n_fields; i++) {
 | 
						|
          result = 0;
 | 
						|
          field = fields[i];
 | 
						|
          name = field.name;
 | 
						|
 | 
						|
          result = field.cmp(A[name], B[name]);
 | 
						|
          if (result !== 0) break;
 | 
						|
        }
 | 
						|
        return result;
 | 
						|
      };
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
</script>
 | 
						|
 | 
						|
<style lang="scss" scoped>
 | 
						|
@import "@/styles/variables.scss";
 | 
						|
@import "@/styles/global.scss";
 | 
						|
@import "@/styles/media-queries.scss";
 | 
						|
 | 
						|
.wines-main-container {
 | 
						|
  margin-bottom: 10em;
 | 
						|
}
 | 
						|
 | 
						|
.info-and-link {
 | 
						|
  display: flex;
 | 
						|
  justify-content: space-between;
 | 
						|
}
 | 
						|
 | 
						|
.requested-count {
 | 
						|
  display: flex;
 | 
						|
  align-items: center;
 | 
						|
  margin-top: -0.5rem;
 | 
						|
  background-color: rgb(244, 244, 244);
 | 
						|
  border-radius: 1.1rem;
 | 
						|
  padding: 0.25rem 1rem;
 | 
						|
  font-size: 1.25em;
 | 
						|
 | 
						|
  span {
 | 
						|
    padding-right: 0.5rem;
 | 
						|
    line-height: 1.25em;
 | 
						|
  }
 | 
						|
  .icon--heart {
 | 
						|
    font-size: 1.5rem;
 | 
						|
    color: var(--link-color);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Call for help
 | 
						|
.wines-container {
 | 
						|
  @media (max-width: 1643px) {
 | 
						|
    *:nth-child(n + 7) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @media (max-width: 2066px) {
 | 
						|
    *:nth-child(n + 9) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @media (max-width: 2490px) {
 | 
						|
    *:nth-child(n + 11) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @media (max-width: 2915px) {
 | 
						|
    *:nth-child(n + 13) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @media (max-width: 3335px) {
 | 
						|
    *:nth-child(n + 15) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @media (max-width: 3758px) {
 | 
						|
    *:nth-child(n + 17) {
 | 
						|
      display: none;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
</style>
 |