From d2c5c6dcaf5a5ad00e890b6a1ca90dbd702e358c Mon Sep 17 00:00:00 2001 From: Will Marshall Date: Tue, 8 Apr 2014 17:52:54 +1000 Subject: [PATCH] Starting to add inline validation and behaviour to checkout --- .../controllers/checkout_controller.js.coffee | 43 ++++++++++++++++++- .../shop/checkout/_authentication.html.haml | 17 +++----- app/views/shop/checkout/_details.html.haml | 43 ++++++++++++------- app/views/shop/checkout/_form.html.haml | 6 ++- app/views/shop/checkout/_summary.html.haml | 2 +- app/views/shop/checkout/edit.html.haml | 3 +- .../checkout_controller_spec.js.coffee | 2 +- 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/checkout_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout_controller.js.coffee index aa34740744..6ebd9d1367 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout_controller.js.coffee @@ -1,18 +1,59 @@ Darkswarm.controller "CheckoutCtrl", ($scope, Order, storage) -> + window.tmp = $scope $scope.order = $scope.Order = Order storage.bind $scope, "user", { defaultValue: true} $scope.disable = -> $scope.user = false $scope.details = true - console.log $scope.details storage.bind $scope, "details" storage.bind $scope, "billing" storage.bind $scope, "shipping" storage.bind $scope, "payment" + # Validation utilities to keep things DRY + $scope.dirtyValid = (name)-> + $scope.dirty(name) and $scope.valid(name) + $scope.dirty = (name)-> + $scope.checkout[name].$dirty + $scope.valid = (name)-> + $scope.checkout[name].$invalid + $scope.error = (name)-> + $scope.checkout[name].$error + $scope.required = (name)-> + $scope.error(name).required + $scope.email = (name)-> + $scope.error(name).email + $scope.number = (name)-> + $scope.error(name).number + +Darkswarm.controller "DetailsSubCtrl", ($scope) -> + $scope.detailsValid = -> + $scope.detailsFields().every (field)-> + $scope.checkout[field].$valid + + $scope.detailsFields = -> + ["order[email]", + "order[bill_address_attributes][phone]", + "order[bill_address_attributes][firstname]", + "order[bill_address_attributes][lastname]"] + + $scope.emailName = 'order[email]' + $scope.emailValid = -> + $scope.dirtyValid($scope.emailName) + $scope.emailError = -> + return "can't be blank" if $scope.required($scope.emailName) + return "must be valid" if $scope.email($scope.emailName) + + $scope.phoneName = "order[bill_address_attributes][phone]" + $scope.phoneValid = -> + $scope.dirtyValid($scope.phoneName) + $scope.phoneError = -> + "must be a number" $scope.purchase = (event)-> event.preventDefault() checkout.submit() + + diff --git a/app/views/shop/checkout/_authentication.html.haml b/app/views/shop/checkout/_authentication.html.haml index 2b81b9383e..ac87ce8e6f 100644 --- a/app/views/shop/checkout/_authentication.html.haml +++ b/app/views/shop/checkout/_authentication.html.haml @@ -1,16 +1,9 @@ %fieldset %accordion-group{heading: "User", "is-open" => "user"} .row - .large-12.columns - .span{"ng-controller" => "AuthenticationActionsCtrl"} - %button{"ng-click" => "toggle('/login')"} Login - %button{"ng-click" => "toggle('/signup')"} Signup + .large-4.columns.text-center{"ng-controller" => "AuthenticationActionsCtrl"} + %button{"ng-click" => "toggle('/login')"} Login + .large-4.columns.text-center{"ng-controller" => "AuthenticationActionsCtrl"} + %button{"ng-click" => "toggle('/signup')"} Signup + .large-4.columns.text-center %button{"ng-click" => "disable()"} Checkout as guest - - -#%section#checkout_login - -#.large-6.columns - -#= render partial: "shop/checkout/login" - -#%section#checkout_signup - -#.large-6.columns - -#= render partial: "shop/checkout/signup" - diff --git a/app/views/shop/checkout/_details.html.haml b/app/views/shop/checkout/_details.html.haml index 20408d0e44..cb7c189ad2 100644 --- a/app/views/shop/checkout/_details.html.haml +++ b/app/views/shop/checkout/_details.html.haml @@ -1,21 +1,32 @@ %fieldset#details %accordion-group{"is-open" => "details"} - %accordion-heading + %div{"ng-controller" => "DetailsSubCtrl"} + {{ detailsValid() }} + %accordion-heading + .row + .large-6.columns + Customer Details + .large-6.columns.text-right + {{ order.bill_address.firstname }} + {{ order.bill_address.lastname }} .row .large-6.columns - Customer Details - .large-6.columns.text-right - {{ order.bill_address.firstname }} - {{ order.bill_address.lastname }} - .row - .large-6.columns - = f.text_field :email + = f.email_field :email, required: "", "ng-model" => "order.email", + "ng-class" => "{error: '!emailValid()'}" + %small.error.medium.input-text{"ng-show" => "emailValid()"} + {{ emailError() }} + + = f.fields_for :bill_address, @order.bill_address do |ba| + .large-6.columns + = ba.number_field :phone, "ng-model" => "order.bill_address.phone", required: "", + "ng-class" => "{error: '!phoneValid()'}" + %small.error.medium.input-text{"ng-show" => "phoneValid()"} + {{ phoneError() }} + = f.fields_for :bill_address, @order.bill_address do |ba| - .large-6.columns - = ba.text_field :phone, "ng-model" => "order.bill_address.phone" - = f.fields_for :bill_address, @order.bill_address do |ba| - .row - .large-6.columns - = ba.text_field :firstname, "ng-model" => "order.bill_address.firstname" - .large-6.columns - = ba.text_field :lastname, "ng-model" => "order.bill_address.lastname" + .row + .large-6.columns + = ba.text_field :firstname, "ng-model" => "order.bill_address.firstname" + .large-6.columns + = ba.text_field :lastname, "ng-model" => "order.bill_address.lastname" + diff --git a/app/views/shop/checkout/_form.html.haml b/app/views/shop/checkout/_form.html.haml index 66bea3b4cf..faf66d578f 100644 --- a/app/views/shop/checkout/_form.html.haml +++ b/app/views/shop/checkout/_form.html.haml @@ -1,4 +1,8 @@ -= f_form_for current_order, url: main_app.shop_update_checkout_path, html: {name: "checkout", id: "checkout_form"} do |f| += f_form_for current_order, url: main_app.shop_update_checkout_path, + html: {name: "checkout", + id: "checkout_form", + novalidate: "", + name: "checkout"} do |f| :javascript angular.module('Darkswarm').value('order', #{render "shop/checkout/order"}) diff --git a/app/views/shop/checkout/_summary.html.haml b/app/views/shop/checkout/_summary.html.haml index 77ec80b1e6..730263a249 100644 --- a/app/views/shop/checkout/_summary.html.haml +++ b/app/views/shop/checkout/_summary.html.haml @@ -23,6 +23,6 @@ %th= label %td= total - = f.submit "Purchase", class: "button" + = f.submit "Purchase", class: "button", "ng-disabled" => "checkout.$invalid" %a.button.secondary{href: cart_url} Back to Cart diff --git a/app/views/shop/checkout/edit.html.haml b/app/views/shop/checkout/edit.html.haml index 2fb957c46a..6d2a0feecc 100644 --- a/app/views/shop/checkout/edit.html.haml +++ b/app/views/shop/checkout/edit.html.haml @@ -15,6 +15,5 @@ = render partial: "shop/checkout/form" .large-3.columns - .row - = render partial: "shop/checkout/summary" + = render partial: "shop/checkout/summary" diff --git a/spec/javascripts/unit/darkswarm/controllers/checkout_controller_spec.js.coffee b/spec/javascripts/unit/darkswarm/controllers/checkout_controller_spec.js.coffee index ab2369dedb..9730989427 100644 --- a/spec/javascripts/unit/darkswarm/controllers/checkout_controller_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/controllers/checkout_controller_spec.js.coffee @@ -11,4 +11,4 @@ describe "CheckoutCtrl", -> ctrl = $controller 'CheckoutCtrl', {$scope: scope, Order: order} it "defaults the user accordion to visible", -> - expect(scope.userpanel).toEqual true + expect(scope.user).toEqual true