814 lines
20 KiB
Vue
814 lines
20 KiB
Vue
<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> |