feat: Wishlist Page
- Navbar icon with badge count for wishlist - Wishlist page with cards - Cards can be moved to cart or removed in a click - Separated all wishlist related methods into wishlist.js - Made a common js method(util) to add/remove wishlist items - Bug fix: Make sure items are removed from session user's wishlist
This commit is contained in:
		
							parent
							
								
									96cc5068b2
								
							
						
					
					
						commit
						59514408b9
					
				| @ -10,18 +10,22 @@ class Wishlist(Document): | |||||||
| 	pass | 	pass | ||||||
| 
 | 
 | ||||||
| @frappe.whitelist() | @frappe.whitelist() | ||||||
| def add_to_wishlist(item_code, price): | def add_to_wishlist(item_code, price, formatted_price=None): | ||||||
| 	"""Insert Item into wishlist.""" | 	"""Insert Item into wishlist.""" | ||||||
| 	web_item_data = frappe.db.get_value("Website Item", {"item_code": item_code}, | 	web_item_data = frappe.db.get_value("Website Item", {"item_code": item_code}, | ||||||
| 		["image", "website_warehouse", "name", "item_name"], as_dict=1) | 		["image", "website_warehouse", "name", "item_name", "item_group", "route"] | ||||||
|  | 		, as_dict=1) | ||||||
| 
 | 
 | ||||||
| 	wished_item_dict = { | 	wished_item_dict = { | ||||||
| 		"item_code": item_code, | 		"item_code": item_code, | ||||||
| 		"item_name": web_item_data.get("item_name"), | 		"item_name": web_item_data.get("item_name"), | ||||||
|  | 		"item_group": web_item_data.get("item_group"), | ||||||
| 		"website_item": web_item_data.get("name"), | 		"website_item": web_item_data.get("name"), | ||||||
| 		"price": frappe.utils.flt(price), | 		"price": frappe.utils.flt(price), | ||||||
|  | 		"formatted_price": formatted_price, | ||||||
| 		"image": web_item_data.get("image"), | 		"image": web_item_data.get("image"), | ||||||
| 		"website_warehouse": web_item_data.get("website_warehouse") | 		"warehouse": web_item_data.get("website_warehouse"), | ||||||
|  | 		"route": web_item_data.get("route") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if not frappe.db.exists("Wishlist", frappe.session.user): | 	if not frappe.db.exists("Wishlist", frappe.session.user): | ||||||
|  | |||||||
| @ -9,13 +9,16 @@ | |||||||
|   "website_item", |   "website_item", | ||||||
|   "column_break_3", |   "column_break_3", | ||||||
|   "item_name", |   "item_name", | ||||||
|  |   "item_group", | ||||||
|   "item_details_section", |   "item_details_section", | ||||||
|   "description", |   "description", | ||||||
|   "column_break_7", |   "column_break_7", | ||||||
|   "section_break_8", |   "route", | ||||||
|   "price", |  | ||||||
|   "image", |   "image", | ||||||
|   "image_view", |   "image_view", | ||||||
|  |   "section_break_8", | ||||||
|  |   "price", | ||||||
|  |   "formatted_price", | ||||||
|   "warehouse_section", |   "warehouse_section", | ||||||
|   "warehouse" |   "warehouse" | ||||||
|  ], |  ], | ||||||
| @ -101,12 +104,28 @@ | |||||||
|    "fieldname": "price", |    "fieldname": "price", | ||||||
|    "fieldtype": "Float", |    "fieldtype": "Float", | ||||||
|    "label": "Price" |    "label": "Price" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |    "fieldname": "item_group", | ||||||
|  |    "fieldtype": "Link", | ||||||
|  |    "label": "Item Group", | ||||||
|  |    "options": "Item Group" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |    "fieldname": "route", | ||||||
|  |    "fieldtype": "Small Text", | ||||||
|  |    "label": "Route" | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |    "fieldname": "formatted_price", | ||||||
|  |    "fieldtype": "Data", | ||||||
|  |    "label": "Formatted Price" | ||||||
|   } |   } | ||||||
|  ], |  ], | ||||||
|  "index_web_pages_for_search": 1, |  "index_web_pages_for_search": 1, | ||||||
|  "istable": 1, |  "istable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-03-12 18:23:03.487891", |  "modified": "2021-03-15 16:37:40.405333", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "E-commerce", |  "module": "E-commerce", | ||||||
|  "name": "Wishlist Items", |  "name": "Wishlist Items", | ||||||
|  | |||||||
| @ -81,7 +81,7 @@ class ProductQuery: | |||||||
| 				item.in_stock = "green" if stock_qty else "red" | 				item.in_stock = "green" if stock_qty else "red" | ||||||
| 
 | 
 | ||||||
