[hub][vue] Category and Published Products pages
diff --git a/erpnext/public/js/hub/marketplace.js b/erpnext/public/js/hub/marketplace.js
index b0e66ca..448ca42 100644
--- a/erpnext/public/js/hub/marketplace.js
+++ b/erpnext/public/js/hub/marketplace.js
@@ -3,18 +3,17 @@
 // pages
 import './pages/home';
 import './pages/search';
-import './pages/category';
 import './pages/item';
 import './pages/seller';
-import './pages/register';
 import './pages/profile';
-import './pages/published_products';
 import './pages/messages';
 import './pages/buying_messages';
 import './pages/not_found';
 
 import SavedProducts from './pages/SavedProducts.vue';
 import Publish from './pages/Publish.vue';
+import Category from './pages/Category.vue';
+import PublishedProducts from './pages/PublishedProducts.vue';
 
 // components
 import { ProfileDialog } from './components/profile_dialog';
@@ -179,7 +178,7 @@
 		}
 
 		if (route[1] === 'category' && route[2] && !this.subpages.category) {
-			this.subpages.category = new erpnext.hub.Category(this.$body);
+			this.subpages.category = new erpnext.hub.CategoryPage(this.$body);
 		}
 
 		if (route[1] === 'item' && route[2] && !this.subpages.item) {
@@ -212,7 +211,7 @@
 		}
 
 		if (route[1] === 'my-products' && !this.subpages['my-products']) {
-			this.subpages['my-products'] = new erpnext.hub.PublishedProducts(this.$body);
+			this.subpages['my-products'] = new erpnext.hub.PublishedProductsPage(this.$body);
 		}
 
 		if (route[1] === 'messages' && !this.subpages['messages']) {
@@ -304,3 +303,40 @@
 	}
 
 }
