Skip to content

Commit 45eb470

Browse files
huchenleigithub-actions
andauthored
Implement top menu user popover (#3631)
Co-authored-by: github-actions <[email protected]>
1 parent 2535957 commit 45eb470

File tree

9 files changed

+133
-34
lines changed

9 files changed

+133
-34
lines changed
Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
11
<!-- A button that shows current authenticated user's avatar -->
22
<template>
3-
<Button
4-
v-if="isAuthenticated"
5-
v-tooltip="{ value: $t('userSettings.title'), showDelay: 300 }"
6-
class="user-profile-button p-1"
7-
severity="secondary"
8-
text
9-
:aria-label="$t('userSettings.title')"
10-
@click="openUserSettings"
11-
>
12-
<div
13-
class="flex items-center rounded-full bg-[var(--p-content-background)]"
3+
<div>
4+
<Button
5+
v-if="isAuthenticated"
6+
v-tooltip="{ value: $t('userSettings.title'), showDelay: 300 }"
7+
class="user-profile-button p-1"
8+
severity="secondary"
9+
text
10+
:aria-label="$t('userSettings.title')"
11+
@click="popover?.toggle($event)"
1412
>
15-
<Avatar
16-
:image="photoURL"
17-
:icon="photoURL ? undefined : 'pi pi-user'"
18-
shape="circle"
19-
aria-label="User Avatar"
20-
/>
13+
<div
14+
class="flex items-center rounded-full bg-[var(--p-content-background)]"
15+
>
16+
<Avatar
17+
:image="photoURL"
18+
:icon="photoURL ? undefined : 'pi pi-user'"
19+
shape="circle"
20+
aria-label="User Avatar"
21+
/>
2122

22-
<i class="pi pi-chevron-down px-1" :style="{ fontSize: '0.5rem' }" />
23-
</div>
24-
</Button>
23+
<i class="pi pi-chevron-down px-1" :style="{ fontSize: '0.5rem' }" />
24+
</div>
25+
</Button>
26+
27+
<Popover ref="popover" :show-arrow="false">
28+
<CurrentUserPopover />
29+
</Popover>
30+
</div>
2531
</template>
2632

2733
<script setup lang="ts">
2834
import Avatar from 'primevue/avatar'
2935
import Button from 'primevue/button'
30-
import { computed } from 'vue'
36+
import Popover from 'primevue/popover'
37+
import { computed, ref } from 'vue'
3138
32-
import { useDialogService } from '@/services/dialogService'
3339
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
3440
41+
import CurrentUserPopover from './CurrentUserPopover.vue'
42+
3543
const authStore = useFirebaseAuthStore()
36-
const dialogService = useDialogService()
44+
45+
const popover = ref<InstanceType<typeof Popover> | null>(null)
3746
const isAuthenticated = computed(() => authStore.isAuthenticated)
3847
const photoURL = computed<string | undefined>(
3948
() => authStore.currentUser?.photoURL ?? undefined
4049
)
41-
42-
const openUserSettings = () => {
43-
dialogService.showSettingsDialog('user')
44-
}
4550
</script>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<!-- A popover that shows current user information and actions -->
2+
<template>
3+
<div class="current-user-popover w-72">
4+
<!-- User Info Section -->
5+
<div class="p-3">
6+
<div class="flex flex-col items-center">
7+
<Avatar
8+
class="mb-3"
9+
:image="user?.photoURL ?? undefined"
10+
:icon="user?.photoURL ? undefined : 'pi pi-user'"
11+
shape="circle"
12+
size="large"
13+
aria-label="User Avatar"
14+
/>
15+
16+
<!-- User Details -->
17+
<h3 class="text-lg font-semibold truncate my-0 mb-1">
18+
{{ user?.displayName || $t('g.user') }}
19+
</h3>
20+
<p v-if="user?.email" class="text-sm text-muted truncate my-0">
21+
{{ user.email }}
22+
</p>
23+
</div>
24+
</div>
25+
26+
<Divider class="my-2" />
27+
28+
<Button
29+
class="justify-start"
30+
:label="$t('userSettings.title')"
31+
icon="pi pi-cog"
32+
text
33+
fluid
34+
severity="secondary"
35+
@click="handleOpenUserSettings"
36+
/>
37+
38+
<Divider class="my-2" />
39+
40+
<div class="w-full flex flex-col gap-2 p-2">
41+
<div class="text-muted text-sm">
42+
{{ $t('credits.yourCreditBalance') }}
43+
</div>
44+
<div class="flex justify-between items-center">
45+
<UserCredit text-class="text-2xl" />
46+
<Button :label="$t('credits.topUp.topUp')" @click="handleTopUp" />
47+
</div>
48+
</div>
49+
</div>
50+
</template>
51+
52+
<script setup lang="ts">
53+
import Avatar from 'primevue/avatar'
54+
import Button from 'primevue/button'
55+
import Divider from 'primevue/divider'
56+
import { computed, onMounted } from 'vue'
57+
58+
import UserCredit from '@/components/common/UserCredit.vue'
59+
import { useDialogService } from '@/services/dialogService'
60+
import { useFirebaseAuthService } from '@/services/firebaseAuthService'
61+
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
62+
63+
const authStore = useFirebaseAuthStore()
64+
const authService = useFirebaseAuthService()
65+
const dialogService = useDialogService()
66+
67+
const user = computed(() => authStore.currentUser)
68+
69+
const handleOpenUserSettings = () => {
70+
dialogService.showSettingsDialog('user')
71+
}
72+
73+
const handleTopUp = () => {
74+
dialogService.showTopUpCreditsDialog()
75+
}
76+
77+
onMounted(() => {
78+
void authService.fetchBalance()
79+
})
80+
</script>

src/locales/en/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"g": {
3+
"user": "User",
34
"currentUser": "Current user",
45
"empty": "Empty",
56
"noWorkflowsFound": "No workflows found.",
@@ -1161,7 +1162,8 @@
11611162
"quickPurchase": "Quick Purchase",
11621163
"maxAmount": "(Max. $1,000 USD)",
11631164
"buyNow": "Buy now",
1164-
"seeDetails": "See details"
1165+
"seeDetails": "See details",
1166+
"topUp": "Top Up"
11651167
}
11661168
},
11671169
"userSettings": {

src/locales/es/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "Créditos insuficientes",
115115
"maxAmount": "(Máx. $1,000 USD)",
116116
"quickPurchase": "Compra rápida",
117-
"seeDetails": "Ver detalles"
117+
"seeDetails": "Ver detalles",
118+
"topUp": "Recargar"
118119
},
119120
"yourCreditBalance": "Tu saldo de créditos"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "Actualizado",
303304
"updating": "Actualizando",
304305
"upload": "Subir",
306+
"user": "Usuario",
305307
"videoFailedToLoad": "Falló la carga del video",
306308
"workflow": "Flujo de trabajo"
307309
},

