Mockups for Designs
All checks were successful
Build And Push Image / docker (push) Successful in 1m55s
All checks were successful
Build And Push Image / docker (push) Successful in 1m55s
This commit is contained in:
814
design-mockups/pages/admin/ProfessionalAdminDashboard.vue
Normal file
814
design-mockups/pages/admin/ProfessionalAdminDashboard.vue
Normal file
@@ -0,0 +1,814 @@
|
||||
<template>
|
||||
<div class="admin-dashboard">
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar" :class="{ 'sidebar--collapsed': isSidebarCollapsed }">
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-logo">
|
||||
<img src="/MONACOUSA-Flags_376x376.png" alt="MonacoUSA" />
|
||||
<span v-if="!isSidebarCollapsed" class="sidebar-title">Admin Portal</span>
|
||||
</div>
|
||||
<button @click="isSidebarCollapsed = !isSidebarCollapsed" class="sidebar-toggle">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav class="sidebar-nav">
|
||||
<a
|
||||
v-for="item in navItems"
|
||||
:key="item.id"
|
||||
:class="['sidebar-item', { 'sidebar-item--active': activeNav === item.id }]"
|
||||
@click="activeNav = item.id"
|
||||
>
|
||||
<span class="sidebar-item-icon">
|
||||
<component :is="item.icon" />
|
||||
</span>
|
||||
<span v-if="!isSidebarCollapsed" class="sidebar-item-label">{{ item.label }}</span>
|
||||
<span v-if="!isSidebarCollapsed && item.badge" class="sidebar-item-badge">{{ item.badge }}</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="sidebar-user">
|
||||
<div class="sidebar-user-avatar">
|
||||
<img src="https://via.placeholder.com/40" alt="Admin" />
|
||||
</div>
|
||||
<div v-if="!isSidebarCollapsed" class="sidebar-user-info">
|
||||
<div class="sidebar-user-name">John Admin</div>
|
||||
<div class="sidebar-user-role">System Admin</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<!-- Top Bar -->
|
||||
<header class="topbar">
|
||||
<div class="topbar-left">
|
||||
<h1 class="topbar-title">Dashboard Overview</h1>
|
||||
<p class="topbar-subtitle">Welcome back, John. Here's what's happening today.</p>
|
||||
</div>
|
||||
|
||||
<div class="topbar-right">
|
||||
<button class="topbar-button">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button class="topbar-button topbar-button--notification">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
|
||||
</svg>
|
||||
<span class="notification-badge">3</span>
|
||||
</button>
|
||||
|
||||
<div class="topbar-divider"></div>
|
||||
|
||||
<button class="topbar-user">
|
||||
<img src="https://via.placeholder.com/32" alt="User" class="topbar-user-avatar" />
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="stats-grid">
|
||||
<StatCard
|
||||
v-for="stat in stats"
|
||||
:key="stat.title"
|
||||
:title="stat.title"
|
||||
:value="stat.value"
|
||||
:change="stat.change"
|
||||
:trend="stat.trend"
|
||||
:icon="stat.icon"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Content Grid -->
|
||||
<div class="content-grid">
|
||||
<!-- Chart Card -->
|
||||
<NeumorphicCard class="chart-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Revenue Overview</h2>
|
||||
<div class="card-actions">
|
||||
<button class="card-action">Day</button>
|
||||
<button class="card-action card-action--active">Week</button>
|
||||
<button class="card-action">Month</button>
|
||||
<button class="card-action">Year</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="chart-container">
|
||||
<canvas ref="chartCanvas"></canvas>
|
||||
</div>
|
||||
</NeumorphicCard>
|
||||
|
||||
<!-- Activity Feed -->
|
||||
<NeumorphicCard class="activity-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Recent Activity</h2>
|
||||
<button class="card-link">View All</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="activity-list">
|
||||
<div v-for="activity in activities" :key="activity.id" class="activity-item">
|
||||
<div class="activity-icon" :class="`activity-icon--${activity.type}`">
|
||||
<component :is="activity.icon" />
|
||||
</div>
|
||||
<div class="activity-content">
|
||||
<p class="activity-description">{{ activity.description }}</p>
|
||||
<span class="activity-time">{{ activity.time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NeumorphicCard>
|
||||
|
||||
<!-- Members Table -->
|
||||
<NeumorphicCard class="table-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Recent Members</h2>
|
||||
<ProfessionalButton variant="outline" size="sm">
|
||||
View All Members
|
||||
</ProfessionalButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Member</th>
|
||||
<th>Status</th>
|
||||
<th>Joined</th>
|
||||
<th>Last Active</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="member in recentMembers" :key="member.id">
|
||||
<td>
|
||||
<div class="member-cell">
|
||||
<img :src="member.avatar" :alt="member.name" class="member-avatar" />
|
||||
<div>
|
||||
<div class="member-name">{{ member.name }}</div>
|
||||
<div class="member-email">{{ member.email }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="status-badge" :class="`status-badge--${member.status}`">
|
||||
{{ member.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ member.joined }}</td>
|
||||
<td>{{ member.lastActive }}</td>
|
||||
<td>
|
||||
<button class="table-action">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" />
|
||||
</svg>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</NeumorphicCard>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||
import StatCard from '../../components/data/StatCard.vue';
|
||||
import Chart from 'chart.js/auto';
|
||||
|
||||
// Icons (simplified for demo)
|
||||
const HomeIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg>' };
|
||||
const UsersIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"/></svg>' };
|
||||
const CalendarIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"/></svg>' };
|
||||
const ChartIcon = { template: '<svg fill="currentColor" viewBox="0 0 20 20"><path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/></svg>' };
|
||||
|
||||
// Data
|
||||
const isSidebarCollapsed = ref(false);
|
||||
const activeNav = ref('dashboard');
|
||||
const chartCanvas = ref<HTMLCanvasElement | null>(null);
|
||||
|
||||
const navItems = [
|
||||
{ id: 'dashboard', label: 'Dashboard', icon: HomeIcon },
|
||||
{ id: 'members', label: 'Members', icon: UsersIcon, badge: '127' },
|
||||
{ id: 'events', label: 'Events', icon: CalendarIcon, badge: '5' },
|
||||
{ id: 'analytics', label: 'Analytics', icon: ChartIcon },
|
||||
];
|
||||
|
||||
const stats = [
|
||||
{ title: 'Total Members', value: '1,247', change: '+12%', trend: 'up', icon: UsersIcon },
|
||||
{ title: 'Active Events', value: '18', change: '+3', trend: 'up', icon: CalendarIcon },
|
||||
{ title: 'Monthly Revenue', value: '$48,392', change: '+8%', trend: 'up', icon: ChartIcon },
|
||||
{ title: 'Engagement Rate', value: '87%', change: '-2%', trend: 'down', icon: ChartIcon },
|
||||
];
|
||||
|
||||
const activities = [
|
||||
{ id: 1, type: 'user', icon: UsersIcon, description: 'New member registration: Sarah Johnson', time: '5 minutes ago' },
|
||||
{ id: 2, type: 'event', icon: CalendarIcon, description: 'Annual Gala event updated', time: '1 hour ago' },
|
||||
{ id: 3, type: 'payment', icon: ChartIcon, description: 'Payment received from Michael Brown', time: '2 hours ago' },
|
||||
{ id: 4, type: 'user', icon: UsersIcon, description: 'Member profile updated: Robert Davis', time: '3 hours ago' },
|
||||
];
|
||||
|
||||
const recentMembers = [
|
||||
{ id: 1, name: 'Sarah Johnson', email: 'sarah@example.com', avatar: 'https://via.placeholder.com/40', status: 'active', joined: 'Jan 15, 2024', lastActive: '2 hours ago' },
|
||||
{ id: 2, name: 'Michael Brown', email: 'michael@example.com', avatar: 'https://via.placeholder.com/40', status: 'active', joined: 'Jan 10, 2024', lastActive: '1 day ago' },
|
||||
{ id: 3, name: 'Emma Wilson', email: 'emma@example.com', avatar: 'https://via.placeholder.com/40', status: 'pending', joined: 'Jan 8, 2024', lastActive: '3 days ago' },
|
||||
{ id: 4, name: 'James Taylor', email: 'james@example.com', avatar: 'https://via.placeholder.com/40', status: 'inactive', joined: 'Dec 20, 2023', lastActive: '1 week ago' },
|
||||
];
|
||||
|
||||
// Initialize chart
|
||||
onMounted(() => {
|
||||
if (chartCanvas.value) {
|
||||
new Chart(chartCanvas.value, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
datasets: [{
|
||||
label: 'Revenue',
|
||||
data: [12000, 19000, 15000, 25000, 22000, 30000, 28000],
|
||||
borderColor: '#DC2626',
|
||||
backgroundColor: 'rgba(220, 38, 38, 0.1)',
|
||||
tension: 0.4,
|
||||
fill: true
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: {
|
||||
display: true,
|
||||
color: 'rgba(0, 0, 0, 0.05)'
|
||||
}
|
||||
},
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../styles/neumorphic-system.scss';
|
||||
|
||||
.admin-dashboard {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
background: $neutral-100;
|
||||
}
|
||||
|
||||
// Sidebar
|
||||
.sidebar {
|
||||
width: $sidebar-width;
|
||||
background: white;
|
||||
box-shadow: $shadow-soft-md;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: width $transition-base;
|
||||
|
||||
&--collapsed {
|
||||
width: $sidebar-width-collapsed;
|
||||
}
|
||||
|
||||
&-header {
|
||||
padding: $space-6;
|
||||
border-bottom: 1px solid $neutral-200;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: $radius-lg;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-weight: $font-semibold;
|
||||
color: $neutral-800;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: $space-2;
|
||||
cursor: pointer;
|
||||
color: $neutral-600;
|
||||
border-radius: $radius-md;
|
||||
transition: all $transition-base;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $neutral-100;
|
||||
}
|
||||
}
|
||||
|
||||
&-nav {
|
||||
flex: 1;
|
||||
padding: $space-4;
|
||||
}
|
||||
|
||||
&-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
padding: $space-3 $space-4;
|
||||
margin-bottom: $space-2;
|
||||
border-radius: $radius-lg;
|
||||
color: $neutral-600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all $transition-base;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: $neutral-100;
|
||||
color: $neutral-800;
|
||||
}
|
||||
|
||||
&--active {
|
||||
background: linear-gradient(135deg, $primary-500, $primary-600);
|
||||
color: white;
|
||||
box-shadow: $shadow-soft-sm;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-label {
|
||||
font-size: $text-sm;
|
||||
font-weight: $font-medium;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-badge {
|
||||
margin-left: auto;
|
||||
padding: 2px 8px;
|
||||
background: $primary-100;
|
||||
color: $primary-700;
|
||||
border-radius: $radius-full;
|
||||
font-size: $text-xs;
|
||||
font-weight: $font-semibold;
|
||||
}
|
||||
}
|
||||
|
||||
&-footer {
|
||||
padding: $space-4;
|
||||
border-top: 1px solid $neutral-200;
|
||||
}
|
||||
|
||||
&-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
padding: $space-3;
|
||||
|
||||
&-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: $radius-full;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&-name {
|
||||
font-size: $text-sm;
|
||||
font-weight: $font-semibold;
|
||||
color: $neutral-800;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-role {
|
||||
font-size: $text-xs;
|
||||
color: $neutral-500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main Content
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
// Topbar
|
||||
.topbar {
|
||||
background: white;
|
||||
padding: $space-6;
|
||||
box-shadow: $shadow-soft-sm;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: $text-2xl;
|
||||
font-weight: $font-bold;
|
||||
color: $neutral-800;
|
||||
margin-bottom: $space-1;
|
||||
}
|
||||
|
||||
&-subtitle {
|
||||
font-size: $text-sm;
|
||||
color: $neutral-600;
|
||||
}
|
||||
|
||||
&-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
}
|
||||
|
||||
&-button {
|
||||
position: relative;
|
||||
padding: $space-2;
|
||||
background: white;
|
||||
border: none;
|
||||
border-radius: $radius-lg;
|
||||
cursor: pointer;
|
||||
color: $neutral-600;
|
||||
box-shadow: $shadow-soft-sm;
|
||||
transition: all $transition-base;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: $shadow-soft-md;
|
||||
color: $neutral-800;
|
||||
}
|
||||
|
||||
&--notification {
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: $error-500;
|
||||
color: white;
|
||||
border-radius: $radius-full;
|
||||
font-size: $text-xs;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: $font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-divider {
|
||||
width: 1px;
|
||||
height: 24px;
|
||||
background: $neutral-200;
|
||||
}
|
||||
|
||||
&-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-2;
|
||||
padding: $space-2;
|
||||
background: white;
|
||||
border: none;
|
||||
border-radius: $radius-lg;
|
||||
cursor: pointer;
|
||||
box-shadow: $shadow-soft-sm;
|
||||
transition: all $transition-base;
|
||||
|
||||
&:hover {
|
||||
box-shadow: $shadow-soft-md;
|
||||
}
|
||||
|
||||
&-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: $radius-full;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stats Grid
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: $space-6;
|
||||
padding: $space-6;
|
||||
}
|
||||
|
||||
// Content Grid
|
||||
.content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: $space-6;
|
||||
padding: 0 $space-6 $space-6;
|
||||
|
||||
@media (max-width: $breakpoint-lg) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Card styles
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: $text-lg;
|
||||
font-weight: $font-semibold;
|
||||
color: $neutral-800;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
gap: $space-2;
|
||||
}
|
||||
|
||||
.card-action {
|
||||
padding: $space-2 $space-3;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: $radius-md;
|
||||
font-size: $text-sm;
|
||||
color: $neutral-600;
|
||||
cursor: pointer;
|
||||
transition: all $transition-base;
|
||||
|
||||
&:hover {
|
||||
background: $neutral-100;
|
||||
color: $neutral-800;
|
||||
}
|
||||
|
||||
&--active {
|
||||
background: $primary-500;
|
||||
color: white;
|
||||
box-shadow: $shadow-soft-sm;
|
||||
}
|
||||
}
|
||||
|
||||
.card-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: $primary-600;
|
||||
font-size: $text-sm;
|
||||
font-weight: $font-medium;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $primary-700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
// Chart
|
||||
.chart-container {
|
||||
height: 300px;
|
||||
padding: $space-4 0;
|
||||
}
|
||||
|
||||
// Activity List
|
||||
.activity-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $space-4;
|
||||
}
|
||||
|
||||
.activity-item {
|
||||
display: flex;
|
||||
gap: $space-3;
|
||||
|
||||
&-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: $radius-lg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&--user {
|
||||
background: $info-100;
|
||||
color: $info-500;
|
||||
}
|
||||
|
||||
&--event {
|
||||
background: $warning-100;
|
||||
color: $warning-500;
|
||||
}
|
||||
|
||||
&--payment {
|
||||
background: $success-100;
|
||||
color: $success-500;
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&-description {
|
||||
font-size: $text-sm;
|
||||
color: $neutral-700;
|
||||
margin-bottom: $space-1;
|
||||
}
|
||||
|
||||
&-time {
|
||||
font-size: $text-xs;
|
||||
color: $neutral-500;
|
||||
}
|
||||
}
|
||||
|
||||
// Table
|
||||
.table-wrapper {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
|
||||
thead {
|
||||
tr {
|
||||
border-bottom: 2px solid $neutral-200;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding: $space-3;
|
||||
font-size: $text-xs;
|
||||
font-weight: $font-semibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: $neutral-600;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
border-bottom: 1px solid $neutral-100;
|
||||
transition: background $transition-base;
|
||||
|
||||
&:hover {
|
||||
background: $neutral-50;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
padding: $space-3;
|
||||
font-size: $text-sm;
|
||||
color: $neutral-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.member-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
}
|
||||
|
||||
.member-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: $radius-full;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
font-weight: $font-medium;
|
||||
color: $neutral-800;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.member-email {
|
||||
font-size: $text-xs;
|
||||
color: $neutral-500;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
border-radius: $radius-full;
|
||||
font-size: $text-xs;
|
||||
font-weight: $font-medium;
|
||||
|
||||
&--active {
|
||||
background: $success-100;
|
||||
color: $success-500;
|
||||
}
|
||||
|
||||
&--pending {
|
||||
background: $warning-100;
|
||||
color: $warning-500;
|
||||
}
|
||||
|
||||
&--inactive {
|
||||
background: $neutral-100;
|
||||
color: $neutral-500;
|
||||
}
|
||||
}
|
||||
|
||||
.table-action {
|
||||
padding: $space-2;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: $neutral-500;
|
||||
border-radius: $radius-md;
|
||||
transition: all $transition-base;
|
||||
|
||||
&:hover {
|
||||
background: $neutral-100;
|
||||
color: $neutral-700;
|
||||
}
|
||||
}</style>
|
||||
419
design-mockups/pages/auth/ProfessionalLogin.vue
Normal file
419
design-mockups/pages/auth/ProfessionalLogin.vue
Normal file
@@ -0,0 +1,419 @@
|
||||
<template>
|
||||
<div class="login-page">
|
||||
<div class="login-container">
|
||||
<!-- Left Side - Branding -->
|
||||
<div class="login-branding">
|
||||
<div class="branding-content">
|
||||
<div class="logo-container">
|
||||
<img src="/MONACOUSA-Flags_376x376.png" alt="MonacoUSA" class="logo" />
|
||||
</div>
|
||||
<h1 class="brand-title">MonacoUSA Portal</h1>
|
||||
<p class="brand-tagline">Excellence in Partnership</p>
|
||||
|
||||
<div class="feature-list">
|
||||
<div class="feature-item" v-for="feature in features" :key="feature">
|
||||
<svg class="feature-icon" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<span>{{ feature }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Background pattern -->
|
||||
<div class="branding-pattern"></div>
|
||||
</div>
|
||||
|
||||
<!-- Right Side - Login Form -->
|
||||
<div class="login-form-section">
|
||||
<NeumorphicCard size="lg" elevation="lg" class="login-card">
|
||||
<template #header>
|
||||
<h2 class="login-title">Welcome Back</h2>
|
||||
<p class="login-subtitle">Sign in to access your account</p>
|
||||
</template>
|
||||
|
||||
<form @submit.prevent="handleLogin" class="login-form">
|
||||
<div class="form-group">
|
||||
<label for="email" class="form-label">Email Address</label>
|
||||
<div class="input-wrapper">
|
||||
<input
|
||||
id="email"
|
||||
v-model="credentials.email"
|
||||
type="email"
|
||||
class="form-input"
|
||||
placeholder="you@example.com"
|
||||
required
|
||||
/>
|
||||
<span class="input-icon">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<div class="input-wrapper">
|
||||
<input
|
||||
id="password"
|
||||
v-model="credentials.password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
class="form-input"
|
||||
placeholder="Enter your password"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@click="showPassword = !showPassword"
|
||||
class="input-icon clickable"
|
||||
>
|
||||
<svg v-if="!showPassword" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
<svg v-else fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-options">
|
||||
<label class="checkbox-label">
|
||||
<input v-model="credentials.rememberMe" type="checkbox" class="checkbox-input" />
|
||||
<span>Remember me</span>
|
||||
</label>
|
||||
|
||||
<button type="button" class="forgot-password-link" @click="showForgotPassword = true">
|
||||
Forgot password?
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ProfessionalButton
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
block
|
||||
:loading="loading"
|
||||
class="login-button"
|
||||
>
|
||||
Sign In
|
||||
</ProfessionalButton>
|
||||
</form>
|
||||
|
||||
<template #footer>
|
||||
<div class="login-footer">
|
||||
<p class="signup-prompt">
|
||||
Don't have an account?
|
||||
<a href="/signup" class="signup-link">Create Account</a>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</NeumorphicCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import NeumorphicCard from '../../components/core/NeumorphicCard.vue';
|
||||
import ProfessionalButton from '../../components/core/ProfessionalButton.vue';
|
||||
|
||||
// Data
|
||||
const credentials = ref({
|
||||
email: '',
|
||||
password: '',
|
||||
rememberMe: false
|
||||
});
|
||||
|
||||
const showPassword = ref(false);
|
||||
const loading = ref(false);
|
||||
const showForgotPassword = ref(false);
|
||||
|
||||
const features = [
|
||||
'Secure Member Access',
|
||||
'Event Management',
|
||||
'Document Library',
|
||||
'Payment Processing'
|
||||
];
|
||||
|
||||
// Methods
|
||||
const handleLogin = async () => {
|
||||
loading.value = true;
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
console.log('Login with:', credentials.value);
|
||||
}, 2000);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../styles/neumorphic-system.scss';
|
||||
|
||||
.login-page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(135deg, $neutral-50 0%, $neutral-100 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
min-height: 100vh;
|
||||
|
||||
@media (max-width: $breakpoint-md) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Left side - Branding
|
||||
.login-branding {
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, $primary-600, $primary-800);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $space-12;
|
||||
overflow: hidden;
|
||||
|
||||
@media (max-width: $breakpoint-md) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.branding-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 auto $space-6;
|
||||
background: white;
|
||||
border-radius: $radius-2xl;
|
||||
padding: $space-4;
|
||||
box-shadow: $shadow-soft-lg;
|
||||
|
||||
.logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.brand-title {
|
||||
font-family: $font-heading;
|
||||
font-size: $text-3xl;
|
||||
font-weight: $font-bold;
|
||||
margin-bottom: $space-2;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.brand-tagline {
|
||||
font-size: $text-lg;
|
||||
opacity: 0.9;
|
||||
margin-bottom: $space-12;
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
text-align: left;
|
||||
max-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-3;
|
||||
margin-bottom: $space-4;
|
||||
font-size: $text-base;
|
||||
|
||||
.feature-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
color: rgba(white, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.branding-pattern {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.05'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// Right side - Login form
|
||||
.login-form-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $space-8;
|
||||
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-family: $font-heading;
|
||||
font-size: $text-2xl;
|
||||
font-weight: $font-bold;
|
||||
color: $neutral-800;
|
||||
margin-bottom: $space-2;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
font-size: $text-base;
|
||||
color: $neutral-600;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
.form-group {
|
||||
margin-bottom: $space-5;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: $text-sm;
|
||||
font-weight: $font-medium;
|
||||
color: $neutral-700;
|
||||
margin-bottom: $space-2;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: $space-3 $space-4;
|
||||
padding-right: $space-12;
|
||||
background: $neutral-50;
|
||||
border: none;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-inset-sm;
|
||||
font-size: $text-base;
|
||||
color: $neutral-800;
|
||||
transition: all $transition-base;
|
||||
|
||||
&::placeholder {
|
||||
color: $neutral-400;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: $shadow-inset-md, 0 0 0 3px rgba($primary-500, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
position: absolute;
|
||||
right: $space-3;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: $neutral-400;
|
||||
|
||||
&.clickable {
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
transition: color $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $neutral-600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: $space-6;
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $space-2;
|
||||
font-size: $text-sm;
|
||||
color: $neutral-700;
|
||||
cursor: pointer;
|
||||
|
||||
.checkbox-input {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: $radius-sm;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.forgot-password-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: $primary-600;
|
||||
font-size: $text-sm;
|
||||
font-weight: $font-medium;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
transition: color $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $primary-700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.login-button {
|
||||
margin-top: $space-4;
|
||||
}
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
text-align: center;
|
||||
|
||||
.signup-prompt {
|
||||
font-size: $text-sm;
|
||||
color: $neutral-600;
|
||||
}
|
||||
|
||||
.signup-link {
|
||||
color: $primary-600;
|
||||
font-weight: $font-medium;
|
||||
text-decoration: none;
|
||||
margin-left: $space-1;
|
||||
transition: color $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $primary-700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode support
|
||||
@include dark-mode {
|
||||
.login-page {
|
||||
background: linear-gradient(135deg, $neutral-900 0%, $neutral-800 100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
1249
design-mockups/pages/board/ProfessionalBoardDashboard.vue
Normal file
1249
design-mockups/pages/board/ProfessionalBoardDashboard.vue
Normal file
File diff suppressed because it is too large
Load Diff
1287
design-mockups/pages/member/ProfessionalMemberDashboard.vue
Normal file
1287
design-mockups/pages/member/ProfessionalMemberDashboard.vue
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user