Changed the way the sidebar works
This commit is contained in:
@@ -1,17 +1,26 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PhCompass, PhList } from "@phosphor-icons/vue"
|
import { PhCompass, PhGlobeHemisphereEast, PhHurricane, PhList } from "@phosphor-icons/vue"
|
||||||
import type { SidebarMenuActionType } from "./SidebarProps";
|
import type { SidebarMenuActionType, SidebarMenuIcon } from "./SidebarProps";
|
||||||
|
|
||||||
const { revealAdvancedSearch } = useCalendar()
|
const { revealAdvancedSearch } = useCalendar()
|
||||||
const { currentMenu } = storeToRefs(useUiStore())
|
const { currentMenu } = storeToRefs(useUiStore())
|
||||||
|
|
||||||
// const user = useSupabaseUser()
|
|
||||||
|
|
||||||
function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
||||||
if (actionType === "event-search") {
|
if (actionType === "event-search") {
|
||||||
revealAdvancedSearch()
|
revealAdvancedSearch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function computeMenuItemIcon(iconString: SidebarMenuIcon) {
|
||||||
|
switch (iconString) {
|
||||||
|
case "universe":
|
||||||
|
return PhHurricane
|
||||||
|
case "world":
|
||||||
|
return PhGlobeHemisphereEast
|
||||||
|
default:
|
||||||
|
return PhCompass
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -27,7 +36,7 @@ function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
|||||||
<UiTooltipProvider :delay-duration="50">
|
<UiTooltipProvider :delay-duration="50">
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<UiButton variant="ghost" size="icon" class="rounded-full" as-child>
|
<UiButton variant="ghost" size="icon" class="rounded-full text-indigo-400" as-child>
|
||||||
<RouterLink to="/explore">
|
<RouterLink to="/explore">
|
||||||
<PhCompass size="24" weight="fill" />
|
<PhCompass size="24" weight="fill" />
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
@@ -42,17 +51,30 @@ function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
|||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<ClientOnly>
|
||||||
<li v-for="(item, i) in currentMenu" :key="i">
|
<li v-for="(item, i) in currentMenu" :key="i">
|
||||||
<UiTooltipProvider :delay-duration="50">
|
<UiTooltipProvider :delay-duration="50">
|
||||||
<UiTooltip>
|
<UiTooltip>
|
||||||
<UiTooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<UiButton v-if="item.to" variant="ghost" size="icon" class="rounded-full" as-child>
|
<UiButton
|
||||||
|
v-if="item.to"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
class="rounded-full"
|
||||||
|
as-child
|
||||||
|
>
|
||||||
<RouterLink :to="item.to">
|
<RouterLink :to="item.to">
|
||||||
<component :is="item.phIcon" size="24" weight="fill" />
|
<component :is="computeMenuItemIcon(item.phIcon)" size="24" :weight="item.phIconWeight || 'fill'" />
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</UiButton>
|
</UiButton>
|
||||||
<UiButton v-if="item.action" variant="ghost" size="icon" class="rounded-full" @click="handleMenuItemAction(item.action!)">
|
<UiButton
|
||||||
<component :is="item.phIcon" size="24" weight="fill" />
|
v-if="item.action"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
class="rounded-full"
|
||||||
|
@click="handleMenuItemAction(item.action!)"
|
||||||
|
>
|
||||||
|
<component :is="computeMenuItemIcon(item.phIcon)" size="24" :weight="item.phIconWeight || 'fill'" />
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</UiTooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<UiTooltipContent :side="'right'" :side-offset="6">
|
<UiTooltipContent :side="'right'" :side-offset="6">
|
||||||
@@ -61,6 +83,7 @@ function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
|||||||
</UiTooltip>
|
</UiTooltip>
|
||||||
</UiTooltipProvider>
|
</UiTooltipProvider>
|
||||||
</li>
|
</li>
|
||||||
|
</ClientOnly>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
<UserCTA />
|
<UserCTA />
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { ShallowRef } from "vue"
|
|
||||||
|
|
||||||
export type SidebarMenuActionType = "event-search"
|
export type SidebarMenuActionType = "event-search"
|
||||||
|
|
||||||
|
export type SidebarMenuIcon = "universe" | "world"
|
||||||
|
|
||||||
export interface SidebarMenuItem {
|
export interface SidebarMenuItem {
|
||||||
phIcon: ShallowRef // use shallowRef to build phIcon
|
phIcon: SidebarMenuIcon,
|
||||||
|
phIconWeight?: "regular" | "light" | "fill" | "duotone" | "bold" | "thin"
|
||||||
|
highlight?: boolean
|
||||||
tooltip: string
|
tooltip: string
|
||||||
action?: SidebarMenuActionType
|
action?: SidebarMenuActionType
|
||||||
to?: string
|
to?: string
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ switch (statusCode) {
|
|||||||
<Title>{{ $t(titleKey) }}</Title>
|
<Title>{{ $t(titleKey) }}</Title>
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<div class="grid justify-items-center opacity-80">
|
<div class="grid text-center justify-items-center opacity-80">
|
||||||
<PhImageBroken v-if="statusCode === 404" size="100" class="opacity-60" />
|
<PhImageBroken v-if="statusCode === 404" size="100" class="opacity-60" />
|
||||||
<PhLinkBreak v-else-if="statusCode === 500" size="100" class="opacity-60" />
|
<PhLinkBreak v-else-if="statusCode === 500" size="100" class="opacity-60" />
|
||||||
<PhBugBeetle v-else size="100" class="opacity-60" />
|
<PhBugBeetle v-else size="100" class="opacity-60" />
|
||||||
@@ -78,7 +78,7 @@ switch (statusCode) {
|
|||||||
{{ $t(titleKey) }}
|
{{ $t(titleKey) }}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<div class="mt-6 md:text-lg text-center">
|
<div class="mt-6 md:text-lg">
|
||||||
<p>{{ $t(descriptionKey) }}</p>
|
<p>{{ $t(descriptionKey) }}</p>
|
||||||
<p>{{ $t(subDescriptionKey) }}</p>
|
<p>{{ $t(subDescriptionKey) }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ export default defineI18nConfig(() => ({
|
|||||||
world: {
|
world: {
|
||||||
nameSingular: "World",
|
nameSingular: "World",
|
||||||
namePlural: "Worlds",
|
namePlural: "Worlds",
|
||||||
|
backToMy: "Back to my universe",
|
||||||
|
backToSingle: "Back to {world}",
|
||||||
addSingle: "Add a world",
|
addSingle: "Add a world",
|
||||||
addSingleFirst: "Add your first world !",
|
addSingleFirst: "Add your first world !",
|
||||||
editSingle: "Edit world",
|
editSingle: "Edit world",
|
||||||
@@ -283,6 +285,10 @@ export default defineI18nConfig(() => ({
|
|||||||
explore: {
|
explore: {
|
||||||
menuLabel: "Explore",
|
menuLabel: "Explore",
|
||||||
title: "Explore worlds",
|
title: "Explore worlds",
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
title: "{user} — My universe",
|
||||||
|
metaTitle: "My universe",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -391,6 +397,8 @@ export default defineI18nConfig(() => ({
|
|||||||
world: {
|
world: {
|
||||||
nameSingular: "Monde",
|
nameSingular: "Monde",
|
||||||
namePlural: "Mondes",
|
namePlural: "Mondes",
|
||||||
|
backToMy: "Retourner à mon univers",
|
||||||
|
backToSingle: "Retourner sur {world}",
|
||||||
addSingle: "Ajouter un monde",
|
addSingle: "Ajouter un monde",
|
||||||
addSingleFirst: "Ajouter votre premier monde !",
|
addSingleFirst: "Ajouter votre premier monde !",
|
||||||
editSingle: "Modifier le monde",
|
editSingle: "Modifier le monde",
|
||||||
@@ -570,6 +578,10 @@ export default defineI18nConfig(() => ({
|
|||||||
explore: {
|
explore: {
|
||||||
menuLabel: "Explorer",
|
menuLabel: "Explorer",
|
||||||
title: "Explorer les mondes",
|
title: "Explorer les mondes",
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
title: "{user} — Mon univers",
|
||||||
|
metaTitle: "Mon univers",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
middleware/resetMenu.ts
Normal file
4
middleware/resetMenu.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default defineNuxtRouteMiddleware(() => {
|
||||||
|
const { resetMenu } = useUiStore()
|
||||||
|
resetMenu()
|
||||||
|
})
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
useHead({
|
useHead({
|
||||||
titleTemplate: null
|
titleTemplate: null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ["reset-menu"]
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -40,6 +40,24 @@ const {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const isLoading = computed(() => calendarStatus.value === "pending" || categoriesStatus.value === "pending")
|
const isLoading = computed(() => calendarStatus.value === "pending" || categoriesStatus.value === "pending")
|
||||||
|
|
||||||
|
// Set custom menu
|
||||||
|
const { t } = useI18n()
|
||||||
|
const { setCurrentMenu } = useUiStore()
|
||||||
|
|
||||||
|
setCurrentMenu([
|
||||||
|
{
|
||||||
|
tooltip: t("entity.world.backToMy"),
|
||||||
|
to: "/my",
|
||||||
|
phIcon: "universe",
|
||||||
|
phIconWeight: "regular"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: t("entity.world.backToSingle", { world: calendar.value?.data.world?.name }),
|
||||||
|
to: `/my/worlds/${calendar.value?.data.world?.id}`,
|
||||||
|
phIcon: "world"
|
||||||
|
},
|
||||||
|
])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const supabase = useSupabaseClient()
|
|||||||
const user = useSupabaseUser()
|
const user = useSupabaseUser()
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ["auth-guard"]
|
middleware: ["auth-guard", "reset-menu"]
|
||||||
})
|
})
|
||||||
|
|
||||||
const { data: worlds } = await useLazyFetch<{ data: World[] }>("/api/worlds/query", { query: { gmId: user?.value!.id } })
|
const { data: worlds } = await useLazyFetch<{ data: World[] }>("/api/worlds/query", { query: { gmId: user?.value!.id } })
|
||||||
@@ -31,7 +31,6 @@ function hideCreateDialog() {
|
|||||||
/** Active world channel */
|
/** Active world channel */
|
||||||
let worldChannel: RealtimeChannel
|
let worldChannel: RealtimeChannel
|
||||||
|
|
||||||
|
|
||||||
/** Handles world insertion realtime events */
|
/** Handles world insertion realtime events */
|
||||||
function handleInsertedWorld(newWorld: WorldChannelPayload) {
|
function handleInsertedWorld(newWorld: WorldChannelPayload) {
|
||||||
if (!worlds.value?.data) return
|
if (!worlds.value?.data) return
|
||||||
@@ -121,10 +120,12 @@ function hideEditModal() {
|
|||||||
<template>
|
<template>
|
||||||
<main class="p-8">
|
<main class="p-8">
|
||||||
<Head>
|
<Head>
|
||||||
<Title>{{ $t("entity.world.namePlural") }}</Title>
|
<Title>{{ $t("pages.profile.metaTitle") }}</Title>
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<Heading level="h1">{{ user?.user_metadata.full_name }}</Heading>
|
<Heading level="h1">
|
||||||
|
{{ $t("pages.profile.title", { user: user?.user_metadata.full_name }) }}
|
||||||
|
</Heading>
|
||||||
|
|
||||||
<section class="mt-4">
|
<section class="mt-4">
|
||||||
<Spacing size="lg">
|
<Spacing size="lg">
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import type { World } from "~/models/World";
|
|||||||
import type { Calendar, CalendarChannelPayload } from "~/models/CalendarConfig";
|
import type { Calendar, CalendarChannelPayload } from "~/models/CalendarConfig";
|
||||||
import { PhArrowBendDoubleUpLeft, PhGlobeHemisphereWest, PhPencil } from "@phosphor-icons/vue";
|
import { PhArrowBendDoubleUpLeft, PhGlobeHemisphereWest, PhPencil } from "@phosphor-icons/vue";
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const supabase = useSupabaseClient()
|
const supabase = useSupabaseClient()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const id = route.params.id
|
const id = route.params.id
|
||||||
@@ -24,6 +26,18 @@ watch(user, (n) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Set custom menu
|
||||||
|
const { setCurrentMenu } = useUiStore()
|
||||||
|
|
||||||
|
setCurrentMenu([
|
||||||
|
{
|
||||||
|
tooltip: t("entity.world.backToMy"),
|
||||||
|
to: "/my",
|
||||||
|
phIcon: "universe",
|
||||||
|
highlight: true
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* === Subscriptions ===
|
* === Subscriptions ===
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ export const useUiStore = defineStore("ui", () => {
|
|||||||
currentMenu.value = items
|
currentMenu.value = items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetMenu() {
|
||||||
|
currentMenu.value = []
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentMenu,
|
currentMenu,
|
||||||
setCurrentMenu
|
setCurrentMenu,
|
||||||
|
resetMenu
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user