Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
115 changes: 110 additions & 5 deletions resources/js/pages/User/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ArrowBigDown,
ArrowRight,
ArrowUpRight,
BadgeCheck,
Calendar,
CheckCircle2,
ChevronRight,
Expand All @@ -29,7 +30,7 @@ import {
X,
Zap,
} from 'lucide-vue-next';
import { computed, 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';
Expand Down Expand Up @@ -246,6 +247,38 @@ const isOwnProfile = computed(

const showSyllabusModal = ref(false);
const showShareModal = ref(false);
const showVerifiedPrompt = ref(false);
const verifiedBadgeContainerRef = ref<HTMLElement | null>(null);

const handleVerifiedClickOutside = (e: MouseEvent) => {
if (
showVerifiedPrompt.value &&
verifiedBadgeContainerRef.value &&
!verifiedBadgeContainerRef.value.contains(e.target as Node)
) {
showVerifiedPrompt.value = false;
}
};

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);
}
});

const activeTab = ref<'forum' | 'blogs' | 'activity'>('forum');
const forumSubTab = ref<'questions' | 'answers'>('questions');
Expand Down Expand Up @@ -588,7 +621,7 @@ const formatGroupName = (group?: string) => {
<div class="mx-auto max-w-3xl space-y-4.5 sm:space-y-6">
<!-- Profile Identity Card -->
<div
class="relative overflow-hidden rounded-2xl border border-slate-200/80 bg-white p-4.5 shadow-xs sm:rounded-3xl sm:p-7 dark:border-gray-800 dark:bg-gray-900"
class="relative rounded-2xl border border-slate-200/80 bg-white p-4.5 shadow-xs sm:rounded-3xl sm:p-7 dark:border-gray-800 dark:bg-gray-900"
>
<div
class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between sm:gap-5"
Expand Down Expand Up @@ -643,10 +676,82 @@ const formatGroupName = (group?: string) => {
{{ profileUser.name }}
</h1>

<VerifiedBadge
<div
v-if="profileUser.is_verified"
size="h-5 w-5"
/>
ref="verifiedBadgeContainerRef"
class="relative inline-flex items-center"
>
<button
type="button"
@click.stop="
showVerifiedPrompt =
!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"
>
<VerifiedBadge size="h-5 w-5" />
</button>

<!-- Floating verification card / popover -->
<Transition
enter-active-class="transition duration-150 ease-out"
enter-from-class="opacity-0 translate-y-1 scale-95"
enter-to-class="opacity-100 translate-y-0 scale-100"
leave-active-class="transition duration-100 ease-in"
leave-from-class="opacity-100 translate-y-0 scale-100"
leave-to-class="opacity-0 translate-y-1 scale-95"
>
<div
v-if="showVerifiedPrompt"
class="absolute top-full -left-20 z-50 mt-2 w-64 max-w-[calc(100vw-4rem)] rounded-2xl border border-slate-200/90 bg-white/95 p-3.5 shadow-xl shadow-slate-900/10 backdrop-blur-xl sm:left-0 sm:w-80 dark:border-gray-800 dark:bg-gray-900/95 dark:shadow-2xl"
role="dialog"
aria-label="Verified contributor information"
>
<div
class="flex items-start gap-2.5"
>
<div
class="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-blue-50 text-blue-600 dark:bg-blue-950/60 dark:text-blue-400"
>
<BadgeCheck
class="h-4 w-4"
/>
</div>
<div class="min-w-0 flex-1">
<div
class="flex items-center justify-between gap-1.5"
>
<p
class="truncate text-xs font-bold text-slate-900 dark:text-gray-100"
>
{{
profileUser.name
}}
</p>
<span
class="inline-flex shrink-0 items-center rounded-full bg-blue-50 px-1.5 py-0.5 text-[9px] font-semibold text-blue-700 dark:bg-blue-950/60 dark:text-blue-300"
>
Verified
</span>
</div>
<p
class="mt-1 text-[11px] leading-relaxed text-slate-500 dark:text-gray-400"
>
প্ল্যাটফর্মে মানসম্মত
কন্টেন্ট ও রিসোর্স শেয়ার
করার জন্য HSCStack
কর্তৃক এই অ্যাকাউন্টটি
যাচাইকৃত।
</p>
</div>
</div>
</div>
</Transition>
</div>
</div>

<!-- Username Tag -->
Expand Down
Loading