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>
|
<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-card-title class="pa-4 bg-warning-lighten-5">
|
||||||
<v-icon class="mr-2" color="warning">mdi-cash-clock</v-icon>
|
<v-icon class="mr-3" color="warning" size="28">mdi-cash-multiple</v-icon>
|
||||||
<span class="text-h6">Dues Management</span>
|
<span class="text-h6 font-weight-bold">Dues Management</span>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
<v-chip color="warning" size="small">
|
<v-chip color="warning" size="small">
|
||||||
{{ overdueMembers.length + upcomingMembers.length }} Action Items
|
{{ overdueMembers.length + upcomingMembers.length }} Action Items
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@
|
||||||
<v-chip size="x-small" color="grey" variant="text" class="pa-0 mr-2">
|
<v-chip size="x-small" color="grey" variant="text" class="pa-0 mr-2">
|
||||||
ID: {{ member.member_id || `MUSA-${member.Id}` }}
|
ID: {{ member.member_id || `MUSA-${member.Id}` }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
<CountryFlag
|
<MultipleCountryFlags
|
||||||
v-if="member.nationality"
|
v-if="member.nationality"
|
||||||
:country-code="member.nationality.split(',')[0]"
|
:country-codes="member.nationality"
|
||||||
:show-name="false"
|
:show-name="false"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
|
|
@ -117,21 +117,6 @@
|
||||||
</div>
|
</div>
|
||||||
</v-card-text>
|
</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 -->
|
<!-- Payment Date Selection Dialog -->
|
||||||
<v-dialog v-model="showPaymentDateDialog" max-width="400">
|
<v-dialog v-model="showPaymentDateDialog" max-width="400">
|
||||||
<v-card>
|
<v-card>
|
||||||
|
|
@ -202,28 +187,39 @@
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
<!-- Quick Actions -->
|
<!-- Quick Actions -->
|
||||||
<v-card-actions class="pa-4 pt-0">
|
<v-card-actions class="pa-4 pt-0 d-flex justify-space-between">
|
||||||
<v-btn
|
<div class="d-flex gap-1">
|
||||||
variant="text"
|
<v-btn
|
||||||
size="small"
|
variant="text"
|
||||||
@click="$emit('view-member', member)"
|
size="small"
|
||||||
>
|
@click="$emit('view-member', member)"
|
||||||
<v-icon start size="16">mdi-account</v-icon>
|
>
|
||||||
View Details
|
<v-icon start size="16">mdi-account</v-icon>
|
||||||
</v-btn>
|
View Details
|
||||||
|
</v-btn>
|
||||||
<v-spacer />
|
|
||||||
|
<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
|
<v-btn
|
||||||
variant="text"
|
color="success"
|
||||||
|
variant="elevated"
|
||||||
size="small"
|
size="small"
|
||||||
:loading="emailLoading"
|
:loading="loading"
|
||||||
:disabled="!member.email"
|
@click="showPaymentDateDialog = true"
|
||||||
@click="sendDuesReminder"
|
|
||||||
v-if="member.email"
|
|
||||||
>
|
>
|
||||||
<v-icon start size="16">mdi-email</v-icon>
|
<v-icon start size="16">mdi-check-circle</v-icon>
|
||||||
Email
|
Mark as Paid
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
@ -232,6 +228,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Member } from '~/utils/types';
|
import type { Member } from '~/utils/types';
|
||||||
import ProfileAvatar from '~/components/ProfileAvatar.vue';
|
import ProfileAvatar from '~/components/ProfileAvatar.vue';
|
||||||
|
import MultipleCountryFlags from '~/components/MultipleCountryFlags.vue';
|
||||||
|
|
||||||
// Extended member type for dues management
|
// Extended member type for dues management
|
||||||
interface DuesMember {
|
interface DuesMember {
|
||||||
|
|
|
||||||
|
|
@ -252,23 +252,38 @@
|
||||||
<!-- Enhanced Profile Card -->
|
<!-- Enhanced Profile Card -->
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<div class="pa-2">
|
<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'">
|
<div class="d-flex align-center" :class="miniVariant ? 'flex-column py-3 px-2' : 'pa-3'">
|
||||||
<!-- Avatar Section -->
|
<!-- Avatar Section -->
|
||||||
<ProfileAvatar
|
<div style="position: relative;">
|
||||||
:member-id="memberData?.member_id || memberData?.Id"
|
<ProfileAvatar
|
||||||
:first-name="memberData?.first_name || user?.firstName"
|
:member-id="memberData?.member_id || memberData?.Id"
|
||||||
:last-name="memberData?.last_name || user?.lastName"
|
:first-name="memberData?.first_name || user?.firstName"
|
||||||
:member-name="memberData?.FullName || user?.name"
|
:last-name="memberData?.last_name || user?.lastName"
|
||||||
:size="miniVariant ? '32' : 'small'"
|
:member-name="memberData?.FullName || user?.name"
|
||||||
:class="miniVariant ? '' : 'mr-3'"
|
: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) -->
|
<!-- Info Section (Hidden in mini mode) -->
|
||||||
<div v-if="!miniVariant" class="flex-grow-1">
|
<div v-if="!miniVariant" class="flex-grow-1">
|
||||||
<div class="text-subtitle-2 font-weight-bold">{{ user?.name || 'Board Member' }}</div>
|
<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>
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
|
|
@ -279,10 +294,12 @@
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
icon
|
icon
|
||||||
:size="miniVariant ? 'small' : 'small'"
|
:size="miniVariant ? 'small' : 'small'"
|
||||||
variant="text"
|
variant="tonal"
|
||||||
|
color="primary"
|
||||||
class="profile-menu-btn"
|
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>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-list density="compact" class="glass-menu" min-width="200">
|
<v-list density="compact" class="glass-menu" min-width="200">
|
||||||
|
|
@ -321,14 +338,6 @@
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
|
||||||
<v-app-bar elevation="0" flat class="glass-app-bar board-bar">
|
<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">
|
<v-toolbar-title class="font-weight-bold text-white">
|
||||||
Board Portal
|
Board Portal
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
|
|
@ -344,14 +353,13 @@
|
||||||
<v-icon>mdi-magnify</v-icon>
|
<v-icon>mdi-magnify</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn icon class="glass-icon-btn">
|
<!-- Move hamburger menu to the right side -->
|
||||||
<v-badge
|
<v-btn
|
||||||
:content="notifications"
|
icon
|
||||||
:value="notifications > 0"
|
@click="toggleDrawer"
|
||||||
color="error"
|
class="glass-icon-btn ml-2"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-bell</v-icon>
|
<v-icon>{{ miniVariant ? 'mdi-menu' : 'mdi-menu-open' }}</v-icon>
|
||||||
</v-badge>
|
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<!-- User Menu -->
|
<!-- User Menu -->
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,20 @@
|
||||||
<h1 class="dashboard-title text-gradient">
|
<h1 class="dashboard-title text-gradient">
|
||||||
Welcome Back, {{ firstName }}!
|
Welcome Back, {{ firstName }}!
|
||||||
</h1>
|
</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">
|
<p class="dashboard-subtitle">
|
||||||
MonacoUSA Board Portal
|
MonacoUSA Board Portal
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -19,40 +33,6 @@
|
||||||
</div>
|
</div>
|
||||||
</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 -->
|
<!-- Board Statistics with Bento Grid -->
|
||||||
<div class="bento-grid mb-6">
|
<div class="bento-grid mb-6">
|
||||||
|
|
@ -142,13 +122,21 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Member } from '~/utils/types';
|
import type { Member } from '~/utils/types';
|
||||||
|
import ProfileAvatar from '~/components/ProfileAvatar.vue';
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'board',
|
layout: 'board',
|
||||||
middleware: 'auth'
|
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
|
// Check board access on mount
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -338,6 +326,18 @@ const generateReport = () => {
|
||||||
inset 0 1px 2px rgba(255, 255, 255, 0.6);
|
inset 0 1px 2px rgba(255, 255, 255, 0.6);
|
||||||
animation: slide-up 0.6s ease-out;
|
animation: slide-up 0.6s ease-out;
|
||||||
text-align: center;
|
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 {
|
.dashboard-title {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue