feat: even more site functionality

This commit is contained in:
2018-08-31 13:37:53 -07:00
parent fc158da8a1
commit 63d02aa3a7
2 changed files with 240 additions and 118 deletions

View File

@@ -1,14 +1,61 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">
<title>Strain Search</title> <title>Strain Search</title>
</head> <style>
.tag:not(body).is-indica {
background-color: hsl(217, 71%, 53%);
color: #fff;
}
<body> .tag:not(body).is-sativa {
background-color: hsl(348, 100%, 61%);
color: #fff;
}
.tag:not(body).is-hybrid {
background-color: hsl(271, 100%, 71%);
color: #fff;
}
#strain-list .cards {
display: flex;
flex-wrap: wrap;
}
#strain-list .cards .card {
width: 100%;
margin: 12px;
}
@media screen and (min-width: 769px) {
#strain-list .cards .card {
width: 45%;
}
}
@media screen and (min-width: 1280px) {
#strain-list .cards .card {
width: 30%;
}
}
#search-form .filters .select {
display: block;
}
#search-form .filters .select select[multiple] {
width: 100%;
}
</style>
</head>
<body>
<noscript><h1>You're going to want to enable JavaScript</h1></noscript> <noscript><h1>You're going to want to enable JavaScript</h1></noscript>
<section class="section"> <section class="section">
@@ -27,29 +74,25 @@
</div> </div>
<!-- Multi-Selects --> <!-- Multi-Selects -->
<div class="columns"> <div class="columns filters">
<div class="column"> <div class="column is-half">
<div class="columns is-mobile"> <div class="columns is-mobile">
<div class="column"> <div class="column is-half">
<div class="field"> <div class="field">
<label class="label">Desired Effects</label> <label class="label">Desired Effects</label>
<div class="select is-multiple"> <div class="select is-multiple">
<select ref="effects" multiple size="6"> <select ref="effects" multiple size="6">
<option value="Happy">Happy</option> <option v-for="effect in effects" :value="effect">{{effect | capitalize}}</option>
<option value="Euphoric">Euphoric</option>
<option value="Sleepy">Sleepy</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="column"> <div class="column is-half">
<div class="field"> <div class="field">
<label class="label">Medical Use</label> <label class="label">Medical Use</label>
<div class="select is-multiple"> <div class="select is-multiple">
<select ref="uses" multiple size="6"> <select ref="uses" multiple size="6">
<option value="Pain">Pain</option> <option v-for="use in uses" :value="use">{{use | capitalize}}</option>
<option value="Depression">Depression</option>
<option value="Insomnia">Insomnia</option>
</select> </select>
</div> </div>
</div> </div>
@@ -57,26 +100,25 @@
</div> </div>
</div> </div>
<div class="column"> <div class="column is-half">
<div class="columns is-mobile"> <div class="columns is-mobile">
<div class="column"> <div class="column is-half">
<div class="field"> <div class="field">
<label class="label">Condition</label> <label class="label">Condition</label>
<div class="select is-multiple"> <div class="select is-multiple">
<select ref="conditions" multiple size="6"> <select ref="conditions" multiple size="6">
<option value="PTSD">PTSD</option> <option v-for="condition in conditions" :value="condition">{{condition | capitalize}}</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="column"> <div class="column is-half">
<div class="field"> <div class="field">
<label class="label">Flavor</label> <label class="label">Flavor</label>
<div class="select is-multiple"> <div class="select is-multiple">
<select ref="flavors" multiple size="6"> <select ref="flavors" multiple size="6">
<option value="Sweet">Sweet</option> <option v-for="flavor in flavors" :value="flavor">{{flavor | capitalize}}</option>
<option value="Woody">Woody</option>
</select> </select>
</div> </div>
</div> </div>
@@ -98,8 +140,26 @@
</form> </form>
</section> </section>
<section class="section"> <section class="section" id="strain-list">
<div class="container" id="strain"></div> <div v-if="strains.length === 0" class="container">
<p>NO MATCHING STRAINS :(</p>
</div>
<div v-if="strains.length > 0" class="container cards">
<div v-for="strain in strains" class="card">
<header class="card-header">
<p class="card-header-title">{{strain.name | capitalize}}</p>
<div class="tags" style="margin: 0 12px;">
<span class="tag is-rounded is-light">{{strain.rating | round}} ({{strain.rating_count}})</span>
</div>
</header>
<div class="card-content">
<span v-if="strain.category === 'indica'" class="tag is-rounded is-indica">{{strain.category}}</span>
<span v-if="strain.category === 'sativa'" class="tag is-rounded is-sativa">{{strain.category}}</span>
<span v-if="strain.category === 'hybrid'" class="tag is-rounded is-hybrid">{{strain.category}}</span>
</div>
</div>
</div>
</section> </section>
<script src="https://unpkg.com/lunr@2.3.1/lunr.js"></script> <script src="https://unpkg.com/lunr@2.3.1/lunr.js"></script>
@@ -112,17 +172,31 @@
const data = <%- data %>; const data = <%- data %>;
const emitter = mitt(); const emitter = mitt();
// debugging...
const target = document.querySelector('#strain').textContent = data.strains[20].name;
// helpers // helpers
const getMultiValues = node => Array.from(node.selectedOptions).map(o => o.value); const getMultiValues = node => Array.from(node.selectedOptions).map(o => o.value);
// vue helpers
Vue.filter('capitalize', value => {
if (!value) return '';
const v = value.toString();
return v.charAt(0).toUpperCase() + v.slice(1);
});
Vue.filter('round', (value, digits = 2) => {
const v = parseFloat(value, 10);
return Math.round(v * (10 * digits)) / (10 * digits);
});
// form handler // form handler
new Vue({ new Vue({
el: '#search-form', el: '#search-form',
data() { data() {
return {}; return {
effects: data.effects,
uses: data.uses,
conditions: data.conditions,
flavors: data.flavors,
};
}, },
methods: { methods: {
handleSubmit() { handleSubmit() {
@@ -133,14 +207,58 @@
conditions: getMultiValues(this.$refs.conditions), conditions: getMultiValues(this.$refs.conditions),
flavors: getMultiValues(this.$refs.flavors), flavors: getMultiValues(this.$refs.flavors),
} }
console.log(requirements) emitter.emit('search', requirements)
}, },
resetForm() { resetForm() {
this.$el.reset(); this.$el.reset();
} }
},
});
new Vue({
el: '#strain-list',
data() {
return {
all_strains: data.strains,
strains: [],
requirements: {
name: '',
effects: [],
uses: [],
conditions: [],
flavors: [],
},
};
},
created() {
emitter.on('search', this.setRequirements);
this.updateStrains();
},
beforeDestroy() {
emitter.off('search', this.setRequirements);
},
methods: {
setRequirements(reqs) {
// this.requirements = reqs;
reqs => console.log('search params', reqs);
},
updateStrains(limit = 20) {
const hasName = this.requirements.name.length > 0;
const hasFilters =
this.requirements.effects.length > 0 ||
this.requirements.uses.length > 0 ||
this.requirements.conditions.length > 0 ||
this.requirements.flavors.length > 0;
if (!hasName && !hasFilters) {
this.strains = this.all_strains.slice(0, limit);
} }
}) }
},
});
})(this); })(this);
</script> </script>
</body> </body>
</html> </html>

View File

@@ -9,7 +9,7 @@ function getData() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.readFile('../scraper/db.json', (err, str) => { fs.readFile('../scraper/db.json', (err, str) => {
if (err) reject(err); if (err) reject(err);
else resolve(str); else resolve(JSON.parse(str));
}); });
}); });
} }
@@ -17,9 +17,13 @@ function getData() {
async function build() { async function build() {
const data = await getData(); const data = await getData();
const options = {}; const options = {};
data.strains = data.strains.sort((n, strain) => {
if (strain.rating === n.rating) return 0;
return strain.rating < n.rating ? -1 : 1;
});
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
ejs.renderFile(srcFile, { data }, options, (err, str) => { ejs.renderFile(srcFile, { data: JSON.stringify(data) }, options, (err, str) => {
if (err) reject(err); if (err) reject(err);
else { else {
fs.writeFile(destFile, str, er => { fs.writeFile(destFile, str, er => {