<template>
<div id="productEditCard">
<div class="card">
<div class="card-header">
<p class="card-header-title" v-if="old.id">
{{ old.id }}: {{ old.name }}
</p>
</div>
<div class="card-image">
<figure v-if="old.id" class="image is-square">
<img :src="thumbnail" :alt="name" />
</figure>
</div>
<div class="card-content">
<div class="field">
<div class="file has-name is-boxed is-centered is-fullwidth ">
<label class="file-label">
<input
class="file-input"
type="file"
name="image"
accept=".jpg,.jpeg,.JPG,.JPEG"
@change="changePhotoSet"
/>
<span class="file-cta">
<span class="file-label has-text-centered">
<p v-if="old.photo_thumbnail">
Replace Photo
</p>
<p v-else>
Upload Photo
</p>
</span>
</span>
<span v-if="filename" class="file-name">
{{ filename }}
</span>
<span v-else class="file-name">
{{ old.photo_thumbnail }}
</span>
</label>
</div>
</div>
<div class="field">
<input
class="input"
type="text"
placeholder="(product name)"
v-model="name"
/>
</div>
<div class="field">
<input
class="input"
type="text"
placeholder="(product category)"
v-model="category"
/>
</div>
<div class="field has-addons">
<p class="control">
<a class="button is-static">
#
</a>
</p>
<p class="control is-expanded">
<input
class="input"
type="text"
placeholder="inventory (quantity)"
v-model="quantity"
/>
</p>
<div class="control">
<a
class="button is-info is-outlined"
@click="incrementQuantity(-1)"
>
▼
</a>
</div>
<div class="control">
<a class="button is-info is-outlined" @click="incrementQuantity(1)">
▲
</a>
</div>
</div>
<div class="field has-addons">
<p class="control">
<a class="button is-static">
$
</a>
</p>
<p class="control is-expanded">
<input
class="input"
type="text"
placeholder="price"
v-model="price"
/>
</p>
</div>
<div class="field">
<textarea
class="textarea"
type="text"
placeholder="(product description)"
v-model="description"
>
</textarea>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="featured" />
Featured?
</label>
</div>
</div>
<div class="card-footer" v-if="isValidPost || isValidPatch">
<div class="card-footer-item">
<button class="button is-primary is-fullwidth" @click="saveProduct">
Save
</button>
</div>
</div>
</div>
</div>
</template>
<script>
const dollarRe = /^\$?(\d+)\.(\d{2})/gm;
export default {
name: "ProductEditCard",
data: function() {
return {
filename: "",
diff: {}
};
},
props: {
oldid: {
type: Number,
required: true
}
},
created() {
this.diff = {
id: (this.old && this.old.id) || null,
name: null,
description: null,
cents: null,
quantity: (this.old && this.old.quantity) || 0,
category_path: null,
featured:
this.old && typeof this.old.featured === "boolean"
? this.old.featured
: false,
photo_set: null
};
},
computed: {
thumbnail: function() {
return process.env.VUE_APP_IMAGE_ROOT + "/" + this.old.photo_thumbnail;
},
old: function() {
return this.$store.getters.products.find(p => p.id == this.oldid) || {};
},
id: function() {
return this.diff.id || this.old.id;
},
name: {
get: function() {
return this.diff.name || this.old.name;
},
set: function(name) {
this.diff.name = name;
}
},
description: {
get: function() {
return this.diff.description || this.old.description;
},
set: function(description) {
this.diff.description = description;
}
},
category: {
get: function() {
return this.diff.category_path || this.old.category;
},
set: function(category) {
this.diff.category_path = category;
}
},
featured: {
get: function() {
return this.diff.featured;
},
set: function(featured) {
this.diff.featured = featured;
}
},
price: {
get: function() {
const cents = this.diff.cents || this.old.cents || 0;
return (cents / 100).toFixed(2);
},
set: function(price) {
const groups = dollarRe.exec(price);
if (groups && groups[1] && groups[2]) {
this.diff.cents = 100 * groups[1] + 1 * groups[2];
}
}
},
quantity: {
get: function() {
return this.diff.quantity || this.old.quantity || 0;
},
set: function(quantity) {
if (Number.isFinite(quantity)) {
this.diff.quantity = quantity;
}
}
},
isValidPost: function() {
return (
!this.diff.id &&
this.diff.name &&
this.diff.description &&
Number.isFinite(this.diff.cents) &&
Number.isFinite(this.diff.quantity) &&
this.diff.photo_set &&
this.diff.category_path &&
typeof this.featured === "boolean"
);
},
isValidPatch: function() {
return (
this.diff.id &&
(this.diff.photo_set ||
(this.diff.name && this.diff.name != this.old.name) ||
(Number.isFinite(this.diff.cents) &&
this.diff.cents != this.old.cents) ||
(this.diff.category_path &&
this.diff.category_path != this.old.category) ||
(Number.isFinite(this.diff.quantity) &&
this.diff.quantity != this.old.quantity) ||
(this.diff.description &&
this.diff.description != this.old.description) ||
this.diff.featured != this.old.featured)
);
}
},
methods: {
incrementQuantity(by) {
if (this.quantity + by >= 0) {
this.diff.quantity += by;
}
},
saveProduct() {
if (this.id) {
// update existing
this.$store.dispatch("updateProduct", this.diff);
} else {
// new product
this.$store.dispatch("createProduct", this.diff);
}
this.diff.photo_set = null;
},
changePhotoSet(event) {
const file = event.target.files[0];
if (!file) {
return;
}
this.$store.dispatch("createPhotoSet", file).then(r => {
this.filename = file.name;
this.diff.photo_set = r[0].id;
});
}
}
};
</script>