Ngiler SH3LL 360
Home
Information
Create File
Create Folder
:
/
home
/
tbf
/
tbf.ro
/
resources
/
js
/
components
/
pages
/
Information Server
MySQL :
OFF
Perl :
OFF
CURL :
ON
WGET :
OFF
PKEXEC :
OFF
Directive
Local Value
IP Address
89.40.16.97
System
Linux server.atelieruldeit.ro 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64
User
tbf
PHP Version
7.3.33
Software
Apache
Doc root
Writable
close
Edit File :
CoursePage.vue
| Size :
21.21
KB
Copy
<template> <div class="content-page-course" v-if="loaded"> <div class="container data-course"> <div class="header-content d-flex align-items-center"> <div class="d-flex align-items-center"> <h2 class="title-course-header"> {{ courseData.name }} </h2> </div> </div> <div class=""> <!-- <div class="rating-course"> <router-link :to="{path: '/reviews/' + courseData.slug }" class="d-flex align-items-center"> <div class="star-rating"> <star :class="'star star-1 average-' + courseData.average_rating"></star> <star :class="'star star-2 average-' + courseData.average_rating"></star> <star :class="'star star-3 average-' + courseData.average_rating"></star> <star :class="'star star-4 average-' + courseData.average_rating"></star> <star :class="'star star-5 average-' + courseData.average_rating"></star> </div> <div class="no-reviews"> {{ courseData.reviews_count }} reviews </div> </router-link> </div> --> <div class="description-course"> {{ courseData.description }} </div> <div class="list-targets" v-if="courseData.checklist.length"> <div class="d-flex align-items-center target" v-for="checkItem in courseData.checklist"> <check style="fill: #666"></check> {{ checkItem.value }} </div> </div> <div class="video-box"> <img src="/build/images/image_text-video.png" class="image-course"> <div class="play_video" @click="startPresentation"> <play style="fill: #FFF"></play> </div> <div class="bar-video"> <div class="play-bar" @click="startPresentation"> <play style="fill: #FFF"></play> </div> <div class="progress-bar-video"> <div class="completed-progress" :style="'width: '+ courseData.percentage_completed +'%;'"></div> </div> </div> <div class="video-player"> <div class="video-course"> <div :id="'wistia_'+video_key" class="wistia_embed lessonEmbedTbf"> </div> </div> </div> <div class="next-course"> <div class="box-content"> <h4>Urmeaza {{ courseData.next_course.name }}</h4> <p>{{ courseData.next_course.description | truncate(200, '...')}}</p> <div class="buttons-next-course"> <div class="next_course_progress"> <div class="next_course_aut" @click="viewNextCourse"> <div class="start_position"> <icon-next-video fill="#FFF"></icon-next-video> <span>Urmatorul fundament</span> </div> <div class="end_position"> <div> <icon-next-video fill="#000"></icon-next-video> <span>Urmatorul fundament</span> </div> </div> </div> <div class="cancel_timeout" @click="cancelTimeOut"> Anuleaza </div> </div> <div class="random_course" @click="viewRandomCourse"> <icon-random-video></icon-random-video> <span>Fundament aleatoriu</span> </div> </div> </div> </div> </div> <h3 class="subtitle mb-80">Alte resurse</h3> <div id="lessons_box"> <div class="grouped-lessons" v-for="lesson in courseData.lessons"> <div class="list-lessons" id="accordion_lessons" v-if="lesson.type != 'qa'"> <div class="main-item"> <div class="lesson-item d-flex align-items-center" v-bind:class="[courseData.paid || lesson.free ? '' : 'block', lesson.complete ? 'complete' : '']" :data-item_id="lesson.id" @click="(courseData.paid || lesson.free) ? ((lesson.type == 'google_sheets' || lesson.type == 'google_docs') ? viewDocGoogle(lesson.google_url) : openFile(lesson.file)) : ''"> <div class="title-lesson"> {{ lesson.name }} </div> <div class="ml-auto column-right"> <span class="type-file" v-if="lesson.type == 'image'">fisier Imagine</span> <span class="type-file" v-if="lesson.type == 'document'">fisier PDF</span> <span class="type-file" v-if="lesson.type == 'google_sheets'">fisier Google Sheets</span> <span class="type-file" v-if="lesson.type == 'google_docs'">fisier Google Docs</span> <div class="icons-right" v-if="courseData.paid || lesson.free"> <icon-download class="icon-download"></icon-download> </div> <div class="block-lesson" v-else><img src="/build/images/lock.svg"></div> </div> </div> </div> </div> <div class="list-lessons" v-if="lesson.type == 'qa'"> <div class="main-item" v-for="questionItem in lesson.questions" v-click-outside="closeAccordion" :data-qa_id="questionItem.id" :data-lesson_id="lesson.id"> <div class="lesson-item d-flex align-items-center" :id="'lesson_' + lesson.id +'_'+ questionItem.id" v-bind:class="[courseData.paid || lesson.free ? '' : 'block', lesson.complete ? 'complete' : '']" :data-item_id="lesson.id" @click.prevent="toggleAccordion(lesson.id, questionItem.id)"> <div class="title-lesson"> {{ questionItem.title }} </div> <div class="ml-auto column-right"> <div class="icons-right" v-if="courseData.paid || lesson.free"> <icon-arr-down class="arrow-down"></icon-arr-down> <icon-close class="close-accordion"></icon-close> </div> <div class="block-lesson" v-else><img src="/build/images/lock.svg"></div> </div> </div> <div class="panel-answer"> <div class="answer-text" v-html="questionItem.answer"></div> </div> </div> </div> </div> </div> <hr class="hr_tbf" v-if="!courseData.paid"> <div class="summary_book" v-if="!courseData.paid"> <div class="d-flex align-items-start content-summary"> <div class="content-course"> <div class="d-flex flex-column"> <div class="item-include"> <check style="fill: #000"></check> 3 lectii in format audio si video </div> <div class="item-include"> <check style="fill: #000"></check> 2 templateuri printabile sau excel </div> <div class="item-include"> <check style="fill: #000"></check> acces online si prin aplicatia TBF (pe viata) </div> </div> </div> <div class="price-book"> <p class="name">Cursul {{ courseData.name }}</p> <p class="initial_price">Pret: {{ courseData.price }} € + TVA</p> <p class="total_price">Total: <strong>{{ courseData.price }} €</strong></p> </div> </div> </div> <hr class="hr_tbf" v-if="!courseData.paid" /> <div class="book-course" v-if="!courseData.paid"> <router-link :to="{path: '/cumpara/' + courseData.slug }" class="btn-tbf">COMANDA CURSUL</router-link> </div> <hr class="hr_tbf" v-if="courseData.relates.length"/> <h3 class="subtitle" v-if="courseData.relates.length">Ce sa urmaresti in continuareā¦</h3> <div class="related_courses" v-if="courseData.relates.length"> <div class="related_item" v-for="relatedItem in courseData.relates" @click="selectCourse(relatedItem)"> <div class="box"> <h5 class="title-course">{{ relatedItem.name }}</h5> <p class="short_description">{{ relatedItem.description }}</p> <!-- <div class="star-rating"> <star :class="'star star-1 average-' + relatedItem.average_rating"></star> <star :class="'star star-2 average-' + relatedItem.average_rating"></star> <star :class="'star star-3 average-' + relatedItem.average_rating"></star> <star :class="'star star-4 average-' + relatedItem.average_rating"></star> <star :class="'star star-5 average-' + relatedItem.average_rating"></star> </div> --> </div> </div> </div> <!-- <hr class="hr_tbf"> <div class="questions-actions"> <div class="box-grey left"> <p>Ai o intrebare buna pe tema acestui curs si consideri ca raspunsul autorului ar ajuta mai multi membri ai comunitatii?<br><br>Da click pe butonul de mai jos si daca intrebarea este votata, autorul va raspunde intr-un audio exclusiv.</p> <button class="btn-tbf" @click="showPopup('question')"><lock class="icon-lock"></lock> Pune o intrebare</button> </div> <div class="box-grey right"> <p>Ai finalizat cursul, ai implementat si acum vrei sa impartasesti rezultatele si efectele cursului cu alte persoane?<br><br>Da click pe butonul de mai jos, raspunde la intrebari, si reviewul tau va ajuta multe persoane indecise sa creasca.</p> <button class="btn-tbf" @click="showPopup('review')"><lock class="icon-lock"></lock> Adauga un review</button> </div> </div> --> <!-- <div class="popup_questions" v-if="show_popup"> <div class="box_white" v-if="courseData.percentage_completed < 70"> <h3>Ne pare rau</h3> <p>Pentru a putea pune o intrebare sau a lasa un review trebuie sa aveti minim 80% din curs completat</p> <button class="btn-tbf" @click="show_popup = !show_popup">Am inteles</button> </div> <div class="box_white" v-else-if="type_popup == 'review'"> <div class="add-review-component"> <h4>Lasa un review</h4> <div class="success-message" v-if="successMessageReview"> Review-ul a fost trimis, va multumim! </div> <div class="create-review d-flex align-items-center"> <div class="star-rating"> <star @click.native="setRating(1)" class="star star-1" @mouseover.native="addClassStar('hv-1')" @mouseleave.native="removeClassStar('hv-1')"></star> <star @click.native="setRating(2)" class="star star-2" @mouseover.native="addClassStar('hv-2')" @mouseleave.native="removeClassStar('hv-2')"></star> <star @click.native="setRating(3)" class="star star-3" @mouseover.native="addClassStar('hv-3')" @mouseleave.native="removeClassStar('hv-3')"></star> <star @click.native="setRating(4)" class="star star-4" @mouseover.native="addClassStar('hv-4')" @mouseleave.native="removeClassStar('hv-4')"></star> <star @click.native="setRating(5)" class="star star-5" @mouseover.native="addClassStar('hv-5')" @mouseleave.native="removeClassStar('hv-5')"></star> </div> <span>Acorda o nota</span> </div> <div class="textarea-review"> <textarea placeholder="Scrie review-ul tau pentru acest curs ..." rows="4" v-model="review.content"></textarea> </div> <div class="errors-review alert_errors" v-if="review_errors"></div> <div class="send-review"> <button class="tbf-btn-primary" @click="sendRating()">TRIMITE</button> <button class="tbf-btn-primary" @click="closeReview">INCHIDE</button> </div> </div> </div> <div class="box_white" v-else-if="type_popup == 'question'"> <div class="add-question-component"> <h4>Pune o intrebare</h4> <div class="success-message" v-if="successMessageQuestion"> Intrebarea a fost trimisa, va multumim! </div> <div class="title-question"> <input placeholder="Scrie o intrebare" type="text" v-model="question_title" class="input-tbf-text" v-bind:class="[errorDataQuestion['title'] ? 'error' : '']" @focus="removeClassError"> </div> <div class="textarea-review"> <textarea placeholder="Scrie o explicatie mai lunga referitoare la intrebare ..." rows="4" v-model="question_content"></textarea> </div> <div class="send-review"> <button class="tbf-btn-primary" @click="sendQuestion(courseData.id, $event)">TRIMITE</button> <button class="tbf-btn-primary" @click="closeQuestion">INCHIDE</button> </div> </div> </div> </div> --> </div> </div> </div> </template> <script> import File from "../icons/File"; import Star from "../icons/Star"; import Check from "../icons/Check"; import Play from "../icons/Play"; import Lock from "../icons/Lock"; import IconClose from "../icons/Close"; import IconArrDown from "../icons/ArrowDown"; import IconDownload from "../icons/Download"; import IconNextVideo from "../icons/NextVideo"; import IconRandomVideo from "../icons/RandomVideo"; var order_no = 0; export default { data(){ return { courseData: {}, publicPath: process.env.MIX_APP_URL, review: {}, review_errors: false, loaded: false, video_key: '', lesson_selected: '', video_play: 0, video_status: '', show_popup: false, type_popup: '', last_lesson: {}, loaded_video: false, question_title: '', question_content: '', errorDataQuestion: [], successMessageQuestion: false, successMessageReview: false, timeOutNextCourse: '', } }, components: { File, Star, Check, Play, Lock, IconClose, IconArrDown, IconDownload, IconNextVideo, IconRandomVideo }, directives: { 'click-outside': { bind: function (el, binding, vnode) { window['event_'+el.dataset.lesson_id+'_'+el.dataset.qa_id] = function (event) { if (!(el == event.target || el.contains(event.target))) { vnode.context[binding.expression](el.dataset.lesson_id, el.dataset.qa_id) } }; document.body.addEventListener('click', window['event_'+el.dataset.lesson_id+'_'+el.dataset.qa_id]) }, unbind: function (el) { document.body.removeEventListener('click', window['event_'+el.dataset.lesson_id+'_'+el.dataset.qa_id]) } } }, watch: { $route (to, from){ if (typeof this.$route.params.slugCourse != "undefined") { this.loaded = false; axios.get("/courseInfo/" + this.$route.params.slugCourse) .then(response => { this.courseData = response.data.courseData; this.loaded = true; this.video_key = response.data.courseData.video_presentation_key }) .catch(error => { if(error.response.status == 404){ this.$router.push("/404"); } }) }; } }, created() {}, async mounted() { if (typeof this.$route.params.slugCourse != "undefined") { await axios.get("/courseInfo/" + this.$route.params.slugCourse) .then(response => { this.courseData = response.data.courseData; this.loaded = true; this.video_key = response.data.courseData.video_presentation_key }) .catch(error => { if(error.response.status == 404){ this.$router.push("/404"); } }) }; }, methods: { openFile(file){ window.open(this.publicPath + "/attachments/" + file, "_blank"); }, setRating(value){ $(".star-rating .star").removeClass('selected sc-' + this.review.value); this.review.value = value; $(".star-rating .star").addClass('selected sc-' + value); }, sendRating(){ this.successMessageReview = false axios.post("/createReview", {rating: this.review.value, content: this.review.content, course_id: this.courseData.id}) .then(response => { this.review_errors = false; this.$set(this.courseData, 'average_rating', response.data.average_rating); this.$set(this.courseData, 'reviews_count', response.data.reviews_count); this.successMessageReview = true; $(e.target).attr('disabled', false); }) .catch(error => { var html_errors = ''; $.each(error.response.data.errors, function( index, value ) { html_errors += value; }); this.review_errors = true; }) .finally(() => { if(this.review_errors){ $('.errors-review').html('Ratingul este obligatoriu!'); }else{ $('.errors-review').html(''); } }); }, addClassStar(starSelected){ $('.star-rating .star').addClass(starSelected); }, removeClassStar(starSelected){ $('.star-rating .star').removeClass(starSelected); }, startPresentation(){ $('.image-course').hide(); $('.play_video').hide(); $('.bar-video').hide(); $('.video-player').show(); setTimeout(() => { var wistiaEmbed = Wistia.embed(this.courseData.video_presentation_key, { autoPlay: true, controlsVisibleOnLoad: false, videoFoam: { maxWidth: 700 }, copyLinkAndThumbnailEnabled: false, playerColor: "000000", seo: true }); wistiaEmbed.hasData( () => { if(this.courseData.time_completed > 0){ wistiaEmbed.time(this.courseData.time_completed); } wistiaEmbed.bind("secondchange", (t) => { if(t % 5 == 0){ axios.post("/setProgress", {seconds: t, course_id: this.courseData.id}) .then(response => { var new_percentage = response.data.success; }); } }); wistiaEmbed.bind("end", (t) => { axios.post("/setProgress", {seconds: 'end', course_id: this.courseData.id}) .then(response => { var new_percentage = response.data.success; }); $('.video-player').hide() $('.image-course').show() $('.next-course').show() $('.next-course .end_position').css('width', '100%') this.timeOutNextCourse = setTimeout(() => { this.$router.push("/cursuri/" + this.courseData.next_course.slug); }, 5000) }); }); }, 0); }, viewNextCourse(){ clearTimeout(this.timeOutNextCourse) this.$router.push("/cursuri/" + this.courseData.next_course.slug); }, viewRandomCourse(){ clearTimeout(this.timeOutNextCourse) this.$router.push("/cursuri/" + this.courseData.random_course.slug); }, cancelTimeOut(){ clearTimeout(this.timeOutNextCourse) document.getElementsByClassName("end_position")[0].style.transitionDuration = "1s"; $('.next-course .end_position').css('transition-duration', '1s !important') setTimeout(() => { $('.next-course .end_position').css({width: '0%'}) }, 0); }, showPopup(type){ this.type_popup = type; this.show_popup = true; }, selectCourse: function(course){ this.$router.push("/cursuri/" + course.slug); }, viewDocGoogle(link_google){ window.open(link_google) }, sendQuestion(course_id, e){ $(e.target).attr('disabled', true) this.successMessageQuestion = false axios.post("/storeQuestion", { title: this.question_title, course_id: course_id, content: this.question_content, }) .then(response => { this.errorDataQuestion = []; this.question_title = ''; this.question_content = ''; this.successMessageQuestion = true; $(e.target).attr('disabled', false); }) .catch(error => { this.errorDataQuestion = []; setTimeout(() => { var errors = []; $.each(error.response.data.errors, (key, value) => { errors[key] = value; }); this.errorDataQuestion = errors; setTimeout(() => { this.hasErrors = true; }, 0); }, 0); }) .finally(() => { $(e.target).attr('disabled', false); }); }, closeQuestion(){ this.successMessageQuestion = false this.show_popup = false }, closeReview(){ this.successMessageReview = false this.show_popup = false }, removeClassError(e){ $(e.target).removeClass('error'); }, toggleAccordion(lesson_id, question_id){ var element = document.getElementById("lesson_" + lesson_id + "_" + question_id) element.classList.toggle("active-accordion"); var panel = element.nextElementSibling; if (panel.style.maxHeight) { panel.style.maxHeight = null; } else { panel.style.maxHeight = panel.scrollHeight + "px"; } if($('#lessons_box .active-accordion').length > 0){ $('#lessons_box').addClass('have-accordion') }else{ $('#lessons_box').removeClass('have-accordion') } }, closeAccordion(lesson_id, question_id){ var element = document.getElementById("lesson_" + lesson_id + "_" + question_id) if(typeof(element) != 'undefined' && element != null && element.classList.contains('active-accordion')){ this.toggleAccordion(lesson_id, question_id) } } }, updated(){ order_no = 0; } } </script>
Back