| 			item.wished = False | 			item.wished = False | ||||||
| 			if frappe.db.exists("Wishlist Items", {"item_code": item.item_code}): | 			if frappe.db.exists("Wishlist Items", {"item_code": item.item_code, "parent": frappe.session.user}): | ||||||
| 				item.wished = True | 				item.wished = True | ||||||
| 
 | 
 | ||||||
| 		return result | 		return result | ||||||
|  | |||||||
| @ -186,5 +186,40 @@ $.extend(shopping_cart, { | |||||||
| 				$(".shopping-cart").toggleClass('hidden', r.message ? false : true); | 				$(".shopping-cart").toggleClass('hidden', r.message ? false : true); | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	animate_add_to_cart(button) { | ||||||
|  | 		// Create 'added to cart' animation
 | ||||||
|  | 		let btn_id = "#" + button[0].id; | ||||||
|  | 		this.toggle_button_class(button, 'not-added', 'added-to-cart'); | ||||||
|  | 		$(btn_id).text('Added to Cart'); | ||||||
|  | 
 | ||||||
|  | 		// undo
 | ||||||
|  | 		setTimeout(() => { | ||||||
|  | 			this.toggle_button_class(button, 'added-to-cart', 'not-added'); | ||||||
|  | 			$(btn_id).text('Add to Cart'); | ||||||
|  | 		}, 2000); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	toggle_button_class(button, remove, add) { | ||||||
|  | 		button.removeClass(remove); | ||||||
|  | 		button.addClass(add); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	bind_add_to_cart_action() { | ||||||
|  | 		$('.page_content').on('click', '.btn-add-to-cart-list', (e) => { | ||||||
|  | 			const $btn = $(e.currentTarget); | ||||||
|  | 			$btn.prop('disabled', true); | ||||||
|  | 
 | ||||||
|  | 			this.animate_add_to_cart($btn); | ||||||
|  | 
 | ||||||
|  | 			const item_code = $btn.data('item-code'); | ||||||
|  | 			erpnext.shopping_cart.update_cart({ | ||||||
|  | 				item_code, | ||||||
|  | 				qty: 1 | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -1,13 +1,12 @@ | |||||||
| frappe.provide("erpnext.e_commerce"); | frappe.provide("erpnext.wishlist"); | ||||||
| var wishlist = erpnext.e_commerce; | var wishlist = erpnext.wishlist; | ||||||
| 
 | 
 | ||||||
| frappe.ready(function() { | frappe.provide("erpnext.shopping_cart"); | ||||||
| 	$(".wishlist").toggleClass('hidden', true); | var shopping_cart = erpnext.shopping_cart; | ||||||
| 	wishlist.set_wishlist_count(); |  | ||||||
| }); |  | ||||||
| 
 | 
 | ||||||
| $.extend(wishlist, { | $.extend(wishlist, { | ||||||
| 	set_wishlist_count: function() { | 	set_wishlist_count: function() { | ||||||
|  | 		// set badge count for wishlist icon
 | ||||||
| 		var wish_count = frappe.get_cookie("wish_count"); | 		var wish_count = frappe.get_cookie("wish_count"); | ||||||
| 		if(frappe.session.user==="Guest") { | 		if(frappe.session.user==="Guest") { | ||||||
| 			wish_count = 0; | 			wish_count = 0; | ||||||
| @ -35,5 +34,127 @@ $.extend(wishlist, { | |||||||
| 		} else { | 		} else { | ||||||
| 			$badge.remove(); | 			$badge.remove(); | ||||||
| 		} | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	bind_move_to_cart_action: function() { | ||||||
|  | 		// move item to cart from wishlist
 | ||||||
|  | 		$('.page_content').on("click", ".btn-add-to-cart", (e) => { | ||||||
|  | 			const $move_to_cart_btn = $(e.currentTarget); | ||||||
|  | 			let item_code = $move_to_cart_btn.data("item-code"); | ||||||
|  | 
 | ||||||
|  | 			shopping_cart.shopping_cart_update({ | ||||||
|  | 				item_code, | ||||||
|  | 				qty: 1, | ||||||
|  | 				cart_dropdown: true | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			let success_action = function() { | ||||||
|  | 				const $card_wrapper = $move_to_cart_btn.closest(".item-card"); | ||||||
|  | 				$card_wrapper.addClass("wish-removed"); | ||||||
|  | 			}; | ||||||
|  | 			let args = { item_code: item_code }; | ||||||
|  | 			this.add_remove_from_wishlist("remove", args, success_action, null, true); | ||||||
|  | 		}); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	bind_remove_action: function() { | ||||||
|  | 		// remove item from wishlist
 | ||||||
|  | 		$('.page_content').on("click", ".remove-wish", (e) => { | ||||||
|  | 			const $remove_wish_btn = $(e.currentTarget); | ||||||
|  | 			let item_code = $remove_wish_btn.data("item-code"); | ||||||
|  | 
 | ||||||
|  | 			let success_action = function() { | ||||||
|  | 				const $card_wrapper = $remove_wish_btn.closest(".item-card"); | ||||||
|  | 				$card_wrapper.addClass("wish-removed"); | ||||||
|  | 			}; | ||||||
|  | 			let args = { item_code: item_code }; | ||||||
|  | 			this.add_remove_from_wishlist("remove", args, success_action); | ||||||
|  | 		}); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	bind_wishlist_action() { | ||||||
|  | 		// 'wish'('like') or 'unwish' item in product listing
 | ||||||
|  | 		$('.page_content').on('click', '.like-action', (e) => { | ||||||
|  | 			const $btn = $(e.currentTarget); | ||||||
|  | 			const $wish_icon = $btn.find('.wish-icon'); | ||||||
|  | 			let me = this; | ||||||
|  | 
 | ||||||
|  | 			let success_action = function() { | ||||||
|  | 				erpnext.wishlist.set_wishlist_count(); | ||||||
|  | 			}; | ||||||
|  | 
 | ||||||
|  | 			if ($wish_icon.hasClass('wished')) { | ||||||
|  | 				// un-wish item
 | ||||||
|  | 				$btn.removeClass("like-animate"); | ||||||
|  | 				this.toggle_button_class($wish_icon, 'wished', 'not-wished'); | ||||||
|  | 
 | ||||||
|  | 				let args = { item_code: $btn.data('item-code') }; | ||||||
|  | 				let failure_action = function() { | ||||||
|  | 					me.toggle_button_class($wish_icon, 'not-wished', 'wished'); | ||||||
|  | 				}; | ||||||
|  | 				this.add_remove_from_wishlist("remove", args, success_action, failure_action); | ||||||
|  | 			} else { | ||||||
|  | 				// wish item
 | ||||||
|  | 				$btn.addClass("like-animate"); | ||||||
|  | 				this.toggle_button_class($wish_icon, 'not-wished', 'wished'); | ||||||
|  | 
 | ||||||
|  | 				let args = { | ||||||
|  | 					item_code: $btn.data('item-code'), | ||||||
|  | 					price: $btn.data('price'), | ||||||
|  | 					formatted_price: $btn.data('formatted-price') | ||||||
|  | 				}; | ||||||
|  | 				let failure_action = function() { | ||||||
|  | 					me.toggle_button_class($wish_icon, 'wished', 'not-wished'); | ||||||
|  | 				}; | ||||||
|  | 				this.add_remove_from_wishlist("add", args, success_action, failure_action); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	toggle_button_class(button, remove, add) { | ||||||
|  | 		button.removeClass(remove); | ||||||
|  | 		button.addClass(add); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	add_remove_from_wishlist(action, args, success_action, failure_action, async=false) { | ||||||
|  | 		/*	AJAX call to add or remove Item from Wishlist | ||||||
|  | 			action: "add" or "remove" | ||||||
|  | 			args: args for method (item_code, price, formatted_price), | ||||||
|  | 			success_action: method to execute on successs, | ||||||
|  | 			failure_action: method to execute on failure, | ||||||
|  | 			async: make call asynchronously (true/false).	*/ | ||||||
|  | 		let method = "erpnext.e_commerce.doctype.wishlist.wishlist.add_to_wishlist"; | ||||||
|  | 		if (action === "remove") { | ||||||
|  | 			method = "erpnext.e_commerce.doctype.wishlist.wishlist.remove_from_wishlist"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		frappe.call({ | ||||||
|  | 			type: "POST", | ||||||
|  | 			method: method, | ||||||
|  | 			args: args, | ||||||
|  | 			callback: function (r) { | ||||||
|  | 				if (r.exc) { | ||||||
|  | 					if (failure_action && (typeof failure_action === 'function')) {failure_action();} | ||||||
|  | 					frappe.msgprint({ | ||||||
|  | 						message: __("Sorry, something went wrong. Please refresh."), | ||||||
|  | 						indicator: "red", title: __("Note") | ||||||
|  | 					}); | ||||||
|  | 				} else { | ||||||
|  | 					if (success_action && (typeof success_action === 'function')) {success_action();} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | frappe.ready(function() { | ||||||
|  | 	if (window.location.pathname !== "/wishlist") { | ||||||
|  | 		$(".wishlist").toggleClass('hidden', true); | ||||||
|  | 		wishlist.set_wishlist_count(); | ||||||
|  | 	} else { | ||||||
|  | 		wishlist.bind_move_to_cart_action(); | ||||||
|  | 		wishlist.bind_remove_action(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| }); | }); | ||||||
| @ -648,3 +648,27 @@ body.product-page { | |||||||
| 		color: white; | 		color: white; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .wishlist-cart-not-added { | ||||||
|  | 	color: var(--blue-500); | ||||||
|  | 	background-color: white; | ||||||
|  | 	border: 1px solid var(--blue-500); | ||||||
|  | 	--icon-stroke: var(--blue-500); | ||||||
|  | 
 | ||||||
|  | 	&:hover { | ||||||
|  | 		background-color: var(--blue-500); | ||||||
|  | 		color: white; | ||||||
|  | 		--icon-stroke: white; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .remove-wish { | ||||||
|  | 	&:hover { | ||||||
|  | 		background-color: var(--gray-100); | ||||||
|  | 		border: 1px solid var(--icon-stroke); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .wish-removed { | ||||||
|  | 	display: none; | ||||||
|  | } | ||||||
|  | |||||||
| @ -118,7 +118,6 @@ | |||||||
| 	'text-left': align == 'Left' or is_featured, | 	'text-left': align == 'Left' or is_featured, | ||||||
| }) -%} | }) -%} | ||||||
| <div class="card-body {{ align_class }}" style="width:100%"> | <div class="card-body {{ align_class }}" style="width:100%"> | ||||||
| 
 |  | ||||||
| 	<div style="margin-top: 16px; display: flex;"> | 	<div style="margin-top: 16px; display: flex;"> | ||||||
| 		<a href="/{{ item.route or '#' }}"> | 		<a href="/{{ item.route or '#' }}"> | ||||||
| 			<div class="product-title">{{ title or '' }}</div> | 			<div class="product-title">{{ title or '' }}</div> | ||||||
| @ -128,7 +127,9 @@ | |||||||
| 		{% endif %} | 		{% endif %} | ||||||
| 		{% if not item.has_variants %} | 		{% if not item.has_variants %} | ||||||
| 			<div class="like-action" | 			<div class="like-action" | ||||||
| 				data-item-code="{{ item.item_code }}" data-price="{{ item.price }}"> | 				data-item-code="{{ item.item_code }}" | ||||||
|  | 				data-price="{{ item.price }}" | ||||||
|  | 				data-formatted-price="{{ item.get('formatted_price') }}"> | ||||||
| 				<svg class="icon sm"> | 				<svg class="icon sm"> | ||||||
| 					{%- set icon_class = "wished" if item.wished else "not-wished"-%} | 					{%- set icon_class = "wished" if item.wished else "not-wished"-%} | ||||||
| 					<use class="{{ icon_class }} wish-icon" href="#icon-heart"></use> | 					<use class="{{ icon_class }} wish-icon" href="#icon-heart"></use> | ||||||
| @ -161,3 +162,63 @@ | |||||||
| 	{% endif %} | 	{% endif %} | ||||||
| </div> | </div> | ||||||
| {%- endmacro -%} | {%- endmacro -%} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {%- macro wishlist_card(item, settings) %} | ||||||
|  | <div class="col-sm-3 item-card" style="min-width: 220px;"> | ||||||
|  | 	<div class="card text-center"> | ||||||
|  | 		{% if item.image %} | ||||||
|  | 			<div class="card-img-container"> | ||||||
|  | 				<a href="/{{ item.route or '#' }}" style="text-decoration: none;"> | ||||||
|  | 					<img class="card-img" src="{{ item.image }}" alt="{{ title }}"> | ||||||
|  | 				</a> | ||||||
|  | 				<div class="remove-wish" | ||||||
|  | 					style="position:absolute; top:10px; right: 20px; border-radius: 50%; border: 1px solid var(--gray-100); width: 25px; height: 25px;" | ||||||
|  | 					data-item-code="{{ item.item_code }}"> | ||||||
|  | 					<span style="padding-bottom: 2px;"> | ||||||
|  | 						<svg class="icon sm remove-wish-icon" style="margin-bottom: 4px; margin-left: 0.5px;"> | ||||||
|  | 							<use class="close" href="#icon-close"></use> | ||||||
|  | 						</svg> | ||||||
|  | 					</span> | ||||||
|  | 				</div> | ||||||
|  | 
 | ||||||
|  | 			</div> | ||||||
|  | 		{% else %} | ||||||
|  | 		<a href="/{{ item.route or '#' }}" style="text-decoration: none;"> | ||||||
|  | 			<div class="card-img-top no-image"> | ||||||
|  | 				{{ frappe.utils.get_abbr(title) }} | ||||||
|  | 			</div> | ||||||
|  | 		</a> | ||||||
|  | 		{% endif %} | ||||||
|  | 
 | ||||||
|  | 		{{ wishlist_card_body(item, settings) }} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | {%- endmacro -%} | ||||||
|  | 
 | ||||||
|  | {%- macro wishlist_card_body(item, settings) %} | ||||||
|  | <div class="card-body text-center" style="width:100%"> | ||||||
|  | 	<div style="margin-top: 16px;"> | ||||||
|  | 		<div class="product-title">{{ item.item_name or item.item_code or ''}}</div> | ||||||
|  | 	</div> | ||||||
|  | 	<div class="product-price">{{ item.formatted_price or '' }}</div> | ||||||
|  | 
 | ||||||
|  | 	{% if (item.available and settings.show_stock_availability) or (not settings.show_stock_availability) %} | ||||||
|  | 	<!-- Show move to cart button if in stock or if showing stock availability is disabled --> | ||||||
|  | 	<button data-item-code="{{ item.item_code}}" class="btn btn-add-to-cart w-100 wishlist-cart-not-added"> | ||||||
|  | 		<span class="mr-2"> | ||||||
|  | 			<svg class="icon icon-md"> | ||||||
|  | 				<use href="#icon-assets"></use> | ||||||
|  | 			</svg> | ||||||
|  | 		</span> | ||||||
|  | 		{{ _("Move to Cart") }} | ||||||
|  | 	</button> | ||||||
|  | 	{% else %} | ||||||
|  | 	<div style="color: #F47A7A; width: 100%;"> | ||||||
|  | 		{{ _("Not in Stock") }} | ||||||
|  | 	</div> | ||||||
|  | 	{% endif %} | ||||||
|  | </div> | ||||||
|  | {%- endmacro -%} | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ | |||||||
| 		</a> | 		</a> | ||||||
| 	</li> | 	</li> | ||||||
| 	<li class="wishlist wishlist-icon hidden"> | 	<li class="wishlist wishlist-icon hidden"> | ||||||
| 		<a class="nav-link" href="/cart"> | 		<a class="nav-link" href="/wishlist"> | ||||||
| 			<svg class="icon icon-lg"> | 			<svg class="icon icon-lg"> | ||||||
| 				<use href="#icon-heart"></use> | 				<use href="#icon-heart"></use> | ||||||
| 			</svg> | 			</svg> | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								erpnext/templates/pages/wishlist.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								erpnext/templates/pages/wishlist.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | {% extends "templates/web.html" %} | ||||||
|  | 
 | ||||||
|  | {% block title %} {{ _("Wishlist") }} {% endblock %} | ||||||
|  | 
 | ||||||
|  | {% block header %}<h3 class="shopping-cart-header mt-2 mb-6">{{ _("Wishlist") }}</h1>{% endblock %} | ||||||
|  | 
 | ||||||
|  | {% block page_content %} | ||||||
|  | {% if items %} | ||||||
|  | 	<div class="row"> | ||||||
|  | 		<div class="col-12 col-md-11 item-card-group-section"> | ||||||
|  | 			<div class="row products-list"> | ||||||
|  | 					{% from "erpnext/templates/includes/macros.html" import wishlist_card %} | ||||||
|  | 					{% for item in items %} | ||||||
|  | 						{{ wishlist_card(item, settings) }} | ||||||
|  | 					{% endfor %} | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% else %} | ||||||
|  | 	<!-- TODO: Make empty state for wishlist --> | ||||||
|  | 	{% include "erpnext/www/all-products/not_found.html" %} | ||||||
|  | {% endif %} | ||||||
|  | 
 | ||||||
|  | {% endblock %} | ||||||
							
								
								
									
										39
									
								
								erpnext/templates/pages/wishlist.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								erpnext/templates/pages/wishlist.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors | ||||||
|  | # License: GNU General Public License v3. See license.txt | ||||||
|  | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
|  | no_cache = 1 | ||||||
|  | 
 | ||||||
|  | import frappe | ||||||
|  | from erpnext.e_commerce.shopping_cart.cart import get_cart_quotation | ||||||
|  | 
 | ||||||
|  | def get_context(context): | ||||||
|  | 	settings = frappe.get_doc("E Commerce Settings") | ||||||
|  | 	items = get_wishlist_items() | ||||||
|  | 
 | ||||||
|  | 	if settings.show_stock_availability: | ||||||
|  | 		for item in items: | ||||||
|  | 			stock_qty = frappe.utils.flt( | ||||||
|  | 				frappe.db.get_value("Bin", | ||||||
|  | 					{ | ||||||
|  | 						"item_code": item.item_code, | ||||||
|  | 						"warehouse": item.get("warehouse") | ||||||
|  | 					}, | ||||||
|  | 					"actual_qty") | ||||||
|  | 				) | ||||||
|  | 			item.available = True if stock_qty else False | ||||||
|  | 
 | ||||||
|  | 	context.items = items | ||||||
|  | 	context.settings = settings | ||||||
|  | 
 | ||||||
|  | def get_wishlist_items(): | ||||||
|  | 	if frappe.db.exists("Wishlist", frappe.session.user): | ||||||
|  | 		return frappe.db.sql(""" | ||||||
|  | 			Select | ||||||
|  | 				item_code, item_name, website_item, price, | ||||||
|  | 				warehouse, image, item_group, route, formatted_price | ||||||
|  | 			from | ||||||
|  | 				`tabWishlist Items` | ||||||
|  | 			where | ||||||
|  | 				parent=%(user)s"""%{"user": frappe.db.escape(frappe.session.user)}, as_dict=1) | ||||||
|  | 	return | ||||||
| @ -73,98 +73,8 @@ $(() => { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bind_card_actions() { | 		bind_card_actions() { | ||||||
| 			this.bind_add_to_cart_action(); | 			erpnext.shopping_cart.bind_add_to_cart_action(); | ||||||
| 			this.bind_wishlist_action(); | 			erpnext.wishlist.bind_wishlist_action(); | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		bind_add_to_cart_action() { |  | ||||||
| 			$('.page_content').on('click', '.btn-add-to-cart-list', (e) => { |  | ||||||
| 				const $btn = $(e.currentTarget); |  | ||||||
| 				$btn.prop('disabled', true); |  | ||||||
| 
 |  | ||||||
| 				this.animate_add_to_cart($btn); |  | ||||||
| 
 |  | ||||||
| 				const item_code = $btn.data('item-code'); |  | ||||||
| 				erpnext.shopping_cart.update_cart({ |  | ||||||
| 					item_code, |  | ||||||
| 					qty: 1 |  | ||||||
| 				}); |  | ||||||
| 
 |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		animate_add_to_cart(button) { |  | ||||||
| 			// Create 'added to cart' animation
 |  | ||||||
| 			let btn_id = "#" + button[0].id; |  | ||||||
| 			this.toggle_button_class(button, 'not-added', 'added-to-cart'); |  | ||||||
| 			$(btn_id).text('Added to Cart'); |  | ||||||
| 
 |  | ||||||
| 			// undo
 |  | ||||||
| 			setTimeout(() => { |  | ||||||
| 				this.toggle_button_class(button, 'added-to-cart', 'not-added'); |  | ||||||
| 				$(btn_id).text('Add to Cart'); |  | ||||||
| 			}, 2000); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		bind_wishlist_action() { |  | ||||||
| 			$('.page_content').on('click', '.like-action', (e) => { |  | ||||||
| 				const $btn = $(e.currentTarget); |  | ||||||
| 				const $wish_icon = $btn.find('.wish-icon'); |  | ||||||
| 				let me = this; |  | ||||||
| 
 |  | ||||||
| 				if ($wish_icon.hasClass('wished')) { |  | ||||||
| 					// un-wish item
 |  | ||||||
| 					$btn.removeClass("like-animate"); |  | ||||||
| 					this.toggle_button_class($wish_icon, 'wished', 'not-wished'); |  | ||||||
| 					frappe.call({ |  | ||||||
| 						type: "POST", |  | ||||||
| 						method: "erpnext.e_commerce.doctype.wishlist.wishlist.remove_from_wishlist", |  | ||||||
| 						args: { |  | ||||||
| 							item_code: $btn.data('item-code') |  | ||||||
| 						}, |  | ||||||
| 						callback: function (r) { |  | ||||||
| 							if (r.exc) { |  | ||||||
| 								me.toggle_button_class($wish_icon, 'wished', 'not-wished'); |  | ||||||
| 								frappe.msgprint({ |  | ||||||
| 									message: __("Sorry, something went wrong. Please refresh."), |  | ||||||
| 									indicator: "red", |  | ||||||
| 									title: __("Note")} |  | ||||||
| 								); |  | ||||||
| 							} else { |  | ||||||
| 								erpnext.e_commerce.set_wishlist_count(); |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 					}); |  | ||||||
| 				} else { |  | ||||||
| 					$btn.addClass("like-animate"); |  | ||||||
| 					this.toggle_button_class($wish_icon, 'not-wished', 'wished'); |  | ||||||
| 					frappe.call({ |  | ||||||
| 						type: "POST", |  | ||||||
| 						method: "erpnext.e_commerce.doctype.wishlist.wishlist.add_to_wishlist", |  | ||||||
| 						args: { |  | ||||||
| 							item_code: $btn.data('item-code'), |  | ||||||
| 							price: $btn.data('price') |  | ||||||
| 						}, |  | ||||||
| 						callback: function (r) { |  | ||||||
| 							if (r.exc) { |  | ||||||
| 								me.toggle_button_class($wish_icon, 'wished', 'not-wished'); |  | ||||||
| 								frappe.msgprint({ |  | ||||||
| 									message: __("Sorry, something went wrong. Please refresh."), |  | ||||||
| 									indicator: "red", |  | ||||||
| 									title: __("Note")} |  | ||||||
| 								); |  | ||||||
| 							} else { |  | ||||||
| 								erpnext.e_commerce.set_wishlist_count(); |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		toggle_button_class(button, remove, add) { |  | ||||||
| 			button.removeClass(remove); |  | ||||||
| 			button.addClass(add); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bind_search() { | 		bind_search() { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user