diff --git a/assets/style/css/variables/box-shadow.css b/assets/style/css/variables/box-shadow.css index 687effa..94bb94a 100644 --- a/assets/style/css/variables/box-shadow.css +++ b/assets/style/css/variables/box-shadow.css @@ -1,3 +1,7 @@ :root { --box-shadow-01: 0 5px 30px rgba(156, 160, 171, 0.25); } + +.dark-mode { + --box-shadow-01: 0 5px 30px rgba(0, 0, 0, 0.25); +} diff --git a/assets/style/css/variables/color.css b/assets/style/css/variables/color.css index 77a835f..8d234e3 100644 --- a/assets/style/css/variables/color.css +++ b/assets/style/css/variables/color.css @@ -83,9 +83,9 @@ --color-icon-01: #aaa; /* Interactive */ - --color-hover-01: #fafafa; - --color-hover-02: #fff; - --color-active-01: #ededed; + --color-hover-01: #383838; + --color-hover-02: #272727; + --color-active-01: #383838; --color-selected-01: #121212; --color-disabled-01: #626262; --color-highlight-01: #ff7878; diff --git a/components/Dropdown/FilterDropdown/FilterDropdown.component.scss b/components/Dropdown/FilterDropdown/FilterDropdown.component.scss new file mode 100644 index 0000000..a22b6c7 --- /dev/null +++ b/components/Dropdown/FilterDropdown/FilterDropdown.component.scss @@ -0,0 +1,79 @@ +.filter-dropdown { + $v-dropdown-menu: '.v-dropdown-menu'; + + #{$v-dropdown-menu} { + &__trigger { + position: relative; + } + + &__container { + padding: calc(var(--base-p-y) / 2) calc(var(--base-p-x) / 2); + color: var(--color-text-02); + background-color: var(--color-ui-02); + border: 1px solid var(--color-border-01); + border-radius: var(--border-radius-01); + box-shadow: var(--box-shadow-01); + margin-block-start: $spacer; + } + } + + &-trigger-button { + $van-button: '.van-button'; + + display: flex; + color: var(--color-text-02); + background-color: var(--color-ui-02); + border: 1px solid var(--color-border-02); + + #{$van-button} { + &__text { + display: flex; + align-items: center; + } + } + + &__icon { + width: 16px; + height: 16px; + margin-inline-end: $spacer; + color: var(--color-icon-02); + + svg { + width: 100% !important; + height: 100% !important; + } + } + } + + &-nav { + position: relative; + + &-item { + display: flex; + align-items: flex-start; + padding: calc(var(--base-p-y) / 2) calc(var(--base-p-x) / 2); + color: var(--color-text-02); + border-radius: var(--border-radius-01); + cursor: pointer; + + &:hover { + background-color: var(--color-hover-01); + } + + &__icon { + margin-inline-end: calc(var(--base-p-x) / 2); + width: 16px; + height: 16px; + + svg { + width: 100% !important; + height: 100% !important; + } + } + + &__title { + font-size: var(--font-size-text-9); + } + } + } +} diff --git a/components/Dropdown/FilterDropdown/FilterDropdown.component.vue b/components/Dropdown/FilterDropdown/FilterDropdown.component.vue new file mode 100644 index 0000000..edee6c3 --- /dev/null +++ b/components/Dropdown/FilterDropdown/FilterDropdown.component.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/components/Dropdown/index.js b/components/Dropdown/index.js new file mode 100644 index 0000000..523debd --- /dev/null +++ b/components/Dropdown/index.js @@ -0,0 +1 @@ +export { default as FilterDropdown } from './FilterDropdown/FilterDropdown.component' diff --git a/components/List/RoomList/RoomList.component.vue b/components/List/RoomList/RoomList.component.vue index 73d082c..28e2124 100644 --- a/components/List/RoomList/RoomList.component.vue +++ b/components/List/RoomList/RoomList.component.vue @@ -22,40 +22,49 @@ template(v-else) List template(v-for="room in list.items") - Cell.room-list-item(v-if="room.isListed" is-link :to="localePath({ name: 'CreatorMode-CreatorModeRoom', query: { id: room.id } })") - template(#title) - span.room-list-item__title {{ room.title }} - - template(#label) - .room-list-item-badge.room-list-item-badge--user.d-flex.d-mobile-none(v-if="room.user") - PlayerAvatar(:size="16" :name="room.user.fingerprint") - span.room-list-item-badge__value {{ room.user.username }} - - .room-list-item__badges - .room-list-item-badge.room-list-item-badge--user(v-if="room.user") + NuxtLink( + :to="localePath({ name: 'CreatorMode-CreatorModeRoom', query: { id: room.id } })" + :title="room.title" + @click.native.prevent.capture="localePath({ name: 'CreatorMode-CreatorModeRoom', query: { id: room.id } })" + ) + Cell.room-list-item( + v-if="room.isListed" + is-link + :to="localePath({ name: 'CreatorMode-CreatorModeRoom', query: { id: room.id } })" + ) + template(#title) + span.room-list-item__title {{ room.title }} + + template(#label) + .room-list-item-badge.room-list-item-badge--user.d-flex.d-mobile-none(v-if="room.user") PlayerAvatar(:size="16" :name="room.user.fingerprint") span.room-list-item-badge__value {{ room.user.username }} - .room-list-item-badge(v-if="room.questionCount") - AppIcon.room-list-item-badge__icon(name="tabler:help-circle" color="var(--color-text-03)" :width="16" :height="16") - span.room-list-item-badge__value {{ room.questionCount }} - - .room-list-item-badge(v-if="room.viewCount") - AppIcon.room-list-item-badge__icon(name="tabler:eye" color="var(--color-text-03)" :width="16" :height="16") - span.room-list-item-badge__value {{ room.viewCount }} - - .room-list-item-badge.room-list-item-badge--rating(v-if="room.rating") - StarRating( - read-only - inline - :show-rating="false" - :rating="room.rating" - :increment="0.1" - :rounded-corners="false" - :star-size="14" - ) - label {{ String(formatRating(room.rating)) }} - span.room-list-item__id ID: {{ room.id }} + .room-list-item__badges + .room-list-item-badge.room-list-item-badge--user(v-if="room.user") + PlayerAvatar(:size="16" :name="room.user.fingerprint") + span.room-list-item-badge__value {{ room.user.username }} + + .room-list-item-badge(v-if="room.questionCount") + AppIcon.room-list-item-badge__icon(name="tabler:help-circle" color="var(--color-text-03)" :width="16" :height="16") + span.room-list-item-badge__value {{ room.questionCount }} + + .room-list-item-badge(v-if="room.viewCount") + AppIcon.room-list-item-badge__icon(name="tabler:eye" color="var(--color-text-03)" :width="16" :height="16") + span.room-list-item-badge__value {{ room.viewCount }} + + .room-list-item-badge.room-list-item-badge--rating(v-if="room.rating") + StarRating( + read-only + inline + :show-rating="false" + :rating="room.rating" + :increment="0.1" + :rounded-corners="false" + :star-size="14" + ) + label {{ String(formatRating(room.rating)) }} + span.room-list-item__id ID: {{ room.id }} InfiniteLoading(@infinite="handleInfiniteLoading") diff --git a/locales/en.js b/locales/en.js index 43821f5..be330f0 100644 --- a/locales/en.js +++ b/locales/en.js @@ -30,7 +30,9 @@ export default { share: 'Share', by: 'By', comments: 'Comments', - noData: 'No data' + noData: 'No data', + filter: 'Filter', + sort: 'Sort' }, introScene: { title: 'CHOOSE GAME MODE', @@ -242,6 +244,12 @@ export default { rooms: { pendingRooms: 'Fetching rooms', selectFromList: 'SELECT FROM LIST', + filters: { + title: 'FILTERS', + recently: 'Recent rooms', + oldest: 'Old rooms', + byViewCount: 'Most viewed' + }, refresh: 'REFRESH', searchField: { placeholder: 'Search room' diff --git a/locales/tr.js b/locales/tr.js index 19503a5..f14a5c0 100644 --- a/locales/tr.js +++ b/locales/tr.js @@ -30,7 +30,9 @@ export default { share: 'Paylaş', by: 'tarafından', comments: 'Yorumlar', - noData: 'Veri yok' + noData: 'Veri yok', + filter: 'Filtrele', + sort: 'Sırala' }, introScene: { title: 'OYUN MODU SEÇ', @@ -241,6 +243,12 @@ export default { rooms: { pendingRooms: 'Odalar getiriliyor', selectFromList: 'LİSTEDEN SEÇ', + filters: { + title: 'SIRALA', + recently: 'En yeni odalar', + oldest: 'En eski odalar', + byViewCount: 'En çok oynanan odalar' + }, refresh: 'TAZELE', searchField: { placeholder: 'Oda ara' diff --git a/package.json b/package.json index 4c71921..69945e8 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "simple-keyboard": "^3.4.65", "swiper": "^8.0.6", "textfit": "^2.4.0", + "v-dropdown-menu": "1.3.2", "vant": "^2.12.54", "vue-infinite-loading": "^2.4.5", "vue-star-rating": "^1.7.0", @@ -106,4 +107,4 @@ "path": "cz-conventional-changelog" } } -} \ No newline at end of file +} diff --git a/pages/CreatorMode/CreatorModeRooms/CreatorModeRooms.page.scss b/pages/CreatorMode/CreatorModeRooms/CreatorModeRooms.page.scss index 6767950..34d59d2 100644 --- a/pages/CreatorMode/CreatorModeRooms/CreatorModeRooms.page.scss +++ b/pages/CreatorMode/CreatorModeRooms/CreatorModeRooms.page.scss @@ -32,6 +32,41 @@ } &-rooms { + &-head { + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + + @include media-breakpoint-down(mobile) { + flex-direction: column; + align-items: flex-start; + } + + &__actions { + display: flex; + align-items: center; + justify-content: space-between; + + @include media-breakpoint-down(mobile) { + margin-block-end: var(--base-m-y); + } + + .filter-dropdown { + $v-dropdown-menu: '.v-dropdown-menu'; + + #{$v-dropdown-menu} { + &__container { + @include media-breakpoint-down(mobile) { + right: auto; + left: 0; + } + } + } + } + } + } + &__refetchButton { color: var(--color-text-02); background-color: var(--color-ui-02); diff --git a/pages/CreatorMode/CreatorModeRooms/index.vue b/pages/CreatorMode/CreatorModeRooms/index.vue index 42a6e11..83b1618 100644 --- a/pages/CreatorMode/CreatorModeRooms/index.vue +++ b/pages/CreatorMode/CreatorModeRooms/index.vue @@ -22,10 +22,17 @@ Divider {{ $t('creatorModeRooms.divider') }} .creator-mode-rooms-page-rooms - .creator-mode-rooms-page__title.creator-mode-rooms-page__title--rooms - h3 {{ $t('creatorModeRooms.rooms.selectFromList') }} ({{ roomTotal }}) - Button.creator-mode-rooms-page-rooms__refetchButton(icon="replay" size="small" round @click="fetch") - | {{ $t('creatorModeRooms.rooms.refresh') }} + .creator-mode-rooms-page-rooms-head + .creator-mode-rooms-page__title.creator-mode-rooms-page__title--rooms + h3 {{ $t('creatorModeRooms.rooms.selectFromList') }} ({{ roomTotal }}) + .creator-mode-rooms-page-rooms-head__actions + Button.creator-mode-rooms-page-rooms__refetchButton.me-1(icon="replay" size="small" round @click="fetch") + | {{ $t('creatorModeRooms.rooms.refresh') }} + FilterDropdown( + :title="$t('creatorModeRooms.rooms.filters.title')" + :options="filterOptions" + @on-select-option="handleFilterOptionSelect" + ) template(v-if="fetchState.pending") Empty(:description="$t('creatorModeRooms.rooms.pendingRooms')") @@ -44,6 +51,7 @@ import { APP_URL } from '@/system/constant' import { Field, Button, Divider, Empty, Notify } from 'vant' import { AppIcon } from '@/components/Icon' import { RoomList } from '@/components/List' +import { FilterDropdown } from '@/components/Dropdown' export default defineComponent({ components: { @@ -53,7 +61,8 @@ export default defineComponent({ Empty, Notify, AppIcon, - RoomList + RoomList, + FilterDropdown }, layout: 'Default/Default.layout', setup() { @@ -71,6 +80,32 @@ export default defineComponent({ const rooms = computed(() => store.getters['creator/rooms']) const roomTotal = computed(() => store.getters['creator/roomTotal']) + const filterOptions = computed(() => { + return [ + { + key: 'recently', + label: i18n.t('creatorModeRooms.rooms.filters.recently'), + icon: 'tabler:clock-up' + }, + { + key: 'byViewCount', + label: i18n.t('creatorModeRooms.rooms.filters.byViewCount'), + icon: 'tabler:chevrons-up' + }, + { + key: 'oldest', + label: i18n.t('creatorModeRooms.rooms.filters.oldest'), + icon: 'tabler:clock-down' + } + ] + }) + + const handleFilterOptionSelect = option => { + store.commit('creator/SET_ROOMS_SORT', option.key) + + fetch() + } + const filteredRooms = ref([]) const form = reactive({ @@ -121,6 +156,8 @@ export default defineComponent({ fetchState, rooms, roomTotal, + filterOptions, + handleFilterOptionSelect, filteredRooms, form, validateRoomUrl, diff --git a/store/creator/actions.js b/store/creator/actions.js index 89c3b1c..d338157 100644 --- a/store/creator/actions.js +++ b/store/creator/actions.js @@ -35,10 +35,23 @@ export default { async fetchRooms({ commit, state }, params) { const { isLoadMore = false, limit, cursor, keyword, locale } = params + const getSort = _sort => { + if (_sort === 'oldest') { + return 'oldest' + } + + if (_sort === 'byViewCount') { + return 'most_played' + } + + return 'newest' + } + const queryDefault = { per_page: 10, cursor: '', search: '', + sort: state.room.sort, locale: this.$i18n.locale } @@ -46,6 +59,7 @@ export default { per_page: limit || queryDefault.per_page, cursor: cursor || queryDefault.cursor, search: keyword || queryDefault.search, + sort: getSort(state.room.sort) || queryDefault.sort, lang: locale || queryDefault.locale } diff --git a/store/creator/mutations.js b/store/creator/mutations.js index 59122f9..fd6e138 100644 --- a/store/creator/mutations.js +++ b/store/creator/mutations.js @@ -1,6 +1,10 @@ import { GAME_TIME_LIMIT } from '@/system/constant' export default { + SET_ROOMS_SORT(state, sort) { + state.room.sort = sort + }, + SET_ROOMS(state, rooms) { state.room.list = rooms }, diff --git a/store/creator/state.js b/store/creator/state.js index 611fda2..7daff18 100644 --- a/store/creator/state.js +++ b/store/creator/state.js @@ -5,6 +5,7 @@ export default () => ({ list: [], pagination: {}, total: null, + sort: 'recently', room: {} }, isGameOver: false, diff --git a/yarn.lock b/yarn.lock index 3a30eff..8b27f9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12027,6 +12027,11 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +v-dropdown-menu@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/v-dropdown-menu/-/v-dropdown-menu-1.3.2.tgz#0e079dfa65ce85e2463b1d56b11f95745b83ffe7" + integrity sha512-MYtOirrgNkPFz5XlN21ory9luggUh2HJ+9dZ/MPw7IeTjydvyN5zSpnRGPmEkCZvanFcCPcIM6xlK0yhE/LTVA== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"