feat: refine content calendar experience
This commit is contained in:
@@ -1,18 +1,78 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useAuthStore } from '@/features/auth/stores/authStore.js';
|
||||
import WorkspaceSelector from './WorkspaceSelector.vue';
|
||||
import {
|
||||
mdiCalendar,
|
||||
mdiChevronDown,
|
||||
mdiCogOutline,
|
||||
mdiFormatListBulleted,
|
||||
mdiLogin,
|
||||
mdiPlus,
|
||||
mdiTable,
|
||||
} from '@mdi/js';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const authStore = useAuthStore();
|
||||
const isContentViewMenuOpen = ref(false);
|
||||
|
||||
const contentViewActions = computed(() => {
|
||||
if (route.name !== 'content-items') {
|
||||
return [];
|
||||
}
|
||||
|
||||
const query = route.query;
|
||||
const activeView = ['upcoming', 'table'].includes(query.view) ? query.view : 'calendar';
|
||||
|
||||
return [
|
||||
{
|
||||
key: 'calendar',
|
||||
label: t('contentItems.views.calendar'),
|
||||
icon: mdiCalendar,
|
||||
active: activeView === 'calendar',
|
||||
route: {
|
||||
name: 'content-items',
|
||||
query: {
|
||||
...query,
|
||||
view: query.view === 'week' ? 'week' : 'month',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'upcoming',
|
||||
label: t('contentItems.upcoming'),
|
||||
icon: mdiFormatListBulleted,
|
||||
active: activeView === 'upcoming',
|
||||
route: {
|
||||
name: 'content-items',
|
||||
query: {
|
||||
...query,
|
||||
view: 'upcoming',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'table',
|
||||
label: t('contentItems.views.table'),
|
||||
icon: mdiTable,
|
||||
active: activeView === 'table',
|
||||
route: {
|
||||
name: 'content-items',
|
||||
query: {
|
||||
...query,
|
||||
view: 'table',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const activeContentViewAction = computed(() =>
|
||||
contentViewActions.value.find(action => action.active) ?? contentViewActions.value[0]
|
||||
);
|
||||
|
||||
const appBarActions = computed(() => {
|
||||
if (!authStore.isAuthenticated) {
|
||||
@@ -79,6 +139,46 @@
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-if="contentViewActions.length"
|
||||
class="view-selector"
|
||||
>
|
||||
<button
|
||||
class="menu-item-action view-selector-button"
|
||||
type="button"
|
||||
@click="isContentViewMenuOpen = !isContentViewMenuOpen"
|
||||
>
|
||||
<v-icon :icon="activeContentViewAction.icon" />
|
||||
<span class="label">{{ activeContentViewAction.label }}</span>
|
||||
<v-icon
|
||||
class="selector-chevron"
|
||||
:icon="mdiChevronDown"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<div
|
||||
v-if="isContentViewMenuOpen"
|
||||
class="view-selector-menu"
|
||||
>
|
||||
<router-link
|
||||
v-for="action in contentViewActions"
|
||||
:key="action.key"
|
||||
:to="action.route"
|
||||
class="menu-action-link"
|
||||
@click="isContentViewMenuOpen = false"
|
||||
>
|
||||
<button
|
||||
class="view-selector-option"
|
||||
:class="{ 'view-selector-option-active': action.active }"
|
||||
type="button"
|
||||
>
|
||||
<v-icon :icon="action.icon" />
|
||||
<span>{{ action.label }}</span>
|
||||
</button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<router-link
|
||||
v-for="action in appBarActions"
|
||||
:key="action.key"
|
||||
@@ -121,6 +221,24 @@
|
||||
@apply justify-end;
|
||||
}
|
||||
|
||||
.view-selector {
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
.view-selector-button {
|
||||
@apply min-w-11 justify-between;
|
||||
}
|
||||
|
||||
.selector-chevron {
|
||||
@apply text-base;
|
||||
}
|
||||
|
||||
.view-selector-menu {
|
||||
@apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex min-w-52 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl;
|
||||
background: #ffffff;
|
||||
border-color: rgba(23, 32, 51, 0.1);
|
||||
}
|
||||
|
||||
.label {
|
||||
@apply hidden text-nowrap md:inline;
|
||||
}
|
||||
@@ -137,6 +255,17 @@
|
||||
color: #fffaf2;
|
||||
}
|
||||
|
||||
.view-selector-option {
|
||||
@apply flex min-h-11 w-full items-center gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold transition;
|
||||
color: #172033;
|
||||
}
|
||||
|
||||
.view-selector-option:hover,
|
||||
.view-selector-option-active {
|
||||
background: #172033;
|
||||
color: #fffaf2;
|
||||
}
|
||||
|
||||
.menu-item-action i {
|
||||
@apply text-xl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user