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 @@
+
+.filter-dropdown.dropdown
+ DropdownMenu(
+ v-bind="$attrs"
+ withDropdownCloser
+ :direction="$attrs.direction || 'right'"
+ :overlay="false"
+ :is-open="isOpen"
+ @closed="onClose"
+ )
+ template(#trigger)
+ Button.filter-dropdown-trigger-button(size="small" round)
+ template(v-if="selectedOption && Object.keys(selectedOption).length > 0")
+ AppIcon.filter-dropdown-trigger-button__icon(:name="selectedOption.icon")
+ span.filter-dropdown-trigger-button__title {{ selectedOption.label }}
+ template(v-else)
+ AppIcon.filter-dropdown-trigger-button__icon(name="tabler:list-details")
+ span.filter-dropdown-trigger-button__title {{ title }}
+ template(#body)
+ nav.filter-dropdown-nav(v-if="options?.length > 0")
+ template(v-for="(item, index) in options")
+ .filter-dropdown-nav-item(:key="index" dropdown-closer @click="handleOptionSelect(item)")
+ AppIcon.filter-dropdown-nav-item__icon(v-if="item.icon" :name="item.icon" :width="20" :height="20")
+ span.filter-dropdown-nav-item__title {{ item.label }}
+
+
+
+
+
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"