Skip to content

Commit ed4c81f

Browse files
authored
Update desktop & mobile NavBar's UserAvatar menu (#1452)
* Add UserMenu component to host navbar dropdown changes * Remove ReportBug routes and related files * Update mobile accordion nav items * Fix race condition on useTimeAgoIntl composable * Force dark mode for UserMenu * Update NavBar unit tests
1 parent ca5351c commit ed4c81f

File tree

15 files changed

+135
-69
lines changed

15 files changed

+135
-69
lines changed

frontend/.env.example

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ VITE_POSTHOG_PROJECT_KEY=
2525
VITE_POSTHOG_HOST=https://us.i.posthog.com
2626
VITE_POSTHOG_UI_HOST=https://us.posthog.com
2727

28-
VITE_REPORT_BUG_URL=https://github.com/thunderbird/appointment/issues/new?assignees=&labels=bug&projects=&template=bug_report.md
29-
3028
# If the browser's hour setting is empty or missing fallback to this value
3129
VITE_DEFAULT_HOUR_FORMAT=12
3230

frontend/.env.prod.example

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ VITE_POSTHOG_PROJECT_KEY=phc_61NZH7teRtwmtZQHpKRltXUEEO7acpEAjpjdSiE5tdu
1616
VITE_POSTHOG_HOST=https://data.appointment.tb.pro
1717
VITE_POSTHOG_UI_HOST=https://us.posthog.com
1818

19-
VITE_REPORT_BUG_URL=https://github.com/thunderbird/appointment/issues/new?assignees=&labels=bug&projects=&template=bug_report.md
20-
2119
# If the browser's hour setting is empty or missing fallback to this value
2220
VITE_DEFAULT_HOUR_FORMAT=12
2321

frontend/.env.stage.example

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ VITE_POSTHOG_PROJECT_KEY=phc_jPP49KIEgnkSKAjsDzCrQrJiGQVzCd0iAyVJetd2abv
1616
VITE_POSTHOG_HOST=https://data.appointment.tb.pro
1717
VITE_POSTHOG_UI_HOST=https://us.posthog.com
1818

19-
VITE_REPORT_BUG_URL=https://github.com/thunderbird/appointment/issues/new?assignees=&labels=bug&projects=&template=bug_report.md
20-
2119
# If the browser's hour setting is empty or missing fallback to this value
2220
VITE_DEFAULT_HOUR_FORMAT=12
2321

frontend/.env.test

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,5 @@ VITE_SENTRY_DSN=
1515
# -- Auth scheme --
1616
VITE_AUTH_SCHEME=password
1717

18-
VITE_REPORT_BUG_URL=
19-
2018
VITE_TB_PRO_URL=https://stage.tb.pro
2119
VITE_SUPPORT_URL=https://accounts-stage.tb.pro/contact