src/locales/fr/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "Crédits insuffisants",
115115
"maxAmount": "(Max. 1 000 $ US)",
116116
"quickPurchase": "Achat rapide",
117-
"seeDetails": "Voir les détails"
117+
"seeDetails": "Voir les détails",
118+
"topUp": "Recharger"
118119
},
119120
"yourCreditBalance": "Votre solde de crédits"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "Mis à jour",
303304
"updating": "Mise à jour",
304305
"upload": "Téléverser",
306+
"user": "Utilisateur",
305307
"videoFailedToLoad": "Échec du chargement de la vidéo",
306308
"workflow": "Flux de travail"
307309
},

src/locales/ja/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "クレジット不足",
115115
"maxAmount": "(最大 $1,000 USD)",
116116
"quickPurchase": "クイック購入",
117-
"seeDetails": "詳細を見る"
117+
"seeDetails": "詳細を見る",
118+
"topUp": "チャージ"
118119
},
119120
"yourCreditBalance": "あなたのクレジット残高"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "更新済み",
303304
"updating": "更新中",
304305
"upload": "アップロード",
306+
"user": "ユーザー",
305307
"videoFailedToLoad": "ビデオの読み込みに失敗しました",
306308
"workflow": "ワークフロー"
307309
},

src/locales/ko/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "크레딧 부족",
115115
"maxAmount": "(최대 $1,000 USD)",
116116
"quickPurchase": "빠른 구매",
117-
"seeDetails": "자세히 보기"
117+
"seeDetails": "자세히 보기",
118+
"topUp": "충전하기"
118119
},
119120
"yourCreditBalance": "보유 크레딧 잔액"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "업데이트 됨",
303304
"updating": "업데이트 중",
304305
"upload": "업로드",
306+
"user": "사용자",
305307
"videoFailedToLoad": "비디오를 로드하지 못했습니다.",
306308
"workflow": "워크플로"
307309
},

src/locales/ru/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "Недостаточно кредитов",
115115
"maxAmount": "(Макс. $1,000 USD)",
116116
"quickPurchase": "Быстрая покупка",
117-
"seeDetails": "Смотреть детали"
117+
"seeDetails": "Смотреть детали",
118+
"topUp": "Пополнить"
118119
},
119120
"yourCreditBalance": "Ваш баланс кредитов"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "Обновлено",
303304
"updating": "Обновление",
304305
"upload": "Загрузить",
306+
"user": "Пользователь",
305307
"videoFailedToLoad": "Не удалось загрузить видео",
306308
"workflow": "Рабочий процесс"
307309
},

src/locales/zh/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@
114114
"insufficientTitle": "积分不足",
115115
"maxAmount": "(最高 $1,000 美元)",
116116
"quickPurchase": "快速购买",
117-
"seeDetails": "查看详情"
117+
"seeDetails": "查看详情",
118+
"topUp": "充值"
118119
},
119120
"yourCreditBalance": "您的积分余额"
120121
},
@@ -302,6 +303,7 @@
302303
"updated": "已更新",
303304
"updating": "更新中",
304305
"upload": "上传",
306+
"user": "用户",
305307
"videoFailedToLoad": "视频加载失败",
306308
"workflow": "工作流"
307309
},

0 commit comments

Comments
 (0)