Improved Client implementation
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 824b9b8..66ac5fe 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -55,7 +55,7 @@
         "stock/dashboard/item_dashboard_list.html",
         "stock/dashboard/item_dashboard.js"
     ],
-    "js/web-academy.min.js": [
-        "public/js/education/web-academy.js"
+    "js/academy.min.js": [
+        "public/js/education/academy/academy.js"
     ]
 }
diff --git a/erpnext/public/js/education/web-academy/AcademyRoot.vue b/erpnext/public/js/education/academy/AcademyRoot.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/AcademyRoot.vue
rename to erpnext/public/js/education/academy/AcademyRoot.vue
diff --git a/erpnext/public/js/education/web-academy.js b/erpnext/public/js/education/academy/academy.js
similarity index 79%
rename from erpnext/public/js/education/web-academy.js
rename to erpnext/public/js/education/academy/academy.js
index 8088a50..08cfc37 100644
--- a/erpnext/public/js/education/web-academy.js
+++ b/erpnext/public/js/education/academy/academy.js
@@ -1,21 +1,20 @@
 import Vue from 'vue/dist/vue.js';
 import VueRouter from 'vue-router/dist/vue-router.js'
 
-import AcademyRoot from "./web-academy/AcademyRoot.vue";
-import AcademyHome from "./web-academy/pages/AcademyHome.vue";
-import AcademyProgramPage from "./web-academy/pages/AcademyProgramPage.vue";
-import AcademyCoursePage from "./web-academy/pages/AcademyCoursePage.vue";
+import AcademyRoot from "./AcademyRoot.vue";
+import routes from './routes';
+import './call';
 
 Vue.use(VueRouter)
 
 
-const routes = [
-	{name: 'home', path: '', component: AcademyHome},
-	{name: 'program', path: '/Program/:code', component: AcademyProgramPage, props: true},
-	{name: 'content', path: '/Program/:code/:course/:type/:content', component: AcademyCoursePage, props: true},
-];
 
-var store = {
+
+frappe.provide('academy')
+
+frappe.utils.make_event_emitter(academy);
+
+academy.store = {
 	debug: true,
 	isLogin: false,
 	completedCourses: new Set(),
@@ -104,19 +103,13 @@
 		this.updateEnrolledPrograms()
 		this.updateEnrolledCourses()
 		this.checkLogin()
-
 	},
 }
 
-const router = new VueRouter({
-	routes: routes,
-});
-
 frappe.ready(() => {
 	window.v = new Vue({
 		el: "#academy",
-		router: router,
-		data: store,
+		router: new VueRouter({ routes }),
 		template: "<academy-root/>",
 		components: { AcademyRoot },
 		created: function() {
@@ -125,4 +118,20 @@
 			}
 		}
 	});
+	academy.store = new Vue({
+		data: store,
+		methods: {
+			checkLogin (){
+				if(frappe.session.user === "Guest"){
+					if (this.debug) console.log('No Session')
+					this.isLogin = false
+				}
+				else {
+					if (this.debug) console.log('Current User: ', frappe.session.user)
+					this.isLogin = true
+				}
+				return this.isLogin
+			}
+		}
+	});
 })
