Settings.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <template>
  2. <div class='route_container route_container--settings'>
  3. <div class='settings_menu'>
  4. <div class='settings_menu__title'>settings</div>
  5. <div class='settings_menu__items'>
  6. <div
  7. class='settings_menu__item'
  8. v-for='(item, index) in menuItems'
  9. :class="{'settings_menu__item--selected': index === selected}"
  10. @click='$router.push("/settings/" + item.route)'
  11. >
  12. <span class='fa' :class='item.icon'></span>
  13. {{item.name}}
  14. </div>
  15. </div>
  16. </div>
  17. <div class='settings_page'>
  18. <router-view></router-view>
  19. </div>
  20. </div>
  21. </template>
  22. <script>
  23. export default {
  24. name: 'settings',
  25. data () {
  26. return {
  27. menuItems: [
  28. { name: 'General', route: 'general', icon: 'fa-cog' },
  29. { name: 'Account', route: 'account', icon: 'fa-lock'},
  30. ],
  31. selected: 0
  32. }
  33. },
  34. watch: {
  35. $route (to, from) {
  36. this.selected = this.getIndexFromRoute(to.path)
  37. },
  38. '$store.state.username' (username) {
  39. if(!username) {
  40. this.$router.push('/')
  41. }
  42. }
  43. },
  44. mounted () {
  45. this.selected = this.getIndexFromRoute(this.$route.path)
  46. },
  47. methods: {
  48. getIndexFromRoute (path) {
  49. let selectedIndex
  50. let route = path.split('/')[2]
  51. this.menuItems.forEach((item, index) => {
  52. if(item.route === route) {
  53. selectedIndex = index
  54. }
  55. })
  56. return selectedIndex
  57. }
  58. },
  59. beforeRouteEnter (to, from, next) {
  60. next(vm => {
  61. if(!vm.$store.state.username) {
  62. vm.$store.commit('setAccountModalState', true);
  63. next('/')
  64. }
  65. })
  66. }
  67. }
  68. </script>
  69. <style lang='scss' scoped>
  70. @import '../../assets/scss/variables.scss';
  71. .route_container--settings {
  72. display: flex;
  73. align-items: flex-start
  74. }
  75. .settings_menu {
  76. width: 15rem;
  77. border: thin solid $color__gray--darker;
  78. background-color: #fff;
  79. padding: 1rem;
  80. border-radius: 0.25rem;
  81. @at-root #{&}__title {
  82. cursor: default;
  83. font-weight: 500;
  84. font-variant: small-caps;
  85. font-size: 1.125rem;
  86. padding-left: 0.25rem;
  87. margin-bottom: 0.5rem;
  88. }
  89. @at-root #{&}__item {
  90. padding: 0.5rem 1rem;
  91. margin-bottom: 0.25rem;
  92. padding-right: 0;
  93. transition: background-color 0.2s;
  94. cursor: pointer;
  95. position: relative;
  96. border-radius: 0.25rem;
  97. &:first-child { margin-top: 0.5rem; }
  98. &:last-child { margin-bottom: 0.5rem; }
  99. &:hover { background-color: $color__lightgray--primary; }
  100. &::before {
  101. content: '';
  102. display: inline-block;
  103. width: 0.25rem;
  104. z-index: 1;
  105. height: 100%;
  106. position: absolute;
  107. left: 0;
  108. border-radius: 0.25rem 0 0 0.25em;
  109. top: 0;
  110. background-color: $color__gray--darkest;
  111. opacity: 0;
  112. transition: opacity 0.2s;
  113. }
  114. span {
  115. color: $color__text--secondary;
  116. margin-right: 0.5rem;
  117. }
  118. @at-root #{&}--selected {
  119. background-color: $color__lightgray--darker;
  120. color: $color__text--primary;
  121. span {
  122. color: $color__text--primary;
  123. }
  124. &:hover { background-color: $color__lightgray--darker; }
  125. &::before {
  126. opacity: 1;
  127. }
  128. }
  129. }
  130. }
  131. .settings_page {
  132. width: calc(100% - 15rem);
  133. background-color: #fff;
  134. border-radius: 0.25rem;
  135. margin-left: 2rem;
  136. border: thin solid $color__gray--darker;
  137. }
  138. @media (max-width: $breakpoint--tablet) and (min-width: $breakpoint--phone) {
  139. div.settings_menu, div.settings_page {
  140. width: calc(100% - 4rem);
  141. margin: 0.5rem 2rem;
  142. padding: 1rem;
  143. }
  144. }
  145. @media (max-width: $breakpoint--tablet) {
  146. .route_container--settings {
  147. flex-direction: column;
  148. }
  149. .settings_menu {
  150. width: 100%;
  151. @at-root #{&}__items {
  152. display: flex;
  153. align-items: baseline;
  154. }
  155. @at-root #{&}__item {
  156. width: 7rem;
  157. margin-right: 0.5rem;
  158. color: $color__text--primary;
  159. &:first-child, &:last-child {
  160. margin-bottom: 0;
  161. margin-top: 0;
  162. }
  163. &::before {
  164. height: 0.2rem;
  165. width: 100%;
  166. left: 0;
  167. border-radius: 0 0 1rem 1rem;
  168. top: auto;
  169. bottom: 0;
  170. }
  171. }
  172. }
  173. .settings_page {
  174. width: 100%;
  175. margin: 0;
  176. margin-top: 1rem;
  177. }
  178. }
  179. </style>