import { Component, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; import { DbDashboardComponent, DbWidgetContentDefDirective, type DbDashboard, type DbWidgetType, } from '@sda/dashboard-elements-ui'; @Component({ selector: 'app-root', standalone: true, imports: [CommonModule, DbDashboardComponent, DbWidgetContentDefDirective], template: `
{{ widget.config?.['value'] ?? 0 }}
{{ widget.config?.['label'] ?? 'Metric' }}
{{ widget.title }}
Product Sales Status Change
Product A $12,450 Active +12.5%
Product B $8,320 Active +8.3%
Product C $5,680 Pending -3.2%
Product D $4,120 Active +15.7%
@for (item of sampleListItems; track item.initial) {
{{ item.initial }}
{{ item.title }}
{{ item.subtitle }}
{{ item.time }}
}
`, styles: [` .demo-container { height: 100vh; display: flex; flex-direction: column; } /* Stats Widget */ .widget-stats { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: 1.5rem; } .stat-value { font-size: 2.5rem; font-weight: 700; color: #3b82f6; margin-bottom: 0.5rem; line-height: 1; } .stat-label { font-size: 0.75rem; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; } /* Chart Widget */ .widget-chart { padding: 1rem; height: 100%; display: flex; flex-direction: column; } .chart-title { font-size: 0.875rem; font-weight: 600; color: #6b7280; margin-bottom: 1rem; } .chart-placeholder { flex: 1; display: flex; align-items: center; justify-content: center; } .chart-svg { width: 100%; height: 100%; max-height: 200px; } /* Table Widget */ .widget-table { padding: 0; overflow: auto; height: 100%; } table { width: 100%; border-collapse: collapse; } th, td { padding: 0.75rem 1rem; text-align: left; border-bottom: 1px solid #e5e7eb; } th { background: #f9fafb; font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280; position: sticky; top: 0; z-index: 1; } td { font-size: 0.875rem; } tbody tr:hover { background: #f9fafb; } .status { display: inline-block; padding: 0.25rem 0.625rem; border-radius: 999px; font-size: 0.75rem; font-weight: 500; } .status--success { background: #d1fae5; color: #065f46; } .status--warning { background: #fef3c7; color: #92400e; } .positive { color: #059669; font-weight: 600; } .negative { color: #dc2626; font-weight: 600; } /* List Widget */ .widget-list { padding: 0.5rem 0; overflow: auto; height: 100%; } .list-item { display: flex; align-items: center; padding: 0.75rem 1rem; gap: 0.75rem; border-bottom: 1px solid #e5e7eb; transition: background 150ms; } .list-item:hover { background: #f9fafb; } .avatar { width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 0.875rem; } .list-item__content { flex: 1; min-width: 0; } .list-item__title { font-size: 0.875rem; font-weight: 500; color: #111827; margin-bottom: 0.25rem; } .list-item__subtitle { font-size: 0.75rem; color: #6b7280; } .list-item__meta { font-size: 0.75rem; color: #9ca3af; } `], }) export class AppComponent { dashboard = signal({ id: 'demo-dashboard', title: 'Analytics Dashboard', layouts: [ { breakpoint: 'lg', columns: 12, rowHeight: 80, gap: 16, widgets: [ { id: 'widget-1', col: 1, row: 1, colSpan: 3, rowSpan: 2 }, { id: 'widget-2', col: 4, row: 1, colSpan: 3, rowSpan: 2 }, { id: 'widget-3', col: 7, row: 1, colSpan: 3, rowSpan: 2 }, { id: 'widget-4', col: 10, row: 1, colSpan: 3, rowSpan: 2 }, { id: 'widget-5', col: 1, row: 3, colSpan: 8, rowSpan: 4 }, { id: 'widget-6', col: 9, row: 3, colSpan: 4, rowSpan: 4 }, ], }, ], widgets: [ { id: 'widget-1', type: 'stats', title: 'Total Users', icon: 'users', layout: { id: 'widget-1', col: 1, row: 1, colSpan: 3, rowSpan: 2 }, config: { value: '2,845', label: 'Total Users' }, }, { id: 'widget-2', type: 'stats', title: 'Revenue', icon: 'dollar-sign', layout: { id: 'widget-2', col: 4, row: 1, colSpan: 3, rowSpan: 2 }, config: { value: '$54.2K', label: 'Monthly Revenue' }, }, { id: 'widget-3', type: 'stats', title: 'Conversion', icon: 'trending-up', layout: { id: 'widget-3', col: 7, row: 1, colSpan: 3, rowSpan: 2 }, config: { value: '28.5%', label: 'Conversion Rate' }, }, { id: 'widget-4', type: 'stats', title: 'Active Now', icon: 'activity', layout: { id: 'widget-4', col: 10, row: 1, colSpan: 3, rowSpan: 2 }, config: { value: '124', label: 'Active Sessions' }, }, { id: 'widget-5', type: 'chart', title: 'Revenue Trend', icon: 'bar-chart-2', layout: { id: 'widget-5', col: 1, row: 3, colSpan: 8, rowSpan: 4 }, }, { id: 'widget-6', type: 'list', title: 'Recent Activity', icon: 'activity', layout: { id: 'widget-6', col: 9, row: 3, colSpan: 4, rowSpan: 4 }, }, ], }); widgetTypes: DbWidgetType[] = [ { type: 'stats', label: 'Stats Card', icon: 'bar-chart', description: 'Display key metrics and statistics', category: 'analytics', defaultLayout: { colSpan: 3, rowSpan: 2, minColSpan: 2, minRowSpan: 2, maxColSpan: 4, maxRowSpan: 3, }, component: class {}, }, { type: 'chart', label: 'Chart', icon: 'line-chart', description: 'Visualize data with charts', category: 'analytics', defaultLayout: { colSpan: 6, rowSpan: 4, minColSpan: 4, minRowSpan: 3, }, component: class {}, }, { type: 'table', label: 'Data Table', icon: 'table', description: 'Display tabular data', category: 'data', defaultLayout: { colSpan: 6, rowSpan: 4, minColSpan: 4, minRowSpan: 3, }, component: class {}, }, { type: 'list', label: 'Activity List', icon: 'list', description: 'Show recent activities or notifications', category: 'data', defaultLayout: { colSpan: 4, rowSpan: 4, minColSpan: 3, minRowSpan: 3, }, component: class {}, }, ]; sampleListItems = [ { initial: 'JD', title: 'John Doe completed a task', subtitle: 'Project Alpha', time: '2m ago' }, { initial: 'SM', title: 'Sarah Miller uploaded a file', subtitle: 'Document.pdf', time: '15m ago' }, { initial: 'RJ', title: 'Robert Johnson commented', subtitle: 'Great work on this!', time: '1h ago' }, { initial: 'EW', title: 'Emily White created an issue', subtitle: 'Bug #234', time: '2h ago' }, { initial: 'MC', title: 'Michael Chen merged PR #45', subtitle: 'Feature: Add dashboard', time: '3h ago' }, ]; onWidgetAdd(event: any) { console.log('Widget added:', event); const newWidgets = [...this.dashboard().widgets, event.widget]; this.dashboard.update(d => ({ ...d, widgets: newWidgets })); } onWidgetRemove(event: any) { console.log('Widget removed:', event); const filtered = this.dashboard().widgets.filter((w: any) => w.id !== event.widget.id); this.dashboard.update(d => ({ ...d, widgets: filtered })); } onWidgetMove(event: any) { console.log('Widget moved:', event); } onSave(event: any) { console.log('Dashboard saved:', event); alert('Dashboard saved successfully!'); } }