@eric-emg/symphiq-components 1.2.247 → 1.2.249
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 +1341 -1288
- package/fesm2022/symphiq-components.mjs.map +1 -1
- package/index.d.ts +61 -51
- 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;
|
|
@@ -56705,8 +56759,7 @@ class LineChartComponent {
|
|
|
56705
56759
|
// Check for explicit keywords
|
|
56706
56760
|
if (name.includes('last year') ||
|
|
56707
56761
|
name.includes('prior year') ||
|
|
56708
|
-
name.includes('previous year')
|
|
56709
|
-
name.includes('comparison')) {
|
|
56762
|
+
name.includes('previous year')) {
|
|
56710
56763
|
return true;
|
|
56711
56764
|
}
|
|
56712
56765
|
// Check for year patterns - extract any 4-digit year and compare to current year
|
|
@@ -56717,13 +56770,6 @@ class LineChartComponent {
|
|
|
56717
56770
|
}
|
|
56718
56771
|
return false;
|
|
56719
56772
|
}
|
|
56720
|
-
isProjectionSeries(seriesData) {
|
|
56721
|
-
if (!seriesData || !seriesData.name) {
|
|
56722
|
-
return false;
|
|
56723
|
-
}
|
|
56724
|
-
const name = seriesData.name.toLowerCase();
|
|
56725
|
-
return name.includes('projection') || name.includes('projected') || name.includes('target');
|
|
56726
|
-
}
|
|
56727
56773
|
extractMetricName(seriesName) {
|
|
56728
56774
|
// Extract metric name from series name by removing year patterns
|
|
56729
56775
|
// e.g., "Purchase Revenue (2025)" -> "Purchase Revenue"
|
|
@@ -56924,8 +56970,6 @@ class LineChartComponent {
|
|
|
56924
56970
|
const seriesColor = color(seriesColorValue);
|
|
56925
56971
|
// Check if this is a prior year series for YoY charts
|
|
56926
56972
|
const isPriorYear = isYoYChart && this.isPriorYearSeries(seriesData);
|
|
56927
|
-
const isProjection = this.isProjectionSeries(seriesData);
|
|
56928
|
-
console.log('[LineChart] Series:', seriesData.name, { isPriorYear, isProjection, isYoYChart, dataPoints: parsedData.length });
|
|
56929
56973
|
if (!this.chartElement || !this.root)
|
|
56930
56974
|
return;
|
|
56931
56975
|
const series = this.chartElement.series.push(LineSeries.new(this.root, {
|
|
@@ -56937,7 +56981,7 @@ class LineChartComponent {
|
|
|
56937
56981
|
stroke: seriesColor
|
|
56938
56982
|
}));
|
|
56939
56983
|
// Store valueFormat and prior year flag in userData for tooltip formatting
|
|
56940
|
-
series.set('userData', { valueFormat: seriesData.valueFormat, isPriorYear
|
|
56984
|
+
series.set('userData', { valueFormat: seriesData.valueFormat, isPriorYear });
|
|
56941
56985
|
// Disable individual series tooltips - use floating tooltip instead
|
|
56942
56986
|
series.set('tooltip', undefined);
|
|
56943
56987
|
// Configure stroke styling based on series type
|
|
@@ -56955,16 +56999,6 @@ class LineChartComponent {
|
|
|
56955
56999
|
stroke.set('strokeOpacity', 0.5);
|
|
56956
57000
|
});
|
|
56957
57001
|
}
|
|
56958
|
-
else if (isProjection) {
|
|
56959
|
-
// Apply dotted line for projection data
|
|
56960
|
-
series.strokes.template.setAll({
|
|
56961
|
-
strokeDasharray: [10, 5],
|
|
56962
|
-
strokeWidth: 3
|
|
56963
|
-
});
|
|
56964
|
-
series.strokes.each((stroke) => {
|
|
56965
|
-
stroke.set('strokeDasharray', [10, 5]);
|
|
56966
|
-
});
|
|
56967
|
-
}
|
|
56968
57002
|
// Add bullets with larger hit area for better hover detection
|
|
56969
57003
|
series.bullets.push(() => {
|
|
56970
57004
|
const bulletConfig = {
|
|
@@ -57018,10 +57052,10 @@ class LineChartComponent {
|
|
|
57018
57052
|
}
|
|
57019
57053
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LineChartComponent, [{
|
|
57020
57054
|
type: Component,
|
|
57021
|
-
args: [{ selector: 'symphiq-line-chart', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57022
|
-
<div class="chart-container" [class.mini-mode]="!showAxisLabels()">
|
|
57023
|
-
<div #chartdiv class="chart" [style.height]="chartHeight()" style="width: 100%;"></div>
|
|
57024
|
-
</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>
|
|
57025
57059
|
`, styles: [".chart-container{width:100%;padding:1rem}.chart-container.mini-mode{padding:.25rem}\n"] }]
|
|
57026
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: [{
|
|
57027
57061
|
type: ViewChild,
|
|
@@ -57110,6 +57144,10 @@ class ProgressToTargetChartComponent {
|
|
|
57110
57144
|
return;
|
|
57111
57145
|
this.chart.series.clear();
|
|
57112
57146
|
this.xAxis.axisRanges.clear();
|
|
57147
|
+
if (this.legend) {
|
|
57148
|
+
this.legend.dispose();
|
|
57149
|
+
this.legend = undefined;
|
|
57150
|
+
}
|
|
57113
57151
|
this.buildChart(chartData);
|
|
57114
57152
|
}
|
|
57115
57153
|
buildChart(chartData) {
|
|
@@ -57216,15 +57254,15 @@ class ProgressToTargetChartComponent {
|
|
|
57216
57254
|
dy: -18,
|
|
57217
57255
|
fill: this.labelColor()
|
|
57218
57256
|
});
|
|
57219
|
-
|
|
57257
|
+
this.legend = this.chart.children.push(Legend.new(this.root, {
|
|
57220
57258
|
centerX: p50,
|
|
57221
57259
|
x: p50,
|
|
57222
57260
|
marginTop: 8
|
|
57223
57261
|
}));
|
|
57224
|
-
legend.labels.template.setAll({
|
|
57262
|
+
this.legend.labels.template.setAll({
|
|
57225
57263
|
fill: this.labelColor()
|
|
57226
57264
|
});
|
|
57227
|
-
legend.data.setAll(this.chart.series.values.slice().reverse());
|
|
57265
|
+
this.legend.data.setAll(this.chart.series.values.slice().reverse());
|
|
57228
57266
|
this.chart.appear(1000, 100);
|
|
57229
57267
|
paceSeries.appear();
|
|
57230
57268
|
currentSeries.appear();
|
|
@@ -57289,20 +57327,20 @@ class ProgressToTargetChartComponent {
|
|
|
57289
57327
|
i0.ɵɵdomElementStart(0, "div", 1);
|
|
57290
57328
|
i0.ɵɵdomElement(1, "div", 2, 0);
|
|
57291
57329
|
i0.ɵɵdomElementEnd();
|
|
57292
|
-
} }, dependencies: [CommonModule], styles: [".progress-chart-container[_ngcontent-%COMP%]{width:100%}"], changeDetection: 0 }); }
|
|
57330
|
+
} }, dependencies: [CommonModule], styles: [".progress-chart-container[_ngcontent-%COMP%]{width:100%;margin-top:50px;overflow:visible}.chart[_ngcontent-%COMP%]{overflow:visible}"], changeDetection: 0 }); }
|
|
57293
57331
|
}
|
|
57294
57332
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ProgressToTargetChartComponent, [{
|
|
57295
57333
|
type: Component,
|
|
57296
|
-
args: [{ selector: 'symphiq-progress-to-target-chart', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
57297
|
-
<div class="progress-chart-container">
|
|
57298
|
-
<div #chartdiv class="chart" style="width: 100%; height: 160px;"></div>
|
|
57299
|
-
</div>
|
|
57300
|
-
`, 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:50px;overflow:visible}.chart{overflow:visible}\n"] }]
|
|
57301
57339
|
}], () => [], { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], chartDiv: [{
|
|
57302
57340
|
type: ViewChild,
|
|
57303
57341
|
args: ['chartdiv', { static: true }]
|
|
57304
57342
|
}] }); })();
|
|
57305
|
-
(() => { (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: 66 }); })();
|
|
57306
57344
|
|
|
57307
57345
|
const _forTrack0$i = ($index, $item) => $item.metric;
|
|
57308
57346
|
function MetricReportModalComponent_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -57410,7 +57448,7 @@ function MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Template
|
|
|
57410
57448
|
} }
|
|
57411
57449
|
function MetricReportModalComponent_Conditional_0_Conditional_65_Template(rf, ctx) { if (rf & 1) {
|
|
57412
57450
|
i0.ɵɵelementStart(0, "div", 16)(1, "h4", 17);
|
|
57413
|
-
i0.ɵɵtext(2, " Contributing
|
|
57451
|
+
i0.ɵɵtext(2, " Contributing Metric Targets ");
|
|
57414
57452
|
i0.ɵɵelementEnd();
|
|
57415
57453
|
i0.ɵɵelementStart(3, "div", 36)(4, "table", 37)(5, "thead")(6, "tr", 38)(7, "th", 39);
|
|
57416
57454
|
i0.ɵɵtext(8, "Metric");
|
|
@@ -57443,6 +57481,12 @@ function MetricReportModalComponent_Conditional_0_Conditional_66_Template(rf, ct
|
|
|
57443
57481
|
i0.ɵɵelementEnd();
|
|
57444
57482
|
i0.ɵɵelementStart(5, "p", 54);
|
|
57445
57483
|
i0.ɵɵtext(6);
|
|
57484
|
+
i0.ɵɵelementEnd();
|
|
57485
|
+
i0.ɵɵelementStart(7, "p", 55);
|
|
57486
|
+
i0.ɵɵtext(8);
|
|
57487
|
+
i0.ɵɵelementEnd();
|
|
57488
|
+
i0.ɵɵelementStart(9, "p", 55);
|
|
57489
|
+
i0.ɵɵtext(10);
|
|
57446
57490
|
i0.ɵɵelementEnd()();
|
|
57447
57491
|
} if (rf & 2) {
|
|
57448
57492
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -57454,7 +57498,15 @@ function MetricReportModalComponent_Conditional_0_Conditional_66_Template(rf, ct
|
|
|
57454
57498
|
i0.ɵɵadvance();
|
|
57455
57499
|
i0.ɵɵproperty("ngClass", ctx_r1.descriptionClasses());
|
|
57456
57500
|
i0.ɵɵadvance();
|
|
57457
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.
|
|
57501
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.chartLegendDescription(), " ");
|
|
57502
|
+
i0.ɵɵadvance();
|
|
57503
|
+
i0.ɵɵproperty("ngClass", ctx_r1.descriptionClasses());
|
|
57504
|
+
i0.ɵɵadvance();
|
|
57505
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.chartDescriptionSentence1(), " ");
|
|
57506
|
+
i0.ɵɵadvance();
|
|
57507
|
+
i0.ɵɵproperty("ngClass", ctx_r1.descriptionClasses());
|
|
57508
|
+
i0.ɵɵadvance();
|
|
57509
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.chartDescriptionSentence2(), " ");
|
|
57458
57510
|
} }
|
|
57459
57511
|
function MetricReportModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
57460
57512
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -57538,7 +57590,7 @@ function MetricReportModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
|
|
|
57538
57590
|
i0.ɵɵconditionalCreate(64, MetricReportModalComponent_Conditional_0_Conditional_64_Template, 6, 10);
|
|
57539
57591
|
i0.ɵɵelementEnd();
|
|
57540
57592
|
i0.ɵɵconditionalCreate(65, MetricReportModalComponent_Conditional_0_Conditional_65_Template, 16, 3, "div", 16);
|
|
57541
|
-
i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template,
|
|
57593
|
+
i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template, 11, 12, "div", 29);
|
|
57542
57594
|
i0.ɵɵelementEnd();
|
|
57543
57595
|
i0.ɵɵelementStart(67, "div", 30)(68, "button", 31);
|
|
57544
57596
|
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()); });
|
|
@@ -57701,6 +57753,18 @@ class MetricReportModalComponent {
|
|
|
57701
57753
|
}
|
|
57702
57754
|
return 0;
|
|
57703
57755
|
}, ...(ngDevMode ? [{ debugName: "samePeriodLastYearValue" }] : []));
|
|
57756
|
+
this.fullYearLastYearValue = computed(() => {
|
|
57757
|
+
const pacingResponse = this.pacingMetrics();
|
|
57758
|
+
const metric = this.metricData();
|
|
57759
|
+
if (!pacingResponse || !metric)
|
|
57760
|
+
return 0;
|
|
57761
|
+
const monthlyData = pacingResponse.lastYearMetricValuesMonthly;
|
|
57762
|
+
if (!monthlyData)
|
|
57763
|
+
return 0;
|
|
57764
|
+
return monthlyData
|
|
57765
|
+
.filter(item => item.metric === metric.metric)
|
|
57766
|
+
.reduce((total, item) => total + (parseFloat(item.value || '0') || 0), 0);
|
|
57767
|
+
}, ...(ngDevMode ? [{ debugName: "fullYearLastYearValue" }] : []));
|
|
57704
57768
|
this.ytdChangePercentage = computed(() => {
|
|
57705
57769
|
const current = this.ytdValue();
|
|
57706
57770
|
const lastYear = this.samePeriodLastYearValue();
|
|
@@ -57794,12 +57858,29 @@ class MetricReportModalComponent {
|
|
|
57794
57858
|
status: pacing.status
|
|
57795
57859
|
};
|
|
57796
57860
|
}, ...(ngDevMode ? [{ debugName: "progressToTargetData" }] : []));
|
|
57797
|
-
this.
|
|
57861
|
+
this.chartLegendDescription = computed(() => {
|
|
57798
57862
|
const metric = this.metricTitle();
|
|
57799
57863
|
const currentYear = this.currentYear();
|
|
57800
57864
|
const priorYear = this.priorYear();
|
|
57801
57865
|
return `This chart shows the ${metric} performance trend for ${currentYear} (solid line), compared to ${priorYear} (dashed line), with the target projection (dotted line) for the remainder of the year.`;
|
|
57802
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
57866
|
+
}, ...(ngDevMode ? [{ debugName: "chartLegendDescription" }] : []));
|
|
57867
|
+
this.chartDescriptionSentence1 = computed(() => {
|
|
57868
|
+
const metricData = this.metricData();
|
|
57869
|
+
const metricName = this.metricTitle().toLowerCase();
|
|
57870
|
+
const startDate = this.ytdStartDate();
|
|
57871
|
+
const endDate = this.ytdEndDate();
|
|
57872
|
+
const ytdValue = this.formatMetricValue(this.ytdValue(), metricData?.metric || '');
|
|
57873
|
+
const samePeriodLastYear = this.formatMetricValue(this.samePeriodLastYearValue(), metricData?.metric || '');
|
|
57874
|
+
const priorYear = this.priorYear();
|
|
57875
|
+
return `For the period (${startDate} - ${endDate}) you had ${ytdValue} ${metricName}, compared to ${samePeriodLastYear} for the same period in ${priorYear}.`;
|
|
57876
|
+
}, ...(ngDevMode ? [{ debugName: "chartDescriptionSentence1" }] : []));
|
|
57877
|
+
this.chartDescriptionSentence2 = computed(() => {
|
|
57878
|
+
const metricData = this.metricData();
|
|
57879
|
+
const metricName = this.metricTitle().toLowerCase();
|
|
57880
|
+
const projectedValue = this.formatMetricValue(this.pacingInfo()?.projectedValue || 0, metricData?.metric || '');
|
|
57881
|
+
const fullYearLastYear = this.formatMetricValue(this.fullYearLastYearValue(), metricData?.metric || '');
|
|
57882
|
+
return `By maintaining this pace, your ${metricName} could increase to ${projectedValue} compared to ${fullYearLastYear} last year.`;
|
|
57883
|
+
}, ...(ngDevMode ? [{ debugName: "chartDescriptionSentence2" }] : []));
|
|
57803
57884
|
this.pacingChartData = computed(() => {
|
|
57804
57885
|
const metric = this.metricData();
|
|
57805
57886
|
const pacingResponse = this.pacingMetrics();
|
|
@@ -57808,16 +57889,10 @@ class MetricReportModalComponent {
|
|
|
57808
57889
|
const currentYearData = this.generateCurrentYearData(pacingResponse, metric.metric);
|
|
57809
57890
|
const priorYearData = this.generatePriorYearData(pacingResponse, metric.metric);
|
|
57810
57891
|
const projectionData = this.generateProjectionData(pacingResponse, metric.metric);
|
|
57811
|
-
console.log('[PaceChart] Metric:', metric.metric);
|
|
57812
|
-
console.log('[PaceChart] Current Year Data:', currentYearData);
|
|
57813
|
-
console.log('[PaceChart] Prior Year Data:', priorYearData);
|
|
57814
|
-
console.log('[PaceChart] Projection Data:', projectionData);
|
|
57815
|
-
console.log('[PaceChart] Pacing Response:', pacingResponse);
|
|
57816
57892
|
return {
|
|
57817
57893
|
chartType: 'LINE',
|
|
57818
57894
|
title: 'Pace',
|
|
57819
57895
|
description: '',
|
|
57820
|
-
lineChartUseCase: LineChartUseCaseEnum.THIS_YEAR_VS_LAST_YEAR,
|
|
57821
57896
|
lineChartData: {
|
|
57822
57897
|
series: [
|
|
57823
57898
|
{
|
|
@@ -57845,86 +57920,58 @@ class MetricReportModalComponent {
|
|
|
57845
57920
|
generateCurrentYearData(pacingResponse, metricEnum) {
|
|
57846
57921
|
const data = [];
|
|
57847
57922
|
const currentYear = this.currentYear();
|
|
57848
|
-
|
|
57849
|
-
|
|
57850
|
-
|
|
57851
|
-
|
|
57852
|
-
|
|
57923
|
+
const monthlyData = pacingResponse?.soFarMetricValuesMonthly;
|
|
57924
|
+
if (monthlyData) {
|
|
57925
|
+
monthlyData
|
|
57926
|
+
.filter(item => item.metric === metricEnum)
|
|
57927
|
+
.forEach((item) => {
|
|
57928
|
+
if (item.value && item.date) {
|
|
57929
|
+
const month = new Date(item.date).getMonth();
|
|
57853
57930
|
data.push({
|
|
57854
|
-
date: this.formatDateForChart(currentYear,
|
|
57855
|
-
value: parseFloat(
|
|
57931
|
+
date: this.formatDateForChart(currentYear, month, 15),
|
|
57932
|
+
value: parseFloat(item.value) || 0
|
|
57856
57933
|
});
|
|
57857
57934
|
}
|
|
57858
57935
|
});
|
|
57859
57936
|
}
|
|
57860
|
-
if (data.length === 0) {
|
|
57861
|
-
const baseValue = this.metricData()?.currentValue || 1000;
|
|
57862
|
-
const now = new Date();
|
|
57863
|
-
const currentMonth = now.getMonth();
|
|
57864
|
-
for (let i = 0; i <= currentMonth; i++) {
|
|
57865
|
-
const value = baseValue * ((i + 1) / 12);
|
|
57866
|
-
data.push({
|
|
57867
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57868
|
-
value: Math.round(value * 100) / 100
|
|
57869
|
-
});
|
|
57870
|
-
}
|
|
57871
|
-
}
|
|
57872
57937
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57873
57938
|
}
|
|
57874
57939
|
generatePriorYearData(pacingResponse, metricEnum) {
|
|
57875
57940
|
const data = [];
|
|
57876
57941
|
const currentYear = this.currentYear();
|
|
57877
|
-
|
|
57878
|
-
|
|
57879
|
-
|
|
57880
|
-
|
|
57881
|
-
|
|
57942
|
+
const monthlyData = pacingResponse?.lastYearMetricValuesMonthly;
|
|
57943
|
+
if (monthlyData) {
|
|
57944
|
+
monthlyData
|
|
57945
|
+
.filter(item => item.metric === metricEnum)
|
|
57946
|
+
.forEach((item) => {
|
|
57947
|
+
if (item.value && item.date) {
|
|
57948
|
+
const month = new Date(item.date).getMonth();
|
|
57882
57949
|
data.push({
|
|
57883
|
-
date: this.formatDateForChart(currentYear,
|
|
57884
|
-
value: parseFloat(
|
|
57950
|
+
date: this.formatDateForChart(currentYear, month, 15),
|
|
57951
|
+
value: parseFloat(item.value) || 0
|
|
57885
57952
|
});
|
|
57886
57953
|
}
|
|
57887
57954
|
});
|
|
57888
57955
|
}
|
|
57889
|
-
if (data.length === 0) {
|
|
57890
|
-
const baseValue = this.metricData()?.currentValue || 1000;
|
|
57891
|
-
for (let i = 0; i < 12; i++) {
|
|
57892
|
-
const value = baseValue * ((i + 1) / 12) * 0.9;
|
|
57893
|
-
data.push({
|
|
57894
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57895
|
-
value: Math.round(value * 100) / 100
|
|
57896
|
-
});
|
|
57897
|
-
}
|
|
57898
|
-
}
|
|
57899
57956
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57900
57957
|
}
|
|
57901
57958
|
generateProjectionData(pacingResponse, metricEnum) {
|
|
57902
57959
|
const data = [];
|
|
57903
57960
|
const currentYear = this.currentYear();
|
|
57904
|
-
|
|
57905
|
-
|
|
57906
|
-
|
|
57907
|
-
|
|
57908
|
-
|
|
57961
|
+
const monthlyData = pacingResponse?.projectedMetricValuesMonthly;
|
|
57962
|
+
if (monthlyData) {
|
|
57963
|
+
monthlyData
|
|
57964
|
+
.filter(item => item.metric === metricEnum)
|
|
57965
|
+
.forEach((item) => {
|
|
57966
|
+
if (item.value && item.date) {
|
|
57967
|
+
const month = new Date(item.date).getMonth();
|
|
57909
57968
|
data.push({
|
|
57910
|
-
date: this.formatDateForChart(currentYear,
|
|
57911
|
-
value: parseFloat(
|
|
57969
|
+
date: this.formatDateForChart(currentYear, month, 15),
|
|
57970
|
+
value: parseFloat(item.value) || 0
|
|
57912
57971
|
});
|
|
57913
57972
|
}
|
|
57914
57973
|
});
|
|
57915
57974
|
}
|
|
57916
|
-
if (data.length === 0) {
|
|
57917
|
-
const targetValue = this.metricData()?.targetValue || 1200;
|
|
57918
|
-
const now = new Date();
|
|
57919
|
-
const currentMonth = now.getMonth();
|
|
57920
|
-
for (let i = currentMonth; i < 12; i++) {
|
|
57921
|
-
const value = targetValue * ((i + 1) / 12);
|
|
57922
|
-
data.push({
|
|
57923
|
-
date: this.formatDateForChart(currentYear, i, 15),
|
|
57924
|
-
value: Math.round(value * 100) / 100
|
|
57925
|
-
});
|
|
57926
|
-
}
|
|
57927
|
-
}
|
|
57928
57975
|
return data.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
57929
57976
|
}
|
|
57930
57977
|
formatMetricValue(value, metric, fromUiData = true) {
|
|
@@ -58071,7 +58118,7 @@ class MetricReportModalComponent {
|
|
|
58071
58118
|
: 'bg-slate-700 hover:bg-slate-600 text-white';
|
|
58072
58119
|
}
|
|
58073
58120
|
static { this.ɵfac = function MetricReportModalComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MetricReportModalComponent)(); }; }
|
|
58074
|
-
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) {
|
|
58121
|
+
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) {
|
|
58075
58122
|
i0.ɵɵconditionalCreate(0, MetricReportModalComponent_Conditional_0_Template, 70, 51, "div", 0);
|
|
58076
58123
|
} if (rf & 2) {
|
|
58077
58124
|
i0.ɵɵconditional(ctx.isOpen() ? 0 : -1);
|
|
@@ -58325,7 +58372,7 @@ class MetricReportModalComponent {
|
|
|
58325
58372
|
@if (contributingMetrics().length > 0) {
|
|
58326
58373
|
<div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
|
|
58327
58374
|
<h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
|
|
58328
|
-
Contributing
|
|
58375
|
+
Contributing Metric Targets
|
|
58329
58376
|
</h4>
|
|
58330
58377
|
<div class="overflow-x-auto">
|
|
58331
58378
|
<table class="w-full">
|
|
@@ -58403,7 +58450,13 @@ class MetricReportModalComponent {
|
|
|
58403
58450
|
/>
|
|
58404
58451
|
</div>
|
|
58405
58452
|
<p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-4">
|
|
58406
|
-
{{
|
|
58453
|
+
{{ chartLegendDescription() }}
|
|
58454
|
+
</p>
|
|
58455
|
+
<p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
|
|
58456
|
+
{{ chartDescriptionSentence1() }}
|
|
58457
|
+
</p>
|
|
58458
|
+
<p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
|
|
58459
|
+
{{ chartDescriptionSentence2() }}
|
|
58407
58460
|
</p>
|
|
58408
58461
|
</div>
|
|
58409
58462
|
}
|
|
@@ -58425,7 +58478,7 @@ class MetricReportModalComponent {
|
|
|
58425
58478
|
`
|
|
58426
58479
|
}]
|
|
58427
58480
|
}], 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"] }] }); })();
|
|
58428
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MetricReportModalComponent, { className: "MetricReportModalComponent", filePath: "lib/components/revenue-calculator-dashboard/metric-report-modal.component.ts", lineNumber:
|
|
58481
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MetricReportModalComponent, { className: "MetricReportModalComponent", filePath: "lib/components/revenue-calculator-dashboard/metric-report-modal.component.ts", lineNumber: 349 }); })();
|
|
58429
58482
|
|
|
58430
58483
|
const _c0$q = ["absoluteInputRef"];
|
|
58431
58484
|
const _c1$b = ["percentageInputRef"];
|
|
@@ -63753,92 +63806,92 @@ class CollapsibleSectionGroupComponent {
|
|
|
63753
63806
|
standalone: true,
|
|
63754
63807
|
imports: [CommonModule, SymphiqIconComponent, ProfileSectionComponent],
|
|
63755
63808
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
63756
|
-
template: `
|
|
63757
|
-
<div [ngClass]="containerClasses()" class="rounded-2xl border shadow-lg overflow-hidden">
|
|
63758
|
-
<div [ngClass]="headerClasses()" class="px-6 py-5 border-b">
|
|
63759
|
-
<div class="flex items-center justify-between">
|
|
63760
|
-
<div class="flex items-center gap-3">
|
|
63761
|
-
<div [ngClass]="iconContainerClasses()" class="p-2.5 rounded-lg">
|
|
63762
|
-
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63763
|
-
<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>
|
|
63764
|
-
</svg>
|
|
63765
|
-
</div>
|
|
63766
|
-
<div>
|
|
63767
|
-
<h2 [ngClass]="titleClasses()" class="text-xl font-bold">
|
|
63768
|
-
Supporting Business Context
|
|
63769
|
-
</h2>
|
|
63770
|
-
<p [ngClass]="subtitleClasses()" class="text-sm mt-0.5">
|
|
63771
|
-
Additional insights gathered from publicly available information
|
|
63772
|
-
</p>
|
|
63773
|
-
</div>
|
|
63774
|
-
</div>
|
|
63775
|
-
</div>
|
|
63776
|
-
</div>
|
|
63777
|
-
|
|
63778
|
-
<div [ngClass]="contentClasses()" class="p-6">
|
|
63779
|
-
<div [ngClass]="infoBoxClasses()" class="mb-6 p-4 rounded-xl border flex items-start gap-3">
|
|
63780
|
-
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" [ngClass]="infoIconClasses()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63781
|
-
<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>
|
|
63782
|
-
</svg>
|
|
63783
|
-
<div class="flex-1">
|
|
63784
|
-
<h4 [ngClass]="infoTitleClasses()" class="font-semibold text-sm mb-1">
|
|
63785
|
-
Building Context for Better Recommendations
|
|
63786
|
-
</h4>
|
|
63787
|
-
<p [ngClass]="infoTextClasses()" class="text-sm leading-relaxed">
|
|
63788
|
-
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.
|
|
63789
|
-
</p>
|
|
63790
|
-
</div>
|
|
63791
|
-
</div>
|
|
63792
|
-
|
|
63793
|
-
<div class="space-y-3">
|
|
63794
|
-
@for (section of sections(); track section.id; let idx = $index) {
|
|
63795
|
-
<div [id]="'collapsible-section-' + idx" [ngClass]="sectionCardClasses()" class="rounded-xl border overflow-hidden transition-all duration-200">
|
|
63796
|
-
<button
|
|
63797
|
-
type="button"
|
|
63798
|
-
(click)="toggleSection(idx)"
|
|
63799
|
-
[ngClass]="sectionHeaderClasses(section, idx)"
|
|
63800
|
-
class="cursor-pointer w-full px-5 py-4 flex items-center justify-between gap-4 text-left transition-colors duration-200">
|
|
63801
|
-
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
63802
|
-
@if (section.icon) {
|
|
63803
|
-
<div [ngClass]="sectionIconContainerClasses(idx)" class="p-2 rounded-lg flex-shrink-0 transition-colors duration-200">
|
|
63804
|
-
<symphiq-icon [icon]="section.icon" size="w-4 h-4"></symphiq-icon>
|
|
63805
|
-
</div>
|
|
63806
|
-
}
|
|
63807
|
-
<div class="flex-1 min-w-0">
|
|
63808
|
-
<h3 [ngClass]="sectionTitleClasses(idx)" class="font-semibold transition-colors duration-200">
|
|
63809
|
-
{{ section.title }}
|
|
63810
|
-
</h3>
|
|
63811
|
-
<p [ngClass]="sectionDescriptionClasses(idx)" class="text-sm mt-0.5 transition-colors duration-200">
|
|
63812
|
-
{{ getSectionItemCount(section) }} items
|
|
63813
|
-
</p>
|
|
63814
|
-
</div>
|
|
63815
|
-
</div>
|
|
63816
|
-
<svg
|
|
63817
|
-
[ngClass]="chevronClasses(idx)"
|
|
63818
|
-
[class.rotate-180]="expandedSections()[idx]"
|
|
63819
|
-
class="w-5 h-5 flex-shrink-0 transition-transform duration-200">
|
|
63820
|
-
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
63821
|
-
</svg>
|
|
63822
|
-
</button>
|
|
63823
|
-
|
|
63824
|
-
<div
|
|
63825
|
-
class="grid transition-[grid-template-rows] duration-300 ease-in-out"
|
|
63826
|
-
[style.grid-template-rows]="expandedSections()[idx] ? '1fr' : '0fr'">
|
|
63827
|
-
<div class="overflow-hidden">
|
|
63828
|
-
<div [ngClass]="sectionContentClasses()" class="border-t">
|
|
63829
|
-
<symphiq-profile-section
|
|
63830
|
-
[section]="section"
|
|
63831
|
-
[viewMode]="viewMode()"
|
|
63832
|
-
[forceExpanded]="false"
|
|
63833
|
-
/>
|
|
63834
|
-
</div>
|
|
63835
|
-
</div>
|
|
63836
|
-
</div>
|
|
63837
|
-
</div>
|
|
63838
|
-
}
|
|
63839
|
-
</div>
|
|
63840
|
-
</div>
|
|
63841
|
-
</div>
|
|
63809
|
+
template: `
|
|
63810
|
+
<div [ngClass]="containerClasses()" class="rounded-2xl border shadow-lg overflow-hidden">
|
|
63811
|
+
<div [ngClass]="headerClasses()" class="px-6 py-5 border-b">
|
|
63812
|
+
<div class="flex items-center justify-between">
|
|
63813
|
+
<div class="flex items-center gap-3">
|
|
63814
|
+
<div [ngClass]="iconContainerClasses()" class="p-2.5 rounded-lg">
|
|
63815
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63816
|
+
<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>
|
|
63817
|
+
</svg>
|
|
63818
|
+
</div>
|
|
63819
|
+
<div>
|
|
63820
|
+
<h2 [ngClass]="titleClasses()" class="text-xl font-bold">
|
|
63821
|
+
Supporting Business Context
|
|
63822
|
+
</h2>
|
|
63823
|
+
<p [ngClass]="subtitleClasses()" class="text-sm mt-0.5">
|
|
63824
|
+
Additional insights gathered from publicly available information
|
|
63825
|
+
</p>
|
|
63826
|
+
</div>
|
|
63827
|
+
</div>
|
|
63828
|
+
</div>
|
|
63829
|
+
</div>
|
|
63830
|
+
|
|
63831
|
+
<div [ngClass]="contentClasses()" class="p-6">
|
|
63832
|
+
<div [ngClass]="infoBoxClasses()" class="mb-6 p-4 rounded-xl border flex items-start gap-3">
|
|
63833
|
+
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" [ngClass]="infoIconClasses()" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
63834
|
+
<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>
|
|
63835
|
+
</svg>
|
|
63836
|
+
<div class="flex-1">
|
|
63837
|
+
<h4 [ngClass]="infoTitleClasses()" class="font-semibold text-sm mb-1">
|
|
63838
|
+
Building Context for Better Recommendations
|
|
63839
|
+
</h4>
|
|
63840
|
+
<p [ngClass]="infoTextClasses()" class="text-sm leading-relaxed">
|
|
63841
|
+
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.
|
|
63842
|
+
</p>
|
|
63843
|
+
</div>
|
|
63844
|
+
</div>
|
|
63845
|
+
|
|
63846
|
+
<div class="space-y-3">
|
|
63847
|
+
@for (section of sections(); track section.id; let idx = $index) {
|
|
63848
|
+
<div [id]="'collapsible-section-' + idx" [ngClass]="sectionCardClasses()" class="rounded-xl border overflow-hidden transition-all duration-200">
|
|
63849
|
+
<button
|
|
63850
|
+
type="button"
|
|
63851
|
+
(click)="toggleSection(idx)"
|
|
63852
|
+
[ngClass]="sectionHeaderClasses(section, idx)"
|
|
63853
|
+
class="cursor-pointer w-full px-5 py-4 flex items-center justify-between gap-4 text-left transition-colors duration-200">
|
|
63854
|
+
<div class="flex items-center gap-3 flex-1 min-w-0">
|
|
63855
|
+
@if (section.icon) {
|
|
63856
|
+
<div [ngClass]="sectionIconContainerClasses(idx)" class="p-2 rounded-lg flex-shrink-0 transition-colors duration-200">
|
|
63857
|
+
<symphiq-icon [icon]="section.icon" size="w-4 h-4"></symphiq-icon>
|
|
63858
|
+
</div>
|
|
63859
|
+
}
|
|
63860
|
+
<div class="flex-1 min-w-0">
|
|
63861
|
+
<h3 [ngClass]="sectionTitleClasses(idx)" class="font-semibold transition-colors duration-200">
|
|
63862
|
+
{{ section.title }}
|
|
63863
|
+
</h3>
|
|
63864
|
+
<p [ngClass]="sectionDescriptionClasses(idx)" class="text-sm mt-0.5 transition-colors duration-200">
|
|
63865
|
+
{{ getSectionItemCount(section) }} items
|
|
63866
|
+
</p>
|
|
63867
|
+
</div>
|
|
63868
|
+
</div>
|
|
63869
|
+
<svg
|
|
63870
|
+
[ngClass]="chevronClasses(idx)"
|
|
63871
|
+
[class.rotate-180]="expandedSections()[idx]"
|
|
63872
|
+
class="w-5 h-5 flex-shrink-0 transition-transform duration-200">
|
|
63873
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
63874
|
+
</svg>
|
|
63875
|
+
</button>
|
|
63876
|
+
|
|
63877
|
+
<div
|
|
63878
|
+
class="grid transition-[grid-template-rows] duration-300 ease-in-out"
|
|
63879
|
+
[style.grid-template-rows]="expandedSections()[idx] ? '1fr' : '0fr'">
|
|
63880
|
+
<div class="overflow-hidden">
|
|
63881
|
+
<div [ngClass]="sectionContentClasses()" class="border-t">
|
|
63882
|
+
<symphiq-profile-section
|
|
63883
|
+
[section]="section"
|
|
63884
|
+
[viewMode]="viewMode()"
|
|
63885
|
+
[forceExpanded]="false"
|
|
63886
|
+
/>
|
|
63887
|
+
</div>
|
|
63888
|
+
</div>
|
|
63889
|
+
</div>
|
|
63890
|
+
</div>
|
|
63891
|
+
}
|
|
63892
|
+
</div>
|
|
63893
|
+
</div>
|
|
63894
|
+
</div>
|
|
63842
63895
|
`
|
|
63843
63896
|
}]
|
|
63844
63897
|
}], null, { sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }] }); })();
|