@eric-emg/symphiq-components 1.2.246 → 1.2.248
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/symphiq-components.mjs +1332 -1275
- package/fesm2022/symphiq-components.mjs.map +1 -1
- package/index.d.ts +52 -43
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/styles.css +70 -37
|
@@ -13667,39 +13667,39 @@ class RelatedRecommendationChipsComponent {
|
|
|
13667
13667
|
standalone: true,
|
|
13668
13668
|
imports: [CommonModule, SymphiqIconComponent],
|
|
13669
13669
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13670
|
-
template: `
|
|
13671
|
-
@if (displayedRecommendations().length > 0) {
|
|
13672
|
-
<div class="space-y-3">
|
|
13673
|
-
<div class="flex flex-wrap gap-2">
|
|
13674
|
-
@for (rec of displayedRecommendations(); track rec.id) {
|
|
13675
|
-
<button
|
|
13676
|
-
type="button"
|
|
13677
|
-
[ngClass]="getChipClasses(rec)"
|
|
13678
|
-
(click)="openRecommendationModal(rec.id!, $event)"
|
|
13679
|
-
class="transition-all duration-200 cursor-pointer"
|
|
13680
|
-
>
|
|
13681
|
-
<symphiq-icon [icon]="getPriorityIcon(rec)" size="w-3.5 h-3.5" class="flex-shrink-0"></symphiq-icon>
|
|
13682
|
-
<span class="font-medium">{{ rec.title }}</span>
|
|
13683
|
-
<symphiq-icon [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }" size="w-3.5 h-3.5" class="flex-shrink-0 opacity-60"></symphiq-icon>
|
|
13684
|
-
</button>
|
|
13685
|
-
}
|
|
13686
|
-
</div>
|
|
13687
|
-
|
|
13688
|
-
@if (hasMoreRecommendations()) {
|
|
13689
|
-
<button
|
|
13690
|
-
type="button"
|
|
13691
|
-
(click)="toggleShowAll($event)"
|
|
13692
|
-
[ngClass]="getViewMoreButtonClasses()"
|
|
13693
|
-
class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200 cursor-pointer"
|
|
13694
|
-
>
|
|
13695
|
-
<span>{{ showAll() ? 'Show Less' : 'View More' }}</span>
|
|
13696
|
-
<svg class="w-4 h-4 transition-transform duration-200" [class.rotate-180]="showAll()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
13697
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
13698
|
-
</svg>
|
|
13699
|
-
</button>
|
|
13700
|
-
}
|
|
13701
|
-
</div>
|
|
13702
|
-
}
|
|
13670
|
+
template: `
|
|
13671
|
+
@if (displayedRecommendations().length > 0) {
|
|
13672
|
+
<div class="space-y-3">
|
|
13673
|
+
<div class="flex flex-wrap gap-2">
|
|
13674
|
+
@for (rec of displayedRecommendations(); track rec.id) {
|
|
13675
|
+
<button
|
|
13676
|
+
type="button"
|
|
13677
|
+
[ngClass]="getChipClasses(rec)"
|
|
13678
|
+
(click)="openRecommendationModal(rec.id!, $event)"
|
|
13679
|
+
class="transition-all duration-200 cursor-pointer"
|
|
13680
|
+
>
|
|
13681
|
+
<symphiq-icon [icon]="getPriorityIcon(rec)" size="w-3.5 h-3.5" class="flex-shrink-0"></symphiq-icon>
|
|
13682
|
+
<span class="font-medium">{{ rec.title }}</span>
|
|
13683
|
+
<symphiq-icon [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }" size="w-3.5 h-3.5" class="flex-shrink-0 opacity-60"></symphiq-icon>
|
|
13684
|
+
</button>
|
|
13685
|
+
}
|
|
13686
|
+
</div>
|
|
13687
|
+
|
|
13688
|
+
@if (hasMoreRecommendations()) {
|
|
13689
|
+
<button
|
|
13690
|
+
type="button"
|
|
13691
|
+
(click)="toggleShowAll($event)"
|
|
13692
|
+
[ngClass]="getViewMoreButtonClasses()"
|
|
13693
|
+
class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200 cursor-pointer"
|
|
13694
|
+
>
|
|
13695
|
+
<span>{{ showAll() ? 'Show Less' : 'View More' }}</span>
|
|
13696
|
+
<svg class="w-4 h-4 transition-transform duration-200" [class.rotate-180]="showAll()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
13697
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
13698
|
+
</svg>
|
|
13699
|
+
</button>
|
|
13700
|
+
}
|
|
13701
|
+
</div>
|
|
13702
|
+
}
|
|
13703
13703
|
`
|
|
13704
13704
|
}]
|
|
13705
13705
|
}], null, { recommendations: [{ type: i0.Input, args: [{ isSignal: true, alias: "recommendations", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], maxInitialDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxInitialDisplay", required: false }] }], inModalContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "inModalContext", required: false }] }] }); })();
|
|
@@ -47936,1001 +47936,1001 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
47936
47936
|
ViewModeSwitcherModalComponent,
|
|
47937
47937
|
ProfileAnalysisModalComponent,
|
|
47938
47938
|
BusinessAnalysisModalComponent,
|
|
47939
|
-
], template: `
|
|
47940
|
-
<div
|
|
47941
|
-
class="bg-transparent"
|
|
47942
|
-
[class.min-h-screen]="!embedded()"
|
|
47943
|
-
[class.relative]="!embedded()"
|
|
47944
|
-
[style.display]="embedded() ? 'block' : null"
|
|
47945
|
-
[style.min-height]="embedded() ? 'auto' : null"
|
|
47946
|
-
#dashboardContainer>
|
|
47947
|
-
<!-- Animated Background Bubbles -->
|
|
47948
|
-
<div class="animated-bubbles" [class.light-mode]="isLightMode()" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100vw; height: 100vh; z-index: 1; pointer-events: none;"></div>
|
|
47949
|
-
|
|
47950
|
-
<!-- Scroll Progress Bar -->
|
|
47951
|
-
<div [class]="embedded() ? 'sticky top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30' : 'fixed top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30'">
|
|
47952
|
-
<div
|
|
47953
|
-
[style.width.%]="scrollProgress()"
|
|
47954
|
-
[ngClass]="isLightMode() ? 'bg-gradient-to-r from-blue-500 to-purple-500' : 'bg-gradient-to-r from-blue-400 to-purple-400'"
|
|
47955
|
-
class="h-full transition-all duration-200 ease-out">
|
|
47956
|
-
</div>
|
|
47957
|
-
</div>
|
|
47958
|
-
|
|
47959
|
-
<header [class]="headerClass()" class="sticky top-0 z-50 animate-fade-in" style="animation-delay: 0s;">
|
|
47960
|
-
<!-- Expanded Header (default state) -->
|
|
47961
|
-
<div
|
|
47962
|
-
class="transition-all duration-300 ease-in-out overflow-hidden"
|
|
47963
|
-
[class.max-h-0]="isScrolled()"
|
|
47964
|
-
[class.opacity-0]="isScrolled()"
|
|
47965
|
-
[class.max-h-96]="!isScrolled()"
|
|
47966
|
-
[class.opacity-100]="!isScrolled()">
|
|
47967
|
-
<div
|
|
47968
|
-
class="max-w-7xl mx-auto px-6 sm:px-8 py-6 sm:py-8"
|
|
47969
|
-
[class.pointer-events-none]="isScrolled()"
|
|
47970
|
-
[class.pointer-events-auto]="!isScrolled()">
|
|
47971
|
-
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-0">
|
|
47972
|
-
<div class="flex-1">
|
|
47973
|
-
<div class="flex items-center gap-3">
|
|
47974
|
-
<h1 class="text-2xl sm:text-3xl font-bold mb-2 bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">{{analysisData()?.title}}</h1>
|
|
47975
|
-
@if (isLoading() && !isShowingLoader()) {
|
|
47976
|
-
<!-- Subtle refresh indicator -->
|
|
47977
|
-
<div class="animate-spin w-4 h-4 border-2 border-blue-500/30 border-t-blue-500 rounded-full" title="Refreshing data..."></div>
|
|
47978
|
-
}
|
|
47979
|
-
</div>
|
|
47980
|
-
<div class="flex flex-wrap items-center justify-between gap-3 sm:gap-4">
|
|
47981
|
-
<p [class]="headerSubtitleClass()" class="text-sm sm:text-base">Revenue Orchestration & Funnel Analysis</p>
|
|
47982
|
-
<div class="flex items-center gap-4">
|
|
47983
|
-
@if (!isSimplifiedView()) {
|
|
47984
|
-
<!-- Search Button -->
|
|
47985
|
-
<button
|
|
47986
|
-
type="button"
|
|
47987
|
-
(click)="searchService.openSearch(); $event.preventDefault()"
|
|
47988
|
-
[class]="buttonClass()"
|
|
47989
|
-
class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200 hover:scale-105"
|
|
47990
|
-
title="Search (/ or Cmd+K)">
|
|
47991
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
47992
|
-
<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"></path>
|
|
47993
|
-
</svg>
|
|
47994
|
-
<span>Search</span>
|
|
47995
|
-
</button>
|
|
47996
|
-
}
|
|
47997
|
-
<!-- View Mode Switcher Button -->
|
|
47998
|
-
<button
|
|
47999
|
-
type="button"
|
|
48000
|
-
(click)="openViewModeSwitcher(); $event.preventDefault()"
|
|
48001
|
-
[class]="buttonClass()"
|
|
48002
|
-
class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200 hover:scale-105">
|
|
48003
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48004
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
48005
|
-
<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"></path>
|
|
48006
|
-
</svg>
|
|
48007
|
-
<span>{{ displayModeLabel() }}</span>
|
|
48008
|
-
</button>
|
|
48009
|
-
@if (!isSimplifiedView()) {
|
|
48010
|
-
<div class="flex items-center gap-2 sm:gap-3 whitespace-nowrap">
|
|
48011
|
-
<label [class]="metaLabelClass()" class="text-xs sm:text-sm font-medium">View:</label>
|
|
48012
|
-
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()">
|
|
48013
|
-
<select
|
|
48014
|
-
[ngModel]="selectedSectionFilter()"
|
|
48015
|
-
(ngModelChange)="changeSectionFilter($event)"
|
|
48016
|
-
[class]="selectClass()"
|
|
48017
|
-
class="px-3 sm:px-4 py-1.5 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors duration-200 cursor-pointer">
|
|
48018
|
-
@for (section of sectionFilters; track section.value) {
|
|
48019
|
-
<option [value]="section.value">{{ section.label }}</option>
|
|
48020
|
-
}
|
|
48021
|
-
</select>
|
|
48022
|
-
</div>
|
|
48023
|
-
</div>
|
|
48024
|
-
}
|
|
48025
|
-
</div>
|
|
48026
|
-
</div>
|
|
48027
|
-
</div>
|
|
48028
|
-
<div class="flex flex-col gap-4 min-w-[180px]">
|
|
48029
|
-
@if (formattedGeneratedDate()) {
|
|
48030
|
-
<div class="text-left sm:text-right">
|
|
48031
|
-
<div [class]="metaLabelClass()" class="text-xs sm:text-sm">Generated At</div>
|
|
48032
|
-
<div [class]="headerTitleClass()" class="text-sm sm:text-base font-medium">{{ formattedGeneratedDate() }}</div>
|
|
48033
|
-
</div>
|
|
48034
|
-
}
|
|
48035
|
-
<div class="text-left sm:text-right">
|
|
48036
|
-
<div [class]="metaLabelClass()" class="text-xs sm:text-sm">Requested by</div>
|
|
48037
|
-
<div [class]="headerTitleClass()" class="text-sm sm:text-base font-medium">{{ requestedByUser()?.firstName }} {{ requestedByUser()?.lastName }}</div>
|
|
48038
|
-
</div>
|
|
48039
|
-
</div>
|
|
48040
|
-
</div>
|
|
48041
|
-
</div>
|
|
48042
|
-
</div>
|
|
48043
|
-
|
|
48044
|
-
<!-- Condensed Header (scrolled state) -->
|
|
48045
|
-
<div
|
|
48046
|
-
class="transition-all duration-300 ease-in-out overflow-hidden"
|
|
48047
|
-
[class.max-h-0]="!isScrolled()"
|
|
48048
|
-
[class.opacity-0]="!isScrolled()"
|
|
48049
|
-
[class.max-h-20]="isScrolled()"
|
|
48050
|
-
[class.opacity-100]="isScrolled()">
|
|
48051
|
-
<div
|
|
48052
|
-
class="max-w-7xl mx-auto px-6 sm:px-8 py-3"
|
|
48053
|
-
[class.pointer-events-none]="!isScrolled()"
|
|
48054
|
-
[class.pointer-events-auto]="isScrolled()">
|
|
48055
|
-
<div class="flex items-center justify-between gap-4">
|
|
48056
|
-
<div class="flex items-center gap-4 flex-1 min-w-0">
|
|
48057
|
-
<h1 class="text-lg font-bold truncate bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">{{analysisData()?.title}}</h1>
|
|
48058
|
-
@if (revenueMetric()) {
|
|
48059
|
-
<div class="hidden lg:flex items-center gap-3 px-4 py-1.5 rounded-lg" [ngClass]="isLightMode() ? 'bg-emerald-50 border border-emerald-200' : 'bg-emerald-500/10 border border-emerald-500/20'">
|
|
48060
|
-
<span [class]="metaLabelClass()" class="text-xs font-medium">Revenue:</span>
|
|
48061
|
-
<span [class]="headerTitleClass()" class="text-sm font-bold">{{ formatValue(revenueValue()) }}</span>
|
|
48062
|
-
<span class="text-xs font-semibold" [ngClass]="revenueTrend() >= 0 ? 'text-emerald-600' : 'text-red-600'">
|
|
48063
|
-
{{ revenueTrend() >= 0 ? '+' : '' }}{{ revenueTrend().toFixed(1) }}%
|
|
48064
|
-
</span>
|
|
48065
|
-
</div>
|
|
48066
|
-
}
|
|
48067
|
-
</div>
|
|
48068
|
-
<div class="flex items-center gap-3">
|
|
48069
|
-
@if (!isSimplifiedView()) {
|
|
48070
|
-
<!-- Search Button (Icon Only in Sticky Header) -->
|
|
48071
|
-
<button
|
|
48072
|
-
type="button"
|
|
48073
|
-
(click)="searchService.openSearch(); $event.preventDefault()"
|
|
48074
|
-
[class]="buttonClass()"
|
|
48075
|
-
title="Search (/ or Cmd+K)"
|
|
48076
|
-
class="p-2 rounded-lg transition-all duration-200 hover:scale-110">
|
|
48077
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48078
|
-
<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"></path>
|
|
48079
|
-
</svg>
|
|
48080
|
-
</button>
|
|
48081
|
-
}
|
|
48082
|
-
<!-- View Mode Switcher (Icon Only in Sticky Header) -->
|
|
48083
|
-
<button
|
|
48084
|
-
type="button"
|
|
48085
|
-
(click)="openViewModeSwitcher(); $event.preventDefault()"
|
|
48086
|
-
[class]="buttonClass()"
|
|
48087
|
-
[title]="'Change View Mode: ' + displayModeLabel()"
|
|
48088
|
-
class="p-2 rounded-lg transition-all duration-200 hover:scale-110">
|
|
48089
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48090
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
48091
|
-
<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"></path>
|
|
48092
|
-
</svg>
|
|
48093
|
-
</button>
|
|
48094
|
-
@if (!isSimplifiedView()) {
|
|
48095
|
-
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()">
|
|
48096
|
-
<select
|
|
48097
|
-
[ngModel]="selectedSectionFilter()"
|
|
48098
|
-
(ngModelChange)="changeSectionFilter($event)"
|
|
48099
|
-
[class]="selectClass()"
|
|
48100
|
-
class="px-3 py-1.5 rounded-lg text-xs font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors duration-200 cursor-pointer">
|
|
48101
|
-
@for (section of sectionFilters; track section.value) {
|
|
48102
|
-
<option [value]="section.value">{{ section.label }}</option>
|
|
48103
|
-
}
|
|
48104
|
-
</select>
|
|
48105
|
-
</div>
|
|
48106
|
-
}
|
|
48107
|
-
</div>
|
|
48108
|
-
</div>
|
|
48109
|
-
</div>
|
|
48110
|
-
</div>
|
|
48111
|
-
</header>
|
|
48112
|
-
|
|
48113
|
-
<!-- Search Breadcrumb -->
|
|
48114
|
-
@if (searchService.activeSearchResult()) {
|
|
48115
|
-
<div [ngClass]="isLightMode() ? 'bg-blue-50/95 border-blue-200' : 'bg-blue-900/20 border-blue-800/30'" class="sticky top-[var(--header-height)] z-40 border-b backdrop-blur-md animate-slide-up-fade">
|
|
48116
|
-
<div class="max-w-7xl mx-auto px-6 sm:px-8 py-3">
|
|
48117
|
-
<div class="flex items-center justify-between gap-4">
|
|
48118
|
-
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
48119
|
-
<svg [ngClass]="isLightMode() ? 'text-blue-600' : 'text-blue-400'" class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48120
|
-
<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"></path>
|
|
48121
|
-
</svg>
|
|
48122
|
-
<div class="flex items-center gap-2 flex-1 min-w-0">
|
|
48123
|
-
<span [ngClass]="isLightMode() ? 'text-blue-900' : 'text-blue-100'" class="text-sm font-medium">Showing:</span>
|
|
48124
|
-
<span [ngClass]="isLightMode() ? 'text-blue-700' : 'text-blue-300'" class="text-sm font-semibold truncate">
|
|
48125
|
-
{{ searchService.activeSearchResult()!.title }}
|
|
48126
|
-
</span>
|
|
48127
|
-
<span [ngClass]="isLightMode() ? 'bg-blue-100 text-blue-700 border-blue-200' : 'bg-blue-800/50 text-blue-300 border-blue-700/50'" class="px-2 py-0.5 rounded text-xs font-medium uppercase border flex-shrink-0">
|
|
48128
|
-
{{ searchService.activeSearchResult()!.type }}
|
|
48129
|
-
</span>
|
|
48130
|
-
</div>
|
|
48131
|
-
</div>
|
|
48132
|
-
<button
|
|
48133
|
-
(click)="clearSearchResult(); $event.stopPropagation()"
|
|
48134
|
-
[ngClass]="isLightMode() ? 'text-blue-600 hover:text-blue-800 hover:bg-blue-100' : 'text-blue-400 hover:text-blue-200 hover:bg-blue-800/50'"
|
|
48135
|
-
class="p-2 rounded-lg transition-colors flex-shrink-0"
|
|
48136
|
-
title="Clear search">
|
|
48137
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48138
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
48139
|
-
</svg>
|
|
48140
|
-
</button>
|
|
48141
|
-
</div>
|
|
48142
|
-
</div>
|
|
48143
|
-
</div>
|
|
48144
|
-
}
|
|
48145
|
-
|
|
48146
|
-
<!-- Floating Table of Contents -->
|
|
48147
|
-
@if (!isSimplifiedView()) {
|
|
48148
|
-
<symphiq-floating-toc
|
|
48149
|
-
[sections]="tocSections()"
|
|
48150
|
-
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48151
|
-
[embedded]="embedded()"
|
|
48152
|
-
[scrollElement]="scrollElement() ?? undefined"
|
|
48153
|
-
/>
|
|
48154
|
-
}
|
|
48155
|
-
|
|
48156
|
-
<!-- Quick Navigation Dots -->
|
|
48157
|
-
@if (!isSimplifiedView()) {
|
|
48158
|
-
<div class="fixed right-6 top-1/2 -translate-y-1/2 z-40 hidden xl:flex flex-col gap-4">
|
|
48159
|
-
@if (showOverallPerformance()) {
|
|
48160
|
-
<button
|
|
48161
|
-
(click)="scrollToTop()"
|
|
48162
|
-
[libSymphiqTooltip]="'Scroll to Top'"
|
|
48163
|
-
[tooltipPosition]="'left'"
|
|
48164
|
-
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48165
|
-
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48166
|
-
</button>
|
|
48167
|
-
}
|
|
48168
|
-
@if (showKeyInsights()) {
|
|
48169
|
-
<button
|
|
48170
|
-
(click)="scrollToSection('section-insights')"
|
|
48171
|
-
[libSymphiqTooltip]="'Key Insights'"
|
|
48172
|
-
[tooltipPosition]="'left'"
|
|
48173
|
-
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48174
|
-
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48175
|
-
</button>
|
|
48176
|
-
}
|
|
48177
|
-
@if (showPerformanceMetrics()) {
|
|
48178
|
-
<button
|
|
48179
|
-
(click)="scrollToSection('section-metrics')"
|
|
48180
|
-
[libSymphiqTooltip]="'Performance Metrics'"
|
|
48181
|
-
[tooltipPosition]="'left'"
|
|
48182
|
-
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48183
|
-
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48184
|
-
</button>
|
|
48185
|
-
}
|
|
48186
|
-
@if (showPerformanceBreakdowns()) {
|
|
48187
|
-
<button
|
|
48188
|
-
(click)="scrollToSection('section-breakdowns')"
|
|
48189
|
-
[libSymphiqTooltip]="'Performance Breakdowns'"
|
|
48190
|
-
[tooltipPosition]="'left'"
|
|
48191
|
-
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48192
|
-
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48193
|
-
</button>
|
|
48194
|
-
}
|
|
48195
|
-
@if (showCompetitiveIntelligence()) {
|
|
48196
|
-
<button
|
|
48197
|
-
(click)="scrollToSection('section-competitive')"
|
|
48198
|
-
[libSymphiqTooltip]="'Competitive Intelligence'"
|
|
48199
|
-
[tooltipPosition]="'left'"
|
|
48200
|
-
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-indigo-500' : 'bg-slate-600 hover:bg-indigo-400'"
|
|
48201
|
-
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48202
|
-
</button>
|
|
48203
|
-
}
|
|
48204
|
-
</div>
|
|
48205
|
-
}
|
|
48206
|
-
|
|
48207
|
-
@if (isSimplifiedView()) {
|
|
48208
|
-
<!-- Journey Progress Banner -->
|
|
48209
|
-
@if (!isOnboarded()) {
|
|
48210
|
-
<symphiq-journey-progress-indicator
|
|
48211
|
-
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48212
|
-
[currentStepId]="JourneyStepIdEnum.FUNNEL_ANALYSIS"
|
|
48213
|
-
[showNextStepAction]="true"
|
|
48214
|
-
[forDemo]="forDemo()"
|
|
48215
|
-
[maxAccessibleStepId]="maxAccessibleStepId()"
|
|
48216
|
-
(stepClick)="stepClick.emit($event)"
|
|
48217
|
-
(nextStepClick)="nextStepClick.emit()"
|
|
48218
|
-
/>
|
|
48219
|
-
}
|
|
48220
|
-
|
|
48221
|
-
<main class="max-w-7xl mx-auto px-6 sm:px-8">
|
|
48222
|
-
<div class="pt-8 sm:pt-12 pb-16 sm:pb-24">
|
|
48223
|
-
<!-- Welcome Banner -->
|
|
48224
|
-
<div class="mb-8">
|
|
48225
|
-
<symphiq-funnel-welcome-banner
|
|
48226
|
-
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48227
|
-
[isOnboarded]="isOnboarded()"
|
|
48228
|
-
/>
|
|
48229
|
-
</div>
|
|
48230
|
-
|
|
48231
|
-
<!-- Key Insights Section -->
|
|
48232
|
-
@if (showKeyInsights()) {
|
|
48233
|
-
<section id="section-insights" class="mb-8">
|
|
48234
|
-
<div class="flex items-center justify-between mb-6">
|
|
48235
|
-
<div class="flex items-center gap-3">
|
|
48236
|
-
<div [ngClass]="isLightMode() ? 'border-l-4 border-blue-500' : 'border-l-4 border-blue-400'" class="pl-4">
|
|
48237
|
-
<div class="flex items-center gap-3">
|
|
48238
|
-
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-blue-500' : 'text-blue-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48239
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
|
48240
|
-
</svg>
|
|
48241
|
-
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Key Insights</h2>
|
|
48242
|
-
</div>
|
|
48243
|
-
</div>
|
|
48244
|
-
</div>
|
|
48245
|
-
<span [class]="metaLabelClass()" class="text-xs sm:text-sm">{{ insights().length }} insights</span>
|
|
48246
|
-
</div>
|
|
48247
|
-
|
|
48248
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
48249
|
-
@for (insight of insights(); track $index) {
|
|
48250
|
-
<symphiq-funnel-analysis-insight-card
|
|
48251
|
-
[insight]="insight"
|
|
48252
|
-
[allMetrics]="allMetrics()"
|
|
48253
|
-
[charts]="chartsForInsight(insight)"
|
|
48254
|
-
[allCharts]="allCharts()"
|
|
48255
|
-
[allBusinessInsights]="allBusinessInsights()"
|
|
48256
|
-
[isLightMode]="isLightMode()"
|
|
48257
|
-
[viewMode]="viewMode()"
|
|
48258
|
-
[isCompactMode]="true"
|
|
48259
|
-
[isLoading]="isDataLoading()" />
|
|
48260
|
-
}
|
|
48261
|
-
</div>
|
|
48262
|
-
</section>
|
|
48263
|
-
}
|
|
48264
|
-
|
|
48265
|
-
<!-- Supporting Data Section -->
|
|
48266
|
-
<symphiq-collapsible-funnel-section-group
|
|
48267
|
-
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK">
|
|
48268
|
-
<!-- Overall Performance Slot -->
|
|
48269
|
-
<div slot="overall-performance">
|
|
48270
|
-
@if (showOverallPerformance()) {
|
|
48271
|
-
<div class="p-6">
|
|
48272
|
-
@if (isDataLoading()) {
|
|
48273
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48274
|
-
} @else {
|
|
48275
|
-
<symphiq-funnel-analysis-overall-assessment
|
|
48276
|
-
[assessment]="performanceOverview().overallAssessment || {}"
|
|
48277
|
-
[revenueMetric]="revenueMetric()"
|
|
48278
|
-
[charts]="chartsForItem('OVERALL_ASSESSMENT')"
|
|
48279
|
-
[metrics]="allMetrics()"
|
|
48280
|
-
[isLightMode]="isLightMode()"
|
|
48281
|
-
[isLoading]="isOverallAssessmentLoading()"
|
|
48282
|
-
[isCompactMode]="true"
|
|
48283
|
-
[isChartsLoading]="areChartsLoading()"
|
|
48284
|
-
[strengths]="strengths()"
|
|
48285
|
-
[weaknesses]="weaknesses()"
|
|
48286
|
-
[currencySymbol]="currencySymbol()"
|
|
48287
|
-
(scrollToSection)="scrollToSection($event)" />
|
|
48288
|
-
}
|
|
48289
|
-
</div>
|
|
48290
|
-
}
|
|
48291
|
-
</div>
|
|
48292
|
-
|
|
48293
|
-
<!-- Performance Metrics Slot -->
|
|
48294
|
-
<div slot="performance-metrics">
|
|
48295
|
-
@if (showPerformanceMetrics()) {
|
|
48296
|
-
<div class="p-6 space-y-8">
|
|
48297
|
-
@for (funnelGroup of groupedMetrics(); track $index; let groupIdx = $index) {
|
|
48298
|
-
<!-- Funnel Stage Metric (Full Width) -->
|
|
48299
|
-
<div class="w-full">
|
|
48300
|
-
<symphiq-funnel-analysis-metric-card
|
|
48301
|
-
[metric]="funnelGroup.funnelMetric"
|
|
48302
|
-
[insights]="insights()"
|
|
48303
|
-
[charts]="chartsForMetric(funnelGroup.funnelMetric)"
|
|
48304
|
-
[allCharts]="allCharts()"
|
|
48305
|
-
[analysis]="analysisData()"
|
|
48306
|
-
[isLightMode]="isLightMode()"
|
|
48307
|
-
[viewMode]="viewMode()"
|
|
48308
|
-
[isCompactMode]="true"
|
|
48309
|
-
[currencySymbol]="currencySymbol()" />
|
|
48310
|
-
</div>
|
|
48311
|
-
<!-- Related Metrics (Grid Layout) -->
|
|
48312
|
-
@if (funnelGroup.relatedMetrics.length > 0) {
|
|
48313
|
-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-4">
|
|
48314
|
-
@for (metric of funnelGroup.relatedMetrics; track $index) {
|
|
48315
|
-
<symphiq-funnel-analysis-metric-card
|
|
48316
|
-
[metric]="metric"
|
|
48317
|
-
[insights]="insights()"
|
|
48318
|
-
[charts]="chartsForMetric(metric)"
|
|
48319
|
-
[allCharts]="allCharts()"
|
|
48320
|
-
[analysis]="analysisData()"
|
|
48321
|
-
[isLightMode]="isLightMode()"
|
|
48322
|
-
[viewMode]="viewMode()"
|
|
48323
|
-
[isCompactMode]="true"
|
|
48324
|
-
[currencySymbol]="currencySymbol()" />
|
|
48325
|
-
}
|
|
48326
|
-
</div>
|
|
48327
|
-
}
|
|
48328
|
-
}
|
|
48329
|
-
</div>
|
|
48330
|
-
}
|
|
48331
|
-
</div>
|
|
48332
|
-
|
|
48333
|
-
<!-- Performance Breakdowns Slot -->
|
|
48334
|
-
<div slot="performance-breakdowns">
|
|
48335
|
-
@if (showPerformanceBreakdowns()) {
|
|
48336
|
-
<div class="p-6 space-y-8">
|
|
48337
|
-
@for (breakdown of breakdowns(); track $index) {
|
|
48338
|
-
<symphiq-funnel-analysis-breakdown-section
|
|
48339
|
-
[breakdown]="breakdown"
|
|
48340
|
-
[charts]="chartsForBreakdown(breakdown)"
|
|
48341
|
-
[isLightMode]="isLightMode()"
|
|
48342
|
-
[isLoading]="isDataLoading()"
|
|
48343
|
-
[isCompactMode]="true"
|
|
48344
|
-
[currencySymbol]="currencySymbol()" />
|
|
48345
|
-
}
|
|
48346
|
-
</div>
|
|
48347
|
-
}
|
|
48348
|
-
</div>
|
|
48349
|
-
|
|
48350
|
-
<!-- Competitive Intelligence Slot -->
|
|
48351
|
-
<div slot="competitive-intelligence">
|
|
48352
|
-
@if (showCompetitiveIntelligence()) {
|
|
48353
|
-
<div class="p-6">
|
|
48354
|
-
<symphiq-competitive-intelligence-view
|
|
48355
|
-
[metrics]="competitiveMetrics()"
|
|
48356
|
-
[allCharts]="allCharts()"
|
|
48357
|
-
[isLightMode]="isLightMode()"
|
|
48358
|
-
[isCompactMode]="true"
|
|
48359
|
-
[competitiveBenchmark]="performanceOverview().overallAssessment?.competitiveBenchmark"
|
|
48360
|
-
[currencySymbol]="currencySymbol()" />
|
|
48361
|
-
</div>
|
|
48362
|
-
}
|
|
48363
|
-
</div>
|
|
48364
|
-
</symphiq-collapsible-funnel-section-group>
|
|
48365
|
-
</div>
|
|
48366
|
-
</main>
|
|
48367
|
-
} @else {
|
|
48368
|
-
<main class="max-w-7xl mx-auto px-6 sm:px-8">
|
|
48369
|
-
<div class="pt-8 sm:pt-12 pb-16 sm:pb-24">
|
|
48370
|
-
@if (showOverallPerformance()) {
|
|
48371
|
-
<div id="section-overall" class="animate-fade-in-up mb-20 sm:mb-28" style="animation-delay: 0.1s;">
|
|
48372
|
-
@if (isDataLoading()) {
|
|
48373
|
-
<!-- Overall Assessment Skeleton -->
|
|
48374
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 sm:p-8 animate-pulse">
|
|
48375
|
-
<div class="space-y-6">
|
|
48376
|
-
<!-- Header -->
|
|
48377
|
-
<div class="flex items-center gap-3">
|
|
48378
|
-
<symphiq-skeleton-loader [width]="'48px'" [height]="'48px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48379
|
-
<div class="flex-1 space-y-2">
|
|
48380
|
-
<symphiq-skeleton-loader [width]="'40%'" [height]="'32px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48381
|
-
<symphiq-skeleton-loader [width]="'60%'" [height]="'20px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48382
|
-
</div>
|
|
48383
|
-
</div>
|
|
48384
|
-
<!-- Summary text -->
|
|
48385
|
-
<div class="space-y-2">
|
|
48386
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48387
|
-
<symphiq-skeleton-loader [width]="'95%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48388
|
-
<symphiq-skeleton-loader [width]="'90%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48389
|
-
</div>
|
|
48390
|
-
<!-- Chart placeholder -->
|
|
48391
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6">
|
|
48392
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48393
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48394
|
-
</div>
|
|
48395
|
-
</div>
|
|
48396
|
-
</div>
|
|
48397
|
-
} @else {
|
|
48398
|
-
<symphiq-funnel-analysis-overall-assessment
|
|
48399
|
-
[assessment]="performanceOverview().overallAssessment || {}"
|
|
48400
|
-
[revenueMetric]="revenueMetric()"
|
|
48401
|
-
[charts]="chartsForItem('OVERALL_ASSESSMENT')"
|
|
48402
|
-
[metrics]="allMetrics()"
|
|
48403
|
-
[isLightMode]="isLightMode()"
|
|
48404
|
-
[isLoading]="isOverallAssessmentLoading()"
|
|
48405
|
-
[isCompactMode]="viewModeService.isCompact()"
|
|
48406
|
-
[isChartsLoading]="areChartsLoading()"
|
|
48407
|
-
[strengths]="strengths()"
|
|
48408
|
-
[weaknesses]="weaknesses()"
|
|
48409
|
-
[currencySymbol]="currencySymbol()"
|
|
48410
|
-
(scrollToSection)="scrollToSection($event)" />
|
|
48411
|
-
}
|
|
48412
|
-
</div>
|
|
48413
|
-
}
|
|
48414
|
-
|
|
48415
|
-
@if (showKeyInsights()) {
|
|
48416
|
-
@if (selectedSectionFilter() === 'ALL') {
|
|
48417
|
-
<!-- Section Divider -->
|
|
48418
|
-
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.15s"></symphiq-section-divider>
|
|
48419
|
-
}
|
|
48420
|
-
|
|
48421
|
-
<section id="section-insights" class="relative">
|
|
48422
|
-
<!-- Background Pattern -->
|
|
48423
|
-
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-blue-50/50 to-transparent' : 'bg-gradient-to-br from-blue-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%);"></div>
|
|
48424
|
-
<div class="relative">
|
|
48425
|
-
<div class="flex items-center justify-between mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.2s;">
|
|
48426
|
-
<div class="flex items-center gap-3">
|
|
48427
|
-
<div [ngClass]="isLightMode() ? 'border-l-4 border-blue-500' : 'border-l-4 border-blue-400'" class="pl-4">
|
|
48428
|
-
<div class="flex items-center gap-3">
|
|
48429
|
-
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-blue-500' : 'text-blue-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48430
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
|
48431
|
-
</svg>
|
|
48432
|
-
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Key Insights</h2>
|
|
48433
|
-
</div>
|
|
48434
|
-
</div>
|
|
48435
|
-
</div>
|
|
48436
|
-
<span [class]="metaLabelClass()" class="text-xs sm:text-sm">{{ insights().length }} insights</span>
|
|
48437
|
-
</div>
|
|
48438
|
-
<!-- Masonry Layout for Insights -->
|
|
48439
|
-
@if (isDataLoading() || (viewModeService.isExpanded() && viewModeService.getIsTransitioning())) {
|
|
48440
|
-
<!-- Skeleton loaders during data loading or transition to expanded view -->
|
|
48441
|
-
<div class="masonry-grid">
|
|
48442
|
-
@for (i of [1,2,3,4,5,6]; track i) {
|
|
48443
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse min-h-[280px]">
|
|
48444
|
-
<div class="space-y-4">
|
|
48445
|
-
<div class="flex items-center gap-3 mb-4">
|
|
48446
|
-
<symphiq-skeleton-loader [width]="'48px'" [height]="'48px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48447
|
-
<symphiq-skeleton-loader [width]="'60%'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48448
|
-
</div>
|
|
48449
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48450
|
-
<symphiq-skeleton-loader [width]="'95%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48451
|
-
<symphiq-skeleton-loader [width]="'85%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48452
|
-
<div class="mt-6 space-y-2">
|
|
48453
|
-
<symphiq-skeleton-loader [width]="'40%'" [height]="'14px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48454
|
-
<symphiq-skeleton-loader [width]="'50%'" [height]="'36px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48455
|
-
</div>
|
|
48456
|
-
<div class="flex gap-2 mt-4">
|
|
48457
|
-
<symphiq-skeleton-loader [width]="'80px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48458
|
-
<symphiq-skeleton-loader [width]="'80px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48459
|
-
</div>
|
|
48460
|
-
</div>
|
|
48461
|
-
</div>
|
|
48462
|
-
}
|
|
48463
|
-
</div>
|
|
48464
|
-
} @else if (viewModeService.isExpanded()) {
|
|
48465
|
-
<div class="masonry-grid">
|
|
48466
|
-
@for (insight of insights(); track $index) {
|
|
48467
|
-
<div
|
|
48468
|
-
[class]="getInsightCardClass(insight)"
|
|
48469
|
-
class="animate-fade-in-up"
|
|
48470
|
-
[style.animation-delay]="(0.3 + $index * 0.1) + 's'"
|
|
48471
|
-
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48472
|
-
[highlightId]="'insight-' + $index">
|
|
48473
|
-
<symphiq-funnel-analysis-insight-card
|
|
48474
|
-
[insight]="insight"
|
|
48475
|
-
[allMetrics]="allMetrics()"
|
|
48476
|
-
[charts]="chartsForInsight(insight)"
|
|
48477
|
-
[allCharts]="allCharts()"
|
|
48478
|
-
[allBusinessInsights]="allBusinessInsights()"
|
|
48479
|
-
[isLightMode]="isLightMode()"
|
|
48480
|
-
[viewMode]="viewMode()"
|
|
48481
|
-
[isCompactMode]="false" />
|
|
48482
|
-
</div>
|
|
48483
|
-
}
|
|
48484
|
-
</div>
|
|
48485
|
-
} @else {
|
|
48486
|
-
<!-- Compact Grid for Insights -->
|
|
48487
|
-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
48488
|
-
@for (insight of insights(); track $index) {
|
|
48489
|
-
<div class="animate-fade-in-up" [style.animation-delay]="(0.3 + $index * 0.1) + 's'"
|
|
48490
|
-
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48491
|
-
[highlightId]="'insight-' + $index">
|
|
48492
|
-
<symphiq-funnel-analysis-insight-card
|
|
48493
|
-
[insight]="insight"
|
|
48494
|
-
[allMetrics]="allMetrics()"
|
|
48495
|
-
[charts]="chartsForInsight(insight)"
|
|
48496
|
-
[allCharts]="allCharts()"
|
|
48497
|
-
[allBusinessInsights]="allBusinessInsights()"
|
|
48498
|
-
[isLightMode]="isLightMode()"
|
|
48499
|
-
[viewMode]="viewMode()"
|
|
48500
|
-
[isCompactMode]="true" />
|
|
48501
|
-
</div>
|
|
48502
|
-
}
|
|
48503
|
-
</div>
|
|
48504
|
-
}
|
|
48505
|
-
</div>
|
|
48506
|
-
</section>
|
|
48507
|
-
}
|
|
48508
|
-
|
|
48509
|
-
@if (showPerformanceMetrics()) {
|
|
48510
|
-
@if (selectedSectionFilter() === 'ALL') {
|
|
48511
|
-
<!-- Section Divider -->
|
|
48512
|
-
<div class="relative mb-14 sm:mb-24 mt-24 sm:mt-32 animate-fade-in" style="animation-delay: 0.35s;">
|
|
48513
|
-
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
|
48514
|
-
<div class="w-full h-px bg-gradient-to-r" [ngClass]="isLightMode() ? 'from-transparent via-emerald-500/30 to-transparent' : 'from-transparent via-emerald-400/20 to-transparent'"></div>
|
|
48515
|
-
</div>
|
|
48516
|
-
<div class="relative flex justify-center">
|
|
48517
|
-
<div class="px-4 py-2 rounded-full" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-emerald-50 to-teal-50 border border-emerald-200/50 shadow-lg shadow-emerald-500/10' : 'bg-gradient-to-br from-slate-900 to-slate-800 border border-emerald-500/20 shadow-lg shadow-emerald-500/5'">
|
|
48518
|
-
<svg class="w-5 h-5" [ngClass]="isLightMode() ? 'text-emerald-500' : 'text-emerald-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48519
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z"></path>
|
|
48520
|
-
</svg>
|
|
48521
|
-
</div>
|
|
48522
|
-
</div>
|
|
48523
|
-
</div>
|
|
48524
|
-
}
|
|
48525
|
-
|
|
48526
|
-
<section id="section-metrics" class="relative">
|
|
48527
|
-
<!-- Background Pattern -->
|
|
48528
|
-
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-tl from-emerald-50/50 to-transparent' : 'bg-gradient-to-tl from-emerald-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at top right, black 0%, transparent 70%);"></div>
|
|
48529
|
-
<div class="relative">
|
|
48530
|
-
<div class="flex flex-col gap-4 mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.4s;">
|
|
48531
|
-
<div class="flex items-center justify-between">
|
|
48532
|
-
<div class="flex items-center gap-3">
|
|
48533
|
-
<div [ngClass]="isLightMode() ? 'border-l-4 border-emerald-500' : 'border-l-4 border-emerald-400'" class="pl-4">
|
|
48534
|
-
<div class="flex items-center gap-3">
|
|
48535
|
-
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-emerald-500' : 'text-emerald-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48536
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
|
48537
|
-
</svg>
|
|
48538
|
-
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Performance Metrics</h2>
|
|
48539
|
-
</div>
|
|
48540
|
-
</div>
|
|
48541
|
-
</div>
|
|
48542
|
-
<!-- Desktop controls -->
|
|
48543
|
-
<div class="hidden sm:flex gap-2 sm:gap-3 items-center relative">
|
|
48544
|
-
@if (isCategoryTransitioning()) {
|
|
48545
|
-
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48546
|
-
<div class="w-4 h-4 border-2 border-blue-500/30 border-t-blue-500 rounded-full animate-spin"></div>
|
|
48547
|
-
</div>
|
|
48548
|
-
}
|
|
48549
|
-
<select
|
|
48550
|
-
[ngModel]="selectedCategory()"
|
|
48551
|
-
(ngModelChange)="changeCategoryFilter($event)"
|
|
48552
|
-
[class]="selectClass()"
|
|
48553
|
-
[class.opacity-70]="isCategoryTransitioning()"
|
|
48554
|
-
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 cursor-pointer">
|
|
48555
|
-
@for (cat of categories; track cat.value) {
|
|
48556
|
-
@if (cat.divider) {
|
|
48557
|
-
<option [value]="cat.value" disabled class="font-semibold">{{ cat.label }}</option>
|
|
48558
|
-
} @else {
|
|
48559
|
-
<option [value]="cat.value">{{ cat.label }}</option>
|
|
48560
|
-
}
|
|
48561
|
-
}
|
|
48562
|
-
</select>
|
|
48563
|
-
<button
|
|
48564
|
-
(click)="toggleSortOrder()"
|
|
48565
|
-
[class]="sortButtonClass()"
|
|
48566
|
-
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all flex items-center gap-2 cursor-pointer hover:scale-105 active:scale-95"
|
|
48567
|
-
[title]="reverseSortOrder() ? 'Sort: Revenue to Views' : 'Sort: Views to Revenue'">
|
|
48568
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48569
|
-
@if (!reverseSortOrder()) {
|
|
48570
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"></path>
|
|
48571
|
-
}
|
|
48572
|
-
@if (reverseSortOrder()) {
|
|
48573
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"></path>
|
|
48574
|
-
}
|
|
48575
|
-
</svg>
|
|
48576
|
-
<span>Sort</span>
|
|
48577
|
-
</button>
|
|
48578
|
-
</div>
|
|
48579
|
-
</div>
|
|
48580
|
-
|
|
48581
|
-
<!-- Mobile horizontal scrolling category pills -->
|
|
48582
|
-
<div class="sm:hidden -mx-6 px-6">
|
|
48583
|
-
<div class="flex gap-2 overflow-x-auto pb-2 snap-x snap-mandatory scrollbar-hide">
|
|
48584
|
-
@for (cat of categories; track cat.value) {
|
|
48585
|
-
@if (!cat.divider) {
|
|
48586
|
-
<button
|
|
48587
|
-
(click)="changeCategoryFilter(cat.value)"
|
|
48588
|
-
[ngClass]="getCategoryPillClass(cat.value)"
|
|
48589
|
-
[class.opacity-70]="isCategoryTransitioning()"
|
|
48590
|
-
class="px-4 py-2 rounded-full text-xs font-medium whitespace-nowrap transition-all duration-200 flex-shrink-0 snap-start active:scale-95">
|
|
48591
|
-
{{ cat.label }}
|
|
48592
|
-
</button>
|
|
48593
|
-
}
|
|
48594
|
-
}
|
|
48595
|
-
</div>
|
|
48596
|
-
</div>
|
|
48597
|
-
</div>
|
|
48598
|
-
@if (isDataLoading()) {
|
|
48599
|
-
<!-- Metrics Skeleton -->
|
|
48600
|
-
<div class="space-y-8 sm:space-y-10">
|
|
48601
|
-
@for (i of [1,2,3]; track i) {
|
|
48602
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48603
|
-
<div class="flex items-center justify-between mb-4">
|
|
48604
|
-
<div class="flex items-center gap-3">
|
|
48605
|
-
<symphiq-skeleton-loader [width]="'40px'" [height]="'40px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48606
|
-
<div class="space-y-2">
|
|
48607
|
-
<symphiq-skeleton-loader [width]="'150px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48608
|
-
<symphiq-skeleton-loader [width]="'100px'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48609
|
-
</div>
|
|
48610
|
-
</div>
|
|
48611
|
-
<symphiq-skeleton-loader [width]="'80px'" [height]="'36px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48612
|
-
</div>
|
|
48613
|
-
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
48614
|
-
@for (j of [1,2,3,4]; track j) {
|
|
48615
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'120px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48616
|
-
}
|
|
48617
|
-
</div>
|
|
48618
|
-
</div>
|
|
48619
|
-
}
|
|
48620
|
-
</div>
|
|
48621
|
-
} @else {
|
|
48622
|
-
<div class="space-y-8 sm:space-y-10" [class.animate-content-change]="isCategoryTransitioning()" [class.transition-opacity-slow]="isCategoryTransitioning()">
|
|
48623
|
-
@for (funnelGroup of groupedMetrics(); track $index; let groupIdx = $index) {
|
|
48624
|
-
<div class="w-full animate-fade-in-up" [style.animation-delay]="(0.5 + groupIdx * 0.15) + 's'"
|
|
48625
|
-
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48626
|
-
[highlightId]="'metric-' + groupIdx">
|
|
48627
|
-
<symphiq-funnel-analysis-metric-card
|
|
48628
|
-
[metric]="funnelGroup.funnelMetric"
|
|
48629
|
-
[insights]="insights()"
|
|
48630
|
-
[charts]="chartsForMetric(funnelGroup.funnelMetric)"
|
|
48631
|
-
[allCharts]="allCharts()"
|
|
48632
|
-
[analysis]="analysisData()"
|
|
48633
|
-
[isLightMode]="isLightMode()"
|
|
48634
|
-
[viewMode]="viewMode()"
|
|
48635
|
-
[isCompactMode]="viewModeService.isCompact()"
|
|
48636
|
-
[currencySymbol]="currencySymbol()" />
|
|
48637
|
-
</div>
|
|
48638
|
-
@if (funnelGroup.relatedMetrics.length > 0) {
|
|
48639
|
-
<!-- Bento Box Grid Layout -->
|
|
48640
|
-
@if (viewModeService.isExpanded()) {
|
|
48641
|
-
<div class="bento-grid mt-4">
|
|
48642
|
-
@for (metric of funnelGroup.relatedMetrics; track $index; let metricIdx = $index) {
|
|
48643
|
-
<div
|
|
48644
|
-
[class]="getBentoCardClass(metric, metricIdx)"
|
|
48645
|
-
class="animate-fade-in-up"
|
|
48646
|
-
[style.animation-delay]="(0.6 + groupIdx * 0.15 + metricIdx * 0.08) + 's'">
|
|
48647
|
-
<symphiq-funnel-analysis-metric-card
|
|
48648
|
-
class="h-full"
|
|
48649
|
-
[metric]="metric"
|
|
48650
|
-
[insights]="insights()"
|
|
48651
|
-
[charts]="chartsForMetric(metric)"
|
|
48652
|
-
[allCharts]="allCharts()"
|
|
48653
|
-
[analysis]="analysisData()"
|
|
48654
|
-
[isLightMode]="isLightMode()"
|
|
48655
|
-
[viewMode]="viewMode()"
|
|
48656
|
-
[isCompactMode]="false"
|
|
48657
|
-
[currencySymbol]="currencySymbol()" />
|
|
48658
|
-
</div>
|
|
48659
|
-
}
|
|
48660
|
-
</div>
|
|
48661
|
-
} @else if (!viewModeService.isExpanded()) {
|
|
48662
|
-
<!-- Compact Grid Layout -->
|
|
48663
|
-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 mt-4">
|
|
48664
|
-
@for (metric of funnelGroup.relatedMetrics; track $index; let metricIdx = $index) {
|
|
48665
|
-
<div class="animate-fade-in-up" [style.animation-delay]="(0.6 + groupIdx * 0.15 + metricIdx * 0.08) + 's'">
|
|
48666
|
-
<symphiq-funnel-analysis-metric-card
|
|
48667
|
-
[metric]="metric"
|
|
48668
|
-
[insights]="insights()"
|
|
48669
|
-
[charts]="chartsForMetric(metric)"
|
|
48670
|
-
[allCharts]="allCharts()"
|
|
48671
|
-
[analysis]="analysisData()"
|
|
48672
|
-
[isLightMode]="isLightMode()"
|
|
48673
|
-
[viewMode]="viewMode()"
|
|
48674
|
-
[isCompactMode]="true"
|
|
48675
|
-
[currencySymbol]="currencySymbol()" />
|
|
48676
|
-
</div>
|
|
48677
|
-
}
|
|
48678
|
-
</div>
|
|
48679
|
-
} @else {
|
|
48680
|
-
<!-- Skeleton loaders during transition to expanded view -->
|
|
48681
|
-
<div class="bento-grid mt-4">
|
|
48682
|
-
@for (i of [1,2,3,4]; track i) {
|
|
48683
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse min-h-[240px]">
|
|
48684
|
-
<div class="space-y-4">
|
|
48685
|
-
<div class="flex items-center justify-between">
|
|
48686
|
-
<symphiq-skeleton-loader [width]="'60%'" [height]="'22px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48687
|
-
<symphiq-skeleton-loader [width]="'60px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48688
|
-
</div>
|
|
48689
|
-
<symphiq-skeleton-loader [width]="'45%'" [height]="'42px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48690
|
-
<div class="flex items-center gap-3 mt-4">
|
|
48691
|
-
<symphiq-skeleton-loader [width]="'24px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48692
|
-
<symphiq-skeleton-loader [width]="'30%'" [height]="'20px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48693
|
-
</div>
|
|
48694
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48695
|
-
<symphiq-skeleton-loader [width]="'85%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48696
|
-
<div class="mt-4">
|
|
48697
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'120px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48698
|
-
</div>
|
|
48699
|
-
</div>
|
|
48700
|
-
</div>
|
|
48701
|
-
}
|
|
48702
|
-
</div>
|
|
48703
|
-
}
|
|
48704
|
-
}
|
|
48705
|
-
} @empty {
|
|
48706
|
-
<div [ngClass]="isLightMode() ? 'bg-slate-50 border-slate-200' : 'bg-slate-800/50 border-slate-700'" class="rounded-xl p-12 border text-center animate-fade-in">
|
|
48707
|
-
<svg class="w-16 h-16 mx-auto mb-4" [ngClass]="isLightMode() ? 'text-slate-300' : 'text-slate-600'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48708
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
|
48709
|
-
</svg>
|
|
48710
|
-
<h3 [ngClass]="isLightMode() ? 'text-slate-900' : 'text-white'" class="text-lg font-semibold mb-2">No Metrics Found</h3>
|
|
48711
|
-
<p [ngClass]="isLightMode() ? 'text-slate-600' : 'text-slate-400'" class="text-sm">No performance metrics match your current filter selection. Try adjusting your filters to see more results.</p>
|
|
48712
|
-
</div>
|
|
48713
|
-
}
|
|
48714
|
-
</div>
|
|
48715
|
-
}
|
|
48716
|
-
</div>
|
|
48717
|
-
</section>
|
|
48718
|
-
}
|
|
48719
|
-
|
|
48720
|
-
@if (showPerformanceBreakdowns()) {
|
|
48721
|
-
@if (selectedSectionFilter() === 'ALL') {
|
|
48722
|
-
<!-- Section Divider -->
|
|
48723
|
-
<div class="mt-28 sm:mt-36">
|
|
48724
|
-
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.65s"></symphiq-section-divider>
|
|
48725
|
-
</div>
|
|
48726
|
-
}
|
|
48727
|
-
|
|
48728
|
-
<section id="section-breakdowns" class="relative">
|
|
48729
|
-
<!-- Background Pattern -->
|
|
48730
|
-
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-tr from-purple-50/50 to-transparent' : 'bg-gradient-to-tr from-purple-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at bottom left, black 0%, transparent 70%);"></div>
|
|
48731
|
-
<div class="relative">
|
|
48732
|
-
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.7s;">
|
|
48733
|
-
<div [ngClass]="isLightMode() ? 'border-l-4 border-purple-500' : 'border-l-4 border-purple-400'" class="pl-4">
|
|
48734
|
-
<div class="flex items-center gap-3">
|
|
48735
|
-
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-purple-500' : 'text-purple-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48736
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"></path>
|
|
48737
|
-
</svg>
|
|
48738
|
-
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Performance Breakdowns</h2>
|
|
48739
|
-
</div>
|
|
48740
|
-
</div>
|
|
48741
|
-
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()" class="relative inline-block">
|
|
48742
|
-
@if (isBreakdownTransitioning()) {
|
|
48743
|
-
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48744
|
-
<div class="w-4 h-4 border-2 border-purple-500/30 border-t-purple-500 rounded-full animate-spin"></div>
|
|
48745
|
-
</div>
|
|
48746
|
-
}
|
|
48747
|
-
<select
|
|
48748
|
-
[ngModel]="selectedBreakdownFilter()"
|
|
48749
|
-
(ngModelChange)="changeBreakdownFilter($event)"
|
|
48750
|
-
[ngClass]="isLightMode()
|
|
48751
|
-
? 'bg-white border-slate-300 text-slate-900 hover:border-blue-400 focus:border-blue-500'
|
|
48752
|
-
: 'bg-slate-700 border-slate-600 text-white hover:border-slate-500 focus:border-blue-500'"
|
|
48753
|
-
[class.opacity-70]="isBreakdownTransitioning()"
|
|
48754
|
-
class="px-3 py-2 text-sm rounded-lg border transition-all duration-200 cursor-pointer focus:ring-2 focus:ring-blue-500 focus:outline-none">
|
|
48755
|
-
@for (filter of breakdownFilters; track filter.value) {
|
|
48756
|
-
@if (filter.divider) {
|
|
48757
|
-
<option [value]="filter.value" disabled class="font-semibold">{{ filter.label }}</option>
|
|
48758
|
-
} @else {
|
|
48759
|
-
<option [value]="filter.value">{{ filter.label }}</option>
|
|
48760
|
-
}
|
|
48761
|
-
}
|
|
48762
|
-
</select>
|
|
48763
|
-
</div>
|
|
48764
|
-
</div>
|
|
48765
|
-
@if (isDataLoading()) {
|
|
48766
|
-
<!-- Breakdowns Skeleton -->
|
|
48767
|
-
<div class="space-y-6">
|
|
48768
|
-
@for (i of [1,2]; track i) {
|
|
48769
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48770
|
-
<div class="flex items-center justify-between mb-4">
|
|
48771
|
-
<symphiq-skeleton-loader [width]="'200px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48772
|
-
<symphiq-skeleton-loader [width]="'100px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48773
|
-
</div>
|
|
48774
|
-
<div class="space-y-3">
|
|
48775
|
-
@for (j of [1,2,3,4]; track j) {
|
|
48776
|
-
<div class="flex items-center justify-between p-3 rounded-lg" [ngClass]="isLightMode() ? 'bg-slate-50' : 'bg-slate-700/50'">
|
|
48777
|
-
<symphiq-skeleton-loader [width]="'150px'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48778
|
-
<symphiq-skeleton-loader [width]="'80px'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48779
|
-
</div>
|
|
48780
|
-
}
|
|
48781
|
-
</div>
|
|
48782
|
-
</div>
|
|
48783
|
-
}
|
|
48784
|
-
</div>
|
|
48785
|
-
} @else {
|
|
48786
|
-
<div class="space-y-6" [class.animate-content-change]="isBreakdownTransitioning()" [class.transition-opacity-slow]="isBreakdownTransitioning()">
|
|
48787
|
-
@for (breakdown of breakdowns(); track $index) {
|
|
48788
|
-
<div class="animate-fade-in-up" [style.animation-delay]="(0.8 + $index * 0.1) + 's'"
|
|
48789
|
-
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48790
|
-
[highlightId]="'breakdown-' + $index">
|
|
48791
|
-
<symphiq-funnel-analysis-breakdown-section
|
|
48792
|
-
[breakdown]="breakdown"
|
|
48793
|
-
[charts]="chartsForBreakdown(breakdown)"
|
|
48794
|
-
[isLightMode]="isLightMode()"
|
|
48795
|
-
[isCompactMode]="viewModeService.isCompact()"
|
|
48796
|
-
[currencySymbol]="currencySymbol()" />
|
|
48797
|
-
</div>
|
|
48798
|
-
} @empty {
|
|
48799
|
-
<div [ngClass]="isLightMode() ? 'bg-slate-50 border-slate-200' : 'bg-slate-800/50 border-slate-700'" class="rounded-xl p-12 border text-center animate-fade-in">
|
|
48800
|
-
<svg class="w-16 h-16 mx-auto mb-4" [ngClass]="isLightMode() ? 'text-slate-300' : 'text-slate-600'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48801
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"></path>
|
|
48802
|
-
</svg>
|
|
48803
|
-
<h3 [ngClass]="isLightMode() ? 'text-slate-900' : 'text-white'" class="text-lg font-semibold mb-2">No Breakdowns Found</h3>
|
|
48804
|
-
<p [ngClass]="isLightMode() ? 'text-slate-600' : 'text-slate-400'" class="text-sm">No performance breakdowns match your current filter selection. Try adjusting your filters to see more results.</p>
|
|
48805
|
-
</div>
|
|
48806
|
-
}
|
|
48807
|
-
</div>
|
|
48808
|
-
}
|
|
48809
|
-
</div>
|
|
48810
|
-
</section>
|
|
48811
|
-
}
|
|
48812
|
-
|
|
48813
|
-
@if (showCompetitiveIntelligence()) {
|
|
48814
|
-
@if (selectedSectionFilter() === 'ALL') {
|
|
48815
|
-
<!-- Section Divider -->
|
|
48816
|
-
<div class="mt-28 sm:mt-36">
|
|
48817
|
-
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.85s"></symphiq-section-divider>
|
|
48818
|
-
</div>
|
|
48819
|
-
}
|
|
48820
|
-
|
|
48821
|
-
<!-- Competitive Intelligence Section -->
|
|
48822
|
-
<section id="section-competitive" class="relative">
|
|
48823
|
-
<!-- Background Pattern -->
|
|
48824
|
-
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-indigo-50/50 to-transparent' : 'bg-gradient-to-br from-indigo-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%);"></div>
|
|
48825
|
-
<div class="relative">
|
|
48826
|
-
<div class="flex items-center justify-between mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.9s;">
|
|
48827
|
-
<div class="flex items-center gap-3">
|
|
48828
|
-
<div [ngClass]="isLightMode() ? 'border-l-4 border-indigo-500' : 'border-l-4 border-indigo-400'" class="pl-4">
|
|
48829
|
-
<div class="flex items-center gap-3">
|
|
48830
|
-
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-indigo-500' : 'text-indigo-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48831
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
|
48832
|
-
</svg>
|
|
48833
|
-
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Competitive Intelligence</h2>
|
|
48834
|
-
</div>
|
|
48835
|
-
</div>
|
|
48836
|
-
</div>
|
|
48837
|
-
<!-- Filter Dropdown -->
|
|
48838
|
-
<div class="hidden sm:block relative">
|
|
48839
|
-
@if (isCompetitiveTransitioning()) {
|
|
48840
|
-
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48841
|
-
<div class="w-4 h-4 border-2 border-indigo-500/30 border-t-indigo-500 rounded-full animate-spin"></div>
|
|
48842
|
-
</div>
|
|
48843
|
-
}
|
|
48844
|
-
<select
|
|
48845
|
-
[ngModel]="selectedCompetitiveFilter()"
|
|
48846
|
-
(ngModelChange)="changeCompetitiveFilter($event)"
|
|
48847
|
-
[class]="selectClass()"
|
|
48848
|
-
[class.opacity-70]="isCompetitiveTransitioning()"
|
|
48849
|
-
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 cursor-pointer">
|
|
48850
|
-
@for (filter of competitiveFilters; track filter.value) {
|
|
48851
|
-
@if (filter.divider) {
|
|
48852
|
-
<option [value]="filter.value" disabled class="font-semibold">{{ filter.label }}</option>
|
|
48853
|
-
} @else {
|
|
48854
|
-
<option [value]="filter.value">{{ filter.label }}</option>
|
|
48855
|
-
}
|
|
48856
|
-
}
|
|
48857
|
-
</select>
|
|
48858
|
-
</div>
|
|
48859
|
-
</div>
|
|
48860
|
-
|
|
48861
|
-
@if (isDataLoading()) {
|
|
48862
|
-
<!-- Competitive Intelligence Skeleton -->
|
|
48863
|
-
<div class="space-y-6">
|
|
48864
|
-
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48865
|
-
<symphiq-skeleton-loader [width]="'60%'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48866
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-6">
|
|
48867
|
-
@for (i of [1,2,3]; track i) {
|
|
48868
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'140px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48869
|
-
}
|
|
48870
|
-
</div>
|
|
48871
|
-
</div>
|
|
48872
|
-
</div>
|
|
48873
|
-
} @else {
|
|
48874
|
-
<symphiq-competitive-intelligence-view
|
|
48875
|
-
[metrics]="competitiveMetrics()"
|
|
48876
|
-
[allCharts]="allCharts()"
|
|
48877
|
-
[isLightMode]="isLightMode()"
|
|
48878
|
-
[isCompactMode]="viewModeService.isCompact()"
|
|
48879
|
-
[competitiveBenchmark]="performanceOverview().overallAssessment?.competitiveBenchmark"
|
|
48880
|
-
[currencySymbol]="currencySymbol()" />
|
|
48881
|
-
}
|
|
48882
|
-
</div>
|
|
48883
|
-
</section>
|
|
48884
|
-
}
|
|
48885
|
-
</div>
|
|
48886
|
-
</main>
|
|
48887
|
-
}
|
|
48888
|
-
|
|
48889
|
-
<symphiq-funnel-analysis-modal
|
|
48890
|
-
[isLightMode]="isLightMode()"
|
|
48891
|
-
[viewMode]="viewMode()"
|
|
48892
|
-
[allMetrics]="allMetrics()"
|
|
48893
|
-
[allInsights]="insights()"
|
|
48894
|
-
[allCharts]="allCharts()"
|
|
48895
|
-
[currencySymbol]="currencySymbol()"
|
|
48896
|
-
[businessProfile]="businessProfile()"></symphiq-funnel-analysis-modal>
|
|
48897
|
-
<symphiq-profile-analysis-modal
|
|
48898
|
-
[isLightMode]="isLightMode()"
|
|
48899
|
-
[allMetrics]="allMetrics()"
|
|
48900
|
-
></symphiq-profile-analysis-modal>
|
|
48901
|
-
<symphiq-business-analysis-modal [isLightMode]="isLightMode()" />
|
|
48902
|
-
<symphiq-tooltip-container></symphiq-tooltip-container>
|
|
48903
|
-
<symphiq-search-bar
|
|
48904
|
-
[isLightMode]="isLightMode()"
|
|
48905
|
-
(resultSelected)="handleSearchResult($event)" />
|
|
48906
|
-
|
|
48907
|
-
<!-- View Mode Switcher Modal -->
|
|
48908
|
-
<symphiq-view-mode-switcher-modal
|
|
48909
|
-
[isOpen]="isViewModeSwitcherOpen()"
|
|
48910
|
-
[currentMode]="displayMode()"
|
|
48911
|
-
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48912
|
-
[isLoading]="isViewModeSwitching()"
|
|
48913
|
-
(close)="closeViewModeSwitcher()"
|
|
48914
|
-
(modeSelected)="handleDisplayModeChange($event)"
|
|
48915
|
-
/>
|
|
48916
|
-
|
|
48917
|
-
<!-- Mobile FAB -->
|
|
48918
|
-
<symphiq-mobile-fab
|
|
48919
|
-
[isLightMode]="isLightMode()"
|
|
48920
|
-
[isCompactMode]="viewModeService.isCompact()"
|
|
48921
|
-
[isExpanded]="fabExpanded()"
|
|
48922
|
-
(expandedChange)="fabExpanded.set($event)"
|
|
48923
|
-
(scrollToTop)="scrollToTop()"
|
|
48924
|
-
(toggleView)="viewModeService.toggleViewMode()" />
|
|
48925
|
-
|
|
48926
|
-
<!-- Mobile Bottom Navigation -->
|
|
48927
|
-
<symphiq-mobile-bottom-nav
|
|
48928
|
-
[isLightMode]="isLightMode()"
|
|
48929
|
-
[sections]="navSections"
|
|
48930
|
-
[activeSection]="activeNavSection()"
|
|
48931
|
-
(navigate)="handleMobileNavigation($event)" />
|
|
48932
|
-
|
|
48933
|
-
</div>
|
|
47939
|
+
], template: `
|
|
47940
|
+
<div
|
|
47941
|
+
class="bg-transparent"
|
|
47942
|
+
[class.min-h-screen]="!embedded()"
|
|
47943
|
+
[class.relative]="!embedded()"
|
|
47944
|
+
[style.display]="embedded() ? 'block' : null"
|
|
47945
|
+
[style.min-height]="embedded() ? 'auto' : null"
|
|
47946
|
+
#dashboardContainer>
|
|
47947
|
+
<!-- Animated Background Bubbles -->
|
|
47948
|
+
<div class="animated-bubbles" [class.light-mode]="isLightMode()" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100vw; height: 100vh; z-index: 1; pointer-events: none;"></div>
|
|
47949
|
+
|
|
47950
|
+
<!-- Scroll Progress Bar -->
|
|
47951
|
+
<div [class]="embedded() ? 'sticky top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30' : 'fixed top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30'">
|
|
47952
|
+
<div
|
|
47953
|
+
[style.width.%]="scrollProgress()"
|
|
47954
|
+
[ngClass]="isLightMode() ? 'bg-gradient-to-r from-blue-500 to-purple-500' : 'bg-gradient-to-r from-blue-400 to-purple-400'"
|
|
47955
|
+
class="h-full transition-all duration-200 ease-out">
|
|
47956
|
+
</div>
|
|
47957
|
+
</div>
|
|
47958
|
+
|
|
47959
|
+
<header [class]="headerClass()" class="sticky top-0 z-50 animate-fade-in" style="animation-delay: 0s;">
|
|
47960
|
+
<!-- Expanded Header (default state) -->
|
|
47961
|
+
<div
|
|
47962
|
+
class="transition-all duration-300 ease-in-out overflow-hidden"
|
|
47963
|
+
[class.max-h-0]="isScrolled()"
|
|
47964
|
+
[class.opacity-0]="isScrolled()"
|
|
47965
|
+
[class.max-h-96]="!isScrolled()"
|
|
47966
|
+
[class.opacity-100]="!isScrolled()">
|
|
47967
|
+
<div
|
|
47968
|
+
class="max-w-7xl mx-auto px-6 sm:px-8 py-6 sm:py-8"
|
|
47969
|
+
[class.pointer-events-none]="isScrolled()"
|
|
47970
|
+
[class.pointer-events-auto]="!isScrolled()">
|
|
47971
|
+
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-0">
|
|
47972
|
+
<div class="flex-1">
|
|
47973
|
+
<div class="flex items-center gap-3">
|
|
47974
|
+
<h1 class="text-2xl sm:text-3xl font-bold mb-2 bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">{{analysisData()?.title}}</h1>
|
|
47975
|
+
@if (isLoading() && !isShowingLoader()) {
|
|
47976
|
+
<!-- Subtle refresh indicator -->
|
|
47977
|
+
<div class="animate-spin w-4 h-4 border-2 border-blue-500/30 border-t-blue-500 rounded-full" title="Refreshing data..."></div>
|
|
47978
|
+
}
|
|
47979
|
+
</div>
|
|
47980
|
+
<div class="flex flex-wrap items-center justify-between gap-3 sm:gap-4">
|
|
47981
|
+
<p [class]="headerSubtitleClass()" class="text-sm sm:text-base">Revenue Orchestration & Funnel Analysis</p>
|
|
47982
|
+
<div class="flex items-center gap-4">
|
|
47983
|
+
@if (!isSimplifiedView()) {
|
|
47984
|
+
<!-- Search Button -->
|
|
47985
|
+
<button
|
|
47986
|
+
type="button"
|
|
47987
|
+
(click)="searchService.openSearch(); $event.preventDefault()"
|
|
47988
|
+
[class]="buttonClass()"
|
|
47989
|
+
class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200 hover:scale-105"
|
|
47990
|
+
title="Search (/ or Cmd+K)">
|
|
47991
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
47992
|
+
<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"></path>
|
|
47993
|
+
</svg>
|
|
47994
|
+
<span>Search</span>
|
|
47995
|
+
</button>
|
|
47996
|
+
}
|
|
47997
|
+
<!-- View Mode Switcher Button -->
|
|
47998
|
+
<button
|
|
47999
|
+
type="button"
|
|
48000
|
+
(click)="openViewModeSwitcher(); $event.preventDefault()"
|
|
48001
|
+
[class]="buttonClass()"
|
|
48002
|
+
class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-all duration-200 hover:scale-105">
|
|
48003
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48004
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
48005
|
+
<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"></path>
|
|
48006
|
+
</svg>
|
|
48007
|
+
<span>{{ displayModeLabel() }}</span>
|
|
48008
|
+
</button>
|
|
48009
|
+
@if (!isSimplifiedView()) {
|
|
48010
|
+
<div class="flex items-center gap-2 sm:gap-3 whitespace-nowrap">
|
|
48011
|
+
<label [class]="metaLabelClass()" class="text-xs sm:text-sm font-medium">View:</label>
|
|
48012
|
+
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()">
|
|
48013
|
+
<select
|
|
48014
|
+
[ngModel]="selectedSectionFilter()"
|
|
48015
|
+
(ngModelChange)="changeSectionFilter($event)"
|
|
48016
|
+
[class]="selectClass()"
|
|
48017
|
+
class="px-3 sm:px-4 py-1.5 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors duration-200 cursor-pointer">
|
|
48018
|
+
@for (section of sectionFilters; track section.value) {
|
|
48019
|
+
<option [value]="section.value">{{ section.label }}</option>
|
|
48020
|
+
}
|
|
48021
|
+
</select>
|
|
48022
|
+
</div>
|
|
48023
|
+
</div>
|
|
48024
|
+
}
|
|
48025
|
+
</div>
|
|
48026
|
+
</div>
|
|
48027
|
+
</div>
|
|
48028
|
+
<div class="flex flex-col gap-4 min-w-[180px]">
|
|
48029
|
+
@if (formattedGeneratedDate()) {
|
|
48030
|
+
<div class="text-left sm:text-right">
|
|
48031
|
+
<div [class]="metaLabelClass()" class="text-xs sm:text-sm">Generated At</div>
|
|
48032
|
+
<div [class]="headerTitleClass()" class="text-sm sm:text-base font-medium">{{ formattedGeneratedDate() }}</div>
|
|
48033
|
+
</div>
|
|
48034
|
+
}
|
|
48035
|
+
<div class="text-left sm:text-right">
|
|
48036
|
+
<div [class]="metaLabelClass()" class="text-xs sm:text-sm">Requested by</div>
|
|
48037
|
+
<div [class]="headerTitleClass()" class="text-sm sm:text-base font-medium">{{ requestedByUser()?.firstName }} {{ requestedByUser()?.lastName }}</div>
|
|
48038
|
+
</div>
|
|
48039
|
+
</div>
|
|
48040
|
+
</div>
|
|
48041
|
+
</div>
|
|
48042
|
+
</div>
|
|
48043
|
+
|
|
48044
|
+
<!-- Condensed Header (scrolled state) -->
|
|
48045
|
+
<div
|
|
48046
|
+
class="transition-all duration-300 ease-in-out overflow-hidden"
|
|
48047
|
+
[class.max-h-0]="!isScrolled()"
|
|
48048
|
+
[class.opacity-0]="!isScrolled()"
|
|
48049
|
+
[class.max-h-20]="isScrolled()"
|
|
48050
|
+
[class.opacity-100]="isScrolled()">
|
|
48051
|
+
<div
|
|
48052
|
+
class="max-w-7xl mx-auto px-6 sm:px-8 py-3"
|
|
48053
|
+
[class.pointer-events-none]="!isScrolled()"
|
|
48054
|
+
[class.pointer-events-auto]="isScrolled()">
|
|
48055
|
+
<div class="flex items-center justify-between gap-4">
|
|
48056
|
+
<div class="flex items-center gap-4 flex-1 min-w-0">
|
|
48057
|
+
<h1 class="text-lg font-bold truncate bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">{{analysisData()?.title}}</h1>
|
|
48058
|
+
@if (revenueMetric()) {
|
|
48059
|
+
<div class="hidden lg:flex items-center gap-3 px-4 py-1.5 rounded-lg" [ngClass]="isLightMode() ? 'bg-emerald-50 border border-emerald-200' : 'bg-emerald-500/10 border border-emerald-500/20'">
|
|
48060
|
+
<span [class]="metaLabelClass()" class="text-xs font-medium">Revenue:</span>
|
|
48061
|
+
<span [class]="headerTitleClass()" class="text-sm font-bold">{{ formatValue(revenueValue()) }}</span>
|
|
48062
|
+
<span class="text-xs font-semibold" [ngClass]="revenueTrend() >= 0 ? 'text-emerald-600' : 'text-red-600'">
|
|
48063
|
+
{{ revenueTrend() >= 0 ? '+' : '' }}{{ revenueTrend().toFixed(1) }}%
|
|
48064
|
+
</span>
|
|
48065
|
+
</div>
|
|
48066
|
+
}
|
|
48067
|
+
</div>
|
|
48068
|
+
<div class="flex items-center gap-3">
|
|
48069
|
+
@if (!isSimplifiedView()) {
|
|
48070
|
+
<!-- Search Button (Icon Only in Sticky Header) -->
|
|
48071
|
+
<button
|
|
48072
|
+
type="button"
|
|
48073
|
+
(click)="searchService.openSearch(); $event.preventDefault()"
|
|
48074
|
+
[class]="buttonClass()"
|
|
48075
|
+
title="Search (/ or Cmd+K)"
|
|
48076
|
+
class="p-2 rounded-lg transition-all duration-200 hover:scale-110">
|
|
48077
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48078
|
+
<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"></path>
|
|
48079
|
+
</svg>
|
|
48080
|
+
</button>
|
|
48081
|
+
}
|
|
48082
|
+
<!-- View Mode Switcher (Icon Only in Sticky Header) -->
|
|
48083
|
+
<button
|
|
48084
|
+
type="button"
|
|
48085
|
+
(click)="openViewModeSwitcher(); $event.preventDefault()"
|
|
48086
|
+
[class]="buttonClass()"
|
|
48087
|
+
[title]="'Change View Mode: ' + displayModeLabel()"
|
|
48088
|
+
class="p-2 rounded-lg transition-all duration-200 hover:scale-110">
|
|
48089
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48090
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
|
48091
|
+
<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"></path>
|
|
48092
|
+
</svg>
|
|
48093
|
+
</button>
|
|
48094
|
+
@if (!isSimplifiedView()) {
|
|
48095
|
+
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()">
|
|
48096
|
+
<select
|
|
48097
|
+
[ngModel]="selectedSectionFilter()"
|
|
48098
|
+
(ngModelChange)="changeSectionFilter($event)"
|
|
48099
|
+
[class]="selectClass()"
|
|
48100
|
+
class="px-3 py-1.5 rounded-lg text-xs font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors duration-200 cursor-pointer">
|
|
48101
|
+
@for (section of sectionFilters; track section.value) {
|
|
48102
|
+
<option [value]="section.value">{{ section.label }}</option>
|
|
48103
|
+
}
|
|
48104
|
+
</select>
|
|
48105
|
+
</div>
|
|
48106
|
+
}
|
|
48107
|
+
</div>
|
|
48108
|
+
</div>
|
|
48109
|
+
</div>
|
|
48110
|
+
</div>
|
|
48111
|
+
</header>
|
|
48112
|
+
|
|
48113
|
+
<!-- Search Breadcrumb -->
|
|
48114
|
+
@if (searchService.activeSearchResult()) {
|
|
48115
|
+
<div [ngClass]="isLightMode() ? 'bg-blue-50/95 border-blue-200' : 'bg-blue-900/20 border-blue-800/30'" class="sticky top-[var(--header-height)] z-40 border-b backdrop-blur-md animate-slide-up-fade">
|
|
48116
|
+
<div class="max-w-7xl mx-auto px-6 sm:px-8 py-3">
|
|
48117
|
+
<div class="flex items-center justify-between gap-4">
|
|
48118
|
+
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
48119
|
+
<svg [ngClass]="isLightMode() ? 'text-blue-600' : 'text-blue-400'" class="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48120
|
+
<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"></path>
|
|
48121
|
+
</svg>
|
|
48122
|
+
<div class="flex items-center gap-2 flex-1 min-w-0">
|
|
48123
|
+
<span [ngClass]="isLightMode() ? 'text-blue-900' : 'text-blue-100'" class="text-sm font-medium">Showing:</span>
|
|
48124
|
+
<span [ngClass]="isLightMode() ? 'text-blue-700' : 'text-blue-300'" class="text-sm font-semibold truncate">
|
|
48125
|
+
{{ searchService.activeSearchResult()!.title }}
|
|
48126
|
+
</span>
|
|
48127
|
+
<span [ngClass]="isLightMode() ? 'bg-blue-100 text-blue-700 border-blue-200' : 'bg-blue-800/50 text-blue-300 border-blue-700/50'" class="px-2 py-0.5 rounded text-xs font-medium uppercase border flex-shrink-0">
|
|
48128
|
+
{{ searchService.activeSearchResult()!.type }}
|
|
48129
|
+
</span>
|
|
48130
|
+
</div>
|
|
48131
|
+
</div>
|
|
48132
|
+
<button
|
|
48133
|
+
(click)="clearSearchResult(); $event.stopPropagation()"
|
|
48134
|
+
[ngClass]="isLightMode() ? 'text-blue-600 hover:text-blue-800 hover:bg-blue-100' : 'text-blue-400 hover:text-blue-200 hover:bg-blue-800/50'"
|
|
48135
|
+
class="p-2 rounded-lg transition-colors flex-shrink-0"
|
|
48136
|
+
title="Clear search">
|
|
48137
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48138
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
48139
|
+
</svg>
|
|
48140
|
+
</button>
|
|
48141
|
+
</div>
|
|
48142
|
+
</div>
|
|
48143
|
+
</div>
|
|
48144
|
+
}
|
|
48145
|
+
|
|
48146
|
+
<!-- Floating Table of Contents -->
|
|
48147
|
+
@if (!isSimplifiedView()) {
|
|
48148
|
+
<symphiq-floating-toc
|
|
48149
|
+
[sections]="tocSections()"
|
|
48150
|
+
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48151
|
+
[embedded]="embedded()"
|
|
48152
|
+
[scrollElement]="scrollElement() ?? undefined"
|
|
48153
|
+
/>
|
|
48154
|
+
}
|
|
48155
|
+
|
|
48156
|
+
<!-- Quick Navigation Dots -->
|
|
48157
|
+
@if (!isSimplifiedView()) {
|
|
48158
|
+
<div class="fixed right-6 top-1/2 -translate-y-1/2 z-40 hidden xl:flex flex-col gap-4">
|
|
48159
|
+
@if (showOverallPerformance()) {
|
|
48160
|
+
<button
|
|
48161
|
+
(click)="scrollToTop()"
|
|
48162
|
+
[libSymphiqTooltip]="'Scroll to Top'"
|
|
48163
|
+
[tooltipPosition]="'left'"
|
|
48164
|
+
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48165
|
+
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48166
|
+
</button>
|
|
48167
|
+
}
|
|
48168
|
+
@if (showKeyInsights()) {
|
|
48169
|
+
<button
|
|
48170
|
+
(click)="scrollToSection('section-insights')"
|
|
48171
|
+
[libSymphiqTooltip]="'Key Insights'"
|
|
48172
|
+
[tooltipPosition]="'left'"
|
|
48173
|
+
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48174
|
+
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48175
|
+
</button>
|
|
48176
|
+
}
|
|
48177
|
+
@if (showPerformanceMetrics()) {
|
|
48178
|
+
<button
|
|
48179
|
+
(click)="scrollToSection('section-metrics')"
|
|
48180
|
+
[libSymphiqTooltip]="'Performance Metrics'"
|
|
48181
|
+
[tooltipPosition]="'left'"
|
|
48182
|
+
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48183
|
+
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48184
|
+
</button>
|
|
48185
|
+
}
|
|
48186
|
+
@if (showPerformanceBreakdowns()) {
|
|
48187
|
+
<button
|
|
48188
|
+
(click)="scrollToSection('section-breakdowns')"
|
|
48189
|
+
[libSymphiqTooltip]="'Performance Breakdowns'"
|
|
48190
|
+
[tooltipPosition]="'left'"
|
|
48191
|
+
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-blue-500' : 'bg-slate-600 hover:bg-blue-400'"
|
|
48192
|
+
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48193
|
+
</button>
|
|
48194
|
+
}
|
|
48195
|
+
@if (showCompetitiveIntelligence()) {
|
|
48196
|
+
<button
|
|
48197
|
+
(click)="scrollToSection('section-competitive')"
|
|
48198
|
+
[libSymphiqTooltip]="'Competitive Intelligence'"
|
|
48199
|
+
[tooltipPosition]="'left'"
|
|
48200
|
+
[ngClass]="isLightMode() ? 'bg-slate-300 hover:bg-indigo-500' : 'bg-slate-600 hover:bg-indigo-400'"
|
|
48201
|
+
class="w-3 h-3 rounded-full transition-all duration-200 hover:scale-150 active:scale-100 cursor-pointer">
|
|
48202
|
+
</button>
|
|
48203
|
+
}
|
|
48204
|
+
</div>
|
|
48205
|
+
}
|
|
48206
|
+
|
|
48207
|
+
@if (isSimplifiedView()) {
|
|
48208
|
+
<!-- Journey Progress Banner -->
|
|
48209
|
+
@if (!isOnboarded()) {
|
|
48210
|
+
<symphiq-journey-progress-indicator
|
|
48211
|
+
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48212
|
+
[currentStepId]="JourneyStepIdEnum.FUNNEL_ANALYSIS"
|
|
48213
|
+
[showNextStepAction]="true"
|
|
48214
|
+
[forDemo]="forDemo()"
|
|
48215
|
+
[maxAccessibleStepId]="maxAccessibleStepId()"
|
|
48216
|
+
(stepClick)="stepClick.emit($event)"
|
|
48217
|
+
(nextStepClick)="nextStepClick.emit()"
|
|
48218
|
+
/>
|
|
48219
|
+
}
|
|
48220
|
+
|
|
48221
|
+
<main class="max-w-7xl mx-auto px-6 sm:px-8">
|
|
48222
|
+
<div class="pt-8 sm:pt-12 pb-16 sm:pb-24">
|
|
48223
|
+
<!-- Welcome Banner -->
|
|
48224
|
+
<div class="mb-8">
|
|
48225
|
+
<symphiq-funnel-welcome-banner
|
|
48226
|
+
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48227
|
+
[isOnboarded]="isOnboarded()"
|
|
48228
|
+
/>
|
|
48229
|
+
</div>
|
|
48230
|
+
|
|
48231
|
+
<!-- Key Insights Section -->
|
|
48232
|
+
@if (showKeyInsights()) {
|
|
48233
|
+
<section id="section-insights" class="mb-8">
|
|
48234
|
+
<div class="flex items-center justify-between mb-6">
|
|
48235
|
+
<div class="flex items-center gap-3">
|
|
48236
|
+
<div [ngClass]="isLightMode() ? 'border-l-4 border-blue-500' : 'border-l-4 border-blue-400'" class="pl-4">
|
|
48237
|
+
<div class="flex items-center gap-3">
|
|
48238
|
+
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-blue-500' : 'text-blue-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48239
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
|
48240
|
+
</svg>
|
|
48241
|
+
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Key Insights</h2>
|
|
48242
|
+
</div>
|
|
48243
|
+
</div>
|
|
48244
|
+
</div>
|
|
48245
|
+
<span [class]="metaLabelClass()" class="text-xs sm:text-sm">{{ insights().length }} insights</span>
|
|
48246
|
+
</div>
|
|
48247
|
+
|
|
48248
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
48249
|
+
@for (insight of insights(); track $index) {
|
|
48250
|
+
<symphiq-funnel-analysis-insight-card
|
|
48251
|
+
[insight]="insight"
|
|
48252
|
+
[allMetrics]="allMetrics()"
|
|
48253
|
+
[charts]="chartsForInsight(insight)"
|
|
48254
|
+
[allCharts]="allCharts()"
|
|
48255
|
+
[allBusinessInsights]="allBusinessInsights()"
|
|
48256
|
+
[isLightMode]="isLightMode()"
|
|
48257
|
+
[viewMode]="viewMode()"
|
|
48258
|
+
[isCompactMode]="true"
|
|
48259
|
+
[isLoading]="isDataLoading()" />
|
|
48260
|
+
}
|
|
48261
|
+
</div>
|
|
48262
|
+
</section>
|
|
48263
|
+
}
|
|
48264
|
+
|
|
48265
|
+
<!-- Supporting Data Section -->
|
|
48266
|
+
<symphiq-collapsible-funnel-section-group
|
|
48267
|
+
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK">
|
|
48268
|
+
<!-- Overall Performance Slot -->
|
|
48269
|
+
<div slot="overall-performance">
|
|
48270
|
+
@if (showOverallPerformance()) {
|
|
48271
|
+
<div class="p-6">
|
|
48272
|
+
@if (isDataLoading()) {
|
|
48273
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48274
|
+
} @else {
|
|
48275
|
+
<symphiq-funnel-analysis-overall-assessment
|
|
48276
|
+
[assessment]="performanceOverview().overallAssessment || {}"
|
|
48277
|
+
[revenueMetric]="revenueMetric()"
|
|
48278
|
+
[charts]="chartsForItem('OVERALL_ASSESSMENT')"
|
|
48279
|
+
[metrics]="allMetrics()"
|
|
48280
|
+
[isLightMode]="isLightMode()"
|
|
48281
|
+
[isLoading]="isOverallAssessmentLoading()"
|
|
48282
|
+
[isCompactMode]="true"
|
|
48283
|
+
[isChartsLoading]="areChartsLoading()"
|
|
48284
|
+
[strengths]="strengths()"
|
|
48285
|
+
[weaknesses]="weaknesses()"
|
|
48286
|
+
[currencySymbol]="currencySymbol()"
|
|
48287
|
+
(scrollToSection)="scrollToSection($event)" />
|
|
48288
|
+
}
|
|
48289
|
+
</div>
|
|
48290
|
+
}
|
|
48291
|
+
</div>
|
|
48292
|
+
|
|
48293
|
+
<!-- Performance Metrics Slot -->
|
|
48294
|
+
<div slot="performance-metrics">
|
|
48295
|
+
@if (showPerformanceMetrics()) {
|
|
48296
|
+
<div class="p-6 space-y-8">
|
|
48297
|
+
@for (funnelGroup of groupedMetrics(); track $index; let groupIdx = $index) {
|
|
48298
|
+
<!-- Funnel Stage Metric (Full Width) -->
|
|
48299
|
+
<div class="w-full">
|
|
48300
|
+
<symphiq-funnel-analysis-metric-card
|
|
48301
|
+
[metric]="funnelGroup.funnelMetric"
|
|
48302
|
+
[insights]="insights()"
|
|
48303
|
+
[charts]="chartsForMetric(funnelGroup.funnelMetric)"
|
|
48304
|
+
[allCharts]="allCharts()"
|
|
48305
|
+
[analysis]="analysisData()"
|
|
48306
|
+
[isLightMode]="isLightMode()"
|
|
48307
|
+
[viewMode]="viewMode()"
|
|
48308
|
+
[isCompactMode]="true"
|
|
48309
|
+
[currencySymbol]="currencySymbol()" />
|
|
48310
|
+
</div>
|
|
48311
|
+
<!-- Related Metrics (Grid Layout) -->
|
|
48312
|
+
@if (funnelGroup.relatedMetrics.length > 0) {
|
|
48313
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-4">
|
|
48314
|
+
@for (metric of funnelGroup.relatedMetrics; track $index) {
|
|
48315
|
+
<symphiq-funnel-analysis-metric-card
|
|
48316
|
+
[metric]="metric"
|
|
48317
|
+
[insights]="insights()"
|
|
48318
|
+
[charts]="chartsForMetric(metric)"
|
|
48319
|
+
[allCharts]="allCharts()"
|
|
48320
|
+
[analysis]="analysisData()"
|
|
48321
|
+
[isLightMode]="isLightMode()"
|
|
48322
|
+
[viewMode]="viewMode()"
|
|
48323
|
+
[isCompactMode]="true"
|
|
48324
|
+
[currencySymbol]="currencySymbol()" />
|
|
48325
|
+
}
|
|
48326
|
+
</div>
|
|
48327
|
+
}
|
|
48328
|
+
}
|
|
48329
|
+
</div>
|
|
48330
|
+
}
|
|
48331
|
+
</div>
|
|
48332
|
+
|
|
48333
|
+
<!-- Performance Breakdowns Slot -->
|
|
48334
|
+
<div slot="performance-breakdowns">
|
|
48335
|
+
@if (showPerformanceBreakdowns()) {
|
|
48336
|
+
<div class="p-6 space-y-8">
|
|
48337
|
+
@for (breakdown of breakdowns(); track $index) {
|
|
48338
|
+
<symphiq-funnel-analysis-breakdown-section
|
|
48339
|
+
[breakdown]="breakdown"
|
|
48340
|
+
[charts]="chartsForBreakdown(breakdown)"
|
|
48341
|
+
[isLightMode]="isLightMode()"
|
|
48342
|
+
[isLoading]="isDataLoading()"
|
|
48343
|
+
[isCompactMode]="true"
|
|
48344
|
+
[currencySymbol]="currencySymbol()" />
|
|
48345
|
+
}
|
|
48346
|
+
</div>
|
|
48347
|
+
}
|
|
48348
|
+
</div>
|
|
48349
|
+
|
|
48350
|
+
<!-- Competitive Intelligence Slot -->
|
|
48351
|
+
<div slot="competitive-intelligence">
|
|
48352
|
+
@if (showCompetitiveIntelligence()) {
|
|
48353
|
+
<div class="p-6">
|
|
48354
|
+
<symphiq-competitive-intelligence-view
|
|
48355
|
+
[metrics]="competitiveMetrics()"
|
|
48356
|
+
[allCharts]="allCharts()"
|
|
48357
|
+
[isLightMode]="isLightMode()"
|
|
48358
|
+
[isCompactMode]="true"
|
|
48359
|
+
[competitiveBenchmark]="performanceOverview().overallAssessment?.competitiveBenchmark"
|
|
48360
|
+
[currencySymbol]="currencySymbol()" />
|
|
48361
|
+
</div>
|
|
48362
|
+
}
|
|
48363
|
+
</div>
|
|
48364
|
+
</symphiq-collapsible-funnel-section-group>
|
|
48365
|
+
</div>
|
|
48366
|
+
</main>
|
|
48367
|
+
} @else {
|
|
48368
|
+
<main class="max-w-7xl mx-auto px-6 sm:px-8">
|
|
48369
|
+
<div class="pt-8 sm:pt-12 pb-16 sm:pb-24">
|
|
48370
|
+
@if (showOverallPerformance()) {
|
|
48371
|
+
<div id="section-overall" class="animate-fade-in-up mb-20 sm:mb-28" style="animation-delay: 0.1s;">
|
|
48372
|
+
@if (isDataLoading()) {
|
|
48373
|
+
<!-- Overall Assessment Skeleton -->
|
|
48374
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 sm:p-8 animate-pulse">
|
|
48375
|
+
<div class="space-y-6">
|
|
48376
|
+
<!-- Header -->
|
|
48377
|
+
<div class="flex items-center gap-3">
|
|
48378
|
+
<symphiq-skeleton-loader [width]="'48px'" [height]="'48px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48379
|
+
<div class="flex-1 space-y-2">
|
|
48380
|
+
<symphiq-skeleton-loader [width]="'40%'" [height]="'32px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48381
|
+
<symphiq-skeleton-loader [width]="'60%'" [height]="'20px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48382
|
+
</div>
|
|
48383
|
+
</div>
|
|
48384
|
+
<!-- Summary text -->
|
|
48385
|
+
<div class="space-y-2">
|
|
48386
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48387
|
+
<symphiq-skeleton-loader [width]="'95%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48388
|
+
<symphiq-skeleton-loader [width]="'90%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48389
|
+
</div>
|
|
48390
|
+
<!-- Chart placeholder -->
|
|
48391
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6">
|
|
48392
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48393
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48394
|
+
</div>
|
|
48395
|
+
</div>
|
|
48396
|
+
</div>
|
|
48397
|
+
} @else {
|
|
48398
|
+
<symphiq-funnel-analysis-overall-assessment
|
|
48399
|
+
[assessment]="performanceOverview().overallAssessment || {}"
|
|
48400
|
+
[revenueMetric]="revenueMetric()"
|
|
48401
|
+
[charts]="chartsForItem('OVERALL_ASSESSMENT')"
|
|
48402
|
+
[metrics]="allMetrics()"
|
|
48403
|
+
[isLightMode]="isLightMode()"
|
|
48404
|
+
[isLoading]="isOverallAssessmentLoading()"
|
|
48405
|
+
[isCompactMode]="viewModeService.isCompact()"
|
|
48406
|
+
[isChartsLoading]="areChartsLoading()"
|
|
48407
|
+
[strengths]="strengths()"
|
|
48408
|
+
[weaknesses]="weaknesses()"
|
|
48409
|
+
[currencySymbol]="currencySymbol()"
|
|
48410
|
+
(scrollToSection)="scrollToSection($event)" />
|
|
48411
|
+
}
|
|
48412
|
+
</div>
|
|
48413
|
+
}
|
|
48414
|
+
|
|
48415
|
+
@if (showKeyInsights()) {
|
|
48416
|
+
@if (selectedSectionFilter() === 'ALL') {
|
|
48417
|
+
<!-- Section Divider -->
|
|
48418
|
+
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.15s"></symphiq-section-divider>
|
|
48419
|
+
}
|
|
48420
|
+
|
|
48421
|
+
<section id="section-insights" class="relative">
|
|
48422
|
+
<!-- Background Pattern -->
|
|
48423
|
+
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-blue-50/50 to-transparent' : 'bg-gradient-to-br from-blue-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%);"></div>
|
|
48424
|
+
<div class="relative">
|
|
48425
|
+
<div class="flex items-center justify-between mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.2s;">
|
|
48426
|
+
<div class="flex items-center gap-3">
|
|
48427
|
+
<div [ngClass]="isLightMode() ? 'border-l-4 border-blue-500' : 'border-l-4 border-blue-400'" class="pl-4">
|
|
48428
|
+
<div class="flex items-center gap-3">
|
|
48429
|
+
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-blue-500' : 'text-blue-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48430
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
|
48431
|
+
</svg>
|
|
48432
|
+
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Key Insights</h2>
|
|
48433
|
+
</div>
|
|
48434
|
+
</div>
|
|
48435
|
+
</div>
|
|
48436
|
+
<span [class]="metaLabelClass()" class="text-xs sm:text-sm">{{ insights().length }} insights</span>
|
|
48437
|
+
</div>
|
|
48438
|
+
<!-- Masonry Layout for Insights -->
|
|
48439
|
+
@if (isDataLoading() || (viewModeService.isExpanded() && viewModeService.getIsTransitioning())) {
|
|
48440
|
+
<!-- Skeleton loaders during data loading or transition to expanded view -->
|
|
48441
|
+
<div class="masonry-grid">
|
|
48442
|
+
@for (i of [1,2,3,4,5,6]; track i) {
|
|
48443
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse min-h-[280px]">
|
|
48444
|
+
<div class="space-y-4">
|
|
48445
|
+
<div class="flex items-center gap-3 mb-4">
|
|
48446
|
+
<symphiq-skeleton-loader [width]="'48px'" [height]="'48px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48447
|
+
<symphiq-skeleton-loader [width]="'60%'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48448
|
+
</div>
|
|
48449
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48450
|
+
<symphiq-skeleton-loader [width]="'95%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48451
|
+
<symphiq-skeleton-loader [width]="'85%'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48452
|
+
<div class="mt-6 space-y-2">
|
|
48453
|
+
<symphiq-skeleton-loader [width]="'40%'" [height]="'14px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48454
|
+
<symphiq-skeleton-loader [width]="'50%'" [height]="'36px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48455
|
+
</div>
|
|
48456
|
+
<div class="flex gap-2 mt-4">
|
|
48457
|
+
<symphiq-skeleton-loader [width]="'80px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48458
|
+
<symphiq-skeleton-loader [width]="'80px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48459
|
+
</div>
|
|
48460
|
+
</div>
|
|
48461
|
+
</div>
|
|
48462
|
+
}
|
|
48463
|
+
</div>
|
|
48464
|
+
} @else if (viewModeService.isExpanded()) {
|
|
48465
|
+
<div class="masonry-grid">
|
|
48466
|
+
@for (insight of insights(); track $index) {
|
|
48467
|
+
<div
|
|
48468
|
+
[class]="getInsightCardClass(insight)"
|
|
48469
|
+
class="animate-fade-in-up"
|
|
48470
|
+
[style.animation-delay]="(0.3 + $index * 0.1) + 's'"
|
|
48471
|
+
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48472
|
+
[highlightId]="'insight-' + $index">
|
|
48473
|
+
<symphiq-funnel-analysis-insight-card
|
|
48474
|
+
[insight]="insight"
|
|
48475
|
+
[allMetrics]="allMetrics()"
|
|
48476
|
+
[charts]="chartsForInsight(insight)"
|
|
48477
|
+
[allCharts]="allCharts()"
|
|
48478
|
+
[allBusinessInsights]="allBusinessInsights()"
|
|
48479
|
+
[isLightMode]="isLightMode()"
|
|
48480
|
+
[viewMode]="viewMode()"
|
|
48481
|
+
[isCompactMode]="false" />
|
|
48482
|
+
</div>
|
|
48483
|
+
}
|
|
48484
|
+
</div>
|
|
48485
|
+
} @else {
|
|
48486
|
+
<!-- Compact Grid for Insights -->
|
|
48487
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
48488
|
+
@for (insight of insights(); track $index) {
|
|
48489
|
+
<div class="animate-fade-in-up" [style.animation-delay]="(0.3 + $index * 0.1) + 's'"
|
|
48490
|
+
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48491
|
+
[highlightId]="'insight-' + $index">
|
|
48492
|
+
<symphiq-funnel-analysis-insight-card
|
|
48493
|
+
[insight]="insight"
|
|
48494
|
+
[allMetrics]="allMetrics()"
|
|
48495
|
+
[charts]="chartsForInsight(insight)"
|
|
48496
|
+
[allCharts]="allCharts()"
|
|
48497
|
+
[allBusinessInsights]="allBusinessInsights()"
|
|
48498
|
+
[isLightMode]="isLightMode()"
|
|
48499
|
+
[viewMode]="viewMode()"
|
|
48500
|
+
[isCompactMode]="true" />
|
|
48501
|
+
</div>
|
|
48502
|
+
}
|
|
48503
|
+
</div>
|
|
48504
|
+
}
|
|
48505
|
+
</div>
|
|
48506
|
+
</section>
|
|
48507
|
+
}
|
|
48508
|
+
|
|
48509
|
+
@if (showPerformanceMetrics()) {
|
|
48510
|
+
@if (selectedSectionFilter() === 'ALL') {
|
|
48511
|
+
<!-- Section Divider -->
|
|
48512
|
+
<div class="relative mb-14 sm:mb-24 mt-24 sm:mt-32 animate-fade-in" style="animation-delay: 0.35s;">
|
|
48513
|
+
<div class="absolute inset-0 flex items-center" aria-hidden="true">
|
|
48514
|
+
<div class="w-full h-px bg-gradient-to-r" [ngClass]="isLightMode() ? 'from-transparent via-emerald-500/30 to-transparent' : 'from-transparent via-emerald-400/20 to-transparent'"></div>
|
|
48515
|
+
</div>
|
|
48516
|
+
<div class="relative flex justify-center">
|
|
48517
|
+
<div class="px-4 py-2 rounded-full" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-emerald-50 to-teal-50 border border-emerald-200/50 shadow-lg shadow-emerald-500/10' : 'bg-gradient-to-br from-slate-900 to-slate-800 border border-emerald-500/20 shadow-lg shadow-emerald-500/5'">
|
|
48518
|
+
<svg class="w-5 h-5" [ngClass]="isLightMode() ? 'text-emerald-500' : 'text-emerald-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48519
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z"></path>
|
|
48520
|
+
</svg>
|
|
48521
|
+
</div>
|
|
48522
|
+
</div>
|
|
48523
|
+
</div>
|
|
48524
|
+
}
|
|
48525
|
+
|
|
48526
|
+
<section id="section-metrics" class="relative">
|
|
48527
|
+
<!-- Background Pattern -->
|
|
48528
|
+
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-tl from-emerald-50/50 to-transparent' : 'bg-gradient-to-tl from-emerald-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at top right, black 0%, transparent 70%);"></div>
|
|
48529
|
+
<div class="relative">
|
|
48530
|
+
<div class="flex flex-col gap-4 mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.4s;">
|
|
48531
|
+
<div class="flex items-center justify-between">
|
|
48532
|
+
<div class="flex items-center gap-3">
|
|
48533
|
+
<div [ngClass]="isLightMode() ? 'border-l-4 border-emerald-500' : 'border-l-4 border-emerald-400'" class="pl-4">
|
|
48534
|
+
<div class="flex items-center gap-3">
|
|
48535
|
+
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-emerald-500' : 'text-emerald-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48536
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
|
48537
|
+
</svg>
|
|
48538
|
+
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Performance Metrics</h2>
|
|
48539
|
+
</div>
|
|
48540
|
+
</div>
|
|
48541
|
+
</div>
|
|
48542
|
+
<!-- Desktop controls -->
|
|
48543
|
+
<div class="hidden sm:flex gap-2 sm:gap-3 items-center relative">
|
|
48544
|
+
@if (isCategoryTransitioning()) {
|
|
48545
|
+
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48546
|
+
<div class="w-4 h-4 border-2 border-blue-500/30 border-t-blue-500 rounded-full animate-spin"></div>
|
|
48547
|
+
</div>
|
|
48548
|
+
}
|
|
48549
|
+
<select
|
|
48550
|
+
[ngModel]="selectedCategory()"
|
|
48551
|
+
(ngModelChange)="changeCategoryFilter($event)"
|
|
48552
|
+
[class]="selectClass()"
|
|
48553
|
+
[class.opacity-70]="isCategoryTransitioning()"
|
|
48554
|
+
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 cursor-pointer">
|
|
48555
|
+
@for (cat of categories; track cat.value) {
|
|
48556
|
+
@if (cat.divider) {
|
|
48557
|
+
<option [value]="cat.value" disabled class="font-semibold">{{ cat.label }}</option>
|
|
48558
|
+
} @else {
|
|
48559
|
+
<option [value]="cat.value">{{ cat.label }}</option>
|
|
48560
|
+
}
|
|
48561
|
+
}
|
|
48562
|
+
</select>
|
|
48563
|
+
<button
|
|
48564
|
+
(click)="toggleSortOrder()"
|
|
48565
|
+
[class]="sortButtonClass()"
|
|
48566
|
+
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all flex items-center gap-2 cursor-pointer hover:scale-105 active:scale-95"
|
|
48567
|
+
[title]="reverseSortOrder() ? 'Sort: Revenue to Views' : 'Sort: Views to Revenue'">
|
|
48568
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48569
|
+
@if (!reverseSortOrder()) {
|
|
48570
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"></path>
|
|
48571
|
+
}
|
|
48572
|
+
@if (reverseSortOrder()) {
|
|
48573
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"></path>
|
|
48574
|
+
}
|
|
48575
|
+
</svg>
|
|
48576
|
+
<span>Sort</span>
|
|
48577
|
+
</button>
|
|
48578
|
+
</div>
|
|
48579
|
+
</div>
|
|
48580
|
+
|
|
48581
|
+
<!-- Mobile horizontal scrolling category pills -->
|
|
48582
|
+
<div class="sm:hidden -mx-6 px-6">
|
|
48583
|
+
<div class="flex gap-2 overflow-x-auto pb-2 snap-x snap-mandatory scrollbar-hide">
|
|
48584
|
+
@for (cat of categories; track cat.value) {
|
|
48585
|
+
@if (!cat.divider) {
|
|
48586
|
+
<button
|
|
48587
|
+
(click)="changeCategoryFilter(cat.value)"
|
|
48588
|
+
[ngClass]="getCategoryPillClass(cat.value)"
|
|
48589
|
+
[class.opacity-70]="isCategoryTransitioning()"
|
|
48590
|
+
class="px-4 py-2 rounded-full text-xs font-medium whitespace-nowrap transition-all duration-200 flex-shrink-0 snap-start active:scale-95">
|
|
48591
|
+
{{ cat.label }}
|
|
48592
|
+
</button>
|
|
48593
|
+
}
|
|
48594
|
+
}
|
|
48595
|
+
</div>
|
|
48596
|
+
</div>
|
|
48597
|
+
</div>
|
|
48598
|
+
@if (isDataLoading()) {
|
|
48599
|
+
<!-- Metrics Skeleton -->
|
|
48600
|
+
<div class="space-y-8 sm:space-y-10">
|
|
48601
|
+
@for (i of [1,2,3]; track i) {
|
|
48602
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48603
|
+
<div class="flex items-center justify-between mb-4">
|
|
48604
|
+
<div class="flex items-center gap-3">
|
|
48605
|
+
<symphiq-skeleton-loader [width]="'40px'" [height]="'40px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48606
|
+
<div class="space-y-2">
|
|
48607
|
+
<symphiq-skeleton-loader [width]="'150px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48608
|
+
<symphiq-skeleton-loader [width]="'100px'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48609
|
+
</div>
|
|
48610
|
+
</div>
|
|
48611
|
+
<symphiq-skeleton-loader [width]="'80px'" [height]="'36px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48612
|
+
</div>
|
|
48613
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
48614
|
+
@for (j of [1,2,3,4]; track j) {
|
|
48615
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'120px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48616
|
+
}
|
|
48617
|
+
</div>
|
|
48618
|
+
</div>
|
|
48619
|
+
}
|
|
48620
|
+
</div>
|
|
48621
|
+
} @else {
|
|
48622
|
+
<div class="space-y-8 sm:space-y-10" [class.animate-content-change]="isCategoryTransitioning()" [class.transition-opacity-slow]="isCategoryTransitioning()">
|
|
48623
|
+
@for (funnelGroup of groupedMetrics(); track $index; let groupIdx = $index) {
|
|
48624
|
+
<div class="w-full animate-fade-in-up" [style.animation-delay]="(0.5 + groupIdx * 0.15) + 's'"
|
|
48625
|
+
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48626
|
+
[highlightId]="'metric-' + groupIdx">
|
|
48627
|
+
<symphiq-funnel-analysis-metric-card
|
|
48628
|
+
[metric]="funnelGroup.funnelMetric"
|
|
48629
|
+
[insights]="insights()"
|
|
48630
|
+
[charts]="chartsForMetric(funnelGroup.funnelMetric)"
|
|
48631
|
+
[allCharts]="allCharts()"
|
|
48632
|
+
[analysis]="analysisData()"
|
|
48633
|
+
[isLightMode]="isLightMode()"
|
|
48634
|
+
[viewMode]="viewMode()"
|
|
48635
|
+
[isCompactMode]="viewModeService.isCompact()"
|
|
48636
|
+
[currencySymbol]="currencySymbol()" />
|
|
48637
|
+
</div>
|
|
48638
|
+
@if (funnelGroup.relatedMetrics.length > 0) {
|
|
48639
|
+
<!-- Bento Box Grid Layout -->
|
|
48640
|
+
@if (viewModeService.isExpanded()) {
|
|
48641
|
+
<div class="bento-grid mt-4">
|
|
48642
|
+
@for (metric of funnelGroup.relatedMetrics; track $index; let metricIdx = $index) {
|
|
48643
|
+
<div
|
|
48644
|
+
[class]="getBentoCardClass(metric, metricIdx)"
|
|
48645
|
+
class="animate-fade-in-up"
|
|
48646
|
+
[style.animation-delay]="(0.6 + groupIdx * 0.15 + metricIdx * 0.08) + 's'">
|
|
48647
|
+
<symphiq-funnel-analysis-metric-card
|
|
48648
|
+
class="h-full"
|
|
48649
|
+
[metric]="metric"
|
|
48650
|
+
[insights]="insights()"
|
|
48651
|
+
[charts]="chartsForMetric(metric)"
|
|
48652
|
+
[allCharts]="allCharts()"
|
|
48653
|
+
[analysis]="analysisData()"
|
|
48654
|
+
[isLightMode]="isLightMode()"
|
|
48655
|
+
[viewMode]="viewMode()"
|
|
48656
|
+
[isCompactMode]="false"
|
|
48657
|
+
[currencySymbol]="currencySymbol()" />
|
|
48658
|
+
</div>
|
|
48659
|
+
}
|
|
48660
|
+
</div>
|
|
48661
|
+
} @else if (!viewModeService.isExpanded()) {
|
|
48662
|
+
<!-- Compact Grid Layout -->
|
|
48663
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 mt-4">
|
|
48664
|
+
@for (metric of funnelGroup.relatedMetrics; track $index; let metricIdx = $index) {
|
|
48665
|
+
<div class="animate-fade-in-up" [style.animation-delay]="(0.6 + groupIdx * 0.15 + metricIdx * 0.08) + 's'">
|
|
48666
|
+
<symphiq-funnel-analysis-metric-card
|
|
48667
|
+
[metric]="metric"
|
|
48668
|
+
[insights]="insights()"
|
|
48669
|
+
[charts]="chartsForMetric(metric)"
|
|
48670
|
+
[allCharts]="allCharts()"
|
|
48671
|
+
[analysis]="analysisData()"
|
|
48672
|
+
[isLightMode]="isLightMode()"
|
|
48673
|
+
[viewMode]="viewMode()"
|
|
48674
|
+
[isCompactMode]="true"
|
|
48675
|
+
[currencySymbol]="currencySymbol()" />
|
|
48676
|
+
</div>
|
|
48677
|
+
}
|
|
48678
|
+
</div>
|
|
48679
|
+
} @else {
|
|
48680
|
+
<!-- Skeleton loaders during transition to expanded view -->
|
|
48681
|
+
<div class="bento-grid mt-4">
|
|
48682
|
+
@for (i of [1,2,3,4]; track i) {
|
|
48683
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse min-h-[240px]">
|
|
48684
|
+
<div class="space-y-4">
|
|
48685
|
+
<div class="flex items-center justify-between">
|
|
48686
|
+
<symphiq-skeleton-loader [width]="'60%'" [height]="'22px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48687
|
+
<symphiq-skeleton-loader [width]="'60px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48688
|
+
</div>
|
|
48689
|
+
<symphiq-skeleton-loader [width]="'45%'" [height]="'42px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48690
|
+
<div class="flex items-center gap-3 mt-4">
|
|
48691
|
+
<symphiq-skeleton-loader [width]="'24px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48692
|
+
<symphiq-skeleton-loader [width]="'30%'" [height]="'20px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48693
|
+
</div>
|
|
48694
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48695
|
+
<symphiq-skeleton-loader [width]="'85%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48696
|
+
<div class="mt-4">
|
|
48697
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'120px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48698
|
+
</div>
|
|
48699
|
+
</div>
|
|
48700
|
+
</div>
|
|
48701
|
+
}
|
|
48702
|
+
</div>
|
|
48703
|
+
}
|
|
48704
|
+
}
|
|
48705
|
+
} @empty {
|
|
48706
|
+
<div [ngClass]="isLightMode() ? 'bg-slate-50 border-slate-200' : 'bg-slate-800/50 border-slate-700'" class="rounded-xl p-12 border text-center animate-fade-in">
|
|
48707
|
+
<svg class="w-16 h-16 mx-auto mb-4" [ngClass]="isLightMode() ? 'text-slate-300' : 'text-slate-600'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48708
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
|
|
48709
|
+
</svg>
|
|
48710
|
+
<h3 [ngClass]="isLightMode() ? 'text-slate-900' : 'text-white'" class="text-lg font-semibold mb-2">No Metrics Found</h3>
|
|
48711
|
+
<p [ngClass]="isLightMode() ? 'text-slate-600' : 'text-slate-400'" class="text-sm">No performance metrics match your current filter selection. Try adjusting your filters to see more results.</p>
|
|
48712
|
+
</div>
|
|
48713
|
+
}
|
|
48714
|
+
</div>
|
|
48715
|
+
}
|
|
48716
|
+
</div>
|
|
48717
|
+
</section>
|
|
48718
|
+
}
|
|
48719
|
+
|
|
48720
|
+
@if (showPerformanceBreakdowns()) {
|
|
48721
|
+
@if (selectedSectionFilter() === 'ALL') {
|
|
48722
|
+
<!-- Section Divider -->
|
|
48723
|
+
<div class="mt-28 sm:mt-36">
|
|
48724
|
+
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.65s"></symphiq-section-divider>
|
|
48725
|
+
</div>
|
|
48726
|
+
}
|
|
48727
|
+
|
|
48728
|
+
<section id="section-breakdowns" class="relative">
|
|
48729
|
+
<!-- Background Pattern -->
|
|
48730
|
+
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-tr from-purple-50/50 to-transparent' : 'bg-gradient-to-tr from-purple-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at bottom left, black 0%, transparent 70%);"></div>
|
|
48731
|
+
<div class="relative">
|
|
48732
|
+
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.7s;">
|
|
48733
|
+
<div [ngClass]="isLightMode() ? 'border-l-4 border-purple-500' : 'border-l-4 border-purple-400'" class="pl-4">
|
|
48734
|
+
<div class="flex items-center gap-3">
|
|
48735
|
+
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-purple-500' : 'text-purple-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48736
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"></path>
|
|
48737
|
+
</svg>
|
|
48738
|
+
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Performance Breakdowns</h2>
|
|
48739
|
+
</div>
|
|
48740
|
+
</div>
|
|
48741
|
+
<div (click)="$event.stopPropagation()" (mousedown)="$event.stopPropagation()" (pointerdown)="$event.stopPropagation()" class="relative inline-block">
|
|
48742
|
+
@if (isBreakdownTransitioning()) {
|
|
48743
|
+
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48744
|
+
<div class="w-4 h-4 border-2 border-purple-500/30 border-t-purple-500 rounded-full animate-spin"></div>
|
|
48745
|
+
</div>
|
|
48746
|
+
}
|
|
48747
|
+
<select
|
|
48748
|
+
[ngModel]="selectedBreakdownFilter()"
|
|
48749
|
+
(ngModelChange)="changeBreakdownFilter($event)"
|
|
48750
|
+
[ngClass]="isLightMode()
|
|
48751
|
+
? 'bg-white border-slate-300 text-slate-900 hover:border-blue-400 focus:border-blue-500'
|
|
48752
|
+
: 'bg-slate-700 border-slate-600 text-white hover:border-slate-500 focus:border-blue-500'"
|
|
48753
|
+
[class.opacity-70]="isBreakdownTransitioning()"
|
|
48754
|
+
class="px-3 py-2 text-sm rounded-lg border transition-all duration-200 cursor-pointer focus:ring-2 focus:ring-blue-500 focus:outline-none">
|
|
48755
|
+
@for (filter of breakdownFilters; track filter.value) {
|
|
48756
|
+
@if (filter.divider) {
|
|
48757
|
+
<option [value]="filter.value" disabled class="font-semibold">{{ filter.label }}</option>
|
|
48758
|
+
} @else {
|
|
48759
|
+
<option [value]="filter.value">{{ filter.label }}</option>
|
|
48760
|
+
}
|
|
48761
|
+
}
|
|
48762
|
+
</select>
|
|
48763
|
+
</div>
|
|
48764
|
+
</div>
|
|
48765
|
+
@if (isDataLoading()) {
|
|
48766
|
+
<!-- Breakdowns Skeleton -->
|
|
48767
|
+
<div class="space-y-6">
|
|
48768
|
+
@for (i of [1,2]; track i) {
|
|
48769
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48770
|
+
<div class="flex items-center justify-between mb-4">
|
|
48771
|
+
<symphiq-skeleton-loader [width]="'200px'" [height]="'28px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48772
|
+
<symphiq-skeleton-loader [width]="'100px'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48773
|
+
</div>
|
|
48774
|
+
<div class="space-y-3">
|
|
48775
|
+
@for (j of [1,2,3,4]; track j) {
|
|
48776
|
+
<div class="flex items-center justify-between p-3 rounded-lg" [ngClass]="isLightMode() ? 'bg-slate-50' : 'bg-slate-700/50'">
|
|
48777
|
+
<symphiq-skeleton-loader [width]="'150px'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48778
|
+
<symphiq-skeleton-loader [width]="'80px'" [height]="'18px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48779
|
+
</div>
|
|
48780
|
+
}
|
|
48781
|
+
</div>
|
|
48782
|
+
</div>
|
|
48783
|
+
}
|
|
48784
|
+
</div>
|
|
48785
|
+
} @else {
|
|
48786
|
+
<div class="space-y-6" [class.animate-content-change]="isBreakdownTransitioning()" [class.transition-opacity-slow]="isBreakdownTransitioning()">
|
|
48787
|
+
@for (breakdown of breakdowns(); track $index) {
|
|
48788
|
+
<div class="animate-fade-in-up" [style.animation-delay]="(0.8 + $index * 0.1) + 's'"
|
|
48789
|
+
[libSymphiqSearchHighlight]="searchService.highlightedResultId()"
|
|
48790
|
+
[highlightId]="'breakdown-' + $index">
|
|
48791
|
+
<symphiq-funnel-analysis-breakdown-section
|
|
48792
|
+
[breakdown]="breakdown"
|
|
48793
|
+
[charts]="chartsForBreakdown(breakdown)"
|
|
48794
|
+
[isLightMode]="isLightMode()"
|
|
48795
|
+
[isCompactMode]="viewModeService.isCompact()"
|
|
48796
|
+
[currencySymbol]="currencySymbol()" />
|
|
48797
|
+
</div>
|
|
48798
|
+
} @empty {
|
|
48799
|
+
<div [ngClass]="isLightMode() ? 'bg-slate-50 border-slate-200' : 'bg-slate-800/50 border-slate-700'" class="rounded-xl p-12 border text-center animate-fade-in">
|
|
48800
|
+
<svg class="w-16 h-16 mx-auto mb-4" [ngClass]="isLightMode() ? 'text-slate-300' : 'text-slate-600'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48801
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"></path>
|
|
48802
|
+
</svg>
|
|
48803
|
+
<h3 [ngClass]="isLightMode() ? 'text-slate-900' : 'text-white'" class="text-lg font-semibold mb-2">No Breakdowns Found</h3>
|
|
48804
|
+
<p [ngClass]="isLightMode() ? 'text-slate-600' : 'text-slate-400'" class="text-sm">No performance breakdowns match your current filter selection. Try adjusting your filters to see more results.</p>
|
|
48805
|
+
</div>
|
|
48806
|
+
}
|
|
48807
|
+
</div>
|
|
48808
|
+
}
|
|
48809
|
+
</div>
|
|
48810
|
+
</section>
|
|
48811
|
+
}
|
|
48812
|
+
|
|
48813
|
+
@if (showCompetitiveIntelligence()) {
|
|
48814
|
+
@if (selectedSectionFilter() === 'ALL') {
|
|
48815
|
+
<!-- Section Divider -->
|
|
48816
|
+
<div class="mt-28 sm:mt-36">
|
|
48817
|
+
<symphiq-section-divider [viewMode]="viewMode()" animationDelay="0.85s"></symphiq-section-divider>
|
|
48818
|
+
</div>
|
|
48819
|
+
}
|
|
48820
|
+
|
|
48821
|
+
<!-- Competitive Intelligence Section -->
|
|
48822
|
+
<section id="section-competitive" class="relative">
|
|
48823
|
+
<!-- Background Pattern -->
|
|
48824
|
+
<div class="absolute inset-0 -mx-6 sm:-mx-8 -mt-8 rounded-3xl opacity-30 backdrop-blur-sm" [ngClass]="isLightMode() ? 'bg-gradient-to-br from-indigo-50/50 to-transparent' : 'bg-gradient-to-br from-indigo-950/20 to-transparent'" style="mask-image: radial-gradient(ellipse at center, black 0%, transparent 70%);"></div>
|
|
48825
|
+
<div class="relative">
|
|
48826
|
+
<div class="flex items-center justify-between mb-6 sm:mb-8 animate-fade-in" style="animation-delay: 0.9s;">
|
|
48827
|
+
<div class="flex items-center gap-3">
|
|
48828
|
+
<div [ngClass]="isLightMode() ? 'border-l-4 border-indigo-500' : 'border-l-4 border-indigo-400'" class="pl-4">
|
|
48829
|
+
<div class="flex items-center gap-3">
|
|
48830
|
+
<svg class="w-6 h-6" [ngClass]="isLightMode() ? 'text-indigo-500' : 'text-indigo-400'" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48831
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
|
48832
|
+
</svg>
|
|
48833
|
+
<h2 [class]="sectionTitleClass()" class="text-xl sm:text-2xl font-bold">Competitive Intelligence</h2>
|
|
48834
|
+
</div>
|
|
48835
|
+
</div>
|
|
48836
|
+
</div>
|
|
48837
|
+
<!-- Filter Dropdown -->
|
|
48838
|
+
<div class="hidden sm:block relative">
|
|
48839
|
+
@if (isCompetitiveTransitioning()) {
|
|
48840
|
+
<div class="absolute -right-2 top-1/2 -translate-y-1/2 z-10">
|
|
48841
|
+
<div class="w-4 h-4 border-2 border-indigo-500/30 border-t-indigo-500 rounded-full animate-spin"></div>
|
|
48842
|
+
</div>
|
|
48843
|
+
}
|
|
48844
|
+
<select
|
|
48845
|
+
[ngModel]="selectedCompetitiveFilter()"
|
|
48846
|
+
(ngModelChange)="changeCompetitiveFilter($event)"
|
|
48847
|
+
[class]="selectClass()"
|
|
48848
|
+
[class.opacity-70]="isCompetitiveTransitioning()"
|
|
48849
|
+
class="px-3 sm:px-4 py-2 rounded-lg text-xs sm:text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 cursor-pointer">
|
|
48850
|
+
@for (filter of competitiveFilters; track filter.value) {
|
|
48851
|
+
@if (filter.divider) {
|
|
48852
|
+
<option [value]="filter.value" disabled class="font-semibold">{{ filter.label }}</option>
|
|
48853
|
+
} @else {
|
|
48854
|
+
<option [value]="filter.value">{{ filter.label }}</option>
|
|
48855
|
+
}
|
|
48856
|
+
}
|
|
48857
|
+
</select>
|
|
48858
|
+
</div>
|
|
48859
|
+
</div>
|
|
48860
|
+
|
|
48861
|
+
@if (isDataLoading()) {
|
|
48862
|
+
<!-- Competitive Intelligence Skeleton -->
|
|
48863
|
+
<div class="space-y-6">
|
|
48864
|
+
<div [ngClass]="isLightMode() ? 'bg-white border-slate-200' : 'bg-slate-800 border-slate-700'" class="rounded-xl border p-6 animate-pulse">
|
|
48865
|
+
<symphiq-skeleton-loader [width]="'60%'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48866
|
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-6">
|
|
48867
|
+
@for (i of [1,2,3]; track i) {
|
|
48868
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'140px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
48869
|
+
}
|
|
48870
|
+
</div>
|
|
48871
|
+
</div>
|
|
48872
|
+
</div>
|
|
48873
|
+
} @else {
|
|
48874
|
+
<symphiq-competitive-intelligence-view
|
|
48875
|
+
[metrics]="competitiveMetrics()"
|
|
48876
|
+
[allCharts]="allCharts()"
|
|
48877
|
+
[isLightMode]="isLightMode()"
|
|
48878
|
+
[isCompactMode]="viewModeService.isCompact()"
|
|
48879
|
+
[competitiveBenchmark]="performanceOverview().overallAssessment?.competitiveBenchmark"
|
|
48880
|
+
[currencySymbol]="currencySymbol()" />
|
|
48881
|
+
}
|
|
48882
|
+
</div>
|
|
48883
|
+
</section>
|
|
48884
|
+
}
|
|
48885
|
+
</div>
|
|
48886
|
+
</main>
|
|
48887
|
+
}
|
|
48888
|
+
|
|
48889
|
+
<symphiq-funnel-analysis-modal
|
|
48890
|
+
[isLightMode]="isLightMode()"
|
|
48891
|
+
[viewMode]="viewMode()"
|
|
48892
|
+
[allMetrics]="allMetrics()"
|
|
48893
|
+
[allInsights]="insights()"
|
|
48894
|
+
[allCharts]="allCharts()"
|
|
48895
|
+
[currencySymbol]="currencySymbol()"
|
|
48896
|
+
[businessProfile]="businessProfile()"></symphiq-funnel-analysis-modal>
|
|
48897
|
+
<symphiq-profile-analysis-modal
|
|
48898
|
+
[isLightMode]="isLightMode()"
|
|
48899
|
+
[allMetrics]="allMetrics()"
|
|
48900
|
+
></symphiq-profile-analysis-modal>
|
|
48901
|
+
<symphiq-business-analysis-modal [isLightMode]="isLightMode()" />
|
|
48902
|
+
<symphiq-tooltip-container></symphiq-tooltip-container>
|
|
48903
|
+
<symphiq-search-bar
|
|
48904
|
+
[isLightMode]="isLightMode()"
|
|
48905
|
+
(resultSelected)="handleSearchResult($event)" />
|
|
48906
|
+
|
|
48907
|
+
<!-- View Mode Switcher Modal -->
|
|
48908
|
+
<symphiq-view-mode-switcher-modal
|
|
48909
|
+
[isOpen]="isViewModeSwitcherOpen()"
|
|
48910
|
+
[currentMode]="displayMode()"
|
|
48911
|
+
[viewMode]="isLightMode() ? ViewModeEnum.LIGHT : ViewModeEnum.DARK"
|
|
48912
|
+
[isLoading]="isViewModeSwitching()"
|
|
48913
|
+
(close)="closeViewModeSwitcher()"
|
|
48914
|
+
(modeSelected)="handleDisplayModeChange($event)"
|
|
48915
|
+
/>
|
|
48916
|
+
|
|
48917
|
+
<!-- Mobile FAB -->
|
|
48918
|
+
<symphiq-mobile-fab
|
|
48919
|
+
[isLightMode]="isLightMode()"
|
|
48920
|
+
[isCompactMode]="viewModeService.isCompact()"
|
|
48921
|
+
[isExpanded]="fabExpanded()"
|
|
48922
|
+
(expandedChange)="fabExpanded.set($event)"
|
|
48923
|
+
(scrollToTop)="scrollToTop()"
|
|
48924
|
+
(toggleView)="viewModeService.toggleViewMode()" />
|
|
48925
|
+
|
|
48926
|
+
<!-- Mobile Bottom Navigation -->
|
|
48927
|
+
<symphiq-mobile-bottom-nav
|
|
48928
|
+
[isLightMode]="isLightMode()"
|
|
48929
|
+
[sections]="navSections"
|
|
48930
|
+
[activeSection]="activeNavSection()"
|
|
48931
|
+
(navigate)="handleMobileNavigation($event)" />
|
|
48932
|
+
|
|
48933
|
+
</div>
|
|
48934
48934
|
`, styles: [":host{display:block;min-height:100%}.bg-gradient-radial{background:radial-gradient(circle,var(--tw-gradient-stops))}.bento-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;grid-auto-flow:dense}@media (min-width: 768px){.bento-grid{grid-template-columns:repeat(6,1fr)}}.bento-small{grid-column:span 2;grid-row:span 1}.bento-medium{grid-column:span 3;grid-row:span 1}.bento-large{grid-column:span 4;grid-row:span 1}.bento-featured{grid-column:span 6;grid-row:span 1}@media (max-width: 767px){.bento-small,.bento-medium,.bento-large,.bento-featured{grid-column:span 1}}.masonry-grid{column-count:1;column-gap:1.5rem}@media (min-width: 768px){.masonry-grid{column-count:2}}@media (min-width: 1280px){.masonry-grid{column-count:3}}.masonry-grid>div{break-inside:avoid;margin-bottom:1.5rem}.masonry-featured{column-span:all}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}@media (max-width: 640px){.animate-fade-in-up{animation-duration:.4s}}\n"] }]
|
|
48935
48935
|
}], () => [{ type: FunnelOrderService }, { type: ViewModeService }, { type: SearchService }, { type: TooltipService }, { type: ProfileContextService }, { type: ProfileItemLookupService }], { modalComponent: [{
|
|
48936
48936
|
type: ViewChild,
|
|
@@ -54699,12 +54699,12 @@ function getPacingColorDark(pacingPercentage) {
|
|
|
54699
54699
|
}
|
|
54700
54700
|
function getPacingBgClass(status, isDark) {
|
|
54701
54701
|
if (status === 'ahead') {
|
|
54702
|
-
return isDark ? 'bg-emerald-
|
|
54702
|
+
return isDark ? 'bg-emerald-500/25' : 'bg-emerald-50';
|
|
54703
54703
|
}
|
|
54704
54704
|
if (status === 'on-pace') {
|
|
54705
|
-
return isDark ? 'bg-amber-
|
|
54705
|
+
return isDark ? 'bg-amber-500/25' : 'bg-amber-50';
|
|
54706
54706
|
}
|
|
54707
|
-
return isDark ? 'bg-red-
|
|
54707
|
+
return isDark ? 'bg-red-500/25' : 'bg-red-50';
|
|
54708
54708
|
}
|
|
54709
54709
|
function getPacingTextClass(status, isDark) {
|
|
54710
54710
|
if (status === 'ahead') {
|
|
@@ -54717,12 +54717,12 @@ function getPacingTextClass(status, isDark) {
|
|
|
54717
54717
|
}
|
|
54718
54718
|
function getPacingBorderClass(status, isDark) {
|
|
54719
54719
|
if (status === 'ahead') {
|
|
54720
|
-
return isDark ? 'border-emerald-
|
|
54720
|
+
return isDark ? 'border-emerald-400/40' : 'border-emerald-200';
|
|
54721
54721
|
}
|
|
54722
54722
|
if (status === 'on-pace') {
|
|
54723
|
-
return isDark ? 'border-amber-
|
|
54723
|
+
return isDark ? 'border-amber-400/40' : 'border-amber-200';
|
|
54724
54724
|
}
|
|
54725
|
-
return isDark ? 'border-red-
|
|
54725
|
+
return isDark ? 'border-red-400/40' : 'border-red-200';
|
|
54726
54726
|
}
|
|
54727
54727
|
function formatPacingDisplay(pacingPercentage) {
|
|
54728
54728
|
const sign = pacingPercentage >= 0 ? '+' : '';
|
|
@@ -54828,7 +54828,7 @@ function PacingStatusBadgeComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
|
|
|
54828
54828
|
i0.ɵɵadvance();
|
|
54829
54829
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.iconSymbol(), " ");
|
|
54830
54830
|
i0.ɵɵadvance();
|
|
54831
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r0.
|
|
54831
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.animatedPercentage(), " ");
|
|
54832
54832
|
i0.ɵɵadvance();
|
|
54833
54833
|
i0.ɵɵclassMap(ctx_r0.sizeClasses());
|
|
54834
54834
|
i0.ɵɵadvance(2);
|
|
@@ -54861,6 +54861,7 @@ class PacingStatusBadgeComponent {
|
|
|
54861
54861
|
this.showAsFullText = input(false, ...(ngDevMode ? [{ debugName: "showAsFullText" }] : []));
|
|
54862
54862
|
this.isCompact = input(false, ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
|
|
54863
54863
|
this.showEmphasizedPercentage = input(false, ...(ngDevMode ? [{ debugName: "showEmphasizedPercentage" }] : []));
|
|
54864
|
+
this.animatedValue = signal(0, ...(ngDevMode ? [{ debugName: "animatedValue" }] : []));
|
|
54864
54865
|
this.displayInfo = computed(() => {
|
|
54865
54866
|
const isDark = this.viewMode() === ViewModeEnum.DARK;
|
|
54866
54867
|
return getPacingDisplayInfo(this.pacingPercentage(), this.status(), isDark);
|
|
@@ -54871,9 +54872,12 @@ class PacingStatusBadgeComponent {
|
|
|
54871
54872
|
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
54872
54873
|
this.containerSizeClasses = computed(() => {
|
|
54873
54874
|
const compact = this.isCompact();
|
|
54875
|
+
const status = this.status();
|
|
54876
|
+
const tiltClass = status === 'ahead' ? 'rotate-1' : status === 'behind' ? '-rotate-1' : '';
|
|
54877
|
+
const baseClasses = 'inline-flex flex-row items-center rounded-xl border-2 overflow-visible transition-transform hover:rotate-0';
|
|
54874
54878
|
return compact
|
|
54875
|
-
?
|
|
54876
|
-
:
|
|
54879
|
+
? `${baseClasses} pl-1.5 ${tiltClass}`
|
|
54880
|
+
: `${baseClasses} pl-2 ${tiltClass}`;
|
|
54877
54881
|
}, ...(ngDevMode ? [{ debugName: "containerSizeClasses" }] : []));
|
|
54878
54882
|
this.badgeClasses = computed(() => {
|
|
54879
54883
|
const info = this.displayInfo();
|
|
@@ -54889,7 +54893,9 @@ class PacingStatusBadgeComponent {
|
|
|
54889
54893
|
}, ...(ngDevMode ? [{ debugName: "sizeClasses" }] : []));
|
|
54890
54894
|
this.fullBadgeSizeClasses = computed(() => {
|
|
54891
54895
|
const isCompact = this.isCompact();
|
|
54892
|
-
const
|
|
54896
|
+
const status = this.status();
|
|
54897
|
+
const tiltClass = status === 'ahead' ? 'rotate-1' : status === 'behind' ? '-rotate-1' : '';
|
|
54898
|
+
const baseClasses = `inline-flex items-center gap-1.5 rounded-xl border-2 font-bold tracking-wide shadow-md transition-all hover:rotate-0 ${tiltClass}`;
|
|
54893
54899
|
if (isCompact) {
|
|
54894
54900
|
return `${baseClasses} px-2.5 py-1 text-xs`;
|
|
54895
54901
|
}
|
|
@@ -54921,6 +54927,9 @@ class PacingStatusBadgeComponent {
|
|
|
54921
54927
|
: this.displayInfo().displayText;
|
|
54922
54928
|
return /\d+\.?\d*%/.test(fullText);
|
|
54923
54929
|
}, ...(ngDevMode ? [{ debugName: "hasPercentage" }] : []));
|
|
54930
|
+
this.animatedPercentage = computed(() => {
|
|
54931
|
+
return `${this.animatedValue().toFixed(1)}%`;
|
|
54932
|
+
}, ...(ngDevMode ? [{ debugName: "animatedPercentage" }] : []));
|
|
54924
54933
|
this.extractPercentage = computed(() => {
|
|
54925
54934
|
const fullText = this.showAsFullText()
|
|
54926
54935
|
? formatPacingDisplayFullText(this.pacingPercentage(), this.status())
|
|
@@ -54940,24 +54949,44 @@ class PacingStatusBadgeComponent {
|
|
|
54940
54949
|
const isDark = this.viewMode() === ViewModeEnum.DARK;
|
|
54941
54950
|
if (status === 'ahead') {
|
|
54942
54951
|
return isDark
|
|
54943
|
-
? 'bg-
|
|
54944
|
-
: 'bg-
|
|
54952
|
+
? 'bg-emerald-600 text-emerald-50'
|
|
54953
|
+
: 'bg-emerald-500 text-white';
|
|
54945
54954
|
}
|
|
54946
54955
|
if (status === 'on-pace') {
|
|
54947
54956
|
return isDark
|
|
54948
|
-
? 'bg-
|
|
54949
|
-
: 'bg-
|
|
54957
|
+
? 'bg-amber-600 text-amber-50'
|
|
54958
|
+
: 'bg-amber-500 text-white';
|
|
54950
54959
|
}
|
|
54951
54960
|
return isDark
|
|
54952
|
-
? 'bg-
|
|
54953
|
-
: 'bg-
|
|
54961
|
+
? 'bg-red-600 text-red-50'
|
|
54962
|
+
: 'bg-red-500 text-white';
|
|
54954
54963
|
}, ...(ngDevMode ? [{ debugName: "overlayBadgeClasses" }] : []));
|
|
54955
54964
|
this.overlaySizeClasses = computed(() => {
|
|
54956
54965
|
const compact = this.isCompact();
|
|
54957
54966
|
return compact
|
|
54958
|
-
? 'px-2 py-1.5 rounded text-sm font-extrabold tracking-
|
|
54959
|
-
: 'px-2.5 py-2 rounded-
|
|
54967
|
+
? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5'
|
|
54968
|
+
: 'px-2.5 py-2 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1';
|
|
54960
54969
|
}, ...(ngDevMode ? [{ debugName: "overlaySizeClasses" }] : []));
|
|
54970
|
+
effect(() => {
|
|
54971
|
+
const target = Math.abs(this.pacingPercentage());
|
|
54972
|
+
this.animateValue(target);
|
|
54973
|
+
});
|
|
54974
|
+
}
|
|
54975
|
+
animateValue(target) {
|
|
54976
|
+
const start = 0;
|
|
54977
|
+
const duration = 800;
|
|
54978
|
+
const startTime = performance.now();
|
|
54979
|
+
const animate = (currentTime) => {
|
|
54980
|
+
const elapsed = currentTime - startTime;
|
|
54981
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
54982
|
+
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
|
|
54983
|
+
const current = start + (target - start) * easeOutQuart;
|
|
54984
|
+
this.animatedValue.set(current);
|
|
54985
|
+
if (progress < 1) {
|
|
54986
|
+
requestAnimationFrame(animate);
|
|
54987
|
+
}
|
|
54988
|
+
};
|
|
54989
|
+
requestAnimationFrame(animate);
|
|
54961
54990
|
}
|
|
54962
54991
|
static { this.ɵfac = function PacingStatusBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PacingStatusBadgeComponent)(); }; }
|
|
54963
54992
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PacingStatusBadgeComponent, selectors: [["symphiq-pacing-status-badge"]], inputs: { viewMode: [1, "viewMode"], pacingPercentage: [1, "pacingPercentage"], status: [1, "status"], showAsFullText: [1, "showAsFullText"], isCompact: [1, "isCompact"], showEmphasizedPercentage: [1, "showEmphasizedPercentage"] }, decls: 2, vars: 1, consts: [[3, "ngClass", "class"], [3, "ngClass"]], template: function PacingStatusBadgeComponent_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -54973,35 +55002,35 @@ class PacingStatusBadgeComponent {
|
|
|
54973
55002
|
standalone: true,
|
|
54974
55003
|
imports: [CommonModule],
|
|
54975
55004
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
54976
|
-
template: `
|
|
54977
|
-
@if (showEmphasizedPercentage() && hasPercentage()) {
|
|
54978
|
-
<div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
|
|
54979
|
-
<div [ngClass]="overlayBadgeClasses()" [class]="overlaySizeClasses()">
|
|
54980
|
-
<span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
|
|
54981
|
-
{{ iconSymbol() }}
|
|
54982
|
-
</span>
|
|
54983
|
-
{{
|
|
54984
|
-
</div>
|
|
54985
|
-
<div
|
|
54986
|
-
[class]="sizeClasses()"
|
|
54987
|
-
>
|
|
54988
|
-
<span>{{ displayTextWithoutPercentage() }}</span>
|
|
54989
|
-
</div>
|
|
54990
|
-
</div>
|
|
54991
|
-
} @else {
|
|
54992
|
-
<div
|
|
54993
|
-
[ngClass]="badgeClasses()"
|
|
54994
|
-
[class]="fullBadgeSizeClasses()"
|
|
54995
|
-
>
|
|
54996
|
-
<span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
|
|
54997
|
-
{{ iconSymbol() }}
|
|
54998
|
-
</span>
|
|
54999
|
-
<span>{{ displayText() }}</span>
|
|
55000
|
-
</div>
|
|
55001
|
-
}
|
|
55005
|
+
template: `
|
|
55006
|
+
@if (showEmphasizedPercentage() && hasPercentage()) {
|
|
55007
|
+
<div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
|
|
55008
|
+
<div [ngClass]="overlayBadgeClasses()" [class]="overlaySizeClasses()">
|
|
55009
|
+
<span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
|
|
55010
|
+
{{ iconSymbol() }}
|
|
55011
|
+
</span>
|
|
55012
|
+
{{ animatedPercentage() }}
|
|
55013
|
+
</div>
|
|
55014
|
+
<div
|
|
55015
|
+
[class]="sizeClasses()"
|
|
55016
|
+
>
|
|
55017
|
+
<span>{{ displayTextWithoutPercentage() }}</span>
|
|
55018
|
+
</div>
|
|
55019
|
+
</div>
|
|
55020
|
+
} @else {
|
|
55021
|
+
<div
|
|
55022
|
+
[ngClass]="badgeClasses()"
|
|
55023
|
+
[class]="fullBadgeSizeClasses()"
|
|
55024
|
+
>
|
|
55025
|
+
<span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
|
|
55026
|
+
{{ iconSymbol() }}
|
|
55027
|
+
</span>
|
|
55028
|
+
<span>{{ displayText() }}</span>
|
|
55029
|
+
</div>
|
|
55030
|
+
}
|
|
55002
55031
|
`
|
|
55003
55032
|
}]
|
|
55004
|
-
}],
|
|
55033
|
+
}], () => [], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], pacingPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingPercentage", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], showAsFullText: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAsFullText", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }], showEmphasizedPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmphasizedPercentage", required: false }] }] }); })();
|
|
55005
55034
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PacingStatusBadgeComponent, { className: "PacingStatusBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/pacing-status-badge.component.ts", lineNumber: 39 }); })();
|
|
55006
55035
|
|
|
55007
55036
|
class TargetChangeBadgeComponent {
|
|
@@ -55011,6 +55040,7 @@ class TargetChangeBadgeComponent {
|
|
|
55011
55040
|
this.metric = input('', ...(ngDevMode ? [{ debugName: "metric" }] : []));
|
|
55012
55041
|
this.priorYear = input(new Date().getFullYear() - 1, ...(ngDevMode ? [{ debugName: "priorYear" }] : []));
|
|
55013
55042
|
this.isCompact = input(false, ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
|
|
55043
|
+
this.animatedValue = signal(0, ...(ngDevMode ? [{ debugName: "animatedValue" }] : []));
|
|
55014
55044
|
this.isDark = computed(() => this.viewMode() === ViewModeEnum.DARK, ...(ngDevMode ? [{ debugName: "isDark" }] : []));
|
|
55015
55045
|
this.isIncreaseBad = computed(() => {
|
|
55016
55046
|
const metricStr = this.metric();
|
|
@@ -55026,11 +55056,11 @@ class TargetChangeBadgeComponent {
|
|
|
55026
55056
|
return '↘';
|
|
55027
55057
|
return '→';
|
|
55028
55058
|
}, ...(ngDevMode ? [{ debugName: "iconSymbol" }] : []));
|
|
55029
|
-
this.
|
|
55059
|
+
this.animatedPercentageText = computed(() => {
|
|
55030
55060
|
const sign = this.isIncreaseBad() ? '' : '+';
|
|
55031
|
-
const absValue = Math.abs(this.
|
|
55061
|
+
const absValue = Math.abs(this.animatedValue());
|
|
55032
55062
|
return `${sign}${formatPercentage(absValue, 1)}`;
|
|
55033
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
55063
|
+
}, ...(ngDevMode ? [{ debugName: "animatedPercentageText" }] : []));
|
|
55034
55064
|
this.descriptionText = computed(() => {
|
|
55035
55065
|
const action = this.isIncreaseBad() ? 'decrease from' : 'increase over';
|
|
55036
55066
|
return `${action} ${this.priorYear()}`;
|
|
@@ -55038,26 +55068,30 @@ class TargetChangeBadgeComponent {
|
|
|
55038
55068
|
this.containerClasses = computed(() => {
|
|
55039
55069
|
const dark = this.isDark();
|
|
55040
55070
|
return dark
|
|
55041
|
-
? 'bg-purple-500/
|
|
55042
|
-
: 'bg-purple-
|
|
55071
|
+
? 'bg-purple-500/25 border-purple-400/40'
|
|
55072
|
+
: 'bg-purple-50 border-purple-200';
|
|
55043
55073
|
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
55074
|
+
this.isIncrease = computed(() => this.percentageChange() > 0, ...(ngDevMode ? [{ debugName: "isIncrease" }] : []));
|
|
55044
55075
|
this.containerSizeClasses = computed(() => {
|
|
55045
55076
|
const compact = this.isCompact();
|
|
55077
|
+
const change = this.percentageChange();
|
|
55078
|
+
const tiltClass = change > 0 ? 'rotate-1' : change < 0 ? '-rotate-1' : '';
|
|
55079
|
+
const baseClasses = 'inline-flex flex-row items-center rounded-xl border-2 overflow-visible transition-transform hover:rotate-0';
|
|
55046
55080
|
return compact
|
|
55047
|
-
?
|
|
55048
|
-
:
|
|
55081
|
+
? `${baseClasses} pl-1.5 ${tiltClass}`
|
|
55082
|
+
: `${baseClasses} pl-2 ${tiltClass}`;
|
|
55049
55083
|
}, ...(ngDevMode ? [{ debugName: "containerSizeClasses" }] : []));
|
|
55050
55084
|
this.overlayClasses = computed(() => {
|
|
55051
55085
|
const dark = this.isDark();
|
|
55052
55086
|
return dark
|
|
55053
|
-
? 'bg-
|
|
55054
|
-
: 'bg-
|
|
55087
|
+
? 'bg-purple-600 text-purple-50'
|
|
55088
|
+
: 'bg-purple-500 text-white';
|
|
55055
55089
|
}, ...(ngDevMode ? [{ debugName: "overlayClasses" }] : []));
|
|
55056
55090
|
this.overlaySizeClasses = computed(() => {
|
|
55057
55091
|
const compact = this.isCompact();
|
|
55058
55092
|
return compact
|
|
55059
|
-
? 'px-2 py-1.5 rounded text-sm font-extrabold tracking-
|
|
55060
|
-
: 'px-2.5 py-2 rounded-
|
|
55093
|
+
? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5'
|
|
55094
|
+
: 'px-2.5 py-2 rounded-lg font-extrabold text-base tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1';
|
|
55061
55095
|
}, ...(ngDevMode ? [{ debugName: "overlaySizeClasses" }] : []));
|
|
55062
55096
|
this.iconSizeClass = computed(() => {
|
|
55063
55097
|
return this.isCompact() ? 'text-sm' : 'text-base';
|
|
@@ -55068,6 +55102,26 @@ class TargetChangeBadgeComponent {
|
|
|
55068
55102
|
? 'px-2.5 py-0.5 text-xs font-semibold inline-block'
|
|
55069
55103
|
: 'px-3 py-0.5 font-semibold text-xs inline-block';
|
|
55070
55104
|
}, ...(ngDevMode ? [{ debugName: "descriptionSizeClasses" }] : []));
|
|
55105
|
+
effect(() => {
|
|
55106
|
+
const target = this.percentageChange();
|
|
55107
|
+
this.animateValue(target);
|
|
55108
|
+
});
|
|
55109
|
+
}
|
|
55110
|
+
animateValue(target) {
|
|
55111
|
+
const start = 0;
|
|
55112
|
+
const duration = 800;
|
|
55113
|
+
const startTime = performance.now();
|
|
55114
|
+
const animate = (currentTime) => {
|
|
55115
|
+
const elapsed = currentTime - startTime;
|
|
55116
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
55117
|
+
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
|
|
55118
|
+
const current = start + (target - start) * easeOutQuart;
|
|
55119
|
+
this.animatedValue.set(current);
|
|
55120
|
+
if (progress < 1) {
|
|
55121
|
+
requestAnimationFrame(animate);
|
|
55122
|
+
}
|
|
55123
|
+
};
|
|
55124
|
+
requestAnimationFrame(animate);
|
|
55071
55125
|
}
|
|
55072
55126
|
static { this.ɵfac = function TargetChangeBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TargetChangeBadgeComponent)(); }; }
|
|
55073
55127
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TargetChangeBadgeComponent, selectors: [["symphiq-target-change-badge"]], inputs: { viewMode: [1, "viewMode"], percentageChange: [1, "percentageChange"], metric: [1, "metric"], priorYear: [1, "priorYear"], isCompact: [1, "isCompact"] }, decls: 7, vars: 13, consts: [[3, "ngClass"]], template: function TargetChangeBadgeComponent_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -55090,7 +55144,7 @@ class TargetChangeBadgeComponent {
|
|
|
55090
55144
|
i0.ɵɵadvance();
|
|
55091
55145
|
i0.ɵɵtextInterpolate(ctx.iconSymbol());
|
|
55092
55146
|
i0.ɵɵadvance();
|
|
55093
|
-
i0.ɵɵtextInterpolate1(" ", ctx.
|
|
55147
|
+
i0.ɵɵtextInterpolate1(" ", ctx.animatedPercentageText(), " ");
|
|
55094
55148
|
i0.ɵɵadvance();
|
|
55095
55149
|
i0.ɵɵclassMap(ctx.descriptionSizeClasses());
|
|
55096
55150
|
i0.ɵɵadvance();
|
|
@@ -55104,19 +55158,19 @@ class TargetChangeBadgeComponent {
|
|
|
55104
55158
|
standalone: true,
|
|
55105
55159
|
imports: [CommonModule],
|
|
55106
55160
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
55107
|
-
template: `
|
|
55108
|
-
<div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
|
|
55109
|
-
<div [ngClass]="overlayClasses()" [class]="overlaySizeClasses()">
|
|
55110
|
-
<span [class]="iconSizeClass()">{{ iconSymbol() }}</span>
|
|
55111
|
-
{{
|
|
55112
|
-
</div>
|
|
55113
|
-
<div [class]="descriptionSizeClasses()">
|
|
55114
|
-
{{ descriptionText() }}
|
|
55115
|
-
</div>
|
|
55116
|
-
</div>
|
|
55161
|
+
template: `
|
|
55162
|
+
<div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
|
|
55163
|
+
<div [ngClass]="overlayClasses()" [class]="overlaySizeClasses()">
|
|
55164
|
+
<span [class]="iconSizeClass()">{{ iconSymbol() }}</span>
|
|
55165
|
+
{{ animatedPercentageText() }}
|
|
55166
|
+
</div>
|
|
55167
|
+
<div [class]="descriptionSizeClasses()">
|
|
55168
|
+
{{ descriptionText() }}
|
|
55169
|
+
</div>
|
|
55170
|
+
</div>
|
|
55117
55171
|
`
|
|
55118
55172
|
}]
|
|
55119
|
-
}],
|
|
55173
|
+
}], () => [], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], percentageChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "percentageChange", required: false }] }], metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: false }] }], priorYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "priorYear", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }] }); })();
|
|
55120
55174
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TargetChangeBadgeComponent, { className: "TargetChangeBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/target-change-badge.component.ts", lineNumber: 23 }); })();
|
|
55121
55175
|
|
|
55122
55176
|
const _forTrack0$j = ($index, $item) => $item.stageMetric.metric;
|
|
@@ -56930,20 +56984,19 @@ class LineChartComponent {
|
|
|
56930
56984
|
series.set('userData', { valueFormat: seriesData.valueFormat, isPriorYear });
|
|
56931
56985
|
// Disable individual series tooltips - use floating tooltip instead
|
|
56932
56986
|
series.set('tooltip', undefined);
|
|
56933
|
-
// Configure stroke styling based on
|
|
56987
|
+
// Configure stroke styling based on series type
|
|
56934
56988
|
series.strokes.template.setAll({
|
|
56935
|
-
strokeWidth: 2
|
|
56989
|
+
strokeWidth: isPriorYear ? 2 : 3
|
|
56936
56990
|
});
|
|
56937
56991
|
if (isPriorYear) {
|
|
56938
56992
|
// Apply dashed line and reduced opacity for prior year data
|
|
56939
56993
|
series.strokes.template.setAll({
|
|
56940
56994
|
strokeDasharray: [5, 5],
|
|
56941
|
-
strokeOpacity: 0.
|
|
56995
|
+
strokeOpacity: 0.5
|
|
56942
56996
|
});
|
|
56943
|
-
// Also set on each individual stroke
|
|
56944
56997
|
series.strokes.each((stroke) => {
|
|
56945
56998
|
stroke.set('strokeDasharray', [5, 5]);
|
|
56946
|
-
stroke.set('strokeOpacity', 0.
|
|
56999
|
+
stroke.set('strokeOpacity', 0.5);
|
|
56947
57000
|
});
|
|
56948
57001
|
}
|
|
56949
57002
|
// Add bullets with larger hit area for better hover detection
|
|
@@ -56953,7 +57006,7 @@ class LineChartComponent {
|
|
|
56953
57006
|
fill: seriesColor
|
|
56954
57007
|
};
|
|
56955
57008
|
if (isPriorYear) {
|
|
56956
|
-
bulletConfig['fillOpacity'] = 0.
|
|
57009
|
+
bulletConfig['fillOpacity'] = 0.5;
|
|
56957
57010
|
}
|
|
56958
57011
|
if (!this.root)
|
|
56959
57012
|
return Bullet.new({}, { sprite: Circle.new({}, {}) });
|
|
@@ -56999,10 +57052,10 @@ class LineChartComponent {
|
|
|
56999
57052
|
}
|
|
57000
57053
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LineChartComponent, [{
|
|
57001
57054
|
type: Component,
|
|
57002
|
-
args: [{ selector: 'symphiq-line-chart', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57003
|
-
<div class="chart-container" [class.mini-mode]="!showAxisLabels()">
|
|
57004
|
-
<div #chartdiv class="chart" [style.height]="chartHeight()" style="width: 100%;"></div>
|
|
57005
|
-
</div>
|
|
57055
|
+
args: [{ selector: 'symphiq-line-chart', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57056
|
+
<div class="chart-container" [class.mini-mode]="!showAxisLabels()">
|
|
57057
|
+
<div #chartdiv class="chart" [style.height]="chartHeight()" style="width: 100%;"></div>
|
|
57058
|
+
</div>
|
|
57006
57059
|
`, styles: [".chart-container{width:100%;padding:1rem}.chart-container.mini-mode{padding:.25rem}\n"] }]
|
|
57007
57060
|
}], () => [], { chart: [{ type: i0.Input, args: [{ isSignal: true, alias: "chart", required: false }] }], showAxisLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAxisLabels", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], currencySymbol: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencySymbol", required: false }] }], chartDiv: [{
|
|
57008
57061
|
type: ViewChild,
|
|
@@ -57064,6 +57117,7 @@ class ProgressToTargetChartComponent {
|
|
|
57064
57117
|
paddingRight: 0
|
|
57065
57118
|
}));
|
|
57066
57119
|
this.chart.zoomOutButton.set('forceHidden', true);
|
|
57120
|
+
this.chart.plotContainer.set('maskContent', false);
|
|
57067
57121
|
const xRenderer = AxisRendererX.new(this.root, {
|
|
57068
57122
|
strokeOpacity: 0.1
|
|
57069
57123
|
});
|
|
@@ -57090,6 +57144,10 @@ class ProgressToTargetChartComponent {
|
|
|
57090
57144
|
return;
|
|
57091
57145
|
this.chart.series.clear();
|
|
57092
57146
|
this.xAxis.axisRanges.clear();
|
|
57147
|
+
if (this.legend) {
|
|
57148
|
+
this.legend.dispose();
|
|
57149
|
+
this.legend = undefined;
|
|
57150
|
+
}
|
|
57093
57151
|
this.buildChart(chartData);
|
|
57094
57152
|
}
|
|
57095
57153
|
buildChart(chartData) {
|
|
@@ -57196,15 +57254,15 @@ class ProgressToTargetChartComponent {
|
|
|
57196
57254
|
dy: -18,
|
|
57197
57255
|
fill: this.labelColor()
|
|
57198
57256
|
});
|
|
57199
|
-
|
|
57257
|
+
this.legend = this.chart.children.push(Legend.new(this.root, {
|
|
57200
57258
|
centerX: p50,
|
|
57201
57259
|
x: p50,
|
|
57202
57260
|
marginTop: 8
|
|
57203
57261
|
}));
|
|
57204
|
-
legend.labels.template.setAll({
|
|
57262
|
+
this.legend.labels.template.setAll({
|
|
57205
57263
|
fill: this.labelColor()
|
|
57206
57264
|
});
|
|
57207
|
-
legend.data.setAll(this.chart.series.values.slice().reverse());
|
|
57265
|
+
this.legend.data.setAll(this.chart.series.values.slice().reverse());
|
|
57208
57266
|
this.chart.appear(1000, 100);
|
|
57209
57267
|
paceSeries.appear();
|
|
57210
57268
|
currentSeries.appear();
|
|
@@ -57269,20 +57327,20 @@ class ProgressToTargetChartComponent {
|
|
|
57269
57327
|
i0.ɵɵdomElementStart(0, "div", 1);
|
|
57270
57328
|
i0.ɵɵdomElement(1, "div", 2, 0);
|
|
57271
57329
|
i0.ɵɵdomElementEnd();
|
|
57272
|
-
} }, dependencies: [CommonModule], styles: [".progress-chart-container[_ngcontent-%COMP%]{width:100
|
|
57330
|
+
} }, dependencies: [CommonModule], styles: [".progress-chart-container[_ngcontent-%COMP%]{width:100%;margin-top:24px}"], changeDetection: 0 }); }
|
|
57273
57331
|
}
|
|
57274
57332
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProgressToTargetChartComponent, [{
|
|
57275
57333
|
type: Component,
|
|
57276
|
-
args: [{ selector: 'symphiq-progress-to-target-chart', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57277
|
-
<div class="progress-chart-container">
|
|
57278
|
-
<div #chartdiv class="chart" style="width: 100%; height: 160px;"></div>
|
|
57279
|
-
</div>
|
|
57280
|
-
`, styles: [".progress-chart-container{width:100
|
|
57334
|
+
args: [{ selector: 'symphiq-progress-to-target-chart', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57335
|
+
<div class="progress-chart-container">
|
|
57336
|
+
<div #chartdiv class="chart" style="width: 100%; height: 160px;"></div>
|
|
57337
|
+
</div>
|
|
57338
|
+
`, styles: [".progress-chart-container{width:100%;margin-top:24px}\n"] }]
|
|
57281
57339
|
}], () => [], { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], chartDiv: [{
|
|
57282
57340
|
type: ViewChild,
|
|
57283
57341
|
args: ['chartdiv', { static: true }]
|
|
57284
57342
|
}] }); })();
|
|
57285
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ProgressToTargetChartComponent, { className: "ProgressToTargetChartComponent", filePath: "lib/components/revenue-calculator-dashboard/progress-to-target-chart.component.ts", lineNumber:
|
|
57343
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ProgressToTargetChartComponent, { className: "ProgressToTargetChartComponent", filePath: "lib/components/revenue-calculator-dashboard/progress-to-target-chart.component.ts", lineNumber: 62 }); })();
|
|
57286
57344
|
|
|
57287
57345
|
const _forTrack0$i = ($index, $item) => $item.metric;
|
|
57288
57346
|
function MetricReportModalComponent_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -57390,7 +57448,7 @@ function MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Template
|
|
|
57390
57448
|
} }
|
|
57391
57449
|
function MetricReportModalComponent_Conditional_0_Conditional_65_Template(rf, ctx) { if (rf & 1) {
|
|
57392
57450
|
i0.ɵɵelementStart(0, "div", 16)(1, "h4", 17);
|
|
57393
|
-
i0.ɵɵtext(2, " Contributing
|
|
57451
|
+
i0.ɵɵtext(2, " Contributing Metric Targets ");
|
|
57394
57452
|
i0.ɵɵelementEnd();
|
|
57395
57453
|
i0.ɵɵelementStart(3, "div", 36)(4, "table", 37)(5, "thead")(6, "tr", 38)(7, "th", 39);
|
|
57396
57454
|
i0.ɵɵtext(8, "Metric");
|
|
@@ -57423,6 +57481,9 @@ function MetricReportModalComponent_Conditional_0_Conditional_66_Template(rf, ct
|
|
|
57423
57481
|
i0.ɵɵelementEnd();
|
|
57424
57482
|
i0.ɵɵelementStart(5, "p", 54);
|
|
57425
57483
|
i0.ɵɵtext(6);
|
|
57484
|
+
i0.ɵɵelementEnd();
|
|
57485
|
+
i0.ɵɵelementStart(7, "p", 55);
|
|
57486
|
+
i0.ɵɵtext(8);
|
|
57426
57487
|
i0.ɵɵelementEnd()();
|
|
57427
57488
|
} if (rf & 2) {
|
|
57428
57489
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -57434,7 +57495,11 @@ function MetricReportModalComponent_Conditional_0_Conditional_66_Template(rf, ct
|
|
|
57434
57495
|
i0.ɵɵadvance();
|
|
57435
57496
|
i0.ɵɵproperty("ngClass", ctx_r1.descriptionClasses());
|
|
57436
57497
|
i0.ɵɵadvance();
|
|
57437
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.
|
|
57498
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.chartDescriptionSentence1(), " ");
|
|
57499
|
+
i0.ɵɵadvance();
|
|
57500
|
+
i0.ɵɵproperty("ngClass", ctx_r1.descriptionClasses());
|
|
57501
|
+
i0.ɵɵadvance();
|
|
57502
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.chartDescriptionSentence2(), " ");
|
|
57438
57503
|
} }
|
|
57439
57504
|
function MetricReportModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
57440
57505
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -57518,7 +57583,7 @@ function MetricReportModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
|
|
|
57518
57583
|
i0.ɵɵconditionalCreate(64, MetricReportModalComponent_Conditional_0_Conditional_64_Template, 6, 10);
|
|
57519
57584
|
i0.ɵɵelementEnd();
|
|
57520
57585
|
i0.ɵɵconditionalCreate(65, MetricReportModalComponent_Conditional_0_Conditional_65_Template, 16, 3, "div", 16);
|
|
57521
|
-
i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template,
|
|
57586
|
+
i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template, 9, 10, "div", 29);
|
|
57522
57587
|
i0.ɵɵelementEnd();
|
|
57523
57588
|
i0.ɵɵelementStart(67, "div", 30)(68, "button", 31);
|
|
57524
57589
|
i0.ɵɵlistener("click", function MetricReportModalComponent_Conditional_0_Template_button_click_68_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
|
|
@@ -57681,6 +57746,18 @@ class MetricReportModalComponent {
|
|
|
57681
57746
|
}
|
|
57682
57747
|
return 0;
|
|
57683
57748
|
}, ...(ngDevMode ? [{ debugName: "samePeriodLastYearValue" }] : []));
|
|
57749
|
+
this.fullYearLastYearValue = computed(() => {
|
|
57750
|
+
const pacingResponse = this.pacingMetrics();
|
|
57751
|
+
const metric = this.metricData();
|
|
57752
|
+
if (!pacingResponse || !metric)
|
|
57753
|
+
return 0;
|
|
57754
|
+
const monthlyData = pacingResponse.lastYearMetricValuesMonthly;
|
|
57755
|
+
if (!monthlyData)
|
|
57756
|
+
return 0;
|
|
57757
|
+
return monthlyData
|
|
57758
|
+
.filter(item => item.metric === metric.metric)
|
|
57759
|
+
.reduce((total, item) => total + (parseFloat(item.value || '0') || 0), 0);
|
|
57760
|
+
}, ...(ngDevMode ? [{ debugName: "fullYearLastYearValue" }] : []));
|
|
57684
57761
|
this.ytdChangePercentage = computed(() => {
|
|
57685
57762
|
const current = this.ytdValue();
|
|
57686
57763
|
const lastYear = this.samePeriodLastYearValue();
|
|
@@ -57774,12 +57851,23 @@ class MetricReportModalComponent {
|
|
|
57774
57851
|
status: pacing.status
|
|
57775
57852
|
};
|
|
57776
57853
|
}, ...(ngDevMode ? [{ debugName: "progressToTargetData" }] : []));
|
|
57777
|
-
this.
|
|
57778
|
-
const
|
|
57779
|
-
const
|
|
57854
|
+
this.chartDescriptionSentence1 = computed(() => {
|
|
57855
|
+
const metricData = this.metricData();
|
|
57856
|
+
const metricName = this.metricTitle().toLowerCase();
|
|
57857
|
+
const startDate = this.ytdStartDate();
|
|
57858
|
+
const endDate = this.ytdEndDate();
|
|
57859
|
+
const ytdValue = this.formatMetricValue(this.ytdValue(), metricData?.metric || '');
|
|
57860
|
+
const samePeriodLastYear = this.formatMetricValue(this.samePeriodLastYearValue(), metricData?.metric || '');
|
|
57780
57861
|
const priorYear = this.priorYear();
|
|
57781
|
-
return `
|
|
57782
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
57862
|
+
return `For the period (${startDate} - ${endDate}) you had ${ytdValue} ${metricName}, compared to ${samePeriodLastYear} for the same period in ${priorYear}.`;
|
|
57863
|
+
}, ...(ngDevMode ? [{ debugName: "chartDescriptionSentence1" }] : []));
|
|
57864
|
+
this.chartDescriptionSentence2 = computed(() => {
|
|
57865
|
+
const metricData = this.metricData();
|
|
57866
|
+
const metricName = this.metricTitle().toLowerCase();
|
|
57867
|
+
const projectedValue = this.formatMetricValue(this.pacingInfo()?.projectedValue || 0, metricData?.metric || '');
|
|
57868
|
+
const fullYearLastYear = this.formatMetricValue(this.fullYearLastYearValue(), metricData?.metric || '');
|
|
57869
|
+
return `By maintaining this pace, your ${metricName} could increase to ${projectedValue} compared to ${fullYearLastYear} last year.`;
|
|
57870
|
+
}, ...(ngDevMode ? [{ debugName: "chartDescriptionSentence2" }] : []));
|
|
57783
57871
|
this.pacingChartData = computed(() => {
|
|
57784
57872
|
const metric = this.metricData();
|
|
57785
57873
|
const pacingResponse = this.pacingMetrics();
|
|
@@ -57792,7 +57880,6 @@ class MetricReportModalComponent {
|
|
|
57792
57880
|
chartType: 'LINE',
|
|
57793
57881
|
title: 'Pace',
|
|
57794
57882
|
description: '',
|
|
57795
|
-
lineChartUseCase: LineChartUseCaseEnum.THIS_YEAR_VS_LAST_YEAR,
|
|
57796
57883
|
lineChartData: {
|
|
57797
57884
|
series: [
|
|
57798
57885
|
{
|
|
@@ -57812,94 +57899,61 @@ class MetricReportModalComponent {
|
|
|
57812
57899
|
};
|
|
57813
57900
|
}, ...(ngDevMode ? [{ debugName: "pacingChartData" }] : []));
|
|
57814
57901
|
}
|
|
57815
|
-
formatDateForChart(year, month, day) {
|
|
57816
|
-
const m = String(month + 1).padStart(2, '0');
|
|
57817
|
-
const d = String(day).padStart(2, '0');
|
|
57818
|
-
return `${year}-${m}-${d}`;
|
|
57819
|
-
}
|
|
57820
57902
|
generateCurrentYearData(pacingResponse, metricEnum) {
|
|
57821
57903
|
const data = [];
|
|
57822
57904
|
const currentYear = this.currentYear();
|
|
57823
|
-
|
|
57824
|
-
|
|
57825
|
-
|
|
57826
|
-
|
|
57827
|
-
|
|
57905
|
+
const monthlyData = pacingResponse?.soFarMetricValuesMonthly;
|
|
57906
|
+
if (monthlyData) {
|
|
57907
|
+
monthlyData
|
|
57908
|
+
.filter(item => item.metric === metricEnum)
|
|
57909
|
+
.forEach((item) => {
|
|
57910
|
+
if (item.value && item.date) {
|
|
57911
|
+
const month = new Date(item.date).getMonth();
|
|
57828
57912
|
data.push({
|
|
57829
|
-
date:
|
|
57830
|
-
value: parseFloat(
|
|
57913
|
+
date: new Date(currentYear, month, 15).toISOString(),
|
|
57914
|
+
value: parseFloat(item.value) || 0
|
|
57831
57915
|
});
|
|
57832
57916
|
}
|
|
57833
57917
|
});
|
|
57834
57918
|
}
|
|
57835
|
-
if (data.length === 0) {
|
|
57836
|
-
const baseValue = this.metricData()?.currentValue || 1000;
|
|
57837
|
-
const now = new Date();
|
|
57838
|
-
const currentMonth = now.getMonth();
|
|
57839
|
-
for (let i = 0; i <= currentMonth; i++) {
|
|
57840
|
-
const value = baseValue * ((i + 1) / 12);
|
|
57841
|
-
data.push({
|
|
57842
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57843
|
-
value: Math.round(value * 100) / 100
|
|
57844
|
-
});
|
|
57845
|
-
}
|
|
57846
|
-
}
|
|
57847
57919
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57848
57920
|
}
|
|
57849
57921
|
generatePriorYearData(pacingResponse, metricEnum) {
|
|
57850
57922
|
const data = [];
|
|
57851
57923
|
const currentYear = this.currentYear();
|
|
57852
|
-
|
|
57853
|
-
|
|
57854
|
-
|
|
57855
|
-
|
|
57856
|
-
|
|
57924
|
+
const monthlyData = pacingResponse?.lastYearMetricValuesMonthly;
|
|
57925
|
+
if (monthlyData) {
|
|
57926
|
+
monthlyData
|
|
57927
|
+
.filter(item => item.metric === metricEnum)
|
|
57928
|
+
.forEach((item) => {
|
|
57929
|
+
if (item.value && item.date) {
|
|
57930
|
+
const month = new Date(item.date).getMonth();
|
|
57857
57931
|
data.push({
|
|
57858
|
-
date:
|
|
57859
|
-
value: parseFloat(
|
|
57932
|
+
date: new Date(currentYear, month, 15).toISOString(),
|
|
57933
|
+
value: parseFloat(item.value) || 0
|
|
57860
57934
|
});
|
|
57861
57935
|
}
|
|
57862
57936
|
});
|
|
57863
57937
|
}
|
|
57864
|
-
if (data.length === 0) {
|
|
57865
|
-
const baseValue = this.metricData()?.currentValue || 1000;
|
|
57866
|
-
for (let i = 0; i < 12; i++) {
|
|
57867
|
-
const value = baseValue * ((i + 1) / 12) * 0.9;
|
|
57868
|
-
data.push({
|
|
57869
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57870
|
-
value: Math.round(value * 100) / 100
|
|
57871
|
-
});
|
|
57872
|
-
}
|
|
57873
|
-
}
|
|
57874
57938
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57875
57939
|
}
|
|
57876
57940
|
generateProjectionData(pacingResponse, metricEnum) {
|
|
57877
57941
|
const data = [];
|
|
57878
57942
|
const currentYear = this.currentYear();
|
|
57879
|
-
|
|
57880
|
-
|
|
57881
|
-
|
|
57882
|
-
|
|
57883
|
-
|
|
57943
|
+
const monthlyData = pacingResponse?.projectedMetricValuesMonthly;
|
|
57944
|
+
if (monthlyData) {
|
|
57945
|
+
monthlyData
|
|
57946
|
+
.filter(item => item.metric === metricEnum)
|
|
57947
|
+
.forEach((item) => {
|
|
57948
|
+
if (item.value && item.date) {
|
|
57949
|
+
const month = new Date(item.date).getMonth();
|
|
57884
57950
|
data.push({
|
|
57885
|
-
date:
|
|
57886
|
-
value: parseFloat(
|
|
57951
|
+
date: new Date(currentYear, month, 15).toISOString(),
|
|
57952
|
+
value: parseFloat(item.value) || 0
|
|
57887
57953
|
});
|
|
57888
57954
|
}
|
|
57889
57955
|
});
|
|
57890
57956
|
}
|
|
57891
|
-
if (data.length === 0) {
|
|
57892
|
-
const targetValue = this.metricData()?.targetValue || 1200;
|
|
57893
|
-
const now = new Date();
|
|
57894
|
-
const currentMonth = now.getMonth();
|
|
57895
|
-
for (let i = currentMonth; i < 12; i++) {
|
|
57896
|
-
const value = targetValue * ((i + 1) / 12);
|
|
57897
|
-
data.push({
|
|
57898
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57899
|
-
value: Math.round(value * 100) / 100
|
|
57900
|
-
});
|
|
57901
|
-
}
|
|
57902
|
-
}
|
|
57903
57957
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57904
57958
|
}
|
|
57905
57959
|
formatMetricValue(value, metric, fromUiData = true) {
|
|
@@ -58046,7 +58100,7 @@ class MetricReportModalComponent {
|
|
|
58046
58100
|
: 'bg-slate-700 hover:bg-slate-600 text-white';
|
|
58047
58101
|
}
|
|
58048
58102
|
static { this.ɵfac = function MetricReportModalComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MetricReportModalComponent)(); }; }
|
|
58049
|
-
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MetricReportModalComponent, selectors: [["symphiq-metric-report-modal"]], inputs: { viewMode: [1, "viewMode"], metricEnum: [1, "metricEnum"], metricData: [1, "metricData"], contributingMetrics: [1, "contributingMetrics"], pacingMetrics: [1, "pacingMetrics"], isOpen: [1, "isOpen"] }, outputs: { closed: "closed" }, decls: 1, vars: 1, consts: [[1, "fixed", "inset-0", "overflow-y-auto", "z-50"], [1, "fixed", "inset-0", "overflow-y-auto", "z-50", 3, "click"], [1, "flex", "items-center", "justify-center", "min-h-screen", "px-4", "pt-4", "pb-20", "text-center", "sm:block", "sm:p-0"], ["aria-hidden", "true", 1, "fixed", "inset-0", "backdrop-blur-md", 3, "ngClass"], ["aria-hidden", "true", 1, "hidden", "sm:inline-block", "sm:align-middle", "sm:h-screen"], [1, "relative", "inline-block", "align-bottom", "rounded-2xl", "text-left", "overflow-hidden", "shadow-xl", "sm:my-8", "sm:align-middle", "sm:w-full", "sm:max-w-4xl", "border", "backdrop-blur-xl", 3, "click", "ngClass"], [1, "px-6", "py-5", "border-b", "backdrop-blur-sm", "sticky", "top-0", "z-10", 3, "ngClass"], [1, "flex", "items-start", "justify-between"], [1, "flex-1"], [1, "flex", "items-center", "gap-3", "mb-2"], [1, "text-xl", "font-bold", 3, "ngClass"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-7", "h-7", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", "self-center", 3, "ngClass", "libSymphiqTooltip"], [1, "ml-4", "transition-all", "rounded-lg", "p-1", "hover:scale-110", "active:scale-90", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-6", "h-6"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M6 18L18 6M6 6l12 12"], [1, "px-6", "py-6", "max-h-[70vh]", "overflow-y-auto", "backdrop-blur-sm", 3, "ngClass"], [1, "rounded-xl", "p-6", "mb-6", 3, "ngClass"], [1, "text-sm", "font-semibold", "uppercase", "tracking-wider", "mb-4", 3, "ngClass"], [1, "grid", "grid-cols-1", "sm:grid-cols-2", "lg:grid-cols-3", "gap-6"], [1, "mb-1.5"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", 3, "ngClass"], [1, "text-xs", 3, "ngClass"], [1, "text-xl", "font-bold", "mb-2", 3, "ngClass"], [3, "viewMode", "percentageChange", "metric", "priorYear", "isCompact"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-1.5", 3, "ngClass"], [1, "mb-4"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-2", 3, "ngClass"], [1, "text-3xl", "font-extrabold", "mb-3", 3, "ngClass"], [1, "text-sm", "leading-relaxed", 3, "ngClass"], [1, "rounded-xl", "p-6", 3, "ngClass"], [1, "px-6", "py-4", "border-t", 3, "ngClass"], [1, "w-full", "px-4", "py-2", "rounded-lg", "transition-all", "font-medium", "hover:scale-[1.02]", "active:scale-[0.98]", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"], [3, "viewMode", "pacingPercentage", "status", "showAsFullText", "isCompact", "showEmphasizedPercentage"], [3, "data", "viewMode"], [1, "overflow-x-auto"], [1, "w-full"], [1, "border-b", 3, "ngClass"], [1, "text-left", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "text-right", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "border-b", "transition-colors", 3, "ngClass"], [1, "py-3", "px-4"], [1, "flex", "items-center", "gap-2"], [1, "text-sm", "font-medium"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-5", "h-5", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", 3, "ngClass", "libSymphiqTooltip"], [1, "py-3", "px-4", "text-right"], [1, "text-sm", "font-semibold", 3, "ngClass"], [1, "flex", "items-center", "justify-end", "gap-2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4", "text-emerald-500"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3", "h-3"], [1, "min-h-[400px]"], [3, "chart", "showAxisLabels", "viewMode", "currencySymbol"], [1, "text-sm", "leading-relaxed", "mt-4", 3, "ngClass"]], template: function MetricReportModalComponent_Template(rf, ctx) { if (rf & 1) {
|
|
58103
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MetricReportModalComponent, selectors: [["symphiq-metric-report-modal"]], inputs: { viewMode: [1, "viewMode"], metricEnum: [1, "metricEnum"], metricData: [1, "metricData"], contributingMetrics: [1, "contributingMetrics"], pacingMetrics: [1, "pacingMetrics"], isOpen: [1, "isOpen"] }, outputs: { closed: "closed" }, decls: 1, vars: 1, consts: [[1, "fixed", "inset-0", "overflow-y-auto", "z-50"], [1, "fixed", "inset-0", "overflow-y-auto", "z-50", 3, "click"], [1, "flex", "items-center", "justify-center", "min-h-screen", "px-4", "pt-4", "pb-20", "text-center", "sm:block", "sm:p-0"], ["aria-hidden", "true", 1, "fixed", "inset-0", "backdrop-blur-md", 3, "ngClass"], ["aria-hidden", "true", 1, "hidden", "sm:inline-block", "sm:align-middle", "sm:h-screen"], [1, "relative", "inline-block", "align-bottom", "rounded-2xl", "text-left", "overflow-hidden", "shadow-xl", "sm:my-8", "sm:align-middle", "sm:w-full", "sm:max-w-4xl", "border", "backdrop-blur-xl", 3, "click", "ngClass"], [1, "px-6", "py-5", "border-b", "backdrop-blur-sm", "sticky", "top-0", "z-10", 3, "ngClass"], [1, "flex", "items-start", "justify-between"], [1, "flex-1"], [1, "flex", "items-center", "gap-3", "mb-2"], [1, "text-xl", "font-bold", 3, "ngClass"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-7", "h-7", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", "self-center", 3, "ngClass", "libSymphiqTooltip"], [1, "ml-4", "transition-all", "rounded-lg", "p-1", "hover:scale-110", "active:scale-90", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-6", "h-6"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M6 18L18 6M6 6l12 12"], [1, "px-6", "py-6", "max-h-[70vh]", "overflow-y-auto", "backdrop-blur-sm", 3, "ngClass"], [1, "rounded-xl", "p-6", "mb-6", 3, "ngClass"], [1, "text-sm", "font-semibold", "uppercase", "tracking-wider", "mb-4", 3, "ngClass"], [1, "grid", "grid-cols-1", "sm:grid-cols-2", "lg:grid-cols-3", "gap-6"], [1, "mb-1.5"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", 3, "ngClass"], [1, "text-xs", 3, "ngClass"], [1, "text-xl", "font-bold", "mb-2", 3, "ngClass"], [3, "viewMode", "percentageChange", "metric", "priorYear", "isCompact"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-1.5", 3, "ngClass"], [1, "mb-4"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-2", 3, "ngClass"], [1, "text-3xl", "font-extrabold", "mb-3", 3, "ngClass"], [1, "text-sm", "leading-relaxed", 3, "ngClass"], [1, "rounded-xl", "p-6", 3, "ngClass"], [1, "px-6", "py-4", "border-t", 3, "ngClass"], [1, "w-full", "px-4", "py-2", "rounded-lg", "transition-all", "font-medium", "hover:scale-[1.02]", "active:scale-[0.98]", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"], [3, "viewMode", "pacingPercentage", "status", "showAsFullText", "isCompact", "showEmphasizedPercentage"], [3, "data", "viewMode"], [1, "overflow-x-auto"], [1, "w-full"], [1, "border-b", 3, "ngClass"], [1, "text-left", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "text-right", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "border-b", "transition-colors", 3, "ngClass"], [1, "py-3", "px-4"], [1, "flex", "items-center", "gap-2"], [1, "text-sm", "font-medium"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-5", "h-5", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", 3, "ngClass", "libSymphiqTooltip"], [1, "py-3", "px-4", "text-right"], [1, "text-sm", "font-semibold", 3, "ngClass"], [1, "flex", "items-center", "justify-end", "gap-2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4", "text-emerald-500"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3", "h-3"], [1, "min-h-[400px]"], [3, "chart", "showAxisLabels", "viewMode", "currencySymbol"], [1, "text-sm", "leading-relaxed", "mt-4", 3, "ngClass"], [1, "text-sm", "leading-relaxed", "mt-2", 3, "ngClass"]], template: function MetricReportModalComponent_Template(rf, ctx) { if (rf & 1) {
|
|
58050
58104
|
i0.ɵɵconditionalCreate(0, MetricReportModalComponent_Conditional_0_Template, 70, 51, "div", 0);
|
|
58051
58105
|
} if (rf & 2) {
|
|
58052
58106
|
i0.ɵɵconditional(ctx.isOpen() ? 0 : -1);
|
|
@@ -58300,7 +58354,7 @@ class MetricReportModalComponent {
|
|
|
58300
58354
|
@if (contributingMetrics().length > 0) {
|
|
58301
58355
|
<div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
|
|
58302
58356
|
<h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
|
|
58303
|
-
Contributing
|
|
58357
|
+
Contributing Metric Targets
|
|
58304
58358
|
</h4>
|
|
58305
58359
|
<div class="overflow-x-auto">
|
|
58306
58360
|
<table class="w-full">
|
|
@@ -58378,7 +58432,10 @@ class MetricReportModalComponent {
|
|
|
58378
58432
|
/>
|
|
58379
58433
|
</div>
|
|
58380
58434
|
<p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-4">
|
|
58381
|
-
{{
|
|
58435
|
+
{{ chartDescriptionSentence1() }}
|
|
58436
|
+
</p>
|
|
58437
|
+
<p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
|
|
58438
|
+
{{ chartDescriptionSentence2() }}
|
|
58382
58439
|
</p>
|
|
58383
58440
|
</div>
|
|
58384
58441
|
}
|
|
@@ -58400,7 +58457,7 @@ class MetricReportModalComponent {
|
|
|
58400
58457
|
`
|
|
58401
58458
|
}]
|
|
58402
58459
|
}], null, { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], metricEnum: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricEnum", required: false }] }], metricData: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricData", required: false }] }], contributingMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "contributingMetrics", required: false }] }], pacingMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingMetrics", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] }); })();
|
|
58403
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MetricReportModalComponent, { className: "MetricReportModalComponent", filePath: "lib/components/revenue-calculator-dashboard/metric-report-modal.component.ts", lineNumber:
|
|
58460
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MetricReportModalComponent, { className: "MetricReportModalComponent", filePath: "lib/components/revenue-calculator-dashboard/metric-report-modal.component.ts", lineNumber: 346 }); })();
|
|
58404
58461
|
|
|
58405
58462
|
const _c0$q = ["absoluteInputRef"];
|
|
58406
58463
|
const _c1$b = ["percentageInputRef"];
|
|
@@ -63728,92 +63785,92 @@ class CollapsibleSectionGroupComponent {
|
|
|
63728
63785
|
standalone: true,
|
|
63729
63786
|
imports: [CommonModule, SymphiqIconComponent, ProfileSectionComponent],
|
|
63730
63787
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
63731
|
-
template: `
|
|
63732
|
-
<div [ngClass]="containerClasses()" class="rounded-2xl border shadow-lg overflow-hidden">
|
|
63733
|
-
<div [ngClass]="headerClasses()" class="px-6 py-5 border-b">
|
|
63734
|
-
<div class="flex items-center justify-between">
|
|
63735
|
-
<div class="flex items-center gap-3">
|
|
63736
|
-
<div [ngClass]="iconContainerClasses()" class="p-2.5 rounded-lg">
|
|
63737
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63738
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
|
|
63739
|
-
</svg>
|
|
63740
|
-
</div>
|
|
63741
|
-
<div>
|
|
63742
|
-
<h2 [ngClass]="titleClasses()" class="text-xl font-bold">
|
|
63743
|
-
Supporting Business Context
|
|
63744
|
-
</h2>
|
|
63745
|
-
<p [ngClass]="subtitleClasses()" class="text-sm mt-0.5">
|
|
63746
|
-
Additional insights gathered from publicly available information
|
|
63747
|
-
</p>
|
|
63748
|
-
</div>
|
|
63749
|
-
</div>
|
|
63750
|
-
</div>
|
|
63751
|
-
</div>
|
|
63752
|
-
|
|
63753
|
-
<div [ngClass]="contentClasses()" class="p-6">
|
|
63754
|
-
<div [ngClass]="infoBoxClasses()" class="mb-6 p-4 rounded-xl border flex items-start gap-3">
|
|
63755
|
-
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" [ngClass]="infoIconClasses()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63756
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
63757
|
-
</svg>
|
|
63758
|
-
<div class="flex-1">
|
|
63759
|
-
<h4 [ngClass]="infoTitleClasses()" class="font-semibold text-sm mb-1">
|
|
63760
|
-
Building Context for Better Recommendations
|
|
63761
|
-
</h4>
|
|
63762
|
-
<p [ngClass]="infoTextClasses()" class="text-sm leading-relaxed">
|
|
63763
|
-
The information below was gathered from your website and competitor research. While recommendations above are based on this initial analysis, connecting your GA4 data will provide quantitative insights that dramatically improve recommendation accuracy.
|
|
63764
|
-
</p>
|
|
63765
|
-
</div>
|
|
63766
|
-
</div>
|
|
63767
|
-
|
|
63768
|
-
<div class="space-y-3">
|
|
63769
|
-
@for (section of sections(); track section.id; let idx = $index) {
|
|
63770
|
-
<div [id]="'collapsible-section-' + idx" [ngClass]="sectionCardClasses()" class="rounded-xl border overflow-hidden transition-all duration-200">
|
|
63771
|
-
<button
|
|
63772
|
-
type="button"
|
|
63773
|
-
(click)="toggleSection(idx)"
|
|
63774
|
-
[ngClass]="sectionHeaderClasses(section, idx)"
|
|
63775
|
-
class="cursor-pointer w-full px-5 py-4 flex items-center justify-between gap-4 text-left transition-colors duration-200">
|
|
63776
|
-
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
63777
|
-
@if (section.icon) {
|
|
63778
|
-
<div [ngClass]="sectionIconContainerClasses(idx)" class="p-2 rounded-lg flex-shrink-0 transition-colors duration-200">
|
|
63779
|
-
<symphiq-icon [icon]="section.icon" size="w-4 h-4"></symphiq-icon>
|
|
63780
|
-
</div>
|
|
63781
|
-
}
|
|
63782
|
-
<div class="flex-1 min-w-0">
|
|
63783
|
-
<h3 [ngClass]="sectionTitleClasses(idx)" class="font-semibold transition-colors duration-200">
|
|
63784
|
-
{{ section.title }}
|
|
63785
|
-
</h3>
|
|
63786
|
-
<p [ngClass]="sectionDescriptionClasses(idx)" class="text-sm mt-0.5 transition-colors duration-200">
|
|
63787
|
-
{{ getSectionItemCount(section) }} items
|
|
63788
|
-
</p>
|
|
63789
|
-
</div>
|
|
63790
|
-
</div>
|
|
63791
|
-
<svg
|
|
63792
|
-
[ngClass]="chevronClasses(idx)"
|
|
63793
|
-
[class.rotate-180]="expandedSections()[idx]"
|
|
63794
|
-
class="w-5 h-5 flex-shrink-0 transition-transform duration-200">
|
|
63795
|
-
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
63796
|
-
</svg>
|
|
63797
|
-
</button>
|
|
63798
|
-
|
|
63799
|
-
<div
|
|
63800
|
-
class="grid transition-[grid-template-rows] duration-300 ease-in-out"
|
|
63801
|
-
[style.grid-template-rows]="expandedSections()[idx] ? '1fr' : '0fr'">
|
|
63802
|
-
<div class="overflow-hidden">
|
|
63803
|
-
<div [ngClass]="sectionContentClasses()" class="border-t">
|
|
63804
|
-
<symphiq-profile-section
|
|
63805
|
-
[section]="section"
|
|
63806
|
-
[viewMode]="viewMode()"
|
|
63807
|
-
[forceExpanded]="false"
|
|
63808
|
-
/>
|
|
63809
|
-
</div>
|
|
63810
|
-
</div>
|
|
63811
|
-
</div>
|
|
63812
|
-
</div>
|
|
63813
|
-
}
|
|
63814
|
-
</div>
|
|
63815
|
-
</div>
|
|
63816
|
-
</div>
|
|
63788
|
+
template: `
|
|
63789
|
+
<div [ngClass]="containerClasses()" class="rounded-2xl border shadow-lg overflow-hidden">
|
|
63790
|
+
<div [ngClass]="headerClasses()" class="px-6 py-5 border-b">
|
|
63791
|
+
<div class="flex items-center justify-between">
|
|
63792
|
+
<div class="flex items-center gap-3">
|
|
63793
|
+
<div [ngClass]="iconContainerClasses()" class="p-2.5 rounded-lg">
|
|
63794
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63795
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
|
|
63796
|
+
</svg>
|
|
63797
|
+
</div>
|
|
63798
|
+
<div>
|
|
63799
|
+
<h2 [ngClass]="titleClasses()" class="text-xl font-bold">
|
|
63800
|
+
Supporting Business Context
|
|
63801
|
+
</h2>
|
|
63802
|
+
<p [ngClass]="subtitleClasses()" class="text-sm mt-0.5">
|
|
63803
|
+
Additional insights gathered from publicly available information
|
|
63804
|
+
</p>
|
|
63805
|
+
</div>
|
|
63806
|
+
</div>
|
|
63807
|
+
</div>
|
|
63808
|
+
</div>
|
|
63809
|
+
|
|
63810
|
+
<div [ngClass]="contentClasses()" class="p-6">
|
|
63811
|
+
<div [ngClass]="infoBoxClasses()" class="mb-6 p-4 rounded-xl border flex items-start gap-3">
|
|
63812
|
+
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" [ngClass]="infoIconClasses()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63813
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
63814
|
+
</svg>
|
|
63815
|
+
<div class="flex-1">
|
|
63816
|
+
<h4 [ngClass]="infoTitleClasses()" class="font-semibold text-sm mb-1">
|
|
63817
|
+
Building Context for Better Recommendations
|
|
63818
|
+
</h4>
|
|
63819
|
+
<p [ngClass]="infoTextClasses()" class="text-sm leading-relaxed">
|
|
63820
|
+
The information below was gathered from your website and competitor research. While recommendations above are based on this initial analysis, connecting your GA4 data will provide quantitative insights that dramatically improve recommendation accuracy.
|
|
63821
|
+
</p>
|
|
63822
|
+
</div>
|
|
63823
|
+
</div>
|
|
63824
|
+
|
|
63825
|
+
<div class="space-y-3">
|
|
63826
|
+
@for (section of sections(); track section.id; let idx = $index) {
|
|
63827
|
+
<div [id]="'collapsible-section-' + idx" [ngClass]="sectionCardClasses()" class="rounded-xl border overflow-hidden transition-all duration-200">
|
|
63828
|
+
<button
|
|
63829
|
+
type="button"
|
|
63830
|
+
(click)="toggleSection(idx)"
|
|
63831
|
+
[ngClass]="sectionHeaderClasses(section, idx)"
|
|
63832
|
+
class="cursor-pointer w-full px-5 py-4 flex items-center justify-between gap-4 text-left transition-colors duration-200">
|
|
63833
|
+
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
63834
|
+
@if (section.icon) {
|
|
63835
|
+
<div [ngClass]="sectionIconContainerClasses(idx)" class="p-2 rounded-lg flex-shrink-0 transition-colors duration-200">
|
|
63836
|
+
<symphiq-icon [icon]="section.icon" size="w-4 h-4"></symphiq-icon>
|
|
63837
|
+
</div>
|
|
63838
|
+
}
|
|
63839
|
+
<div class="flex-1 min-w-0">
|
|
63840
|
+
<h3 [ngClass]="sectionTitleClasses(idx)" class="font-semibold transition-colors duration-200">
|
|
63841
|
+
{{ section.title }}
|
|
63842
|
+
</h3>
|
|
63843
|
+
<p [ngClass]="sectionDescriptionClasses(idx)" class="text-sm mt-0.5 transition-colors duration-200">
|
|
63844
|
+
{{ getSectionItemCount(section) }} items
|
|
63845
|
+
</p>
|
|
63846
|
+
</div>
|
|
63847
|
+
</div>
|
|
63848
|
+
<svg
|
|
63849
|
+
[ngClass]="chevronClasses(idx)"
|
|
63850
|
+
[class.rotate-180]="expandedSections()[idx]"
|
|
63851
|
+
class="w-5 h-5 flex-shrink-0 transition-transform duration-200">
|
|
63852
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
63853
|
+
</svg>
|
|
63854
|
+
</button>
|
|
63855
|
+
|
|
63856
|
+
<div
|
|
63857
|
+
class="grid transition-[grid-template-rows] duration-300 ease-in-out"
|
|
63858
|
+
[style.grid-template-rows]="expandedSections()[idx] ? '1fr' : '0fr'">
|
|
63859
|
+
<div class="overflow-hidden">
|
|
63860
|
+
<div [ngClass]="sectionContentClasses()" class="border-t">
|
|
63861
|
+
<symphiq-profile-section
|
|
63862
|
+
[section]="section"
|
|
63863
|
+
[viewMode]="viewMode()"
|
|
63864
|
+
[forceExpanded]="false"
|
|
63865
|
+
/>
|
|
63866
|
+
</div>
|
|
63867
|
+
</div>
|
|
63868
|
+
</div>
|
|
63869
|
+
</div>
|
|
63870
|
+
}
|
|
63871
|
+
</div>
|
|
63872
|
+
</div>
|
|
63873
|
+
</div>
|
|
63817
63874
|
`
|
|
63818
63875
|
}]
|
|
63819
63876
|
}], null, { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }] }); })();
|