<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Bike Finder</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <div id="app">
        <product></product>
    </div>
</body>

</html>
.question-section {
    margin-bottom: 2rem;
}

.container__question {
    margin-bottom: 2rem;
}

input[type="checkbox"].favourite-brand {
    display: none;
}

input[type="checkbox"].favourite-brand#apollo+label {
    background-image: url('images/brands/brand_apollo.png')
}

input[type="checkbox"].favourite-brand#assist+label {
    background-image: url('images/brands/brand_assist.png')
}

input[type="checkbox"].favourite-brand#boardman+label {
    background-image: url('images/brands/brand_boardman.png')
}

input[type="checkbox"].favourite-brand#carrera+label {
    background-image: url('images/brands/brand_carrera.png')
}

input[type="checkbox"].favourite-brand#voodoo+label {
    background-image: url('images/brands/brand_voodoo.png')
}

label.favourite-brand {
    display: inline-block;
    margin-right: 1rem;
    width: 200px;
    height: 200px;
    cursor: pointer;
    background-color: #66a1bf;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: 100%;
    transition: background-size 0.1s linear;
}

input.favourite-brand:checked+label {
    background-size: 90%;
    background-color: #244f66;
}

.container__answer--colours{
    display: flex;
}

input[type="checkbox"].colour {
    display: none;
}

label.colour {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    margin-right: 1rem;
    width: 50px;
    height: 50px;
    cursor: pointer;
    border: 1px solid black;
    border-radius: 50%;
    opacity: 1;
}

input#multicoloured+label{
    background: rgb(255,0,0);
    background: -moz-linear-gradient(180deg, rgba(255,0,0,1) 0%, rgba(255,158,0,1) 10%, rgba(255,248,0,1) 25%, rgba(91,255,0,1) 40%, rgba(0,224,255,1) 55%, rgba(0,22,255,1) 70%, rgba(192,0,255,1) 85%, rgba(255,0,219,1) 100%);
    background: -webkit-linear-gradient(180deg, rgba(255,0,0,1) 0%, rgba(255,158,0,1) 10%, rgba(255,248,0,1) 25%, rgba(91,255,0,1) 40%, rgba(0,224,255,1) 55%, rgba(0,22,255,1) 70%, rgba(192,0,255,1) 85%, rgba(255,0,219,1) 100%);
    background: linear-gradient(180deg, rgba(255,0,0,1) 0%, rgba(255,158,0,1) 10%, rgba(255,248,0,1) 25%, rgba(91,255,0,1) 40%, rgba(0,224,255,1) 55%, rgba(0,22,255,1) 70%, rgba(192,0,255,1) 85%, rgba(255,0,219,1) 100%);
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff0000",endColorstr="#ff00db",GradientType=1);
}

label.colour::before {
    content: " ";
    position: absolute;
    height: 25px;
    transition-duration: 0.4s;
}

input.colour:checked+label.colour::before {
    content: '✓';
    color: #66a1bf;
}

.product-feed{
    display: grid;
    flex-direction: row;
    grid-template-columns: repeat(4, 0.25fr);
    grid-gap: 1rem;
}

.product-feed__item{
    padding: 1rem;
    outline: 1px solid grey;
    border-radius: 10px;
}

.product-feed__item--womens{
    background-color: lightpink;
}

.product-feed__item--mens{
    background-color: lightblue;
}

.product-feed__item--neutral{
    background-color: lightgray;
}

.product-feed__item--kids{
    background-color: lightgreen;
}

.product-feed__item__brand{
    font-weight: 600;
    text-transform: capitalize;
}

.product-feed__item__image{
    width: 100%;
}

