diff --git a/backend/app/plugins/wiaas/assets/css/package.css b/backend/app/plugins/wiaas/assets/css/package.css new file mode 100644 index 0000000..af1b8ec --- /dev/null +++ b/backend/app/plugins/wiaas/assets/css/package.css @@ -0,0 +1,92 @@ +#wiaas_product_price { + padding: 20px; +} + +#wiaas_product_price label { + display:block; + line-height: 24px; + float: left; + width: 270px; + padding: 0; + margin: 0; +} + +#wiaas_product_price_controls { + float: right; +} + +#wiaas_product_price_controls > select { + margin-right: 20px; +} + +#wiaas_product_pricing_rules h4 { + border-bottom: 1px solid #E5E5E5; + padding-bottom: 6px; + font-size: 1.2em; + margin: 1em 0 1em; + text-transform: none; + margin-top: 0px; + cursor: move; +} + +#wiaas_product_pricing_rules > .wiaas-pricing-rule { + border-color:#dfdfdf; + border-width:1px; + border-style:solid; + -moz-border-radius:3px; + -khtml-border-radius:3px; + -webkit-border-radius:3px; + border-radius:3px; + padding: 0; + border-style:solid; + border-spacing:0; + background-color:#F9F9F9; + margin-bottom: 12px; + margin-left: 12px; +} + +#wiaas_product_pricing_rules > .wiaas-pricing-rule .section { + display: block; + overflow: hidden; + zoom: 1; + margin: 9px 0 0; + font-size: 12px; + padding: 5px 9px; +} + +#wiaas_product_pricing_rules > .wiaas-pricing-rule input, #wiaas_product_pricing_rules .wiaas_input_container { + width: 160px; +} + +#wiaas_product_pricing_rules .wiaas_label_container { + width: 270px; +} + +.delete_wiaas_pricing_rule { + color: #a00; + float: right; + font-size: 10px; + font-weight: 400; + letter-spacing: 0.5px; +} + +.wiaas_hidden { + display: none; +} + +.wiaas_separator { + display: inline-block; + width: 1px; + background-color: #727272; + opacity: .25; + height: 28px; + margin: 0 10px; +} + +.wiaas-pricing-rule table { + padding: 5px 9px; +} +.wiaas-pricing-rule tr { + font-size: 12px; + height: 36px; +} diff --git a/backend/app/plugins/wiaas/includes/admin/package/class-wiaas-admin-package-pricing.php b/backend/app/plugins/wiaas/includes/admin/package/class-wiaas-admin-package-pricing.php new file mode 100644 index 0000000..d01e17b --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/package/class-wiaas-admin-package-pricing.php @@ -0,0 +1,356 @@ + __( 'Pricing', 'wiaas' ), + 'target' => 'wiaas_package_price', + 'class' => array( 'show_if_bundle', 'bundled_package_tab' ), + 'priority' => 50 + ); + + return $tabs; + } + + public static function package_data_panel() { + + global $post; + $package = wc_get_product( $post->ID ); + $pricing_rules = Wiaas_Package_Pricing::get_package_prices($package); + + ?> +
+
+ + +
+ +
+
+ $pricing_rule_set ) { + $pay_type = $available_pay_types[$name]; + ?> +
+
+

+ + REMOVE + +

+
+
+ + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+
+ 0) { + $label .= '(' . $pay_type['services_contract_period'] . ' ' . $pay_type['period_unit'] . ')'; + } else { + $label .= '(Unbound)'; + } + + ?> + + + + + + + + + + + + + + 0) { + ?> + + + Final total: + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 && $pay_type['package_pay_period'] > 0) { + $value += $pricing_rule['principal_amount'] / $pay_type['package_pay_period']; + } + + ?> + + + + + + + + + $pay_type) { + if (!isset($pricing_rule_sets[$name])) { + $has_available_pay_types = true; + break; + } + } + + $class = $has_available_pay_types ? '' : 'wiaas_hidden'; + + ?> +
+ + +
+ + + 'GET', + 'callback' => array(__CLASS__, 'get_cart_count'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'items', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_cart_items'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'documents', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'get_cart_documents'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'add', array( + 'methods' => 'post', + 'callback' => array(__CLASS__, 'add_package_to_cart'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'remove', array( + 'methods' => 'post', + 'callback' => array(__CLASS__, 'remove_package_from_cart'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'update-quantity', array( + 'methods' => 'post', + 'callback' => array(__CLASS__, 'update_package_quantity'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + + register_rest_route( self::$namespace, 'place-order', array( + 'methods' => 'post', + 'callback' => array(__CLASS__, 'place_order'), + 'permission_callback' => array( __CLASS__, 'permission_check' ), + ) ); + } + + public static function permission_check() { + if (!is_user_logged_in()) { + return new WP_Error( 'wiaas_rest_authorization_required', + __( 'Sorry, only authorized users can access!', 'wiaas' ), + array( 'status' => rest_authorization_required_code() ) ); + } + return true; + } + + /** + * Get cart count + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + */ + public static function get_cart_count() { + $items = WC()->cart->get_cart_contents(); + + $count = 0; + + foreach ($items as $key => $item) { + if (isset($item['bundled_by'])) { + continue; + } + $count++; + } + + return new WP_REST_Response(array( + 'count' => $count, + )); + } + + /** + * Get cart items + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + */ + public static function get_cart_items() { + $items = WC()->cart->get_cart_contents(); + + $result = array(); + + foreach ($items as $key => $item) { + if (isset($item['bundled_by'])) { + continue; + } + + $package = wc_get_product($item['product_id']); + + $result[] = array( + 'idPackage' => $item['product_id'], + 'key' => $item['key'], + 'packageName' => $package->get_title(), + 'additionalPackages' => array(), + 'areAdditionalAvailable' => true, + 'areOptionsAvailable' => true, + 'bids' => array(), + 'commercialLead' => 'Coor Service Management', + 'country' => array( + 'currency' => 'SEK' + ), + 'options' => array(), + 'quantity' => $item['quantity'], + + 'idPayType' => $item['_wiaas_price']['id'], + 'payType' => $item['_wiaas_price']['payment_type'], + 'periodUnit' => $item['_wiaas_price']['period_unit'], + 'idPrice' => $item['_wiaas_price']['id'], + 'fixedPrice' => $item['_wiaas_price']['minimal_fixed_price'], + 'recurentPrice' => $item['_wiaas_price']['recurrent_price'], + 'servicesPrice' => $item['_wiaas_price']['minimal_services_price'], + + 'totalPrices' => array( + 'fixedPrice' => $item['_wiaas_price']['minimal_fixed_price'], + 'recurentPrice' => $item['_wiaas_price']['recurrent_price'], + 'servicesPrice' => $item['_wiaas_price']['minimal_services_price'], + ), + + 'status' => 'available', + 'idCommercialLead' => 14, + ); + } + return new WP_REST_Response( + array( + 'cartItems' => $result, + 'totalPrice' => '' + ) + ); + } + + /** + * Get cart documents + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + */ + public static function get_cart_documents() { + return new WP_REST_Response(array( + 'areFilesUploaded' => true, + 'templates' => array(), + 'uploaded' => array() + )); + } + + /** + * Add package to cart + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + * @throws Exception + */ + public static function add_package_to_cart() { + $package_id = $_POST['package_id']; + $price_id = $_POST['price_id']; + + $package = wc_get_product($package_id); + $prices = Wiaas_Package_Pricing::get_package_prices($package); + $selected_price = $prices[$price_id]; + + WC()->session->set('wiaas_price_' . $package_id, $price_id); + + $success = WC()->cart->add_to_cart( + $package_id, + 1, + 0, + array(), + array( + '_wiaas_price' => $selected_price, + )); + + if ($success) { + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'success', + 'message' => 'PACKAGE_ADDED' + ) + ) + )); + } + + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'error', + 'message' => 'PACKAGE_ALREADY_IN_CART' + ) + ) + )); + } + + /* + * Remove package from cart + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + */ + public static function remove_package_from_cart() { + $package_cart_key = $_POST['package_item_key']; + + $success = WC()->cart->remove_cart_item($package_cart_key); + + if ($success) { + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'success', + 'message' => 'PACKAGE_REMOVED' + ) + ) + )); + } + + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'error', + 'message' => 'PACKAGE_NOT_REMOVED' + ) + ) + )); + } + + /** + * Update package quantity in cart + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + */ + public static function update_package_quantity() { + $package_item_key = $_POST['package_item_key']; + $new_quantity = $_POST['quantity']; + + $success = WC()->cart->set_quantity($package_item_key, $new_quantity, true); + + if ($success) { + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'success', + 'message' => 'QUANTITY_UPDATED' + ) + ) + )); + } + + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'error', + 'message' => 'QUANTITY_NOT_UPDATED' + ) + ) + )); + } + + /** + * Placing order as part of checkout process + * TODO: This implementation is temporary to enable flow trough basic checkout process and should be changed + * @return WP_REST_Response + * @throws Exception + */ + public static function place_order() { + + $details = $_POST['details']; + $vat_code = $_POST['vat']; + $company_name = $_POST['companyName']; + $delivery_address = $_POST['delivery']; + $billing_address = $_POST['billing']; + + $order_id = WC()->checkout()->create_order(array()); + $order = wc_get_order( $order_id ); + + $order->set_shipping_city($delivery_address['city']); + $order->set_shipping_country($delivery_address['countryName']); + $order->set_shipping_address_1($delivery_address['detailedAddress']); + $order->set_shipping_postcode($delivery_address['zipCode']); + + $order->set_billing_city($billing_address['city']); + $order->set_billing_country($billing_address['countryName']); + $order->set_billing_address_1($billing_address['detailedAddress']); + $order->set_billing_postcode($billing_address['zipCode']); + $order->set_billing_first_name($billing_address['firstName']); + $order->set_billing_last_name($billing_address['lastName']); + + $order->payment_complete(); + + + add_post_meta($order_id, '_wiaas_vat_code', $vat_code); + add_post_meta($order_id, '_wiaas_company_name', $company_name); + add_post_meta($order_id, '_wiaas_project_id', $details['idProject']); + add_post_meta($order_id, '_wiaas_reference', $details['reference']); + add_post_meta($order_id, '_wiaas_tender', $details['tender']); + + // $order->get_li + + WC()->cart->empty_cart( true ); + + return new WP_REST_Response(array( + 'messages' => array( + array( + 'code' => 'success', + 'message' => 'ORDER_PLACED' + ) + ), + 'details' => $details + )); + } +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-admin.php b/backend/app/plugins/wiaas/includes/class-wiaas-admin.php new file mode 100644 index 0000000..d63ecae --- /dev/null +++ b/backend/app/plugins/wiaas/includes/class-wiaas-admin.php @@ -0,0 +1,14 @@ +set_data($data); return $response; @@ -102,6 +104,17 @@ class Wiaas_Order { * PRIVATE */ + /** + * Append specific wiaas order details, like reference + * @param $data + * @param $order + * @param $request + */ + private static function _append_wiaas_order_details($data, $order, $request) { + $data['reference'] = get_post_meta($order->get_id(), '_wiaas_reference', true); + + return $data; + } /** * Appends additional wiaas customer lead info to order json response * @param $data @@ -160,18 +173,22 @@ class Wiaas_Order { foreach ($data['line_items'] as $index => $product_line) { // add only product lines that represent product bundles if (empty($product_line['bundled_by'])) { + + $item = $order->get_item($product_line['id']); + $payment = $item->get_meta('_wiaas_payment', true); + # lock all products to `Purchase` payment type - $product_line['payment_type'] = 'Purchase'; + $product_line['payment_type'] = $payment['payment_type']; # lock all products to have no service - $product_line['service_price'] = 0; - $product_line['service_contract_period'] = 0; - $product_line['max_contract_period'] = 36; - $product_line['period_unit'] = 'month'; + $product_line['service_price'] = $payment['minimal_services_price']; + $product_line['service_contract_period'] = $payment['services_contract_period']; + $product_line['max_contract_period'] = $payment['max_contract_period']; + $product_line['period_unit'] = $payment['period_unit']; # simplify payment for all products - $product_line['recurring_price'] = 0; - $product_line['pay_period'] = 0; + $product_line['recurring_price'] = $payment['recurrent_price']; + $product_line['pay_period'] = $payment['package_pay_period']; # collect status from order if ($data['status'] === 'completed') { diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-package.php b/backend/app/plugins/wiaas/includes/class-wiaas-package.php new file mode 100644 index 0000000..dc1c162 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/class-wiaas-package.php @@ -0,0 +1,46 @@ +get_data(); + + $data = self::_append_package_prices($data, $package, $request); + + $response->set_data($data); + + return $response; + } + + /** + * Append configured package prices on package json response + * @param $data + * @param $package + * @param $request + * + * @return mixed + */ + private static function _append_package_prices($data, $package, $request) { + $package_prices = array_values(Wiaas_Package_Pricing::get_package_prices($package)); + + $data['prices'] = $package_prices; + + return $data; + } +} + +Wiaas_Package::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/package/class-wiaas-package-pricing.php b/backend/app/plugins/wiaas/includes/package/class-wiaas-package-pricing.php new file mode 100644 index 0000000..b2362f1 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/package/class-wiaas-package-pricing.php @@ -0,0 +1,167 @@ + array( + 'title' => 'Purchase', + 'package_pay_period' => 0, + 'services_contract_period' => 0, + 'max_contract_period' => 36, + 'period_unit' => 'month', + 'labe' + ), + 'purchase_24' => array( + 'title' => 'Purchase with 24M commitment', + 'package_pay_period' => 0, + 'services_contract_period' => 24, + 'max_contract_period' => 36, + 'period_unit' => 'month' + ), + 'managed_36' => array( + 'title' => 'Managed service 36M rent', + 'package_pay_period' => 36, + 'services_contract_period'=> 36, + 'max_contract_period' => 36, + 'period_unit' => 'month' + ) + ); + + /** + * Payment fields for pricing rules + * @var array + */ + private static $payment_fields = array( + 'minimal_fixed_price' => 0, + 'principal_amount' => 0, + 'minimal_services_price' => 0 + ); + + /** + * Meta key for pricing rules + * @var string + */ + private static $package_prices_meta_key = '_wiaas_pricing_rules'; + + public static function init() { + + add_filter( 'woocommerce_product_get_price', array( __CLASS__, 'on_get_price' ), 10, 2 ); + + add_filter('woocommerce_checkout_create_order_line_item_object', array( __CLASS__, 'record_price_for_order_line_item' ), 10, 4); + } + + /** + * Get configuration for available payment types + * @return array + */ + public static function get_available_pay_types() { + return self::$pay_types; + } + + /** + * Get empty payment rule with initialized fields to default values + * @return array + */ + public static function get_empty_pricing_rule() { + return self::$payment_fields; + } + + /** + * Retrieve customer selected package price from session when adding package to cart + * @param $base_price + * @param $product + * + * @return mixed + */ + public static function on_get_price($base_price, $package) { + if ( empty( $package ) || + empty( $base_price ) || + $package->get_type() !== 'bundle' || + !isset(WC()->session)) { + return $base_price; + } + $result_price = $base_price; + + $preferred_price_id = WC()->session->get('wiaas_price_' . $package->get_id(), null); + + if (isset($preferred_price_id)) { + $prices = self::get_package_prices($package); + $preferred_price = $prices[$preferred_price_id]; + $result_price = $preferred_price['minimal_fixed_price']; + } + + return $result_price; + } + + /** + * Persist used payment type informations for package in corresponding order line item + * @param $order_item + * @param $cart_item_key + * @param $cart_item + * @param $order + * + * @return mixed + */ + public static function record_price_for_order_line_item($order_item, $cart_item_key, $cart_item, $order) { + if (wc_pb_is_bundle_container_cart_item($cart_item)) { + $order_item->add_meta_data('_wiaas_payment', $cart_item['_wiaas_price']); + } + + return $order_item; + } + + /** + * Retrieve configured payment prices for package + * @param $package + * + * @return array + */ + public static function get_package_prices($package) { + $pricing_rules = $package->get_meta( self::$package_prices_meta_key ); + + $prices = array(); + foreach ($pricing_rules as $type => $pricing_rule) { + + $pay_type = self::$pay_types[$type]; + + $prices[$type] = array( + 'id' => $type, + 'payment_type' => $pay_type['title'], + 'max_contract_period' => $pay_type['max_contract_period'], + 'package_pay_period' => floatval($pay_type['package_pay_period']), + 'period_unit' => $pay_type['period_unit'], + 'services_contract_period' => $pay_type['services_contract_period'], + + 'minimal_fixed_price' => floatval($pricing_rule['minimal_fixed_price']), + 'principal_amount' => floatval($pricing_rule['principal_amount']), + 'recurrent_price' => 0, + 'minimal_services_price' => floatval($pricing_rule['minimal_services_price']), + ); + } + + return $prices; + } + + /** + * Persist payment prices configuration for package + * @param $package + * @param $pricing_rules + */ + public static function set_package_prices($package, $pricing_rules) { + if ( isset( $pricing_rules ) ) { + $package->update_meta_data( self::$package_prices_meta_key, $pricing_rules ); + } else { + $package->delete_meta_data( self::$package_prices_meta_key ); + } + $package->save_meta_data(); + } +} + +Wiaas_Package_Pricing::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/wiaas.php b/backend/app/plugins/wiaas/wiaas.php index 7adfec6..fa6fb49 100644 --- a/backend/app/plugins/wiaas/wiaas.php +++ b/backend/app/plugins/wiaas/wiaas.php @@ -26,6 +26,10 @@ include_once WIAAS_DIR . '/includes/class-wiaas-delivery-process.php'; include_once WIAAS_DIR . '/includes/class-wiaas-order.php'; +include_once WIAAS_DIR . '/includes/class-wiaas-package.php'; + include_once WIAAS_DIR . '/includes/class-wiaas-user.php'; include_once WIAAS_DIR . '/includes/class-wiaas-api.php'; + +include_once WIAAS_DIR . '/includes/class-wiaas-admin.php'; diff --git a/frontend/src/actions/cart/cartActions.js b/frontend/src/actions/cart/cartActions.js index 6f071db..1374e02 100644 --- a/frontend/src/actions/cart/cartActions.js +++ b/frontend/src/actions/cart/cartActions.js @@ -57,24 +57,21 @@ export const receiveCustomerDetails = (json) => ({ export const fetchCartCount = () => { return dispatch => { dispatch(requestShopCartCount()); - //TODO : fetch cart count from woocommerce (requires plugin) - dispatch(receiveShopCartCount(0)); - /* - return client.fetch({url: `${API_SERVER}/cart/api/getCartCount`}).then(response => { - if (typeof response.data !== 'undefined' && 'cartItemsCount' in response.data) { - dispatch(receiveShopCartCount(response.data.cartItemsCount)); + + return client.fetch({url: `${API_SERVER}/wp-json/wiaas/cart/count`}).then(response => { + if (typeof response.data !== 'undefined' && 'count' in response.data) { + dispatch(receiveShopCartCount(response.data.count)); } }).catch(error => { client.onError(error, dispatch); }); - */ } } export const fetchCartItems = (isForSteps = false) => { return dispatch => { dispatch(requestShopCartItems()); - return client.fetch({url: `${API_SERVER}/cart/api/getCartItems`}).then(response => { + return client.fetch({url: `${API_SERVER}/wp-json/wiaas/cart/items`}).then(response => { if (typeof response.data !== 'undefined' && 'cartItems' in response.data) { dispatch(receiveShopCartItems(response.data.cartItems)); dispatch(fetchCartDocuments(response.data.cartItems.map((cartItem) => cartItem.idPackage), isForSteps)); @@ -95,6 +92,7 @@ const updateCartItems = (newItem)=>( export const updateQuantity = (cartItem, quantity, updateCartAllItems) => { const params = { idPackage: cartItem.idPackage || 0, + package_item_key: cartItem.key, idCustomerInstance: cartItem.idCustomerInstance || 0, idPrice: cartItem.idPrice || 0, quantity @@ -102,7 +100,7 @@ export const updateQuantity = (cartItem, quantity, updateCartAllItems) => { return dispatch => { return client.fetch({ - url: `${API_SERVER}/cart/api/updateQuantity`, + url: `${API_SERVER}/wp-json/wiaas/cart/update-quantity`, method: 'post', data: params }).then(response => { @@ -124,12 +122,14 @@ export const updateQuantity = (cartItem, quantity, updateCartAllItems) => { } } -export const removeCartItem = (idCart) => { +export const removeCartItem = (cartItemKey) => { return dispatch => { return client.fetch({ - url: `${API_SERVER}/cart/api/removeFromCart`, + url: `${API_SERVER}/wp-json/wiaas/cart/remove`, method: 'post', - data: {idCart} + data: { + package_item_key: cartItemKey + } }).then(response => { if (typeof response.data !== 'undefined' && 'messages' in response.data) { dispatch(updateMessages(response.data.messages, cartMessages)); @@ -180,15 +180,46 @@ const resetSteps = () => ({type: RESET_STEPS}); export const getCustomerDetails = () => { return dispatch => { - return client.fetch({url: `${API_SERVER}/cart/api/getCustomerDetails`}) - .then(response => { - if (typeof response.data !== 'undefined' && response.data.customerDetails) { - const customerDetails = response.data.customerDetails; - dispatch(receiveCustomerDetails(customerDetails)); - } - }).catch(error => { - client.onError(error, dispatch); - }); + dispatch(receiveCustomerDetails({ + "companyName": "Coor Service Management AB", + "vatCode": "556084-6783", + "details": { + "idBillingAddress": null, + "idDeliveryAddress": null, + "idProject": null, + "reference": null, + "tender": null + }, + "billing": [ + { + "id": 1, + "city": "Göteborg", + "countryName": "SE", + "detailedAddress": "Lilla Bommen 2", + "firstName": "Customer", + "lastName": "User", + "zipCode": "12323" + } + ], + "deliveryAddresses": [ + { + "id": 1, + "city": "Göteborg", + "countryName": "Göteborg", + "detailedAddress": "Lilla Bommen 2", + "zipCode": "12323" + } + ] + })); + // return client.fetch({url: `${API_SERVER}/wp-json/wiaas/cart/customer-details`}) + // .then(response => { + // if (typeof response.data !== 'undefined' && response.data.customerDetails) { + // const customerDetails = response.data.customerDetails; + // dispatch(receiveCustomerDetails(customerDetails)); + // } + // }).catch(error => { + // client.onError(error, dispatch); + // }); } } @@ -239,8 +270,8 @@ export const fetchCartDocuments = (packages, isForSteps = false) => { dispatch(requestCartDocuments()); return client.fetch({ - url: `${API_SERVER}/cart/api/getCartDocuments`, - method: 'post', + url: `${API_SERVER}/wp-json/wiaas/cart/documents`, + method: 'get', data: {packages} }).then(response => { if (response.data) { @@ -262,18 +293,20 @@ export const selectCountryBilling = (country) => ({type: SELECT_COUNTRY_BILLING, export const saveOrderDetails = (orderDetails, cartItems) => { const orderInfo = {orderDetails, cartItems}; return dispatch => { - return client.fetch({ - url: `${API_SERVER}/cart/api/saveOrderDetails`, - method: 'post', - data: {orderDetails, cartItems} - }).then(response => { - if (typeof response.data !== 'undefined' && 'messages' in response.data) { - dispatch(getCustomerDetails()); - dispatch(setOrderInfo(orderInfo)); - } - }).catch(error => { - client.onError(error, dispatch); - }); + dispatch(getCustomerDetails()); + dispatch(setOrderInfo(orderInfo)); + // return client.fetch({ + // url: `${API_SERVER}/cart/api/saveOrderDetails`, + // method: 'post', + // data: {orderDetails, cartItems} + // }).then(response => { + // if (typeof response.data !== 'undefined' && 'messages' in response.data) { + // dispatch(getCustomerDetails()); + // dispatch(setOrderInfo(orderInfo)); + // } + // }).catch(error => { + // client.onError(error, dispatch); + // }); } } @@ -286,9 +319,9 @@ export const placeOrder = (orderInfo) => { const {orderDetails, cartItems} = orderInfo; return dispatch => { return client.fetch({ - url: `${API_SERVER}/cart/api/placeOrder`, + url: `${API_SERVER}/wp-json/wiaas/cart/place-order`, method: 'post', - data: {orderDetails, cartItems} + data: orderDetails }).then(response => { if (typeof response.data !== 'undefined' && 'messages' in response.data) { dispatch(updateMessages(response.data.messages, cartMessages)); diff --git a/frontend/src/actions/coMarket/coMarketPackageDetailsActions.js b/frontend/src/actions/coMarket/coMarketPackageDetailsActions.js index 644052f..a3a651b 100644 --- a/frontend/src/actions/coMarket/coMarketPackageDetailsActions.js +++ b/frontend/src/actions/coMarket/coMarketPackageDetailsActions.js @@ -16,6 +16,7 @@ import { } from '../../constants/coMarketConstants'; import {updateMessages} from '../notification/notificationActions'; import {fetchCartCount} from '../cart/cartActions'; +import { fromWCPackage } from '../../helpers/PackageHelper'; const client = new HtmlClient(); const priceHelper = new PriceHelper(); @@ -41,28 +42,27 @@ export const fetchPackageDetails = (params) => { return dispatch => { dispatch(requestPackageDetails()); return client.fetch({ - url: `${API_SERVER}/coMarket/api/getShopPackageDetails`, - method: 'post', - data: params + url: `${API_SERVER}/wp-json/wc/v2/products/${params.idPackage}`, + method: 'get' }) .then(response => { if(response.data){ - const jsonData = response.data; + const packageData = fromWCPackage(response.data); dispatch(clearSelections()); - if(jsonData.prices && jsonData.prices.length){ - dispatch(selectAgreement(jsonData.prices[0])); + if(packageData.prices && packageData.prices.length){ + dispatch(selectAgreement(packageData.prices[0])); } - if(jsonData.groups){ - Object.keys(jsonData.groups).forEach((idGroup) => { - const defaultOption = jsonData.groups[idGroup].options.find((option) => {return parseInt(option.isDefault, 10) === 1}); + if(packageData.groups){ + Object.keys(packageData.groups).forEach((idGroup) => { + const defaultOption = packageData.groups[idGroup].options.find((option) => {return parseInt(option.isDefault, 10) === 1}); if(defaultOption){ dispatch(selectOption(idGroup, defaultOption)); } }); } - dispatch(recievePackageDetails(jsonData)); + dispatch(recievePackageDetails(packageData)); } }) .catch(error => { @@ -104,25 +104,25 @@ const requestAddToCart = () => ({ }); export const addToCart = (addParams) => { - const options = generateOptions(addParams.selectedOptions, addParams.selectedAdditionals, addParams.selectedAgreement); + // const options = generateOptions(addParams.selectedOptions, addParams.selectedAdditionals, addParams.selectedAgreement); const params = { - idPackage: addParams.selectedPackage.packageInfo.idPackage, - idPrice: addParams.selectedAgreement.idPrice, - options: options.extraPackages + 'package_id': addParams.selectedPackage.id, + 'price_id': addParams.selectedAgreement.idPrice, + //options: options.extraPackages }; - if(options.unavailablePackages.length){ - const unavailable = options.unavailablePackages.map((unavailable) =>{return unavailable.optionName || unavailable.packageName;}); - const message = coMarketMessages.UNAVAILABLE_PACKAGES + ' ' + unavailable.join(); - - return dispatch => {dispatch(updateMessages([{code: 'warning', message}], coMarketMessages))}; - } + // if(options.unavailablePackages.length){ + // const unavailable = options.unavailablePackages.map((unavailable) =>{return unavailable.optionName || unavailable.packageName;}); + // const message = coMarketMessages.UNAVAILABLE_PACKAGES + ' ' + unavailable.join(); + // + // return dispatch => {dispatch(updateMessages([{code: 'warning', message}], coMarketMessages))}; + // } return dispatch => { dispatch(requestAddToCart()); return client.fetch({ - url: `${API_SERVER}/coMarket/api/addToCart`, + url: `${API_SERVER}/wp-json/wiaas/cart/add`, method: 'post', data: params }) diff --git a/frontend/src/actions/login/authActions.js b/frontend/src/actions/login/authActions.js index 3b10fd8..b1b9881 100644 --- a/frontend/src/actions/login/authActions.js +++ b/frontend/src/actions/login/authActions.js @@ -49,8 +49,36 @@ export const validateAccessToken = (token) => { // const serverTime = response.data.serverTime || 1; dispatch(loggedIn({ - accessToken: token - // userInfo: response.data.userInfo + accessToken: token, + userInfo: { + "id": 2, + "name": "Customer User", + "mail": "customer@mail.com", + "phone": "", + "userType": "customer", + "vatCode": "556084-6783", + "companyName": "Coor Service Management AB", + "billingAddresses": [ + { + "id": 1, + "city": "fsdfcsdfcs", + "countryName": "SE", + "detailedAddress": "sdfcsvfsdf, fdfvds, fdfvds", + "firstName": "Customer", + "lastName": "User", + "zipCode": "323232" + } + ], + "profileAddresses": [ + { + "id": 1, + "city": "fsdfcsdfcs", + "countryName": "fsdfcsdfcs", + "detailedAddress": "sdfcsvfsdf, fdfvds, fdfvds", + "zipCode": "323232" + } + ] + } })); // refreshToken = response.data.refreshToken; // startRefreshTimer(dispatch, serverTime); diff --git a/frontend/src/actions/orderProjects/orderProjectsActions.js b/frontend/src/actions/orderProjects/orderProjectsActions.js index f00f9b2..becc88c 100644 --- a/frontend/src/actions/orderProjects/orderProjectsActions.js +++ b/frontend/src/actions/orderProjects/orderProjectsActions.js @@ -33,18 +33,41 @@ const generateOptions = (orderProjects) => { export const getOrderProjects = () => { return dispatch => { dispatch(requestOrderProjects()); - return htmlClient.fetch({ - url: `${API_SERVER}/orderProjects/api/getOrderProjects` - }) - .then(response => { - if (response.data) { - const orderProjects = generateOptions(response.data); - dispatch(recieveOrderProjects(orderProjects)); - } - }) - .catch(error => { - htmlClient.onError(error, dispatch); - }); + + dispatch(recieveOrderProjects(generateOptions([ + { + "idProject": 1, + "projectName": "Innovation Center", + "isAvailable": 1 + }, + { + "idProject": 2, + "projectName": "Demo01", + "isAvailable": 1 + }, + { + "idProject": 3, + "projectName": "Kontorsrådet", + "isAvailable": 1 + }, + { + "idProject": 4, + "projectName": "PerProj01", + "isAvailable": 1 + } + ]))); + // return htmlClient.fetch({ + // url: `${API_SERVER}/orderProjects/api/getOrderProjects` + // }) + // .then(response => { + // if (response.data) { + // const orderProjects = generateOptions(response.data); + // dispatch(recieveOrderProjects(orderProjects)); + // } + // }) + // .catch(error => { + // htmlClient.onError(error, dispatch); + // }); } } diff --git a/frontend/src/actions/profileSettings/profileSettingsActions.js b/frontend/src/actions/profileSettings/profileSettingsActions.js index ede791a..8f5ad69 100644 --- a/frontend/src/actions/profileSettings/profileSettingsActions.js +++ b/frontend/src/actions/profileSettings/profileSettingsActions.js @@ -29,19 +29,49 @@ export const recieveProfileInfo = (json) => ({ export const fetchProfileInfo = (idUser) => { return dispatch => { dispatch(requestProfileInfo()); - return client.fetch({ - url: `${API_SERVER}/profileSettings/api/getProfileInfo`, - method: 'post', - data: {idUser} - }) - .then(response => { - if(response.data){ - dispatch(recieveProfileInfo(response.data)); + + dispatch(recieveProfileInfo({ + "id": 2, + "name": "Customer User", + "mail": "customer@mail.com", + "phone": "", + "userType": "customer", + "vatCode": "556084-6783", + "companyName": "Coor Service Management AB", + "billingAddresses": [ + { + "id": 1, + "city": "Göteborg", + "countryName": "SE", + "detailedAddress": "Lilla Bommen 2", + "firstName": "Customer", + "lastName": "User", + "zipCode": "12323" } - }) - .catch(error => { - client.onError(error, dispatch); - }); + ], + "profileAddresses": [ + { + "id": 1, + "city": "Göteborg", + "countryName": "Göteborg", + "detailedAddress": "Lilla Bommen 2", + "zipCode": "12323" + } + ] + })); + // return client.fetch({ + // url: `${API_SERVER}/wp-json/wiaas/cart/customer-info`, + // method: 'get', + // data: {idUser} + // }) + // .then(response => { + // if(response.data){ + // dispatch(recieveProfileInfo(response.data)); + // } + // }) + // .catch(error => { + // client.onError(error, dispatch); + // }); } }; @@ -107,17 +137,32 @@ const recieveCountries = (json) => ({ export const fetchCountries = () => { return dispatch => { dispatch(requestCountries()); - return client.fetch({ - url: `${API_SERVER}/profileSettings/api/getCoutnries`, - method: 'get' - }) - .then(response => { - if(response.data){ - dispatch(recieveCountries(response.data)); - } - }) - .catch(error => { - client.onError(error, dispatch); - }); + + dispatch(recieveCountries([ + { + "idCountry": 3, + "countryName": "Denmark" + }, + { + "idCountry": 4, + "countryName": "Finland" + }, + { + "idCountry": 2, + "countryName": "Sweden" + } + ])); + // return client.fetch({ + // url: `${API_SERVER}/profileSettings/api/getCoutnries`, + // method: 'get' + // }) + // .then(response => { + // if(response.data){ + // dispatch(recieveCountries(response.data)); + // } + // }) + // .catch(error => { + // client.onError(error, dispatch); + // }); } }; diff --git a/frontend/src/constants/coMarketConstants.js b/frontend/src/constants/coMarketConstants.js index cb21191..d78376d 100644 --- a/frontend/src/constants/coMarketConstants.js +++ b/frontend/src/constants/coMarketConstants.js @@ -96,7 +96,7 @@ export const coMarketTexts = { AVAILABLE_IN: 'Available in', DOCUMENTS: 'Documents', NEW_PRODUCTS: 'New Products', - SEARCH_PACKAGE: 'search package...', + SEARCH_PACKAGE: 'Search...', COMMERCIAL_HEADER_1: 'Next-generation Collaboration', COMMERCIAL_HEADER_2: `Ricoh is now launching Huddle Concept - a stylishly designed, multifunctional workspace that integrates video conferencing diff --git a/frontend/src/containers/cart/CartCustomerDetailsContainer.jsx b/frontend/src/containers/cart/CartCustomerDetailsContainer.jsx index 1cd43bb..564f69e 100644 --- a/frontend/src/containers/cart/CartCustomerDetailsContainer.jsx +++ b/frontend/src/containers/cart/CartCustomerDetailsContainer.jsx @@ -45,7 +45,8 @@ class CartCustomerDetailsContainer extends Component { this.props.dispatch(fetchCartItems()); this.props.dispatch(setNextActionFct(this.handleNextAction)); this.props.dispatch(setPrevActionFct(this.handlePrevAction)); - this.props.dispatch(fetchProfileInfo(this.props.userInfo.wiaas_id_user)); + //this.props.dispatch(fetchProfileInfo(this.props.userInfo.wiaas_id_user)); + this.props.dispatch(fetchProfileInfo()); this.props.dispatch(fetchCountries()); } @@ -191,7 +192,7 @@ class CartCustomerDetailsContainer extends Component { (profileInfo && !isProfileLoading) && + idUser={0}/> } @@ -205,7 +206,7 @@ class CartCustomerDetailsContainer extends Component { + idUser={0}/> } diff --git a/frontend/src/containers/cart/components/CartIcon.jsx b/frontend/src/containers/cart/components/CartIcon.jsx index 4a55192..7b36872 100644 --- a/frontend/src/containers/cart/components/CartIcon.jsx +++ b/frontend/src/containers/cart/components/CartIcon.jsx @@ -4,17 +4,11 @@ import {cartTexts} from '../../../constants/cartConstants'; class CartIcon extends Component { render() { let {cartCount} = this.props; - cartCount = parseInt(cartCount, 10); + cartCount = parseInt(cartCount, 10) || 0; return ( - { cartCount === 0 - ? {cartTexts.labels.EMPTY_CART_ICON} - : cartCount === 1 - ? 1 item in cart - : {cartCount} {cartTexts.labels.ITEMS_IN_CART_ICON} - } - + {cartCount} ); } diff --git a/frontend/src/containers/cart/components/CartItem.jsx b/frontend/src/containers/cart/components/CartItem.jsx index a36633e..4e6648c 100644 --- a/frontend/src/containers/cart/components/CartItem.jsx +++ b/frontend/src/containers/cart/components/CartItem.jsx @@ -14,7 +14,7 @@ class CartItem extends Component { this.state = { tooltipOpen: false, itemQuantity: 1, - idCart: 0 + key: 0 }; this.toggleTooltip = this.toggleTooltip.bind(this); @@ -58,11 +58,11 @@ class CartItem extends Component { } removeItemFromCart() { - this.props.dispatch(removeCartItem(this.state.idCart)); + this.props.dispatch(removeCartItem(this.state.key)); } setDialogParams(cartItem, dialogContent) { - this.setState({idCart: cartItem.idCart}); + this.setState({key: cartItem.key}); this.props.dispatch(setDialogOpenFlag(true)); dialogContent.bodyVariable = cartItem.packageName; this.props.dispatch(setDialogContent(dialogContent)); @@ -144,91 +144,98 @@ class CartItem extends Component { const cartItemNo = this.props.cartItemNo ? this.props.cartItemNo + 1 : 1; return ( -
- - - {cartItemNo}. {cartItem.packageName} - - - - { isFormDisabled - ? cartItem.quantity === 1 - ? cartItem.quantity + ' pc' - : cartItem.quantity + ' pcs' - : this.updateQuantity(cartItem, e.target.value)} - onBlur={e => this.resetQuantity(cartItem, e.target.value)} - /> - } - - - - - {cartTexts.labels.REMOVE_FROM_CART} - - - - { (!cartItem.areAdditionalAvailable || !cartItem.areOptionsAvailable || cartItem.status === 'not-available') && + + + + + {cartItem.packageName} + + + + + + { isFormDisabled + ? cartItem.quantity === 1 + ? cartItem.quantity + ' pc' + : cartItem.quantity + ' pcs' + : this.updateQuantity(cartItem, e.target.value)} + onBlur={e => this.resetQuantity(cartItem, e.target.value)} + /> + } + + { !isFormDisabled &&
} + { + !isFormDisabled && ( + + + {cartTexts.labels.REMOVE_FROM_CART} + + ) + } +
+ +
+ { (!cartItem.areAdditionalAvailable || !cartItem.areOptionsAvailable || cartItem.status === 'not-available') && + xl="12" lg="12" md="12" sm="12" xs="12" + className="not-available"> {cartTexts.labels.PACKAGE_UNAVAILABLE} - } - {cartItem.options.length > 0 && + } + {cartItem.options.length > 0 && cartItem.options.map((packageOption) => - + {packageOption.groupName}: - + {packageOption.packageName} ) - } - {cartItem.additionalPackages.length > 0 && + } + {cartItem.additionalPackages.length > 0 && cartItem.additionalPackages.map((additionalPackage) => - + {cartTexts.labels.ADDITIOONAL_PACKAGE}: - + {additionalPackage.packageName} ) - } - - Payment type: - - {cartItem.payType} - - - - Price: - - - + } + + + {cartItem.payType}: + + +
+ - - + + - -
{cartTexts.labels.ON_DELIVERY} {cartTexts.labels.MONTHLY}
{ @@ -260,11 +267,12 @@ class CartItem extends Component { }
- -
-
+ + + + + + ); } } diff --git a/frontend/src/containers/cart/style/Cart.scss b/frontend/src/containers/cart/style/Cart.scss index adfb256..02b1bd3 100644 --- a/frontend/src/containers/cart/style/Cart.scss +++ b/frontend/src/containers/cart/style/Cart.scss @@ -2,6 +2,10 @@ #cart-count { vertical-align: middle; + color: $cart-count-color; + font-size: 1.5rem; + border-radius: 1rem; + font-family: arial,sans-serif; } #cart-container { @@ -12,7 +16,7 @@ border-radius: $box-radius; .cart-show-items { - padding-top: 1rem; + padding: 1rem; } .quantity-field { @@ -22,7 +26,7 @@ } .remove-item { - color: $redColor; + color: #111; cursor: pointer; font-size: 1.3rem; padding-top: 0.375rem; @@ -42,6 +46,30 @@ font-weight: $font-weight; } + .cart-item-details { + .item-name { + } + .item-quantity { + + } + + .wiaas-divider { + height: 40px; + margin: 0 20px; + min-width: 1px; + } + } + + .item-payment-type { + font-weight: 600; + } + + .item-price { + background-color: $hoverColor; + margin-top: 1rem; + border-radius: $box-radius; + } + .cart-total-price { padding: 1rem 0; font-size: $font-size-big; @@ -163,6 +191,11 @@ .cart-address-box { margin-top: 2rem; } + + #order-projects .actions-button, .add-address-btn, .address-icons { + opacity: 0.3; + pointer-events: none; + } } #cart-customer-main-information-container { diff --git a/frontend/src/containers/coMarket/CoMarketNavContainer.jsx b/frontend/src/containers/coMarket/CoMarketNavContainer.jsx index 8a32b25..a1a5716 100644 --- a/frontend/src/containers/coMarket/CoMarketNavContainer.jsx +++ b/frontend/src/containers/coMarket/CoMarketNavContainer.jsx @@ -22,12 +22,13 @@ class CoMarketNavContainer extends Component { render() { return ( - +
{coMarketTexts.labels.NEW_PRODUCTS}
+
- +
diff --git a/frontend/src/containers/coMarket/CoMarketPackageDetailsContainer.jsx b/frontend/src/containers/coMarket/CoMarketPackageDetailsContainer.jsx index 31d31fc..c5eeeb7 100644 --- a/frontend/src/containers/coMarket/CoMarketPackageDetailsContainer.jsx +++ b/frontend/src/containers/coMarket/CoMarketPackageDetailsContainer.jsx @@ -54,14 +54,16 @@ class CoMarketPackageDetailsContainer extends Component {
- { selectedPackage.groups && Object.keys(selectedPackage.groups).length > 0 && selectedAgreement && - + currency={selectedPackage.currency}/> + + + {messages && {messages[0].message}}
diff --git a/frontend/src/containers/coMarket/components/AgreementOptionItemContainer.jsx b/frontend/src/containers/coMarket/components/AgreementOptionItemContainer.jsx index 13753bb..dce6595 100644 --- a/frontend/src/containers/coMarket/components/AgreementOptionItemContainer.jsx +++ b/frontend/src/containers/coMarket/components/AgreementOptionItemContainer.jsx @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import {connect} from 'react-redux'; -import {Label, Popover, PopoverBody, Input, Col} from 'reactstrap'; +import {Label, Popover, PopoverBody, Input, Col, Row} from 'reactstrap'; import {selectAgreement} from '../../../actions/coMarket/coMarketPackageDetailsActions'; import PriceHelper from '../../../helpers/coMarket/PriceHelper'; import {coMarketTexts} from '../../../constants/coMarketConstants'; @@ -35,49 +35,39 @@ class AgreementOptionItem extends Component { } render() { - const {price, selectedAgreement, country} = this.props; + const {price, selectedAgreement, currency} = this.props; return ( - -
-
+ {price.payType} + + + {price.fixedExtra.toLocaleString()} {currency} + + + + { + priceHelper.hasRecurrentPrice(price) + ? `${priceHelper.sumPrices([price.recurentExtra, price.servicesExtra]).toLocaleString()} ${currency}` + : '0' + } + + + + 0 &&
{coMarketTexts.labels.RECURRENT_PRICE}: - {(price.recurentExtra).toLocaleString()} {country.currency} / {price.periodUnit} + {(price.recurentExtra).toLocaleString()} {currency} / {price.periodUnit} { price.packagePayPeriod > 0 && @@ -103,7 +93,7 @@ class AgreementOptionItem extends Component { price.servicesExtra > 0 &&
{coMarketTexts.labels.SERVICE_PRICE}: - {(price.servicesExtra).toLocaleString()} {country.currency} / {price.periodUnit} + {(price.servicesExtra).toLocaleString()} {currency} / {price.periodUnit} { price.servicesContractPeriod > 0 && @@ -115,7 +105,7 @@ class AgreementOptionItem extends Component {
- + ); } } diff --git a/frontend/src/containers/coMarket/components/AgreementOptions.jsx b/frontend/src/containers/coMarket/components/AgreementOptions.jsx index 7ff36bd..eeffa93 100644 --- a/frontend/src/containers/coMarket/components/AgreementOptions.jsx +++ b/frontend/src/containers/coMarket/components/AgreementOptions.jsx @@ -1,24 +1,86 @@ import React, {Component} from 'react'; -import {Row} from 'reactstrap'; +import {Row, Col} from 'reactstrap'; import AgreementOptionItemContainer from './AgreementOptionItemContainer.jsx'; import {coMarketTexts} from '../../../constants/coMarketConstants'; +import {connect} from "react-redux"; class AgreementOptions extends Component { + constructor(props) { + super(props); + + this.getFinalPrice = this.getFinalPrice.bind(this); + this.filterByAgreement = this.filterByAgreement.bind(this); + } + + filterByAgreement(price) { + return price.idPaymentType === this.props.selectedAgreement.idPaymentType; + } + + getExtra(selected, priceType) { + const extraPriceObj = selected.prices.find(this.filterByAgreement); + const extraPrice = extraPriceObj ? extraPriceObj[priceType] : 0; + + return extraPrice; + } + + getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, priceType) { + let price = selectedAgreement ? selectedAgreement[priceType] : 0; + + if(selectedAgreement && selectedOptions) { + Object.keys(selectedOptions).forEach((idGroup) => { + price += this.getExtra(selectedOptions[idGroup], priceType); + }); + } + if(selectedAgreement && selectedAdditionals) { + selectedAdditionals.forEach((additional) => { + price += this.getExtra(additional, priceType); + }); + } + + return price; + } + render() { - const {prices, country} = this.props; + const {prices, currency, selectedAgreement, selectedOptions, selectedAdditionals} = this.props; return ( -
-
{coMarketTexts.labels.AGREEMENT_OPTIONS}:
- +
+ + +
{coMarketTexts.labels.ON_DELIVERY}
+ + +
{coMarketTexts.labels.MONTHLY}
+ +
+
{ prices && prices.map((price) => { - return + return () }) } +
+ + +
Price:
+ + + {this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {currency} + + + {(this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'recurentExtra') + + this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'servicesExtra')).toLocaleString()} + {' '}{currency} +
); } } -export default AgreementOptions; +const mapStateToProps = (state) => ({ + selectedAgreement: state.coMarketPackageDetailsReducer.selectedAgreement, + selectedOptions: state.coMarketPackageDetailsReducer.selectedOptions, + selectedAdditionals: state.coMarketPackageDetailsReducer.selectedAdditionals +}); + +export default connect(mapStateToProps) (AgreementOptions); diff --git a/frontend/src/containers/coMarket/components/PackageInfo.jsx b/frontend/src/containers/coMarket/components/PackageInfo.jsx index 25fdffb..d0bba52 100644 --- a/frontend/src/containers/coMarket/components/PackageInfo.jsx +++ b/frontend/src/containers/coMarket/components/PackageInfo.jsx @@ -14,28 +14,26 @@ class PackageInfo extends Component { } render() { - const {packageInfo, documents} = this.props; + const { name, reference, shortDescription, country, countryCode, documents } = this.props; return (
- { packageInfo && - -

{packageInfo.name}

-
{packageInfo.reference}
- - -
{coMarketTexts.labels.AVAILABLE_IN}:
-
- {packageInfo.country} -
- -
- } + +

{name}

+
{reference}
+ + +
{coMarketTexts.labels.AVAILABLE_IN}:
+
+ {country} +
+ +
{ documents && documents.length > 0 && @@ -55,12 +55,12 @@ class PackagePrice extends Component { - {this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {country.currency} + {this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'fixedExtra').toLocaleString()} {currency} {(this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'recurentExtra') + this.getFinalPrice(selectedAgreement, selectedOptions, selectedAdditionals, 'servicesExtra')).toLocaleString()} - {' '}{country.currency} + {' '}{currency} diff --git a/frontend/src/containers/coMarket/components/ShopItem.jsx b/frontend/src/containers/coMarket/components/ShopItem.jsx index 9817c9d..a9a142e 100644 --- a/frontend/src/containers/coMarket/components/ShopItem.jsx +++ b/frontend/src/containers/coMarket/components/ShopItem.jsx @@ -11,13 +11,14 @@ class ShopItem extends Component { render() { const {shopPackage, idCommercialLead} = this.props; + return ( - + -
+ Card image cap diff --git a/frontend/src/containers/coMarket/style/CoMarket.scss b/frontend/src/containers/coMarket/style/CoMarket.scss index 6a24ec7..b8f0501 100644 --- a/frontend/src/containers/coMarket/style/CoMarket.scss +++ b/frontend/src/containers/coMarket/style/CoMarket.scss @@ -56,8 +56,18 @@ margin-left: 0.2rem; } + .wiaas-box-header { + padding: 1rem; + align-items: center; + display: flex; + .wiaas-box-visibility-icon { + top: 50%; + transform: translateY(-50%); + } + } + .co-market-nav { - font-size: $font-size-msmall; + font-size: $font-size-small; text-align: left; color: $warmGreyColor; vertical-align: middle; @@ -77,17 +87,20 @@ .search-layer div{ position: relative; + flex-grow: 1; + padding-right: 1rem; } .wiaas-input { - border-radius: 3.125rem; + border-radius: 4rem; background-color: $whiteColor; border: solid 1px $borderColor; - padding: 0.2rem 1.4rem; - font-size: $font-size-xsmal; + padding: 0.2rem 3rem; + font-size: $font-size-small; font-weight: 300; text-align: left; color: $warmGreyColor; + height: 2.2rem; } input:focus { @@ -96,16 +109,15 @@ .search-package-icon { position: absolute; - font-size: $font-size-xsmal; - left: 0.4rem; - top: 0.3rem; + font-size: $font-size-normal; + left: 1.6rem; + top: 0.6rem; color: $warmGreyColor; } .shop-image-photo{ - width:100%; height:129px; - background-size: cover; + object-fit: cover; } } diff --git a/frontend/src/containers/coMarket/style/CoMarketPackageDetailsContainer.scss b/frontend/src/containers/coMarket/style/CoMarketPackageDetailsContainer.scss index cf120f9..50eb2a3 100644 --- a/frontend/src/containers/coMarket/style/CoMarketPackageDetailsContainer.scss +++ b/frontend/src/containers/coMarket/style/CoMarketPackageDetailsContainer.scss @@ -55,6 +55,16 @@ #shop-package-buy-info{ padding: 2rem; + .shop-package-pricing { + > div.row { + margin: 0 32px 0 0; + } + } + + .shop-package-calculated-price { + font-weight: $font-weight; + } + .shop-package-options{ margin: 1rem 0; border-bottom: 2px solid $title-color; @@ -71,7 +81,7 @@ .price-info-btn { color: $info-color; cursor: pointer; - margin-left: 0.2rem; + padding: 0.5rem; } .add-to-cart-btn { @@ -83,32 +93,39 @@ } .selected-option { - font-weight: $font-weight; background: $hoverColor; - border-radius: $box-radius; } .option-selection { - display: inline-block; - vertical-align: top; - padding: 0.5rem; + padding: 0.5rem 0; + margin: 0; + flex-wrap: nowrap; + + > label { + cursor: pointer; + margin: 0; + flex-wrap: nowrap; + } + + input.price-type-option { + position: relative; + margin: 0 10px 0 0; + } + + span.option-name { + font-size: $font-size-small; + } } .option-selection:hover { background: $footer-background; color: $whiteColor; - border-radius: $box-radius; } .option-selection:hover .price-info-btn { color: $whiteColor; } - .option-name { - font-size: $font-size-msmall; - height: 2rem; - } - .option-description { padding-top: 0.5rem; font-size: $font-size-msmall; @@ -131,11 +148,6 @@ font-weight: bold; } - .option-prices { - margin-top: 0.5rem; - border-radius: $box-radius; - } - .price-table { width: 8rem; } diff --git a/frontend/src/containers/orders/components/OrderPackage.jsx b/frontend/src/containers/orders/components/OrderPackage.jsx index 5a1bf43..70ceab2 100644 --- a/frontend/src/containers/orders/components/OrderPackage.jsx +++ b/frontend/src/containers/orders/components/OrderPackage.jsx @@ -7,7 +7,7 @@ import '../style/Orders.css'; class OrderPackage extends Component { calculateRecuringPrice(packageDetails) { - return packageDetails.units * (parseFloat(packageDetails.packageRecuringPrice) + parseFloat(packageDetails.packageServicePrice)); + return packageDetails.quantity * (parseFloat(packageDetails.recurringPrice) + parseFloat(packageDetails.servicePrice)); } calculateQuantityPrice(quantity, price, recurringPrice = 0) { @@ -68,7 +68,7 @@ class OrderPackage extends Component { ({orderPackage.paymentType}) - {this.calculateQuantityPrice(orderPackage.quantity, orderPackage.servicePrice, orderPackage.recurringPrice).toLocaleString() + ' / ' + orderPackage.periodUnit + ' '} + {this.calculateRecuringPrice(orderPackage).toLocaleString() + ' / ' + orderPackage.periodUnit + ' '} {orderTexts.labels.EXTEND} {orderPackage.periodUnit} (Max {orderPackage.maxContractPeriod}) diff --git a/frontend/src/helpers/OrderHelper.js b/frontend/src/helpers/OrderHelper.js index 27c1389..9eafd55 100644 --- a/frontend/src/helpers/OrderHelper.js +++ b/frontend/src/helpers/OrderHelper.js @@ -16,7 +16,7 @@ export const fromWCOrder = (WCOrder) => { dateCreated: formatDate(WCOrder['date_created']), dateCompleted: formatDate(WCOrder['date_completed']), estimatedDeliveryDate: undefined, - reference: 'reference field', + reference: WCOrder['reference'], assignedTo: 'assigned to', fixedPrice: WCOrder.total, recurringPrice: 0, diff --git a/frontend/src/helpers/PackageHelper.js b/frontend/src/helpers/PackageHelper.js index 97a276b..142bf9f 100644 --- a/frontend/src/helpers/PackageHelper.js +++ b/frontend/src/helpers/PackageHelper.js @@ -6,11 +6,27 @@ export const fromWCPackage = wcPackage => { id: wcPackage.id, reference: wcPackage.slug, image: wcPackage.images[0].src || DEFAULT_PACKAGE_IMG, + hasImage: !!wcPackage.images.length, name: wcPackage.name, country: 'Sweden', countryCode: 'se', currency: 'SEK', documents: [], shortDescription: wcPackage.description, + prices: wcPackage.prices.map(price => ({ + idPrice: price.id, + idPaymentType: price.id, + payType: price['payment_type'], + isSameCompanyAsCl: false, + idPackage: wcPackage.id, + periodUnit: price['period_unit'], + maxContractPeriod: price['max_contract_period'], + packagePayPeriod: price['package_pay_period'], + servicesContractPeriod: price['services_contract_period'], + fixedExtra: price['minimal_fixed_price'], + servicesExtra: price['minimal_services_price'], + recurentExtra: price['recurrent_price'] + })) || [], + groups: [], } }; \ No newline at end of file diff --git a/frontend/src/mainComponents/menu/Menu.jsx b/frontend/src/mainComponents/menu/Menu.jsx index 66f23e7..4e4d40f 100644 --- a/frontend/src/mainComponents/menu/Menu.jsx +++ b/frontend/src/mainComponents/menu/Menu.jsx @@ -84,11 +84,13 @@ class Menu extends Component { ) } +
diff --git a/frontend/src/mainComponents/menu/menu.scss b/frontend/src/mainComponents/menu/menu.scss index 255a727..2e71c50 100644 --- a/frontend/src/mainComponents/menu/menu.scss +++ b/frontend/src/mainComponents/menu/menu.scss @@ -58,18 +58,29 @@ .nav-btn-cart { padding: 0.2rem; - background-color: rgba(113, 194, 191, 0.5); - width: 11.5rem; + &:hover { + background-color: rgba(113, 194, 191, 0.5); + } } .cart-icon { - font-size: 1.2rem; + font-size: 1.6rem; vertical-align: middle; } +.cart-label { + margin-left: 0.5rem; + font-size: 0.8rem; + vertical-align: sub; +} + .items-cart-count { - margin-left: 1rem; - width: 12rem; + margin-right: 0.5rem; + padding-left: 0.5rem; +} + +.nav-btn-cart-divider { + height: 2.4rem !important; } .navbar-collapse { diff --git a/frontend/src/reducers/cart/cartReducers.js b/frontend/src/reducers/cart/cartReducers.js index 2b69908..394b281 100644 --- a/frontend/src/reducers/cart/cartReducers.js +++ b/frontend/src/reducers/cart/cartReducers.js @@ -35,8 +35,8 @@ const calculateTotalPrice = (cartItems) => { return { fixedPrice, recurrentPrice: priceHelper.sumPrices([recurrentPrice, servicesPrice]), - periodUnit: cartItems[0].periodUnit, - currency: cartItems[0].country.currency + periodUnit: cartItems[0] ? cartItems[0].periodUnit : '', + currency: cartItems[0] ? cartItems[0].country.currency : '' } } diff --git a/frontend/src/styleConstants.scss b/frontend/src/styleConstants.scss index fabdd98..c8fb70f 100644 --- a/frontend/src/styleConstants.scss +++ b/frontend/src/styleConstants.scss @@ -57,3 +57,5 @@ $warm-grey: #7e7e7e; $info-color: #337ab7; $danger: #F70D1A; $warning: #FF8040; + +$cart-count-color: #FFD3A1;