frontend/src/App.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ const routeIsFTUE = computed(
152152
const routeIsPostLogin = computed(
153153
() => ['post-login'].includes(typeof route.name === 'string' ? route.name : ''),
154154
);
155+
const routeIsLogout = computed(
156+
() => ['logout'].includes(typeof route.name === 'string' ? route.name : ''),
157+
);
155158
156159
// retrieve calendars and appointments after checking login and persisting user to db
157160
const getDbData = async () => {
@@ -320,7 +323,7 @@ onMounted(async () => {
320323

321324
<template>
322325
<!-- Home page is actually just a redirect to another route -->
323-
<template v-if="routeIsHome || (routeIsLogin && isOidcAuth) || routeIsFTUE || routeIsPostLogin">
326+
<template v-if="routeIsHome || (routeIsLogin && isOidcAuth) || routeIsFTUE || routeIsPostLogin || routeIsLogout">
324327
<router-view/>
325328
</template>
326329

frontend/src/components/NavBar.vue

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script setup lang="ts">
2-
import { inject, ref } from 'vue';
2+
import { ref } from 'vue';
33
import { useI18n } from 'vue-i18n';
44
import { useRoute } from 'vue-router';
55
import { useUserStore } from '@/stores/user-store';
66
import NavBarItem from '@/elements/NavBarItem.vue';
77
import { TooltipPosition } from '@/definitions';
88
import { PhLinkSimple } from '@phosphor-icons/vue';
9-
import { UserAvatar, ToolTip, BaseButton } from '@thunderbirdops/services-ui';
10-
import { accountsTbProfileUrlKey } from '@/keys';
9+
import { ToolTip, BaseButton } from '@thunderbirdops/services-ui';
10+
import UserMenu from '@/components/UserMenu.vue';
1111
1212
// component constants
1313
const tbProUrl = import.meta.env.VITE_TB_PRO_URL;
@@ -21,8 +21,6 @@ interface Props {
2121
}
2222
defineProps<Props>();
2323
24-
const accountsTbProfileUrl = inject(accountsTbProfileUrlKey);
25-
2624
const myLinkTooltip = ref(t('label.copyLink'));
2725
2826
/**
@@ -86,9 +84,7 @@ const copyLink = async () => {
8684
</button>
8785
</div>
8886

89-
<a :href="accountsTbProfileUrl">
90-
<user-avatar :username="user.data.username" :avatar-url="user.data.avatarUrl" />
91-
</a>
87+
<user-menu :username="user.data.username" :avatar-url="user.data.avatarUrl" />
9288
</div>
9389
</template>
9490

frontend/src/components/NavBarMobile.vue

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { inject, ref } from 'vue';
2+
import { ref } from 'vue';
33
import { useI18n } from 'vue-i18n';
44
import { useUserStore } from '@/stores/user-store';
55
import {
@@ -15,7 +15,6 @@ import {
1515
PhUserSquare,
1616
} from '@phosphor-icons/vue';
1717
import { PrimaryButton, UserAvatar } from '@thunderbirdops/services-ui';
18-
import { accountsTbProfileUrlKey } from '@/keys';
1918
2019
// component constants
2120
const userStore = useUserStore();
@@ -28,7 +27,8 @@ const navItems = [
2827
{ route: 'settings', i18nKey: 'settings', icon: PhGear },
2928
];
3029
31-
const accountsTbProfileUrl = inject(accountsTbProfileUrlKey);
30+
const accountsTbProfileUrl = import.meta.env?.VITE_TB_ACCOUNT_DASHBOARD_URL;
31+
const supportUrl = import.meta.env?.VITE_SUPPORT_URL;
3232
3333
const menuOpen = ref(false);
3434
const myLinkTooltip = ref(t('navBar.shareMyLink'));
@@ -108,21 +108,15 @@ async function copyLink() {
108108
<a :href="accountsTbProfileUrl">
109109
<li>
110110
<ph-user-square size="24" />
111-
{{ t('label.userProfile') }}
111+
{{ t('label.account') }}
112112
</li>
113113
</a>
114-
<router-link to="report-bug">
114+
<a :href="supportUrl">
115115
<li>
116116
<ph-arrow-square-out size="24" />
117-
{{ t('navBar.reportBug') }}
117+
{{ t('label.support') }}
118118
</li>
119-
</router-link>
120-
<router-link to="contact">
121-
<li>
122-
<ph-arrow-square-out size="24" />
123-
{{ t('label.contact') }}
124-
</li>
125-
</router-link>
119+
</a>
126120
</ul>
127121
</details>
128122
<router-link to="logout">
@@ -291,7 +285,7 @@ nav {
291285
display: flex;
292286
gap: 0.75rem;
293287
padding: 0.5rem 0;
294-
margin-top: 1rem;
288+
margin-top: 0.625rem;
295289
text-decoration: none;
296290
color: inherit;
297291
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script setup lang="ts">
2+
import { ref, onMounted, onBeforeUnmount } from 'vue';
3+
import { useI18n } from 'vue-i18n';
4+
import { UserAvatar } from '@thunderbirdops/services-ui';
5+
6+
defineProps<{
7+
username: string;
8+
avatarUrl?: string;
9+
}>();
10+
11+
const accountsTbProfileUrl = import.meta.env?.VITE_TB_ACCOUNT_DASHBOARD_URL;
12+
const supportUrl = import.meta.env?.VITE_SUPPORT_URL;
13+
14+
const { t } = useI18n();
15+
16+
const showMenu = ref(false);
17+
const menuRef = ref<HTMLElement | null>(null);
18+
19+
const toggleMenu = () => {
20+
showMenu.value = !showMenu.value;
21+
};
22+
23+
const handleClickOutside = (event: MouseEvent) => {
24+
if (menuRef.value && !menuRef.value.contains(event.target as Node)) {
25+
showMenu.value = false;
26+
}
27+
};
28+
29+
onMounted(() => {
30+
document.addEventListener('click', handleClickOutside);
31+
});
32+
33+
onBeforeUnmount(() => {
34+
document.removeEventListener('click', handleClickOutside);
35+
});
36+
</script>
37+
38+
<template>
39+
<button class="user-menu" ref="menuRef">
40+
<user-avatar :username="username" class="avatar" @click="toggleMenu" />
41+
42+
<div v-if="showMenu" class="dropdown">
43+
<a :href="accountsTbProfileUrl">
44+
{{ t('label.account') }}
45+
</a>
46+
<a :href="supportUrl">
47+
{{ t('label.support') }}
48+
</a>
49+
<router-link to="logout">
50+
{{ t('label.logOut') }}
51+
</router-link>
52+
</div>
53+
</button>
54+
</template>
55+
56+
<style scoped>
57+
.user-menu {
58+
position: relative;
59+
display: inline-block;
60+
background: none;
61+
border: none;
62+
cursor: pointer;
63+
64+
.avatar {
65+
& :first-child {
66+
color: var(--colour-ti-base-dark);
67+
}
68+
}
69+
70+
.dropdown {
71+
position: absolute;
72+
right: 0;
73+
margin-top: 0.5rem;
74+
background: var(--colour-ti-base-light);
75+
border: 1px solid rgba(255, 255, 255, 0.08);
76+
border-radius: 0.5rem;
77+
box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.2);
78+
padding: 0.5rem 0.25rem;
79+
min-width: 150px;
80+
81+
a {
82+
display: flex;
83+
align-items: flex-end;
84+
justify-content: space-between;
85+
color: white;
86+
text-decoration: none;
87+
padding: 0.75rem 0.375rem;
88+
font-family: metropolis;
89+
font-size: 0.6875rem;
90+
text-transform: uppercase;
91+
font-weight: 500;
92+
border-radius: 0.25rem;
93+
94+
&:hover {
95+
background: rgba(255, 255, 255, 0.06);
96+
}
97+
}
98+
}
99+
}
100+
</style>

frontend/src/locales/de.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@
441441
"status": "Status",
442442
"subscribe": "Abonnieren",
443443
"success": "Erfolg",
444+
"support": "Support",
444445
"sync": "Synchronisieren",
445446
"syncCalendars": "Kalender synchronisieren",
446447
"system": "System",
@@ -526,7 +527,6 @@
526527
}
527528
},
528529
"navBar": {
529-
"reportBug": "Fehler melden",
530530
"shareMyLink": "Meinen Link teilen"
531531
},
532532
"placeholder": {

frontend/src/locales/en.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@
345345
"loading": "Loading",
346346
"location": "Location",
347347
"logIn": "Log in",
348-
"logOut": "Log out",
348+
"logOut": "Logout",
349349
"loginToContinue": "Log in to continue",
350350
"manageBookingLink": "Manage booking link",
351351
"meetingDuration": "Meeting duration",
@@ -445,6 +445,7 @@
445445
"status": "Status",
446446
"subscribe": "Subscribe",
447447
"success": "Success",
448+
"support": "Support",
448449
"sync": "Sync",
449450
"syncCalendars": "Sync Calendars",
450451
"system": "System",
@@ -530,7 +531,6 @@
530531
}
531532
},
532533
"navBar": {
533-
"reportBug": "Report Bug",
534534
"shareMyLink": "Share my link"
535535
},
536536
"placeholder": {

0 commit comments

Comments
 (0)