UI improvements for Board Portal dashboard
Build And Push Image / docker (push) Successful in 2m0s
Details
Build And Push Image / docker (push) Successful in 2m0s
Details
- Added profile picture between welcome message and title
- Removed Events and Members boxes from dashboard
- Added distinct borders and icon to Dues Management card
- Moved hamburger menu to the right side of app bar
- Removed notification bell icon from app bar
- Enhanced profile card appearance in sidebar with gradient background
- Fixed Mark as Paid button alignment to be inline with other action buttons
- Added support for displaying multiple nationality flags in dues cards
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b67100df2a
commit
95c253a552
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<v-card elevation="2" class="dues-management-card">
|
||||
<v-card elevation="4" class="dues-management-card" style="border: 2px solid #dc2626; border-radius: 16px;">
|
||||
<v-card-title class="pa-4 bg-warning-lighten-5">
|
||||
<v-icon class="mr-2" color="warning">mdi-cash-clock</v-icon>
|
||||
<span class="text-h6">Dues Management</span>
|
||||
<v-icon class="mr-3" color="warning" size="28">mdi-cash-multiple</v-icon>
|
||||
<span class="text-h6 font-weight-bold">Dues Management</span>
|
||||
<v-spacer />
|
||||
<v-chip color="warning" size="small">
|
||||
{{ overdueMembers.length + upcomingMembers.length }} Action Items
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@
|
|||
<v-chip size="x-small" color="grey" variant="text" class="pa-0 mr-2">
|
||||
ID: {{ member.member_id || `MUSA-${member.Id}` }}
|
||||
</v-chip>
|
||||
<CountryFlag
|
||||
<MultipleCountryFlags
|
||||
v-if="member.nationality"
|
||||
:country-code="member.nationality.split(',')[0]"
|
||||
:country-codes="member.nationality"
|
||||
:show-name="false"
|
||||
size="small"
|
||||
/>
|
||||
|
|
@ -117,21 +117,6 @@
|
|||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<v-card-actions class="pa-4 pt-0 d-flex justify-center">
|
||||
<v-btn
|
||||
color="success"
|
||||
variant="elevated"
|
||||
height="44"
|
||||
:loading="loading"
|
||||
@click="showPaymentDateDialog = true"
|
||||
class="px-4"
|
||||
>
|
||||
<v-icon start size="16">mdi-check-circle</v-icon>
|
||||
Mark as Paid
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
|
||||
<!-- Payment Date Selection Dialog -->
|
||||
<v-dialog v-model="showPaymentDateDialog" max-width="400">
|
||||
<v-card>
|
||||
|
|
@ -202,28 +187,39 @@
|
|||
</v-dialog>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<v-card-actions class="pa-4 pt-0">
|
||||
<v-btn
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="$emit('view-member', member)"
|
||||
>
|
||||
<v-icon start size="16">mdi-account</v-icon>
|
||||
View Details
|
||||
</v-btn>
|
||||
|
||||
<v-spacer />
|
||||
<v-card-actions class="pa-4 pt-0 d-flex justify-space-between">
|
||||
<div class="d-flex gap-1">
|
||||
<v-btn
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="$emit('view-member', member)"
|
||||
>
|
||||
<v-icon start size="16">mdi-account</v-icon>
|
||||
View Details
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
variant="text"
|
||||
size="small"
|
||||
:loading="emailLoading"
|
||||
:disabled="!member.email"
|
||||
@click="sendDuesReminder"
|
||||
v-if="member.email"
|
||||
>
|
||||
<v-icon start size="16">mdi-email</v-icon>
|
||||
Email
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<v-btn
|
||||
variant="text"
|
||||
color="success"
|
||||
variant="elevated"
|
||||
size="small"
|
||||
:loading="emailLoading"
|
||||
:disabled="!member.email"
|
||||
@click="sendDuesReminder"
|
||||
v-if="member.email"
|
||||
:loading="loading"
|
||||
@click="showPaymentDateDialog = true"
|
||||
>
|
||||
<v-icon start size="16">mdi-email</v-icon>
|
||||
Email
|
||||
<v-icon start size="16">mdi-check-circle</v-icon>
|
||||
Mark as Paid
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
|
@ -232,6 +228,7 @@
|
|||
<script setup lang="ts">
|
||||
import type { Member } from '~/utils/types';
|
||||
import ProfileAvatar from '~/components/ProfileAvatar.vue';
|
||||
import MultipleCountryFlags from '~/components/MultipleCountryFlags.vue';
|
||||
|
||||
// Extended member type for dues management
|
||||
interface DuesMember {
|
||||
|
|
|
|||
|
|
@ -252,23 +252,38 @@
|
|||
<!-- Enhanced Profile Card -->
|
||||
<template v-slot:append>
|
||||
<div class="pa-2">
|
||||
<v-card class="glass-profile-card overflow-visible">
|
||||
<v-card class="glass-profile-card overflow-visible" style="background: linear-gradient(135deg, rgba(220, 38, 38, 0.08), rgba(255, 255, 255, 0.95)); border: 1px solid rgba(220, 38, 38, 0.2);">
|
||||
<div class="d-flex align-center" :class="miniVariant ? 'flex-column py-3 px-2' : 'pa-3'">
|
||||
<!-- Avatar Section -->
|
||||
<ProfileAvatar
|
||||
:member-id="memberData?.member_id || memberData?.Id"
|
||||
:first-name="memberData?.first_name || user?.firstName"
|
||||
:last-name="memberData?.last_name || user?.lastName"
|
||||
:member-name="memberData?.FullName || user?.name"
|
||||
:size="miniVariant ? '32' : 'small'"
|
||||
:class="miniVariant ? '' : 'mr-3'"
|
||||
/>
|
||||
<div style="position: relative;">
|
||||
<ProfileAvatar
|
||||
:member-id="memberData?.member_id || memberData?.Id"
|
||||
:first-name="memberData?.first_name || user?.firstName"
|
||||
:last-name="memberData?.last_name || user?.lastName"
|
||||
:member-name="memberData?.FullName || user?.name"
|
||||
:size="miniVariant ? '32' : '48'"
|
||||
:class="miniVariant ? '' : 'mr-3'"
|
||||
show-border
|
||||
style="border: 2px solid #dc2626; box-shadow: 0 2px 8px rgba(220, 38, 38, 0.2);"
|
||||
/>
|
||||
<v-icon
|
||||
v-if="!miniVariant"
|
||||
size="16"
|
||||
color="green"
|
||||
style="position: absolute; bottom: 0; right: 12px; background: white; border-radius: 50%; padding: 2px;"
|
||||
>
|
||||
mdi-check-circle
|
||||
</v-icon>
|
||||
</div>
|
||||
|
||||
<!-- Info Section (Hidden in mini mode) -->
|
||||
<div v-if="!miniVariant" class="flex-grow-1">
|
||||
<div class="text-subtitle-2 font-weight-bold">{{ user?.name || 'Board Member' }}</div>
|
||||
<div class="text-caption text-medium-emphasis">{{ user?.email?.split('@')[0] || 'board' }}</div>
|
||||
<v-chip size="x-small" class="mt-1 glass-badge">Board</v-chip>
|
||||
<v-chip size="x-small" class="mt-1" style="background: linear-gradient(135deg, #dc2626, #b91c1c); color: white;">
|
||||
<v-icon start size="12">mdi-shield-check</v-icon>
|
||||
Board
|
||||
</v-chip>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
|
|
@ -279,10 +294,12 @@
|
|||
v-bind="props"
|
||||
icon
|
||||
:size="miniVariant ? 'small' : 'small'"
|
||||
variant="text"
|
||||
variant="tonal"
|
||||
color="primary"
|
||||
class="profile-menu-btn"
|
||||
style="background: rgba(220, 38, 38, 0.1);"
|
||||
>
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list density="compact" class="glass-menu" min-width="200">
|
||||
|
|
@ -321,14 +338,6 @@
|
|||
</v-navigation-drawer>
|
||||
|
||||
<v-app-bar elevation="0" flat class="glass-app-bar board-bar">
|
||||
<v-btn
|
||||
icon
|
||||
@click="toggleDrawer"
|
||||
class="glass-icon-btn mr-2"
|
||||
>
|
||||
<v-icon>{{ miniVariant ? 'mdi-menu' : 'mdi-menu-open' }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-toolbar-title class="font-weight-bold text-white">
|
||||
Board Portal
|
||||
</v-toolbar-title>
|
||||
|
|
@ -344,14 +353,13 @@
|
|||
<v-icon>mdi-magnify</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon class="glass-icon-btn">
|
||||
<v-badge
|
||||
:content="notifications"
|
||||
:value="notifications > 0"
|
||||
color="error"
|
||||
>
|
||||
<v-icon>mdi-bell</v-icon>
|
||||
</v-badge>
|
||||
<!-- Move hamburger menu to the right side -->
|
||||
<v-btn
|
||||
icon
|
||||
@click="toggleDrawer"
|
||||
class="glass-icon-btn ml-2"
|
||||
>
|
||||
<v-icon>{{ miniVariant ? 'mdi-menu' : 'mdi-menu-open' }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<!-- User Menu -->
|
||||
|
|
|
|||
|
|
@ -8,6 +8,20 @@
|
|||
<h1 class="dashboard-title text-gradient">
|
||||
Welcome Back, {{ firstName }}!
|
||||
</h1>
|
||||
|
||||
<!-- Profile Picture Section -->
|
||||
<div class="profile-picture-section my-4">
|
||||
<ProfileAvatar
|
||||
:member-id="memberData?.member_id || memberData?.Id"
|
||||
:first-name="memberData?.first_name || user?.firstName"
|
||||
:last-name="memberData?.last_name || user?.lastName"
|
||||
:member-name="memberData?.FullName || user?.name"
|
||||
size="80"
|
||||
show-border
|
||||
class="profile-avatar-main"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p class="dashboard-subtitle">
|
||||
MonacoUSA Board Portal
|
||||
</p>
|
||||
|
|
@ -19,40 +33,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Board Tools with Bento Grid -->
|
||||
<div class="bento-grid mb-6">
|
||||
<div class="bento-item bento-item--large">
|
||||
<v-card class="glass-card pa-4 text-center animated-entrance">
|
||||
<v-icon size="48" color="primary" class="mb-2">mdi-calendar</v-icon>
|
||||
<h3 class="mb-2">Events</h3>
|
||||
<p class="text-body-2 mb-4">View and manage association events</p>
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
style="border-color: #a31515; color: #a31515;"
|
||||
@click="navigateToEvents"
|
||||
>
|
||||
View Events
|
||||
</v-btn>
|
||||
</v-card>
|
||||
</div>
|
||||
|
||||
<div class="bento-item bento-item--large">
|
||||
<v-card class="glass-card pa-4 text-center animated-entrance">
|
||||
<v-icon size="48" color="primary" class="mb-2">mdi-account-group</v-icon>
|
||||
<h3 class="mb-2">Members</h3>
|
||||
<p class="text-body-2 mb-4">View and manage association members</p>
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
style="border-color: #a31515; color: #a31515;"
|
||||
@click="navigateToMembers"
|
||||
>
|
||||
View Members
|
||||
</v-btn>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Board Statistics with Bento Grid -->
|
||||
<div class="bento-grid mb-6">
|
||||
|
|
@ -142,13 +122,21 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import type { Member } from '~/utils/types';
|
||||
import ProfileAvatar from '~/components/ProfileAvatar.vue';
|
||||
|
||||
definePageMeta({
|
||||
layout: 'board',
|
||||
middleware: 'auth'
|
||||
});
|
||||
|
||||
const { firstName, isBoard, isAdmin } = useAuth();
|
||||
const { firstName, isBoard, isAdmin, user } = useAuth();
|
||||
|
||||
// Fetch member data for profile
|
||||
const { data: sessionData } = await useFetch<{ success: boolean; member: Member | null }>('/api/auth/session', {
|
||||
server: false
|
||||
});
|
||||
|
||||
const memberData = computed<Member | null>(() => sessionData.value?.member || null);
|
||||
|
||||
// Check board access on mount
|
||||
onMounted(() => {
|
||||
|
|
@ -338,6 +326,18 @@ const generateReport = () => {
|
|||
inset 0 1px 2px rgba(255, 255, 255, 0.6);
|
||||
animation: slide-up 0.6s ease-out;
|
||||
text-align: center;
|
||||
|
||||
.profile-picture-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.profile-avatar-main {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
border: 3px solid white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
|
|
|
|||
Loading…
Reference in New Issue