mirror of
				https://github.com/KevinMidboe/planetposen.git
				synced 2025-10-29 17:50:32 +00:00 
			
		
		
		
	Fully supports editing product and its variations.
Edit page now handles customizing most properties of a product. This uses new color and size picker.
This commit is contained in:
		| @@ -7,42 +7,117 @@ | ||||
|         <h2>Edit mode</h2> | ||||
|         <div class="edit-product" v-if="product"> | ||||
|           <h4>Product</h4> | ||||
|           <input v-model="product.color" placeholder="color" /> | ||||
|           <div class="row"> | ||||
|             <div class="row-item"> | ||||
|               Name: | ||||
|               <input v-model="product.name" placeholder="name" /> | ||||
|           <input v-model="product.description" placeholder="description" /> | ||||
|           <input v-model="product.image" placeholder="image" /> | ||||
|           <input v-model="product.slug" placeholder="slug (default: empty)" /> | ||||
|             </div> | ||||
|             <div class="row-item"> | ||||
|               Color: | ||||
|               <color-picker @selectedColor="colorSelected" :color="product.color" /> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|         <div v-if="variation"> | ||||
|           <div class="row"> | ||||
|             <div class="row-item"> | ||||
|               Description: | ||||
|               <input v-model="product.description" placeholder="description" /> | ||||
|             </div> | ||||
|             <div class="row-item"> | ||||
|               Image: | ||||
|               <input v-model="product.image" placeholder="image" /> | ||||
|             </div> | ||||
|             <div class="row-item"> | ||||
|               Slug (default empty): | ||||
|               <input v-model="product.urlSlug" placeholder="slug" /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <div v-if="product && product.variations"> | ||||
|           <h4>Variations</h4> | ||||
|           <input v-for="key in Object.keys(variation)" v-model="variation[key]" :placeholder="key" /> | ||||
|  | ||||
|           <div v-for="(variation, index) in product.variations" class="variation"> | ||||
|             <div class="variation-controls"> | ||||
|               <i class="icon icon--arrow-dropup" @click="moveVariation(variation, -1)" | ||||
|                  v-if="index != 0"></i> | ||||
|               <i v-else class="icon"></i> | ||||
|  | ||||
|               <i class="icon icon--close-circle-outline" @click="removeVariation(variation)"></i> | ||||
|  | ||||
|               <i class="icon icon--arrow-dropdown" @click="moveVariation(variation, 1)" | ||||
|                  v-if="index + 1 < product.variations.length"></i> | ||||
|               <i v-else class="icon"></i> | ||||
|             </div> | ||||
|             <div> | ||||
|               <div class="row"> | ||||
|                 <div class="row-item"> | ||||
|                   Stock: | ||||
|                   <input v-model="variation.stock" type="number" placeholder="0" min="0" /> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="row-item"> | ||||
|                   Price (NOK): | ||||
|                   <input v-model="variation.price" type="number" placeholder="0.00" min="0" /> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
|               <div class="row"> | ||||
|                 <div class="row-item"> | ||||
|                   Discounted price (empty if none): | ||||
|                   <input v-model="variation.discount" type="number" placeholder="0.00" min="0" /> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
|               <div class="row"> | ||||
|                 <div class="row-item"> | ||||
|                   Available sizes: | ||||
|                   <size-picker :sizeVariable.sync="variation.size" /> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
|               <hr /> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|          <Button :small="true" color="yellow" @click="addVariation"> | ||||
|             Add variation | ||||
|             <i class="add-variation icon icon--add-circle"></i> | ||||
|           </Button> | ||||
|          </div> | ||||
|  | ||||
|         <Button :small="true" @click="hide = !hide">Preview</Button> | ||||
|         <Button :small="true" color="green">Submit new bag</Button> | ||||
|         <Button :small="true" color="green">Update</Button> | ||||
|       </div> | ||||
|  | ||||
|       <product :product="product" /> | ||||
|       <product v-if="product" :product="product" /> | ||||
|     </main> | ||||
|     <main v-else> | ||||
|       <Button @click="hide = !hide" class="pos-abs" :small="true">Close preview</Button> | ||||
|       <product :product="product" /> | ||||
|       <product :product="product" v-if="product" /> | ||||
|     </main> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import ColorPicker from '@/components/ui/colorPicker'; | ||||
| import SizePicker from '@/components/ui/sizePicker'; | ||||
| import Product from '@/components/ui/product'; | ||||
| import Button from '@/components/ui/Button'; | ||||
|  | ||||
| export default { | ||||
|   components: { Product, Button }, | ||||
|   components: { | ||||
|     ColorPicker, | ||||
|     SizePicker, | ||||
|     Product, | ||||
|     Button | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       hide: false, | ||||
|       product: undefined, | ||||
|       variation: undefined | ||||
|       productTemplate: undefined, | ||||
|       variationTemplate: undefined | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
| @@ -53,10 +128,28 @@ export default { | ||||
|       this.getAndSetProductBySlug(this.$route.params.slug); | ||||
|     } else { | ||||
|       this.getProductSchema() | ||||
|       this.getVariationSchema() | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     colorSelected(color) { | ||||
|       this.product.color = color; | ||||
|     }, | ||||
|     moveVariation(variation, direction) { | ||||
|       let variations = [ ...this.product.variations ]; | ||||
|       const variationIndex = variations.findIndex(el => el == variation); | ||||
|  | ||||
|       variations = variations.filter(el => el != variation); | ||||
|       variations.splice(variationIndex + direction, 0, variation); | ||||
|       this.product.variations = variations; | ||||
|     }, | ||||
|     removeVariation(variation) { | ||||
|       this.product.variations = this.product.variations.filter(el => el != variation); | ||||
|     }, | ||||
|     async addVariation() { | ||||
|       if (this.variationTemplate == undefined) | ||||
|         await this.getVariationSchema(); | ||||
|       this.product.variations.push({ ...this.variationTemplate }) | ||||
|     }, | ||||
|     getProductSchema() { | ||||
|       let url = '/api/product/schema'; | ||||
|       if (window.location.href.includes('localhost')) | ||||
| @@ -64,7 +157,8 @@ export default { | ||||
|  | ||||
|       fetch(url) | ||||
|         .then(resp => resp.json()) | ||||
|         .then(product => this.product = product); | ||||
|         .then(product => this.product = product) | ||||
|         .then(this.getVariationSchema) | ||||
|     }, | ||||
|     getVariationSchema() { | ||||
|       let url = '/api/variation/schema'; | ||||
| @@ -73,7 +167,11 @@ export default { | ||||
|  | ||||
|       fetch(url) | ||||
|         .then(resp => resp.json()) | ||||
|         .then(variation => this.variation = variation); | ||||
|         .then(variation => { | ||||
|           this.variationTemplate = variation; | ||||
|           if (this.product.variations.length == 0) | ||||
|             this.product.variations = [{ ...variation }]; | ||||
|         }) | ||||
|     }, | ||||
|     getAndSetProductBySlug(slug) { | ||||
|       let url = `/api/product/${ slug }`; | ||||
| @@ -105,16 +203,58 @@ h2 { | ||||
|   margin-top: 0.75rem; | ||||
| } | ||||
|  | ||||
|  | ||||
| .row:not(:first-of-type) { | ||||
|   margin-top: 0.5rem; | ||||
| } | ||||
|  | ||||
| .row-item { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   display: inline-flex; | ||||
|  | ||||
|   &:not(:first-of-type) { | ||||
|     margin-left: 0.5rem; | ||||
|   } | ||||
| } | ||||
| .heading { | ||||
| //  display: block; | ||||
| } | ||||
|  | ||||
| input { | ||||
|   border-color: black; | ||||
|   padding: 0.5rem; | ||||
|   font-size: 1rem; | ||||
|  | ||||
|   &[type=number] { | ||||
|     width: 5rem; | ||||
|   } | ||||
| } | ||||
|  | ||||
| button { | ||||
|   margin-top: 0.5rem; | ||||
| }  | ||||
|  | ||||
| .variation { | ||||
|   display: flex; | ||||
| } | ||||
|  | ||||
| .variation-controls { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   justify-content: space-around; | ||||
|   margin-right: 1rem; | ||||
|  | ||||
|   .icon { | ||||
|     font-size: 2em; | ||||
|     cursor: pointer; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .add-variation { | ||||
| //  font-size: 1.5em; | ||||
| } | ||||
|  | ||||
| .edit { | ||||
|   color: var(--color-background); | ||||
|   margin: 2rem auto; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user