+
+erpnext.hub.CategoryPage = class {
+	constructor(parent) {
+		this.$wrapper = $(`<div id="vue-area-category">`).appendTo($(parent));
+
+		new Vue({
+			render: h => h(Category)
+		}).$mount('#vue-area-category');
+	}
+
+	show() {
+		$('[data-page-name="category"]').show();
+	}
+
+	hide() {
+		$('[data-page-name="category"]').hide();
+	}
+}
+
+erpnext.hub.PublishedProductsPage = class {
+	constructor(parent) {
+		this.$wrapper = $(`<div id="vue-area-published-products">`).appendTo($(parent));
+
+		new Vue({
+			render: h => h(PublishedProducts)
+		}).$mount('#vue-area-published-products');
+	}
+
+	show() {
+		$('[data-page-name="published-products"]').show();
+	}
+
+	hide() {
+		$('[data-page-name="published-products"]').hide();
+	}
+}
+
diff --git a/erpnext/public/js/hub/pages/Category.vue b/erpnext/public/js/hub/pages/Category.vue
new file mode 100644
index 0000000..c346ca9
--- /dev/null
+++ b/erpnext/public/js/hub/pages/Category.vue
@@ -0,0 +1,64 @@
+<template>
+	<div
+		class="marketplace-page"
+		:data-page-name="page_name"
+	>
+		<h5>{{ page_title }}</h5>
+
+		<item-cards-container
+			:items="items"
+			:item_id_fieldname="item_id_fieldname"
+			:on_click="go_to_item_details_page"
+			:empty_state_message="empty_state_message"
+		>
+		</item-cards-container>
+	</div>
+</template>
+
+<script>
+import ItemCardsContainer from '../components/ItemCardsContainer.vue';
+
+export default {
+	name: 'saved-products-page',
+	components: {
+		ItemCardsContainer
+	},
+	data() {
+		return {
+			page_name: frappe.get_route()[1],
+			category: frappe.get_route()[2],
+			items: [],
+			item_id_fieldname: 'hub_item_code',
+
+			// Constants
+			empty_state_message: __(`No products in this category yet.`)
+		};
+	},
+	computed: {
+		page_title() {
+			return __(this.category);
+		}
+	},
+	created() {
+		this.get_items();
+	},
+	methods: {
+		get_items() {
+			hub.call('get_items', {
+				filters: {
+					hub_category: this.category
+				}
+			})
+			.then((items) => {
+				this.items = items;
+			})
+		},
+
+		go_to_item_details_page(hub_item_code) {
+			frappe.set_route(`marketplace/item/${hub_item_code}`);
+		}
+	}
+}
+</script>
+
+<style scoped></style>
diff --git a/erpnext/public/js/hub/pages/PublishedProducts.vue b/erpnext/public/js/hub/pages/PublishedProducts.vue
new file mode 100644
index 0000000..cbebc03
--- /dev/null
+++ b/erpnext/public/js/hub/pages/PublishedProducts.vue
@@ -0,0 +1,60 @@
+<template>
+	<div
+		class="marketplace-page"
+		:data-page-name="page_name"
+	>
+		<h5>{{ page_title }}</h5>
+
+		<item-cards-container
+			:items="items"
+			:item_id_fieldname="item_id_fieldname"
+			:on_click="go_to_item_details_page"
+			:empty_state_message="empty_state_message"
+		>
+		</item-cards-container>
+	</div>
+</template>
+
+<script>
+import ItemCardsContainer from '../components/ItemCardsContainer.vue';
+
+export default {
+	name: 'saved-products-page',
+	components: {
+		ItemCardsContainer
+	},
+	data() {
+		return {
+			page_name: frappe.get_route()[1],
+			items: [],
+			item_id_fieldname: 'hub_item_code',
+
+			// Constants
+			page_title: __('Published Products'),
+			// TODO: Add empty state action
+			empty_state_message: __(`You haven't published any products yet. Publish.`)
+		};
+	},
+	created() {
+		this.get_items();
+	},
+	methods: {
+		get_items() {
+			hub.call('get_items', {
+				filters: {
+					hub_seller: hub.settings.company_email
+				}
+			})
+			.then((items) => {
+				this.items = items;
+			})
+		},
+
+		go_to_item_details_page(hub_item_code) {
+			frappe.set_route(`marketplace/item/${hub_item_code}`);
+		}
+	}
+}
+</script>
+
+<style scoped></style>
diff --git a/erpnext/public/js/hub/pages/SavedProducts.vue b/erpnext/public/js/hub/pages/SavedProducts.vue
index a80c7ec..a094a1c 100644
--- a/erpnext/public/js/hub/pages/SavedProducts.vue
+++ b/erpnext/public/js/hub/pages/SavedProducts.vue
@@ -26,7 +26,6 @@
 		return {
 			page_name: frappe.get_route()[1],
 			items: [],
-			all_items: [],
 			item_id_fieldname: 'hub_item_code',
 
 			// Constants
diff --git a/erpnext/public/js/hub/pages/category.js b/erpnext/public/js/hub/pages/category.js
deleted file mode 100644
index c279c1a..0000000
--- a/erpnext/public/js/hub/pages/category.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import SubPage from './subpage';
-import { get_item_card_container_html } from '../components/items_container';
-
-erpnext.hub.Category = class Category extends SubPage {
-	refresh() {
-		this.category = frappe.get_route()[2];
-		this.get_items_for_category(this.category)
-			.then(items => {
-				this.render(items);
-			});
-	}
-
-	get_items_for_category(category) {
-		this.$wrapper.find('.hub-items-container').empty();
-		return hub.call('get_items', {
-			filters: {
-				hub_category: category
-			}
-		});
-	}
-
-	render(items) {
-		const html = get_item_card_container_html(items, __(this.category));
-		this.$wrapper.append(html)
-	}
-}
diff --git a/erpnext/public/js/hub/pages/published_products.js b/erpnext/public/js/hub/pages/published_products.js
deleted file mode 100644
index 17c115e..0000000
--- a/erpnext/public/js/hub/pages/published_products.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import SubPage from './subpage';
-import { get_item_card_container_html } from '../components/items_container';
-
-erpnext.hub.PublishedProducts = class PublishedProducts extends SubPage {
-	get_items_and_render() {
-		this.$wrapper.find('.hub-items-container').empty();
-		this.get_published_products()
-			.then(items => this.render(items));
-	}
-
-	refresh() {
-		this.get_items_and_render();
-	}
-
-	render(items) {
-		const items_container = $(get_item_card_container_html(items, __('Your Published Products')));
-		this.$wrapper.append(items_container);
-	}
-
-	get_published_products() {
-		return hub.call('get_items', { hub_seller: hub.settings.company_email });
-	}
-}
diff --git a/erpnext/public/js/hub/pages/register.js b/erpnext/public/js/hub/pages/register.js
deleted file mode 100644
index 36b0842..0000000
--- a/erpnext/public/js/hub/pages/register.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import SubPage from './subpage';
-
-erpnext.hub.Register = class Register extends SubPage {
-	make_wrapper() {
-		super.make_wrapper();
-		this.$register_container = $(`<div class="row register-container">`)
-			.appendTo(this.$wrapper);
-		this.$form_container = $('<div class="col-md-8 col-md-offset-1 form-container">')
-			.appendTo(this.$wrapper);
-	}
-
-	refresh() {
-		this.$register_container.empty();
-		this.$form_container.empty();
-		this.render();
-	}
-
-	render() {
-		this.make_field_group();
-	}
-
-	make_field_group() {
-		const fields = [
-			{
-				fieldtype: 'Link',
-				fieldname: 'company',
-				label: __('Company'),
-				options: 'Company',
-				onchange: () => {
-					const value = this.field_group.get_value('company');
-
-					if (value) {
-						frappe.db.get_doc('Company', value)
-							.then(company => {
-								this.field_group.set_values({
-									country: company.country,
-									company_email: company.email,
-									currency: company.default_currency
-								});
-							});
-					}
-				}
-			},
-			{
-				fieldname: 'company_email',
-				label: __('Email'),
-				fieldtype: 'Data'
-			},
-			{
-				fieldname: 'country',
-				label: __('Country'),
-				fieldtype: 'Read Only'
-			},
-			{
-				fieldname: 'currency',
-				label: __('Currency'),
-				fieldtype: 'Read Only'
-			},
-			{
-				fieldtype: 'Text',
-				label: __('About your Company'),
-				fieldname: 'company_description'
-			}
-		];
-
-		this.field_group = new frappe.ui.FieldGroup({
-			parent: this.$form_container,
-			fields
-		});
-
-		this.field_group.make();
-
-		const default_company = frappe.defaults.get_default('company');
-		this.field_group.set_value('company', default_company);
-
-		this.$form_container.find('.form-column').append(`
-			<div class="text-right">
-				<button type="submit" class="btn btn-primary btn-register btn-sm">${__('Submit')}</button>
-			</div>
-		`);
-
-		this.$form_container.find('.form-message').removeClass('hidden small').addClass('h4').text(__('Become a Seller'))
-
-		this.$form_container.on('click', '.btn-register', (e) => {
-			this.register_seller();
-		});
-	}
-
-	register_seller() {
-		const form_values = this.field_group.get_values();
-
-		let values_filled = true;
-		const mandatory_fields = ['company', 'company_email', 'company_description'];
-		mandatory_fields.forEach(field => {
-			const value = form_values[field];
-			if (!value) {
-				this.field_group.set_df_property(field, 'reqd', 1);
-				values_filled = false;
-			}
-		});
-		if (!values_filled) return;
-
-		frappe.call({
-			method: 'erpnext.hub_node.doctype.hub_settings.hub_settings.register_seller',
-			args: form_values,
-			btn: $(e.currentTarget)
-		}).then(() => {
-			frappe.set_route('marketplace', 'publish');
-
-			erpnext.hub.trigger('seller-registered');
-		});
-	}
-}