Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
class="dashboard-card"
[class]="'card-' + color"
[class.zero-value]="isZero"
[class.shake-animation]="isZero"
[class.clickable]="clickable"
(click)="onClick()">
<mat-card-content>
Expand All @@ -20,8 +19,9 @@

<div class="card-body">
<h3 class="card-title">{{ title }}</h3>
<div class="card-value">{{ value }}</div>
<p class="card-subtitle" *ngIf="subtitle">{{ subtitle }}</p>
<div class="card-value" *ngIf="!isZero">{{ value }}</div>
<div class="card-value zero-state-cta" *ngIf="isZero">{{ zeroStateText }}</div>
<p class="card-subtitle" *ngIf="subtitle && !isZero">{{ subtitle }}</p>
<ng-content></ng-content>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

&.clickable {
cursor: pointer;

&:hover {
transform: translateY(-4px);
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15);
Expand All @@ -38,6 +38,9 @@
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 1;
transition: transform 0.3s ease;

fa-icon {
font-size: 24px;
Expand Down Expand Up @@ -100,6 +103,18 @@
font-weight: 600;
color: #333;
line-height: 1.2;

&.zero-state-cta {
font-size: 20px;
font-weight: 600;
line-height: 1.3;
background: linear-gradient(135deg, #7f11e0, #9333ea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
padding: 8px 0;
transition: all 0.3s ease;
}
}

.card-subtitle {
Expand All @@ -120,160 +135,114 @@
}
}

// Prompt styling
// Prompt styling - professional and clean
::ng-deep [prompt] {
font-size: 14px;
color: #d32f2f;
font-weight: 600;
font-size: 13px;
color: #666;
font-weight: 400;
display: flex;
align-items: center;
gap: 6px;
animation: urgent-pulse 1.5s infinite;
text-shadow: 0 0 8px rgba(211, 47, 47, 0.3);
letter-spacing: 0.5px;
gap: 8px;
margin-top: 12px;
padding: 8px 12px;
background: rgba(127, 17, 224, 0.04);
border-radius: 6px;
transition: all 0.2s ease;

span {
position: relative;

&::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #d32f2f, transparent);
animation: underline-slide 2s infinite;
}
}
}

@keyframes urgent-pulse {
0%,
100% {
opacity: 0.9;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.02);
}
}

@keyframes underline-slide {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
flex: 1;
}
}

@keyframes pulse {
0% {
opacity: 0.8;
}
50% {
opacity: 1;
}
100% {
opacity: 0.8;
}
}

// Zero value styling
// Zero value styling - professional and inviting
.dashboard-card.zero-value {
background: linear-gradient(135deg, #fff5f5 0%, #ffe0e0 100%);
border: 2px solid #ff6b6b;
background: #ffffff;
border: 1.5px solid rgba(147, 51, 234, 0.3);
position: relative;
overflow: hidden;
box-shadow: 0 0 20px rgba(255, 107, 107, 0.2);
animation: glow-pulse 2.5s infinite;
box-shadow: 0 2px 12px rgba(147, 51, 234, 0.08);
cursor: pointer !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

&::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(
90deg,
transparent,
rgba(255, 107, 107, 0.3),
transparent
);
animation: shimmer 3s infinite;
}

.card-value {
color: #d32f2f !important;
font-weight: 700 !important;
text-shadow: 0 0 3px rgba(211, 47, 47, 0.2);
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, #7f11e0, #9333ea);
opacity: 1;
}

.icon-container {
animation: attention-pulse 2s infinite;
box-shadow: 0 0 15px rgba(255, 107, 107, 0.3);
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);

// Keep original colors for each icon type
&.icon-primary {
background: linear-gradient(135deg, #7f11e0 0%, #5c239a 100%);
}

&.icon-success {
background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);
}

&.icon-info {
background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
}
}

&:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 4px 30px rgba(255, 107, 107, 0.3);
.card-value.zero-state-cta {
position: relative;

&::after {
content: '→';
position: absolute;
right: -25px;
top: 50%;
transform: translateY(-50%);
font-size: 20px;
color: #9333ea;
opacity: 0;
transition: all 0.3s ease;
}
}
}

