]> _ Git - pmi.git/commitdiff
Cart and quote functionality. WIP #2769 @6
authorStephen Cameron <stephen@cubedesigners.com>
Wed, 14 Aug 2019 15:50:46 +0000 (17:50 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Wed, 14 Aug 2019 15:50:46 +0000 (17:50 +0200)
app/Http/Controllers/AjaxController.php
public/images/icon-cart.svg
resources/js/app.js
resources/js/components/CartItem.vue
resources/styles/components/cart.styl
resources/views/pages/cart.blade.php
resources/views/pages/product-detail.blade.php
resources/views/partials/cart.blade.php
resources/views/partials/form.blade.php

index ab07625f0d7aa23f7df037bee160ae3c8176d802..e9a2161b69a40e7b80589df1a0129c189898efd6 100644 (file)
@@ -14,10 +14,8 @@ use Illuminate\Support\Facades\Validator;
 
 class AjaxController extends CubistFrontController
 {
-    public function mailform(Request $request)
-    {
-        $response = [];
-
+    // Shared validation logic for dynamic CMS forms
+    protected function _validate_form(Request $request) {
         $data = $request->all();
         /** @var PageData $page */
         $page = Page::find($data['page'])->getPageData();
@@ -46,6 +44,14 @@ class AjaxController extends CubistFrontController
         $validator->validate();
 
         $validatedData = $validator->validated();
+
+        return $validatedData;
+    }
+
+    public function mailform(Request $request)
+    {
+        $validatedData = $this->_validate_form($request);
+
         $contents = [];
         foreach ($labels as $key => $label) {
             if (isset($validatedData[$key])) {
@@ -131,6 +137,17 @@ class AjaxController extends CubistFrontController
         return Product::getCartData();
     }
 
+    public function request_quote(Request $request) {
+
+        // Array of product IDs => quantity
+        $cartData = (array) json_decode($request->input('cart_data'));
+
+        // Validated form fields
+        $validatedData = $this->_validate_form($request);
+
+        // Todo: save this data to db using quotes model, then send a notification e-mail with link to new record in the backend
+    }
+
     // Subscribe to newsletter via MailChimp API
     public function newsletter(Request $request)
     {
index ae494feef293b7a3bd5f1f891e02eedfd995e220..870020995bbef0dbf3560be3023fdda6579ac0f1 100644 (file)
@@ -1,11 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="34.797" height="37.5" viewBox="0 0 34.797 37.5">
-  <g id="Groupe_54" data-name="Groupe 54" transform="translate(-1701.748 -39.25)">
-    <path id="Tracé_40" data-name="Tracé 40" d="M5340.723-877.773v-24.138L5337-904" transform="translate(-3632.018 944)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
-    <path id="Tracé_41" data-name="Tracé 41" d="M5346.927-850h22.294l1.736,2.483" transform="translate(-3635.163 923.517)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
-    <g id="Rectangle_378" data-name="Rectangle 378" transform="translate(1711.999 49)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5">
-      <rect width="21.552" height="22.055" stroke="none"/>
-      <rect x="0.75" y="0.75" width="20.052" height="20.555" fill="none"/>
-    </g>
-    <circle id="Ellipse_16" data-name="Ellipse 16" cx="4.966" cy="4.966" r="4.966" transform="translate(1702.498 66.069)" stroke-width="1.5" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
-  </g>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34.8 37.5"><path d="M6.952 27.75c-.4 0-.8-.3-.8-.8V3.25l-3.3-1.9c-.4-.2-.5-.7-.3-1 .2-.4.7-.5 1-.3l3.7 2.1c.2.1.4.4.4.7v24.1c.1.4-.3.8-.7.8zM34.052 37.55c-.2 0-.5-.1-.6-.3l-1.5-2.2h-21.9c-.4 0-.8-.3-.8-.8s.3-.8.8-.8h22.3c.2 0 .5.1.6.3l1.7 2.5c.2.3.2.8-.2 1-.1.2-.3.3-.4.3z"/><path fill="none" d="M10.251 9.75h21.6v22.1h-21.6z"/><path d="M31.051 31.85h-20c-.4 0-.8-.3-.8-.8v-20.5c0-.5.3-.8.8-.8h20.1c.4 0 .8.3.8.8v20.6c-.1.3-.5.7-.9.7zm-19.3-1.5h18.6v-19.1h-18.6v19.1z"/><path d="M5.752 37.55c-3.2 0-5.7-2.6-5.7-5.7s2.6-5.7 5.7-5.7 5.7 2.6 5.7 5.7-2.6 5.7-5.7 5.7zm0-10c-2.3 0-4.2 1.9-4.2 4.2s1.9 4.2 4.2 4.2 4.2-1.9 4.2-4.2-1.9-4.2-4.2-4.2z"/></svg>
index b9759ab6ba3753de2944699530637bba3d7f42d5..d396607d995a59a3235acbda6876df4600d69e60 100644 (file)
@@ -66,6 +66,10 @@ const app = new Vue({
       cartItemCount() {
         // Todo: See if this should count just number of items or make a sum of all quantities? What is more useful? The sum of quantities can be found using map/reduce functions but this needs to be adapted for the object structure using Object.keys as the source.
         return Object.keys(this.items).length;
+      },
+
+      cartData() {
+          return JSON.stringify(this.items.reduce((obj, item) => Object.assign(obj, { [item.id]: item.quantity }), {}));
       }
     },
 
index 09753f57bfa83bc1f7eb3a2fe2715cc2d31628b4..ed3ec7c2cdd56381346bdb7d2607448859114b6f 100644 (file)
@@ -1,6 +1,6 @@
 <template>
     <div class="cart-item flex mb-1v">
-        <div class="border-gray-100 border-2 bg-center bg-contain bg-no-repeat"
+        <div class="border-gray-100 border-2 bg-center bg-contain bg-no-repeat flex-shrink-0"
              :style="`background-image: url(${item.image}); width: 144px; height: 144px`">
         </div>
         <div class="pl-6 leading-relaxed flex-grow">
index 24b7b0237c85e4e0afc40f1e0b737d9e0645391c..3caaf5215ea9dc9984051e398dcfb118e5696ee3 100644 (file)
@@ -6,12 +6,21 @@
     +below(1200px)
       display: none
 
-  &-icon
+  &-icon-wrapper
     display: inline-block
     width: 34px
     height: 36px
-    background: url(/images/icon-cart.svg) no-repeat center
-    background-size: contain
+    position: relative
+
+  &-icon
+    position: absolute
+    top: 0
+    left: 0
+    width: 100%
+    height: 100%
+
+  &-count
+    display: block
     text-align: center
     line-height: 40px
     font-size: 14px
index 949c494c888008cfd83a9bb9b9d227c96b292843..91cec1903f73d94f28e9fcd58b345d64a8e20b4c 100644 (file)
 
             <div>
                 <div class="bg-grey-100 p-1v">
-                    @form
+                    @form([
+                        'action' => '/ajax/request_quote',
+                        'extra_fields' => '<input type="hidden" name="cart_data" :value="cartData">' // Populated by VueJS
+                    ])
                 </div>
             </div>
 
index 4addb9e6fee25cbc3f356b4cd4d1d1b73a7d46e6..6f1c73f458927d21782420d724f97031a949f506 100644 (file)
@@ -7,7 +7,7 @@
 @section('content')
 
     <content class="pt-1v">
-        <text-block title-class="h1 text-6xl" title-tag="h1" :title="$product->name">
+        <text-block title-tag="h1" :title="$product->name">
             <slot name="preTitle">
                 <div class="text-navy text-bold font-display text-xl -mb-2">Ref: {{ $product->reference }}</div>
             </slot>
@@ -25,7 +25,9 @@
 
             {{-- Product text --}}
             <text-block class="product-detail-text sm:mt-6">
-                @markdown($product->highlights)
+                <div class="mb-6">
+                    @markdown($product->highlights)
+                </div>
 
                 @if($technical_sheet)
                     <p class="mt-4">
index 236a6f31fc286591164892812af632e4c7eb7411..f26cb44e35c841854f560ca3287ad22b981ac96e 100644 (file)
@@ -1,2 +1,5 @@
 <span class="cart-header-title">{{ __('Ma sélection') }}</span>
-<span class="cart-header-icon" v-html="cartItemCount"></span>
+<span class="cart-header-icon-wrapper">
+    @svg('icon-cart', 'cart-header-icon')
+    <span class="cart-header-count" v-html="cartItemCount"></span>
+</span>
index 4fd98106c0389a60f4f6202c3eaf82b76f0ea522..c86ca5eb5ef167da8a28a5598b7b325e6721f968 100644 (file)
@@ -9,9 +9,12 @@
         @if($page->get('form_intro'))
             <p class="form-info text-navy">{{$page->get('form_intro')}}</p>
         @endif
-        <form class="text-navy mailform" action="/ajax/mailform" method="post"
+        <form class="text-navy mailform" action="{{ $action ?? '/ajax/mailform' }}" method="post"
               data-confirmation="{{$page->get('form_confirmation')??__('Votre message a bien été envoyé')}}" novalidate>
             <input type="hidden" value="{{$page->get('id')}}" name="page">
+
+            {!! $extra_fields ?? '' !!}
+
             <div class="fields grid" >
                 @foreach($page->get('form') as $field)
                     @php