\ No newline at end of file
diff --git a/erpnext/public/js/education/academy/call.js b/erpnext/public/js/education/academy/call.js
new file mode 100644
index 0000000..108a6e1
--- /dev/null
+++ b/erpnext/public/js/education/academy/call.js
@@ -0,0 +1,13 @@
+frappe.provide('academy');
+
+academy.call = (method, args) => {
+    const method_path = 'erpnext.www.academy.' + method;
+    return new Promise((resolve, reject) => {
+        return frappe.call({
+            method: method_path,
+            args,
+        })
+        .then(r => resolve(r.message))
+        .fail(reject)
+    });
+}
\ No newline at end of file
diff --git a/erpnext/public/js/education/academy/components/AcademyCourseCard.vue b/erpnext/public/js/education/academy/components/AcademyCourseCard.vue
new file mode 100644
index 0000000..eda382f
--- /dev/null
+++ b/erpnext/public/js/education/academy/components/AcademyCourseCard.vue
@@ -0,0 +1,94 @@
+<template>
+<div class="card mt-3" data-list="getting-started">
+    <div class='card-body'>
+        <div class="row">
+            <div class="course-details col-xs-8 col-sm-9 col-md-10">
+                <h5 class="card-title">{{ course.course_name }}</h5>
+                <span class="course-list text-muted" id="getting-started">
+                    Course Content
+                    <ul class="mb-0 mt-1">
+                            <li v-for="content in course.course_content" :key="content.name">{{ content.content }}</li>
+                    </ul>
+                </span>
+            </div>
+            <div v-if="$root.$data.isLogin" class='course-buttons text-center col-xs-4 col-sm-3 col-md-2'>
+                <!-- <AcademyCourseCardButton
+                    v-if="this.$root.$data.checkProgramEnrollment(this.$route.params.code)"
+                    :course="course.name"
+                    :nextContent="nextContent"
+                    :nextContentType="nextContentType"
+                /> -->
+
+                <a-button
+                    v-if="showCompleted"
+                    type="success"
+                    size="sm"
+                    :route="firstContentRoute"
+                >
+                    Completed
+                </a-button>
+                <a-button
+                    v-if="showStart"
+                    type="primary"
+                    size="sm"
+                    :route="firstContentRoute"
+                >
+                    Start
+                </a-button>
+            </div>
+        </div>
+    </div>
+</div>
+</template>
+
+<script>
+import AButton from './Button';
+import AcademyCourseCardButton from './AcademyCourseCardButton.vue'
+
+export default {
+    props: ['course'],
+    name: "AcademyCourseCard",
+    data() {
+        return {
+            nextContent: '',
+            nextContentType: ''
+        }
+    },
+    mounted() {
+        if(this.$root.$data.checkLogin()) {
+            frappe.call({
+                method: "erpnext.www.academy.get_starting_content",
+                args: {
+                    course_name: this.course.name
+                }
+            }).then(r => {
+                this.nextContent = r.message.content,
+                this.nextContentType = r.message.content_type
+            });
+        }
+    },
+    components: {
+        AcademyCourseCardButton,
+        AButton
+    },
+    computed: {
+        showStart() {
+            return academy.loggedIn && !this.course.completed;
+        },
+        showCompleted() {
+            return academy.loggedIn && this.course.completed;
+        },
+        firstContentRoute() {
+            return `${course.name}/${course.content_type}/${data.content}`
+        }
+    }
+};
+</script>
+
+<style scoped>
+    @media only screen and (max-width: 576px) {
+    .course-buttons {
+        margin-top: 1em;
+    }
+}
+</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/web-academy/components/AcademyCourseCardButton.vue b/erpnext/public/js/education/academy/components/AcademyCourseCardButton.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/AcademyCourseCardButton.vue
rename to erpnext/public/js/education/academy/components/AcademyCourseCardButton.vue
diff --git a/erpnext/public/js/education/web-academy/components/AcademyList.vue b/erpnext/public/js/education/academy/components/AcademyList.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/AcademyList.vue
rename to erpnext/public/js/education/academy/components/AcademyList.vue
diff --git a/erpnext/public/js/education/web-academy/components/AcademyProgramCard.vue b/erpnext/public/js/education/academy/components/AcademyProgramCard.vue
similarity index 92%
rename from erpnext/public/js/education/web-academy/components/AcademyProgramCard.vue
rename to erpnext/public/js/education/academy/components/AcademyProgramCard.vue
index 605dec2..ef3ac08 100644
--- a/erpnext/public/js/education/web-academy/components/AcademyProgramCard.vue
+++ b/erpnext/public/js/education/academy/components/AcademyProgramCard.vue
@@ -38,14 +38,14 @@
     methods: {
         primaryAction(){
             if(this.$root.$data.isLogin){
-                if(this.$root.$data.checkProgramEnrollment(program_code)){
+                if(this.$root.$data.checkProgramEnrollment(this.program_code)){
                     this.$router.push('/Program/' + program.name)
                 }
                 else {
                     this.enroll()
                 }
             }
-        }
+        },
         enroll() {
             frappe.call({
                 method: "erpnext.www.academy.enroll_in_program",
@@ -57,11 +57,11 @@
             this.$root.$data.enrolledPrograms.add(this.program_code)
             this.$root.$data.updateEnrolledPrograms()
         }
-    }
+    },
     computed: {
         buttonName() {
             if(this.$root.$data.isLogin){
-                if(this.$root.$data.checkProgramEnrollment(program_code)){
+                if(this.$root.$data.checkProgramEnrollment(this.program_code)){
                     return "Start Course"
                 }
                 else {
diff --git a/erpnext/public/js/education/web-academy/components/AcademyTopSection.vue b/erpnext/public/js/education/academy/components/AcademyTopSection.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/AcademyTopSection.vue
rename to erpnext/public/js/education/academy/components/AcademyTopSection.vue
diff --git a/erpnext/public/js/education/web-academy/components/AcademyTopSectionButton.vue b/erpnext/public/js/education/academy/components/AcademyTopSectionButton.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/AcademyTopSectionButton.vue
rename to erpnext/public/js/education/academy/components/AcademyTopSectionButton.vue
diff --git a/erpnext/public/js/education/academy/components/Button.vue b/erpnext/public/js/education/academy/components/Button.vue
new file mode 100644
index 0000000..4d8df4b
--- /dev/null
+++ b/erpnext/public/js/education/academy/components/Button.vue
@@ -0,0 +1,25 @@
+<template>
+	<button :class="classList" v-on="$listeners" v-bind="$attrs" @click="goToRoute">
+		<slot></slot>
+	</button>
+</template>
+<script>
+export default {
+	name: 'AButton',
+	props: ['type', 'size', 'route'],
+	computed: {
+		classList() {
+			return [
+				'btn',
+				'btn-' + this.type,
+				'btn-' + this.size
+			]
+		}
+	},
+	methods: {
+		goToRoute() {
+			this.$router.push(this.route);
+		}
+	}
+}
+</script>
diff --git a/erpnext/public/js/education/web-academy/components/ContentArticle.vue b/erpnext/public/js/education/academy/components/ContentArticle.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/ContentArticle.vue
rename to erpnext/public/js/education/academy/components/ContentArticle.vue
diff --git a/erpnext/public/js/education/web-academy/components/ContentNavigation.vue b/erpnext/public/js/education/academy/components/ContentNavigation.vue
similarity index 92%
rename from erpnext/public/js/education/web-academy/components/ContentNavigation.vue
rename to erpnext/public/js/education/academy/components/ContentNavigation.vue
index 28f5a70..7fa20a5 100644
--- a/erpnext/public/js/education/web-academy/components/ContentNavigation.vue
+++ b/erpnext/public/js/education/academy/components/ContentNavigation.vue
@@ -41,9 +41,12 @@
 						enrollment: this.$root.$data.enrolledCourses[this.$route.params.course]
 					}
 				})
-			this.$root.$data.addCompletedCourses(this.$route.params.course)
+			// this.$root.$data.addCompletedCourses(this.$route.params.course)
 			this.$root.$data.updateCompletedCourses()
 			this.$router.push({ name: 'program', params: { code: this.$route.params.code}})
+
+			//
+			academy.trigger('course-completed', course_name);
 		}
 	}
 };
