From 4937b9816c4e2e47634b77884780b228f1943c59 Mon Sep 17 00:00:00 2001 From: TR Tajim Date: Sun, 11 Oct 2026 10:01:26 +0600 Subject: [PATCH 1/3] feat(profile): add interactive popover details to verified contributor badge --- resources/js/pages/User/Show.vue | 91 ++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/resources/js/pages/User/Show.vue b/resources/js/pages/User/Show.vue index 64dcbf26..e8db64d5 100644 --- a/resources/js/pages/User/Show.vue +++ b/resources/js/pages/User/Show.vue @@ -6,6 +6,7 @@ import { ArrowBigDown, ArrowRight, ArrowUpRight, + BadgeCheck, Calendar, CheckCircle2, ChevronDown, @@ -32,7 +33,7 @@ import { X, Zap, } from 'lucide-vue-next'; -import { computed, ref, watch } from 'vue'; +import { computed, onBeforeUnmount, ref, watch } from 'vue'; import BaseModal from '@/components/BaseModal.vue'; import EmptyState from '@/components/EmptyState.vue'; import ImageViewerModal from '@/components/ImageViewerModal.vue'; @@ -249,6 +250,29 @@ const isOwnProfile = computed( const showSyllabusModal = ref(false); const showShareModal = ref(false); +const showVerifiedPrompt = ref(false); +const verifiedBadgeContainerRef = ref(null); + +const handleVerifiedClickOutside = (e: MouseEvent) => { + if ( + showVerifiedPrompt.value && + verifiedBadgeContainerRef.value && + !verifiedBadgeContainerRef.value.contains(e.target as Node) + ) { + showVerifiedPrompt.value = false; + } +}; + +if (typeof window !== 'undefined') { + window.addEventListener('click', handleVerifiedClickOutside); +} + +onBeforeUnmount(() => { + if (typeof window !== 'undefined') { + window.removeEventListener('click', handleVerifiedClickOutside); + } +}); + const showAlgorithmInfo = ref(false); const expandedSubjects = ref>(new Set()); @@ -656,10 +680,69 @@ const formatGroupName = (group?: string) => { {{ profileUser.name }} - + ref="verifiedBadgeContainerRef" + class="relative inline-flex items-center" + > + + + + +
+
+
+ +
+
+

+ {{ profileUser.name }} + একজন ভেরিফায়েড + কন্ট্রিবিউটর +

+

+ প্ল্যাটফর্মে মানসম্মত + কন্টেন্ট ও রিসোর্স শেয়ার + করার জন্য HSCStack + কর্তৃক এই অ্যাকাউন্টটি + যাচাইকৃত। +

+
+
+
+
+ From 691375850809b0528342b621423eaae55dbda536 Mon Sep 17 00:00:00 2001 From: TR Tajim Date: Sun, 11 Oct 2026 10:12:22 +0600 Subject: [PATCH 2/3] fix(profile): improve verified badge popover mobile responsiveness --- GEMINI.md | 1 + resources/js/pages/User/Show.vue | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/GEMINI.md b/GEMINI.md index f17d6b86..6f6e1dd7 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -6,6 +6,7 @@ - Only run automated check commands when: 1. The user explicitly instructs to `"push"` or `"commit"`. 2. The user explicitly asks to check or fix formatting/linting issues. +- **Fast-Path Lint/Format Fixes**: When asked to fix linting or formatting, immediately run the automated fix commands (`npm run format && composer lint && npm run lint`) first. Do NOT spend time manually inspecting files or CI logs beforehand; only manually edit files if the automated fix commands fail and report non-autofixable errors. - **Quick Push Bypass**: When instructed with `"quick push"` or `"push direct"`, bypass all formatting and linting commands and proceed directly to commit/push. ```bash diff --git a/resources/js/pages/User/Show.vue b/resources/js/pages/User/Show.vue index e8db64d5..470bf599 100644 --- a/resources/js/pages/User/Show.vue +++ b/resources/js/pages/User/Show.vue @@ -625,7 +625,7 @@ const formatGroupName = (group?: string) => {
{ >
{ />
-

- {{ profileUser.name }} - একজন ভেরিফায়েড - কন্ট্রিবিউটর -

+

+ {{ + profileUser.name + }} +

+ + Verified + +

From df12bc516d98adcd577a3bda8760d72105f5ffd4 Mon Sep 17 00:00:00 2001 From: TR Tajim Date: Sun, 11 Oct 2026 10:23:03 +0600 Subject: [PATCH 3/3] fix(profile): improve verified badge popover accessibility and lifecycle cleanup --- resources/js/pages/User/Show.vue | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/resources/js/pages/User/Show.vue b/resources/js/pages/User/Show.vue index 470bf599..4e7283d0 100644 --- a/resources/js/pages/User/Show.vue +++ b/resources/js/pages/User/Show.vue @@ -33,7 +33,7 @@ import { X, Zap, } from 'lucide-vue-next'; -import { computed, onBeforeUnmount, ref, watch } from 'vue'; +import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'; import BaseModal from '@/components/BaseModal.vue'; import EmptyState from '@/components/EmptyState.vue'; import ImageViewerModal from '@/components/ImageViewerModal.vue'; @@ -263,13 +263,23 @@ const handleVerifiedClickOutside = (e: MouseEvent) => { } }; -if (typeof window !== 'undefined') { - window.addEventListener('click', handleVerifiedClickOutside); -} +const handleVerifiedKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape' && showVerifiedPrompt.value) { + showVerifiedPrompt.value = false; + } +}; + +onMounted(() => { + if (typeof window !== 'undefined') { + window.addEventListener('click', handleVerifiedClickOutside); + window.addEventListener('keydown', handleVerifiedKeyDown); + } +}); onBeforeUnmount(() => { if (typeof window !== 'undefined') { window.removeEventListener('click', handleVerifiedClickOutside); + window.removeEventListener('keydown', handleVerifiedKeyDown); } }); @@ -692,6 +702,8 @@ const formatGroupName = (group?: string) => { !showVerifiedPrompt " class="inline-flex cursor-pointer rounded-full transition-transform hover:scale-110 focus:outline-none" + :aria-expanded="showVerifiedPrompt" + aria-haspopup="dialog" aria-label="Verified contributor details" title="Verified Contributor" > @@ -710,6 +722,8 @@ const formatGroupName = (group?: string) => {