@keyframes glow-pulse {
0%,
100% {
box-shadow: 0 0 20px rgba(255, 107, 107, 0.2);
}
50% {
box-shadow: 0 0 30px rgba(255, 107, 107, 0.4);
::ng-deep [prompt] {
background: rgba(127, 17, 224, 0.06);
color: #7f11e0;
font-weight: 500;
}
}

// Shake animation for zero value cards
.dashboard-card.shake-animation {
animation: subtle-shake 4s infinite;
}
&:hover {
transform: translateY(-6px);
box-shadow: 0 12px 28px rgba(147, 51, 234, 0.15);
border-color: rgba(127, 17, 224, 0.5);
background: linear-gradient(180deg, #ffffff 0%, #faf8ff 100%);

@keyframes subtle-shake {
0%,
90%,
100% {
transform: translateX(0);
}
92% {
transform: translateX(-2px) rotate(-0.5deg);
}
94% {
transform: translateX(2px) rotate(0.5deg);
}
96% {
transform: translateX(-1px) rotate(-0.3deg);
}
98% {
transform: translateX(1px) rotate(0.3deg);
}
}
.icon-container {
transform: scale(1.08);
}

@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(200%);
}
}
.card-value.zero-state-cta {
transform: translateX(-5px);
&::after {
opacity: 1;
right: -30px;
}
}

@keyframes attention-pulse {
0%,
100% {
transform: scale(1);
::ng-deep [prompt] {
background: rgba(127, 17, 224, 0.08);
transform: translateY(-1px);
}
}
50% {
transform: scale(1.1);

&:active {
transform: translateY(-3px);
box-shadow: 0 6px 16px rgba(147, 51, 234, 0.12);
}
}

Expand All @@ -289,6 +258,13 @@

.card-value {
color: #fff;

&.zero-state-cta {
background: linear-gradient(135deg, #bb86fc, #9333ea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
}

.card-subtitle {
Expand All @@ -305,30 +281,35 @@
}

&.zero-value {
background: linear-gradient(135deg, #4a1a1a 0%, #3d1515 100%);
border: 2px solid #ff6b6b;
background: #2e2e2e;
border: 1.5px solid rgba(147, 51, 234, 0.4);
box-shadow: 0 2px 12px rgba(147, 51, 234, 0.12);

&::before {
background: linear-gradient(
90deg,
transparent,
rgba(255, 107, 107, 0.2),
transparent
);
background: linear-gradient(90deg, #bb86fc, #9333ea);
}

.card-value {
color: #ff8a80 !important;
.card-value.zero-state-cta {
&::after {
color: #bb86fc;
}
}

&:hover {
background: linear-gradient(180deg, #2e2e2e 0%, #352840 100%);
border-color: rgba(187, 134, 252, 0.6);
box-shadow: 0 12px 28px rgba(187, 134, 252, 0.2);
}

::ng-deep [prompt] {
background: rgba(187, 134, 252, 0.08);
color: #bb86fc;
}
}
}

::ng-deep [prompt] {
color: #ff8a80;
text-shadow: 0 0 10px rgba(255, 138, 128, 0.5);

span::after {
background: linear-gradient(90deg, transparent, #ff8a80, transparent);
}
color: #aaa;
background: rgba(255, 255, 255, 0.04);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class DfDashboardCardComponent {
@Input() footerText?: string;
@Input() showPrompt?: boolean = false;
@Input() isZero?: boolean = false;
@Input() zeroStateText?: string = 'Click to get started!';
@Input() color: 'primary' | 'accent' | 'success' | 'info' | 'warn' =
'primary';
@Input() clickable?: boolean = false;
Expand Down
3 changes: 3 additions & 0 deletions src/app/adf-home/df-dashboard/df-dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[subtitle]="'home.dashboard.services.total' | transloco"
[showPrompt]="stats.services.total === 0"
[isZero]="stats.services.total === 0"
[zeroStateText]="'Create your first API'"
[clickable]="stats.services.total === 0"
(cardClick)="onServicesCardClick()"
color="primary">
Expand All @@ -38,6 +39,7 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[subtitle]="'home.dashboard.apiKeys.total' | transloco"
[showPrompt]="stats.apiKeys.total === 0"
[isZero]="stats.apiKeys.total === 0"
[zeroStateText]="'Generate your API key'"
[clickable]="stats.apiKeys.total === 0"
(cardClick)="onApiKeysCardClick()"
color="success">
Expand All @@ -54,6 +56,7 @@ <h2 class="dashboard-title">{{ 'home.dashboard.title' | transloco }}</h2>
[subtitle]="'home.dashboard.roles.total' | transloco"
[showPrompt]="stats.roles.total === 0"
[isZero]="stats.roles.total === 0"
[zeroStateText]="'Set up your first role'"
[clickable]="stats.roles.total === 0"
(cardClick)="onRolesCardClick()"
color="info">
Expand Down
Loading