diff --git a/erpnext/public/js/education/web-academy/components/ContentQuiz.vue b/erpnext/public/js/education/academy/components/ContentQuiz.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/ContentQuiz.vue
rename to erpnext/public/js/education/academy/components/ContentQuiz.vue
diff --git a/erpnext/public/js/education/web-academy/components/ContentTitle.vue b/erpnext/public/js/education/academy/components/ContentTitle.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/ContentTitle.vue
rename to erpnext/public/js/education/academy/components/ContentTitle.vue
diff --git a/erpnext/public/js/education/web-academy/components/ContentVideo.vue b/erpnext/public/js/education/academy/components/ContentVideo.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/ContentVideo.vue
rename to erpnext/public/js/education/academy/components/ContentVideo.vue
diff --git a/erpnext/public/js/education/web-academy/components/Quiz/QuizSingleChoice.vue b/erpnext/public/js/education/academy/components/Quiz/QuizSingleChoice.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/components/Quiz/QuizSingleChoice.vue
rename to erpnext/public/js/education/academy/components/Quiz/QuizSingleChoice.vue
diff --git a/erpnext/public/js/education/web-academy/pages/AcademyCoursePage.vue b/erpnext/public/js/education/academy/pages/AcademyCoursePage.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/pages/AcademyCoursePage.vue
rename to erpnext/public/js/education/academy/pages/AcademyCoursePage.vue
diff --git a/erpnext/public/js/education/web-academy/pages/AcademyHome.vue b/erpnext/public/js/education/academy/pages/AcademyHome.vue
similarity index 100%
rename from erpnext/public/js/education/web-academy/pages/AcademyHome.vue
rename to erpnext/public/js/education/academy/pages/AcademyHome.vue
diff --git a/erpnext/public/js/education/academy/pages/AcademyProgramPage.vue b/erpnext/public/js/education/academy/pages/AcademyProgramPage.vue
new file mode 100644
index 0000000..7bea1ed
--- /dev/null
+++ b/erpnext/public/js/education/academy/pages/AcademyProgramPage.vue
@@ -0,0 +1,73 @@
+<template>
+<div>
+	<AcademyTopSection v-bind:title="program.program_name" v-bind:description="program.description">
+        <!-- <AcademyTopSectionButton/> -->
+		<a-button @click="startCourse">Start Course</a-button>
+		<a-button @click="continueCourse">Continue Course</a-button>
+    </AcademyTopSection>
+	<AcademyList :title="'Courses'" :description="''">
+        <AcademyCourseCard v-for="course in course_list" :course="course" :key="course.name"/>
+    </AcademyList>
+</div>
+</template>
+<script>
+import Button from '../components/Button.vue';
+import AcademyTopSection from "../components/AcademyTopSection.vue"
+import AcademyList from "../components/AcademyList.vue"
+import AcademyCourseCard from "../components/AcademyCourseCard.vue"
+import AcademyTopSectionButton from "../components/AcademyTopSectionButton.vue";
+
+
+export default {
+	props: ['program_name'],
+    name: "AcademyProgramPage",
+    components: {
+        AButton: Button,
+		AcademyTopSection,
+		AcademyList,
+		AcademyCourseCard,
+        AcademyTopSectionButton
+	},
+	data() {
+		return {
+			program: {},
+			course_list: []
+		}
+	},
+    beforeMount() {
+        if(this.$root.$data.isLogin) this.$root.$data.updateCompletedCourses()
+    },
+	mounted() {
+		this.getProgramDetails().then(data => this.program = data);
+		this.getCourses().then(data => this.course_list = data);
+		
+		academy.on(`course-completed`, (course_name) => {
+			const course = this.course_list.findIndex(c => c.name === course_name);
+			this.course_list[course].completed = true;
+		});
+	},
+	methods: {
+		startCourse() {
+			this.getContentForNextCourse()
+				.then((data) => 
+					this.$router.push(`/Program/${this.program_name}/${data.course}/${data.content_type}/${data.content}`)
+				)
+		},
+		getContentForNextCourse() {
+			return academy.call('get_continue_data', {
+				program_name: this.program_name
+			});
+		},
+		getProgramDetails() {
+			return academy.call('get_program_details', {
+				program_name: this.program_name
+			});
+		},
+		getCourses() {
+			return academy.call('get_courses', {
+				program_name: this.program_name
+			})
+		}
+	}
+};
+</script>
\ No newline at end of file
diff --git a/erpnext/public/js/education/academy/routes.js b/erpnext/public/js/education/academy/routes.js
new file mode 100644
index 0000000..51c280d
--- /dev/null
+++ b/erpnext/public/js/education/academy/routes.js
@@ -0,0 +1,11 @@
+import AcademyHome from "./academy/pages/AcademyHome.vue";
+import AcademyProgramPage from "./academy/pages/AcademyProgramPage.vue";
+import AcademyCoursePage from "./academy/pages/AcademyCoursePage.vue";
+
+const routes = [
+	{name: 'home', path: '', component: AcademyHome},
+	{name: 'program', path: '/Program/:program_name', component: AcademyProgramPage, props: true},
+	{name: 'content', path: '/Program/:code/:course/:type/:content', component: AcademyCoursePage, props: true},
+];
+
+export default routes;
\ No newline at end of file
diff --git a/erpnext/public/js/education/web-academy/components/AcademyCourseCard.vue b/erpnext/public/js/education/web-academy/components/AcademyCourseCard.vue
deleted file mode 100644
index 9c47473..0000000
--- a/erpnext/public/js/education/web-academy/components/AcademyCourseCard.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-<template>
-<div class="card mt-3" data-list="getting-started">
-    <div class='card-body'>
-        <div class="row">
-            <div class="course-details col-xs-8 col-sm-9 col-md-10">
-                <h5 class="card-title">{{ course.course_name }}</h5>
-                <span class="course-list text-muted" id="getting-started">
-                    Course Content
-                    <ul class="mb-0 mt-1">
-                            <li v-for="content in course.course_content" :key="content.name">{{ content.content }}</li>
-                    </ul>
-                </span>
-            </div>
-            <div v-if="$root.$data.isLogin" class='course-buttons text-center col-xs-4 col-sm-3 col-md-2'>
-                <AcademyCourseCardButton v-if="this.$root.$data.checkProgramEnrollment(this.$route.params.code)" :course="course.name" :nextContent="nextContent" :nextContentType="nextContentType"/>
-            </div>
-        </div>
-    </div>
-</div>
-</template>
-
-<script>
-import AcademyCourseCardButton from './AcademyCourseCardButton.vue'
-
-export default {
-    props: ['course'],
-    name: "AcademyCourseCard",
-    data() {
-        return {
-            nextContent: '',
-            nextContentType: ''
-        }
-    },
-    mounted() {
-        if(this.$root.$data.checkLogin()){
-            frappe.call({
-                method: "erpnext.www.academy.get_starting_content",
-                args: {
-                    course_name: this.course.name
-                }
-            }).then(r => {
-                this.nextContent = r.message.content,
-                this.nextContentType = r.message.content_type
-            });
-        }
-    },
-    components: {
-        AcademyCourseCardButton
-    }
-};
-</script>
-
-<style scoped>
-    @media only screen and (max-width: 576px) {
-    .course-buttons {
-        margin-top: 1em;
-    }
-}
-</style>
\ No newline at end of file
diff --git a/erpnext/public/js/education/web-academy/pages/AcademyProgramPage.vue b/erpnext/public/js/education/web-academy/pages/AcademyProgramPage.vue
deleted file mode 100644
index 030c3ed..0000000
--- a/erpnext/public/js/education/web-academy/pages/AcademyProgramPage.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<template>
-<div>
-	<AcademyTopSection v-bind:title="program.program_name" v-bind:description="program.description">
-        <AcademyTopSectionButton/>
-    </AcademyTopSection>
-	<AcademyList :title="'Courses'" :description="''">
-        <AcademyCourseCard v-for="course in course_list" :course="course" :key="course.name"/>
-    </AcademyList>
-</div>
-</template>
-<script>
-import AcademyTopSection from "../components/AcademyTopSection.vue"
-import AcademyList from "../components/AcademyList.vue"
-import AcademyCourseCard from "../components/AcademyCourseCard.vue"
-import AcademyTopSectionButton from "../components/AcademyTopSectionButton.vue"
-
-export default {
-	props: ['code'],
-    name: "AcademyProgramPage",
-    components: {
-		AcademyTopSection,
-		AcademyList,
-		AcademyCourseCard,
-        AcademyTopSectionButton
-	},
-	data() {
-		return {
-			program: '',
-			course_list: []
-		}
-	},
-    beforeMount(){
-        if(this.$root.$data.isLogin) this.$root.$data.updateCompletedCourses()
-    },
-	mounted() {
-		frappe.call({
-            method: "erpnext.www.academy.get_program_details",
-            args: {
-                program_name: this.code
-            }
-        }).then(r => {
-    		this.program = r.message
-    	});
-    	frappe.call({
-    		method: "erpnext.www.academy.get_courses",
-    		args: {
-    			program_name: this.code
-    		}
-    	}).then(r => {
-    		this.course_list = r.message
-    	})
-	},
-};
-</script>
\ No newline at end of file