index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <div>
  3. <Header
  4. title="Manage your Blogs"
  5. exitLink="/"
  6. />
  7. <div class="instructor-blogs">
  8. <div class="container">
  9. <div class="section">
  10. <div class="header-block">
  11. <h2>Your Stories</h2>
  12. <div class="title-menu">
  13. <button @click="$router.push('/instructor/blog/editor')" class="button">Write a story</button>
  14. </div>
  15. </div>
  16. <div class="tabs">
  17. <ul>
  18. <!-- set here active tab -->
  19. <li @click="activeTab = 0">
  20. <a :class="{'is-active': activeTab === 0}">Drafts</a>
  21. </li>
  22. <!-- set here active tab -->
  23. <li @click="activeTab = 1">
  24. <a :class="{'is-active': activeTab === 1}">Published</a>
  25. </li>
  26. </ul>
  27. </div>
  28. <div class="blogs-container">
  29. <template v-if="activeTab === 0">
  30. <div v-if="drafts && drafts.length > 0">
  31. <div
  32. v-for="dBlog in drafts"
  33. :key="dBlog._id"
  34. class="blog-card">
  35. <h2>{{displayBlogTitle(dBlog)}}</h2>
  36. <div class="blog-card-footer">
  37. <span>
  38. Last Edited {{dBlog.updatedAt | formatDate('LLLL')}}
  39. </span>
  40. <dropdown
  41. @optionChanged="handleOption($event, dBlog)"
  42. :items="draftsOptions" />
  43. <!-- Dropdown with menu here -->
  44. </div>
  45. </div>
  46. </div>
  47. <!-- In case of no drafts blogs -->
  48. <div v-else class="blog-error">
  49. No Drafts :(
  50. </div>
  51. </template>
  52. <template v-if="activeTab === 1">
  53. <div v-if="published && published.length > 0">
  54. <div
  55. v-for="pBlog in published"
  56. :key="pBlog._id"
  57. :class="{featured: pBlog.featured}"
  58. class="blog-card">
  59. <h2>{{displayBlogTitle(pBlog)}}</h2>
  60. <div class="blog-card-footer">
  61. <span>
  62. Last Edited {{pBlog.updatedAt | formatDate('LLLL')}}
  63. </span>
  64. <dropdown
  65. @optionChanged="handleOption($event, pBlog)"
  66. :items="publishedOptions(pBlog.featured)" />
  67. <!-- Dropdown with menu here -->
  68. </div>
  69. </div>
  70. </div>
  71. <!-- In case of no drafts blogs -->
  72. <div v-else class="blog-error">
  73. No Drafts :(
  74. </div>
  75. </template>
  76. </div>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </template>
  82. <script>
  83. import Header from '~/components/shared/Header'
  84. import Dropdown from '~/components/shared/Dropdown'
  85. import { createPublishedOptions,
  86. createDraftsOptions,
  87. commands } from '~/pages/instructor/options'
  88. import { mapState } from 'vuex';
  89. export default {
  90. layout: 'instructor',
  91. components: {Header, Dropdown},
  92. data() {
  93. return {
  94. activeTab: 0
  95. }
  96. },
  97. computed: {
  98. ...mapState({
  99. published : ({instructor}) => instructor.blog.items.published,
  100. drafts : ({instructor}) => instructor.blog.items.drafts,
  101. }),
  102. draftsOptions() {
  103. return createDraftsOptions()
  104. }
  105. },
  106. methods: {
  107. handleOption(command, blog) {
  108. // console.log(blogId)
  109. if (command === commands.EDIT_BLOG) {
  110. this.$router.push(`/instructor/blog/${blog._id}/edit`)
  111. }
  112. if (command === commands.DELETE_BLOG) {
  113. // alert('Deleting Blog')
  114. this.displayDeleteWarning(blog)
  115. }
  116. if (command === commands.TOGGLE_FEATURE) {
  117. this.updateBlog(blog)
  118. }
  119. },
  120. async updateBlog(blog) {
  121. // this.$store.dispatch('instructor/blog/updatePublishedBlog')
  122. const featured = !blog.featured
  123. const featureStatus = featured ? 'Featured' : 'Un-Featured'
  124. const result = await this.$store.dispatch('instructor/blog/updatePublishedBlog', {id: blog._id, data: {featured}})
  125. if(result.isAxiosError !== true){
  126. this.$toasted.success(`Blog has been ${featureStatus}!`, {duration: 2000})
  127. }
  128. },
  129. publishedOptions(isFeatured) {
  130. return createPublishedOptions(isFeatured)
  131. },
  132. displayDeleteWarning(blog) {
  133. const isConfirm = confirm('Are you sure you want to delete blog ?')
  134. if (isConfirm) {
  135. const result = this.$store.dispatch('instructor/blog/deleteBlog', blog)
  136. if(result === true) {
  137. this.$toasted.success('Blog was succesfuly deleted!', {duration: 2000})
  138. }
  139. }
  140. },
  141. displayBlogTitle(blog) {
  142. return blog.title || blog.subtitle || 'Blog without title & subtitle :('
  143. }
  144. },
  145. async fetch({store}) {
  146. await store.dispatch('instructor/blog/fetchUserBlogs')
  147. },
  148. }
  149. </script>
  150. <style scoped lang="scss">
  151. .is-active {
  152. border-bottom-color: #363636;
  153. color: #363636;
  154. }
  155. .blog-error {
  156. font-size: 35px;
  157. }
  158. .blog-card {
  159. border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  160. padding: 20px 0;
  161. > h2 {
  162. font-size: 30px;
  163. font-weight: bold;
  164. }
  165. &-footer {
  166. color: rgba(0, 0, 0, 0.54);
  167. }
  168. &.featured {
  169. border-left: 8px solid #3cc314;
  170. padding-left: 10px;
  171. transition: border ease-out 0.2s;
  172. }
  173. }
  174. .header-block {
  175. display: flex;
  176. flex-direction: row;
  177. align-items: center;
  178. > h2 {
  179. font-size: 40px;
  180. font-weight: bold;
  181. }
  182. .title-menu {
  183. margin-left: auto;
  184. }
  185. }
  186. </style>