.product-feed__item__gender{
    text-transform: capitalize;
}
Vue.component('product', {
    props: {

    },
    template: `
    <div class="container">
        <h2>About You</h2>
        <div class="question-section question-section--aboutyou">
            <div class="container__question">
                <strong>Preferred bike gender?</strong>
                <div>
                    <template v-for="gender in filteredGenders">
                        <input type="radio" :id="gender" name="gender" :key="gender"><label :for="gender">{{gender}}</label>
                    </template>
                </div>
            </div>
            <div class="container__question">
                <strong>What terrain do you normally ride on?</strong>
                <div>
                    <template v-for="terrain in filteredTerrains">
                        <input type="checkbox" :id="terrain" :name="terrain" :key="terrain"><label :for="terrain">{{terrain}}</label>
                    </template>
                </div>
            </div>
        </div>
        <h2>Products:</h2>
        <div v-html="productFeed" class="product-feed"></div>
    </div>
    `,

    data() {
        return {
            "bikes": [
                {
                    id: 1,
                    image: "womens_hybrid_apollo_cosmo_blue.jpg",
                    terrain: "gravel",
                    gender: "womens",
                    type: "hybrid",
                    brand: "apollo",
                    name: "cosmo",
                    colour: "blue",
                    gears: 18,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 205,
                    priceEuros: null
                },
                {
                    id: 2,
                    image: "mens_hybrid_boardman_hyb89_blue.jpg",
                    terrain: "road",
                    gender: "mens",
                    type: "hybrid",
                    brand: "boardman",
                    name: "hyb89",
                    colour: "blue",
                    gears: 20,
                    suspension: "hard tail",
                    brakeType: "hydraulic disc brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: 2,
                    pricePounds: 750,
                    priceEuros: null
                },
                {
                    id: 3,
                    image: "mens_hybrid_carrera_code_orange.jpg",
                    terrain: "gravel",
                    gender: "mens",
                    type: "hybrid",
                    brand: "carrera",
                    name: "code",
                    colour: "orange",
                    gears: 16,
                    suspension: "hard tail",
                    brakeType: "mechanical disc brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 350,
                    priceEuros: null
                },
                {
                    id: 4,
                    image: "mens_mountain_apollo_valier_green.jpg",
                    terrain: "mountain",
                    gender: "mens",
                    type: "mountain",
                    brand: "apollo",
                    name: "valier",
                    colour: "green",
                    gears: 21,
                    suspension: "hard tail",
                    brakeType: "mechanical disc brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: 4,
                    pricePounds: 228,
                    priceEuros: null
                },
                {
                    id: 5,
                    image: "neutral_adventure_voodoo_limba_green.jpg",
                    terrain: "mountain",
                    gender: "neutral",
                    type: "adventure",
                    brand: "voodoo",
                    name: "limba",
                    colour: "green",
                    gears: 16,
                    suspension: "none",
                    brakeType: "mechanical disc brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: 2,
                    pricePounds: 428,
                    priceEuros: null
                },
                {
                    id: 6,
                    image: "neutral_bmx_voodoo_malice_grey.jpg",
                    terrain: "stunt",
                    gender: "neutral",
                    type: "bmx",
                    brand: "voodoo",
                    name: "malice",
                    colour: "black",
                    gears: 0,
                    suspension: "none",
                    brakeType: "u brakes",
                    electricMilesMaxRange: null,
                    inStock: false,
                    stockLeadtimeWeeks: 1,
                    pricePounds: 200,
                    priceEuros: null
                },
                {
                    id: 7,
                    image: "neutral_folding_apollo_tuck_blue.jpg",
                    terrain: "road",
                    gender: "neutral",
                    type: "folding",
                    brand: "apollo",
                    name: "tuck",
                    colour: "blue",
                    gears: 1,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 235,
                    priceEuros: null
                },
                {
                    id: 8,
                    image: "neutral_hybrid_electric_assist_2021_white.jpg",
                    terrain: "gravel",
                    gender: "neutral",
                    type: "electric",
                    brand: "assist",
                    name: "2021",
                    colour: "white",
                    gears: 1,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: 20,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 649,
                    priceEuros: null
                },
                {
                    id: 9,
                    image: "neutral_hybrid_electric_assist_stepthru_silver.jpg",
                    terrain: "gravel",
                    gender: "neutral",
                    type: "electric",
                    brand: "assist",
                    name: "stepthru",
                    colour: "silver",
                    gears: 1,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: 20,
                    inStock: false,
                    stockLeadtimeWeeks: 3,
                    pricePounds: 649,
                    priceEuros: null
                },
                {
                    id: 10,
                    image: "kids_hybrid_apollo_haze_goldwhite.jpg",
                    terrain: "road",
                    gender: "kids",
                    type: "hybrid",
                    brand: "apollo",
                    name: "haze",
                    colour: "gold white",
                    gears: 6,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: 2,
                    pricePounds: 150,
                    priceEuros: null
                },
                {
                    id: 11,
                    image: "kids_hybrid_carrera_saruna_red.jpg",
                    terrain: "road",
                    gender: "kids",
                    type: "hybrid",
                    brand: "carrera",
                    name: "saruna",
                    colour: "red",
                    gears: 7,
                    suspension: "none",
                    brakeType: "v-brakes",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: 2,
                    pricePounds: 260,
                    priceEuros: null
                },
                {
                    id: 12,
                    image: "kids_training_apollo_pawpatrol_blueyellow.jpg",
                    terrain: "road",
                    gender: "kids",
                    type: "training",
                    brand: "apollo",
                    name: "paw patrol",
                    colour: "blue yellow",
                    gears: 0,
                    suspension: "none",
                    brakeType: "caliper",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 130,
                    priceEuros: null
                },
                {
                    id: 13,
                    image: "kids_training_apollo_peppapig_pink.jpg",
                    terrain: "road",
                    gender: "kids",
                    type: "training",
                    brand: "apollo",
                    name: "peppa pig",
                    colour: "pink",
                    gears: 0,
                    suspension: "none",
                    brakeType: "caliper",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 130,
                    priceEuros: null
                },
                {
                    id: 14,
                    image: "kids_training_apollo_batman_black.jpg",
                    terrain: "road",
                    gender: "kids",
                    type: "training",
                    brand: "apollo",
                    name: "batman",
                    colour: "black",
                    gears: 0,
                    suspension: "none",
                    brakeType: "caliper",
                    electricMilesMaxRange: null,
                    inStock: true,
                    stockLeadtimeWeeks: null,
                    pricePounds: 175,
                    priceEuros: null
                }
            ]

        }
    },
    methods: {
        cleanData(dataType, dataToClean) {
            const cleanData = [];
            let multiColouredDuplicate = false;

            // Loop through data to clean based on amount of data
            for (let i = 0; i < dataToClean.length; i++) {

                // Grab data at index
                let filteredData = dataToClean[i];
                let spaceFound;

                // If data is a string, find spaces
                if (typeof filteredData === "string") {
                    spaceFound = filteredData.indexOf(' ') > 0;
                }

                // If dataType is colour, check for duplicate colour names
                if (dataType === "colour") {

                    // If space found but duplicate multicoloured result, skip
                    if (spaceFound && multiColouredDuplicate) {
                        multiColouredDuplicate = false;
                        continue;

                        // If space found and first multicoloured
                    } else if (spaceFound && !multiColouredDuplicate) {
                        filteredData = "multicoloured";
                        multiColouredDuplicate = true;
                    }
                }

                // Return filteredData value
                cleanData.push(filteredData);
            }

            return cleanData;
        },
    },
    computed: {
        filteredGenders() {
            const typeGender = "gender";
            const filteredGenders = Array.from(new Set(this.bikes.map(bike => bike.gender)));

            let formattedGenders = this.cleanData(typeGender, filteredGenders);

console.log(formattedGenders);

            return formattedGenders;
        },
        filteredTerrains() {
            const typeTerrain = "terrain";
            const filteredTerrains = Array.from(new Set(this.bikes.map(bike => bike.terrain)));

            let formattedTerrains = this.cleanData(typeTerrain, filteredTerrains);

            return formattedTerrains;
        },
        productFeed() {
            let productFeed = "";

            for (let i = 0; i < this.bikes.length; i++) {
                let productFeedItem = this.bikes[i];

                productFeed += `
                <div class="product-feed__item product-feed__item--${productFeedItem.gender}">
                    <span class="product-feed__item__brand">${productFeedItem.brand}</span> - <span class="product-feed__item__gender">${productFeedItem.gender}</span>
                </div>`;
                //console.log(`${this.bikes[i].brand}`)
            }

            return productFeed;
        },
    }

})

// Creates new Vue instance with options
var app = new Vue({

    // Property to connect to div with 'app' ID
    el: '#app',
    data: {
        premium: true
    }
})
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.8/vue.min.js