@eric-emg/symphiq-components 1.3.87 → 1.3.89
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.
|
@@ -1874,8 +1874,10 @@ class TooltipDataService {
|
|
|
1874
1874
|
return undefined;
|
|
1875
1875
|
}
|
|
1876
1876
|
const series = chart.areaChartData.series;
|
|
1877
|
-
const
|
|
1878
|
-
const
|
|
1877
|
+
const currentYear = new Date().getFullYear().toString();
|
|
1878
|
+
const priorYear = (new Date().getFullYear() - 1).toString();
|
|
1879
|
+
const currentSeries = series.find((s) => s.name === currentYear || s.name === 'This Year');
|
|
1880
|
+
const priorSeries = series.find((s) => s.name === priorYear || s.name === 'Last Year');
|
|
1879
1881
|
const current = currentSeries?.data?.map((d) => d.value || 0) || [];
|
|
1880
1882
|
const prior = priorSeries?.data?.map((d) => d.value || 0);
|
|
1881
1883
|
if (current.length === 0) {
|
|
@@ -5760,7 +5762,7 @@ function OverallAssessmentComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
|
|
|
5760
5762
|
} }
|
|
5761
5763
|
function OverallAssessmentComponent_Conditional_1_Conditional_13_Conditional_1_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
5762
5764
|
i0.ɵɵelementStart(0, "div", 55)(1, "span", 51);
|
|
5763
|
-
i0.ɵɵtext(2
|
|
5765
|
+
i0.ɵɵtext(2);
|
|
5764
5766
|
i0.ɵɵelementEnd();
|
|
5765
5767
|
i0.ɵɵelementStart(3, "span", 54);
|
|
5766
5768
|
i0.ɵɵtext(4);
|
|
@@ -5770,7 +5772,9 @@ function OverallAssessmentComponent_Conditional_1_Conditional_13_Conditional_1_C
|
|
|
5770
5772
|
i0.ɵɵproperty("libSymphiqTooltip", ctx_r0.revenueStatusTooltip())("tooltipPosition", "top");
|
|
5771
5773
|
i0.ɵɵadvance();
|
|
5772
5774
|
i0.ɵɵclassMap(ctx_r0.badgeLabelClass());
|
|
5773
|
-
i0.ɵɵadvance(
|
|
5775
|
+
i0.ɵɵadvance();
|
|
5776
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.currentYear(), " Pacing: ");
|
|
5777
|
+
i0.ɵɵadvance();
|
|
5774
5778
|
i0.ɵɵclassMap(ctx_r0.titleClass());
|
|
5775
5779
|
i0.ɵɵadvance();
|
|
5776
5780
|
i0.ɵɵtextInterpolate(ctx_r0.formattedRevenuePacing());
|
|
@@ -5807,7 +5811,7 @@ function OverallAssessmentComponent_Conditional_1_Conditional_13_Conditional_1_T
|
|
|
5807
5811
|
i0.ɵɵelementStart(23, "span", 54);
|
|
5808
5812
|
i0.ɵɵtext(24);
|
|
5809
5813
|
i0.ɵɵelementEnd()()();
|
|
5810
|
-
i0.ɵɵconditionalCreate(25, OverallAssessmentComponent_Conditional_1_Conditional_13_Conditional_1_Conditional_25_Template, 5,
|
|
5814
|
+
i0.ɵɵconditionalCreate(25, OverallAssessmentComponent_Conditional_1_Conditional_13_Conditional_1_Conditional_25_Template, 5, 8, "div", 55);
|
|
5811
5815
|
i0.ɵɵelementEnd();
|
|
5812
5816
|
i0.ɵɵelementStart(26, "div", 56)(27, "span", 57);
|
|
5813
5817
|
i0.ɵɵtext(28);
|
|
@@ -5878,7 +5882,7 @@ function OverallAssessmentComponent_Conditional_1_Conditional_13_Template(rf, ct
|
|
|
5878
5882
|
} }
|
|
5879
5883
|
function OverallAssessmentComponent_Conditional_1_Conditional_14_Conditional_0_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
5880
5884
|
i0.ɵɵelementStart(0, "div", 55)(1, "span", 66);
|
|
5881
|
-
i0.ɵɵtext(2
|
|
5885
|
+
i0.ɵɵtext(2);
|
|
5882
5886
|
i0.ɵɵelementEnd();
|
|
5883
5887
|
i0.ɵɵelementStart(3, "span", 67);
|
|
5884
5888
|
i0.ɵɵtext(4);
|
|
@@ -5888,7 +5892,9 @@ function OverallAssessmentComponent_Conditional_1_Conditional_14_Conditional_0_C
|
|
|
5888
5892
|
i0.ɵɵproperty("libSymphiqTooltip", ctx_r0.revenueStatusTooltip())("tooltipPosition", "top");
|
|
5889
5893
|
i0.ɵɵadvance();
|
|
5890
5894
|
i0.ɵɵclassMap(ctx_r0.badgeLabelClass());
|
|
5891
|
-
i0.ɵɵadvance(
|
|
5895
|
+
i0.ɵɵadvance();
|
|
5896
|
+
i0.ɵɵtextInterpolate1("", ctx_r0.currentYear(), " Pacing: ");
|
|
5897
|
+
i0.ɵɵadvance();
|
|
5892
5898
|
i0.ɵɵclassMap(ctx_r0.titleClass());
|
|
5893
5899
|
i0.ɵɵadvance();
|
|
5894
5900
|
i0.ɵɵtextInterpolate(ctx_r0.formattedRevenuePacing());
|
|
@@ -5925,7 +5931,7 @@ function OverallAssessmentComponent_Conditional_1_Conditional_14_Conditional_0_T
|
|
|
5925
5931
|
i0.ɵɵelementStart(25, "span", 67);
|
|
5926
5932
|
i0.ɵɵtext(26);
|
|
5927
5933
|
i0.ɵɵelementEnd()()();
|
|
5928
|
-
i0.ɵɵconditionalCreate(27, OverallAssessmentComponent_Conditional_1_Conditional_14_Conditional_0_Conditional_27_Template, 5,
|
|
5934
|
+
i0.ɵɵconditionalCreate(27, OverallAssessmentComponent_Conditional_1_Conditional_14_Conditional_0_Conditional_27_Template, 5, 8, "div", 55);
|
|
5929
5935
|
i0.ɵɵelementEnd()();
|
|
5930
5936
|
i0.ɵɵelementStart(28, "div", 68)(29, "div", 17);
|
|
5931
5937
|
i0.ɵɵtext(30, "Status");
|
|
@@ -6332,6 +6338,7 @@ class OverallAssessmentComponent {
|
|
|
6332
6338
|
const metricWithProjected = metric;
|
|
6333
6339
|
return metricWithProjected.projectedValue !== undefined && metricWithProjected.projectedValue !== null;
|
|
6334
6340
|
}, ...(ngDevMode ? [{ debugName: "hasRevenuePacing" }] : []));
|
|
6341
|
+
this.currentYear = computed(() => new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "currentYear" }] : []));
|
|
6335
6342
|
this.formattedRevenuePacing = computed(() => {
|
|
6336
6343
|
const metric = this.revenueMetric();
|
|
6337
6344
|
if (!metric)
|
|
@@ -6679,291 +6686,291 @@ class OverallAssessmentComponent {
|
|
|
6679
6686
|
standalone: true,
|
|
6680
6687
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
6681
6688
|
imports: [CommonModule, ChartContainerComponent, TooltipDirective, SkeletonLoaderComponent, CompetitivePositioningSummaryComponent],
|
|
6682
|
-
template: `
|
|
6683
|
-
@if (isLoading()) {
|
|
6684
|
-
<div [class]="containerClass()" class="rounded-2xl p-4 sm:p-6 lg:p-8 border shadow-xl backdrop-blur-lg">
|
|
6685
|
-
<div class="space-y-6">
|
|
6686
|
-
<div class="flex items-start justify-between gap-4">
|
|
6687
|
-
<div class="flex-1 space-y-3">
|
|
6688
|
-
<symphiq-skeleton-loader [width]="'60%'" [height]="'32px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6689
|
-
<symphiq-skeleton-loader [width]="'80%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6690
|
-
</div>
|
|
6691
|
-
<div class="flex gap-3 justify-end">
|
|
6692
|
-
<symphiq-skeleton-loader [width]="'100px'" [height]="'70px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6693
|
-
</div>
|
|
6694
|
-
</div>
|
|
6695
|
-
<div class="grid grid-cols-2 gap-4">
|
|
6696
|
-
@for (i of [1,2,3,4]; track i) {
|
|
6697
|
-
<div class="space-y-2">
|
|
6698
|
-
<symphiq-skeleton-loader [width]="'50%'" [height]="'14px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6699
|
-
<symphiq-skeleton-loader [width]="'70%'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6700
|
-
</div>
|
|
6701
|
-
}
|
|
6702
|
-
</div>
|
|
6703
|
-
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6704
|
-
</div>
|
|
6705
|
-
</div>
|
|
6706
|
-
} @else {
|
|
6707
|
-
<div [class]="containerClass()" class="rounded-2xl p-4 sm:p-6 lg:p-8 border shadow-xl transition-all duration-500 hover:shadow-2xl group backdrop-blur-lg">
|
|
6708
|
-
<div class="flex flex-col sm:flex-row items-start justify-between gap-4 mb-4 sm:mb-6">
|
|
6709
|
-
<div class="flex-1">
|
|
6710
|
-
<h2 [class]="titleClass()" class="text-2xl sm:text-3xl font-bold mb-2">Overall Performance</h2>
|
|
6711
|
-
<p [class]="subtitleClass()" class="text-sm sm:text-base">{{ assessment().targetPacingStatus }}</p>
|
|
6712
|
-
</div>
|
|
6713
|
-
<div class="flex items-center gap-3 sm:gap-4 w-full sm:w-auto justify-end">
|
|
6714
|
-
<div
|
|
6715
|
-
[class]="gradeBadgeClass()"
|
|
6716
|
-
[class.animate-pulse]="shouldPulseGrade()"
|
|
6717
|
-
class="flex-1 sm:flex-initial transition-all duration-300 hover:scale-110"
|
|
6718
|
-
[libSymphiqTooltip]="gradeTooltip()"
|
|
6719
|
-
tooltipType="badge"
|
|
6720
|
-
[tooltipPosition]="'bottom'">
|
|
6721
|
-
<div [class]="badgeLabelClass()" class="text-xs font-semibold uppercase tracking-wider mb-1">Grade</div>
|
|
6722
|
-
<div class="text-3xl sm:text-4xl font-bold">{{ assessment().grade }}</div>
|
|
6723
|
-
</div>
|
|
6724
|
-
</div>
|
|
6725
|
-
</div>
|
|
6726
|
-
|
|
6727
|
-
@if (isCompactMode()) {
|
|
6728
|
-
<div class="flex flex-wrap gap-4 mb-6 sm:mb-8">
|
|
6729
|
-
@if (revenueMetric()) {
|
|
6730
|
-
<div [class]="revenueCardClass()" class="flex-shrink-0 rounded-xl p-6 sm:p-8 border-2 transition-all duration-500 hover:scale-[1.01]">
|
|
6731
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6732
|
-
<div [class]="revenueIconBgClass()" class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6733
|
-
<svg [class]="revenueIconClass()" class="w-6 h-6 sm:w-7 sm:h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6734
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6735
|
-
</svg>
|
|
6736
|
-
</div>
|
|
6737
|
-
<div class="min-w-0 flex-1">
|
|
6738
|
-
<h3 [class]="badgeLabelClass()" class="text-xs sm:text-sm font-semibold uppercase tracking-wider">Your Revenue</h3>
|
|
6739
|
-
<p
|
|
6740
|
-
[class]="titleClass()"
|
|
6741
|
-
class="text-2xl sm:text-3xl lg:text-4xl font-bold truncate transition-all duration-300 hover:scale-105"
|
|
6742
|
-
[libSymphiqTooltip]="revenueTooltip()"
|
|
6743
|
-
tooltipType="metric"
|
|
6744
|
-
[tooltipPosition]="'bottom'">
|
|
6745
|
-
{{ formattedRevenueValue() }}
|
|
6746
|
-
</p>
|
|
6747
|
-
</div>
|
|
6748
|
-
</div>
|
|
6749
|
-
<div class="flex flex-col gap-2 mb-3">
|
|
6750
|
-
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
|
6751
|
-
<div
|
|
6752
|
-
class="flex items-center gap-2"
|
|
6753
|
-
[libSymphiqTooltip]="revenueTrendTooltip()"
|
|
6754
|
-
tooltipType="trend"
|
|
6755
|
-
[tooltipPosition]="'top'">
|
|
6756
|
-
<svg [class]="trendIconClass()" class="w-4 h-4 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
6757
|
-
<path fill-rule="evenodd" [attr.d]="revenueTrendArrowPath()" clip-rule="evenodd" />
|
|
6758
|
-
</svg>
|
|
6759
|
-
<span [class]="trendValueClass()" class="font-semibold text-base">{{ formattedRevenueTrend() }}%</span>
|
|
6760
|
-
<span [class]="badgeLabelClass()" class="text-xs">vs last year</span>
|
|
6761
|
-
</div>
|
|
6762
|
-
<div class="hidden sm:block h-6 w-px bg-slate-600"></div>
|
|
6763
|
-
<div
|
|
6764
|
-
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6765
|
-
tooltipType="status"
|
|
6766
|
-
[tooltipPosition]="'top'">
|
|
6767
|
-
<span [class]="badgeLabelClass()" class="text-xs">Target: </span>
|
|
6768
|
-
<span [class]="titleClass()" class="font-semibold text-sm">{{ formattedRevenueTarget() }}</span>
|
|
6769
|
-
</div>
|
|
6770
|
-
</div>
|
|
6771
|
-
@if (hasRevenuePacing()) {
|
|
6772
|
-
<div
|
|
6773
|
-
class="flex items-center gap-2"
|
|
6774
|
-
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6775
|
-
tooltipType="status"
|
|
6776
|
-
[tooltipPosition]="'top'">
|
|
6777
|
-
<span [class]="badgeLabelClass()" class="text-xs">
|
|
6778
|
-
<span [class]="titleClass()" class="font-semibold text-sm">{{ formattedRevenuePacing() }}</span>
|
|
6779
|
-
</div>
|
|
6780
|
-
}
|
|
6781
|
-
</div>
|
|
6782
|
-
<div
|
|
6783
|
-
[class]="revenueStatusClass()"
|
|
6784
|
-
[ngStyle]="getRevenueStatusStyle()"
|
|
6785
|
-
class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-lg font-bold text-base sm:text-lg transition-all duration-300"
|
|
6786
|
-
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6787
|
-
tooltipType="status"
|
|
6788
|
-
[tooltipPosition]="'top'">
|
|
6789
|
-
<span class="text-lg">{{ getRevenueStatusIcon() }}</span>
|
|
6790
|
-
<span>{{ revenueStatusLabel() }}</span>
|
|
6791
|
-
</div>
|
|
6792
|
-
</div>
|
|
6793
|
-
}
|
|
6794
|
-
<div
|
|
6795
|
-
[class]="narrativeBoxClass()"
|
|
6796
|
-
class="flex-1 min-w-[300px] rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:shadow-xl hover:scale-[1.01] group">
|
|
6797
|
-
<p [class]="narrativeTextClass()" class="text-sm sm:text-base leading-relaxed">{{ assessment().narrative }}</p>
|
|
6798
|
-
</div>
|
|
6799
|
-
</div>
|
|
6800
|
-
} @else {
|
|
6801
|
-
@if (revenueMetric()) {
|
|
6802
|
-
<div [class]="revenueCardClass()" class="rounded-xl p-6 sm:p-8 mb-6 sm:mb-8 border-2 transition-all duration-500 hover:scale-[1.01]">
|
|
6803
|
-
<div class="flex flex-col md:flex-row items-start md:items-center gap-4 md:gap-0">
|
|
6804
|
-
<div class="flex-1 w-full">
|
|
6805
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6806
|
-
<div [class]="revenueIconBgClass()" class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6807
|
-
<svg [class]="revenueIconClass()" class="w-6 h-6 sm:w-7 sm:h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6808
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6809
|
-
</svg>
|
|
6810
|
-
</div>
|
|
6811
|
-
<div class="min-w-0 flex-1">
|
|
6812
|
-
<h3 [class]="badgeLabelClass()" class="text-xs sm:text-sm font-semibold uppercase tracking-wider">Your Revenue</h3>
|
|
6813
|
-
<p
|
|
6814
|
-
[class]="titleClass()"
|
|
6815
|
-
class="text-2xl sm:text-3xl lg:text-4xl font-bold truncate transition-all duration-300 hover:scale-105"
|
|
6816
|
-
[libSymphiqTooltip]="revenueTooltip()"
|
|
6817
|
-
tooltipType="metric"
|
|
6818
|
-
[tooltipPosition]="'bottom'">
|
|
6819
|
-
{{ formattedRevenueValue() }}
|
|
6820
|
-
</p>
|
|
6821
|
-
</div>
|
|
6822
|
-
</div>
|
|
6823
|
-
<div class="flex flex-col gap-2 mt-4">
|
|
6824
|
-
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
|
6825
|
-
<div
|
|
6826
|
-
class="flex items-center gap-2"
|
|
6827
|
-
[libSymphiqTooltip]="revenueTrendTooltip()"
|
|
6828
|
-
tooltipType="trend"
|
|
6829
|
-
[tooltipPosition]="'top'">
|
|
6830
|
-
<svg [class]="trendIconClass()" class="w-4 h-4 sm:w-5 sm:h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
6831
|
-
<path fill-rule="evenodd" [attr.d]="revenueTrendArrowPath()" clip-rule="evenodd" />
|
|
6832
|
-
</svg>
|
|
6833
|
-
<span [class]="trendValueClass()" class="font-semibold text-base sm:text-lg">{{ formattedRevenueTrend() }}%</span>
|
|
6834
|
-
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">vs last year</span>
|
|
6835
|
-
</div>
|
|
6836
|
-
<div class="hidden sm:block h-6 w-px bg-slate-600"></div>
|
|
6837
|
-
<div
|
|
6838
|
-
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6839
|
-
tooltipType="status"
|
|
6840
|
-
[tooltipPosition]="'top'">
|
|
6841
|
-
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">Target: </span>
|
|
6842
|
-
<span [class]="titleClass()" class="font-semibold text-sm sm:text-base">{{ formattedRevenueTarget() }}</span>
|
|
6843
|
-
</div>
|
|
6844
|
-
</div>
|
|
6845
|
-
@if (hasRevenuePacing()) {
|
|
6846
|
-
<div
|
|
6847
|
-
class="flex items-center gap-2"
|
|
6848
|
-
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6849
|
-
tooltipType="status"
|
|
6850
|
-
[tooltipPosition]="'top'">
|
|
6851
|
-
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">
|
|
6852
|
-
<span [class]="titleClass()" class="font-semibold text-sm sm:text-base">{{ formattedRevenuePacing() }}</span>
|
|
6853
|
-
</div>
|
|
6854
|
-
}
|
|
6855
|
-
</div>
|
|
6856
|
-
</div>
|
|
6857
|
-
<div class="w-full md:w-auto md:text-right md:ml-4">
|
|
6858
|
-
<div [class]="badgeLabelClass()" class="text-xs font-semibold uppercase tracking-wider mb-1">Status</div>
|
|
6859
|
-
<div [class]="revenueStatusClass()" [ngStyle]="getRevenueStatusStyle()" class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-lg font-bold text-base sm:text-lg transition-all duration-300">
|
|
6860
|
-
<span class="text-lg">{{ getRevenueStatusIcon() }}</span>
|
|
6861
|
-
<span>{{ revenueStatusLabel() }}</span>
|
|
6862
|
-
</div>
|
|
6863
|
-
<div [class]="badgeLabelClass()" class="mt-2 text-xs sm:text-sm">{{ revenueMetric()!.description }}</div>
|
|
6864
|
-
</div>
|
|
6865
|
-
</div>
|
|
6866
|
-
</div>
|
|
6867
|
-
}
|
|
6868
|
-
|
|
6869
|
-
<div [class]="narrativeBoxClass()" class="rounded-xl p-4 sm:p-6 mb-4 sm:mb-6 border transition-all duration-300 hover:shadow-xl hover:scale-[1.01] group">
|
|
6870
|
-
<p [class]="narrativeTextClass()" class="text-sm sm:text-base leading-relaxed">{{ assessment().narrative }}</p>
|
|
6871
|
-
</div>
|
|
6872
|
-
}
|
|
6873
|
-
|
|
6874
|
-
@if (charts() && charts().length > 0) {
|
|
6875
|
-
<div class="mb-4 sm:mb-6">
|
|
6876
|
-
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
6877
|
-
@for (chart of charts(); track $index) {
|
|
6878
|
-
<symphiq-chart-container [chart]="chart" [isLightMode]="isLightMode()" [isCompactMode]="isCompactMode()" [collapsibleIn]="'compact'" [isLoading]="isChartsLoading()" [currencySymbol]="currencySymbol()" (chartClick)="openChartModal($event)" />
|
|
6879
|
-
}
|
|
6880
|
-
</div>
|
|
6881
|
-
</div>
|
|
6882
|
-
}
|
|
6883
|
-
|
|
6884
|
-
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6">
|
|
6885
|
-
<div [class]="strengthsCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6886
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6887
|
-
<div [class]="strengthsIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6888
|
-
<svg [class]="strengthsIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6889
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6890
|
-
</svg>
|
|
6891
|
-
</div>
|
|
6892
|
-
<h3 [class]="strengthsTitleClass()" class="text-base sm:text-lg font-semibold">Key Strengths</h3>
|
|
6893
|
-
</div>
|
|
6894
|
-
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed mb-4">{{ assessment().keyStrengths }}</p>
|
|
6895
|
-
@if (strengths().length > 0) {
|
|
6896
|
-
<button
|
|
6897
|
-
type="button"
|
|
6898
|
-
(click)="openStrengthsModal()"
|
|
6899
|
-
[class]="strengthsButtonClass()"
|
|
6900
|
-
class="w-full px-4 py-2.5 rounded-lg font-semibold text-sm transition-all duration-300 hover:scale-105 hover:shadow-lg active:scale-95 cursor-pointer">
|
|
6901
|
-
View {{ strengths().length }} {{ strengths().length === 1 ? 'Strength' : 'Strengths' }}
|
|
6902
|
-
</button>
|
|
6903
|
-
}
|
|
6904
|
-
</div>
|
|
6905
|
-
|
|
6906
|
-
<div [class]="improvementCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6907
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6908
|
-
<div [class]="improvementIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6909
|
-
<svg [class]="improvementIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6910
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
6911
|
-
</svg>
|
|
6912
|
-
</div>
|
|
6913
|
-
<h3 [class]="improvementTitleClass()" class="text-base sm:text-lg font-semibold">Areas for Improvement</h3>
|
|
6914
|
-
</div>
|
|
6915
|
-
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed mb-4">{{ assessment().areasForImprovement }}</p>
|
|
6916
|
-
@if (weaknesses().length > 0) {
|
|
6917
|
-
<button
|
|
6918
|
-
type="button"
|
|
6919
|
-
(click)="openWeaknessesModal()"
|
|
6920
|
-
[class]="weaknessesButtonClass()"
|
|
6921
|
-
class="w-full px-4 py-2.5 rounded-lg font-semibold text-sm transition-all duration-300 hover:scale-105 hover:shadow-lg active:scale-95 cursor-pointer">
|
|
6922
|
-
View {{ weaknesses().length }} {{ weaknesses().length === 1 ? 'Weakness' : 'Weaknesses' }}
|
|
6923
|
-
</button>
|
|
6924
|
-
}
|
|
6925
|
-
</div>
|
|
6926
|
-
|
|
6927
|
-
<div [class]="trendCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6928
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6929
|
-
<div [class]="trendIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6930
|
-
<svg [class]="trendIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6931
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
|
6932
|
-
</svg>
|
|
6933
|
-
</div>
|
|
6934
|
-
<h3 [class]="trendTitleClass()" class="text-base sm:text-lg font-semibold">Prior Year Trend</h3>
|
|
6935
|
-
</div>
|
|
6936
|
-
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed">{{ assessment().priorYearTrend }}</p>
|
|
6937
|
-
</div>
|
|
6938
|
-
|
|
6939
|
-
<div [class]="actionCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6940
|
-
<div class="flex items-center gap-3 mb-3">
|
|
6941
|
-
<div [class]="actionIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6942
|
-
<svg [class]="actionIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6943
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" />
|
|
6944
|
-
</svg>
|
|
6945
|
-
</div>
|
|
6946
|
-
<h3 [class]="actionTitleClass()" class="text-base sm:text-lg font-semibold">Recommended Actions</h3>
|
|
6947
|
-
</div>
|
|
6948
|
-
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed">{{ assessment().recommendedActions }}</p>
|
|
6949
|
-
</div>
|
|
6950
|
-
</div>
|
|
6951
|
-
|
|
6952
|
-
<!-- Competitive Positioning Summary -->
|
|
6953
|
-
@if (hasCompetitiveData()) {
|
|
6954
|
-
<div class="mt-6 sm:mt-8">
|
|
6955
|
-
<symphiq-competitive-positioning-summary
|
|
6956
|
-
[metrics]="metrics()"
|
|
6957
|
-
[isLightMode]="isLightMode()"
|
|
6958
|
-
[isCompactMode]="isCompactMode()"
|
|
6959
|
-
[overallDescription]="assessment().competitiveBenchmark?.description"
|
|
6960
|
-
[competitiveBenchmark]="assessment().competitiveBenchmark"
|
|
6961
|
-
[currencySymbol]="currencySymbol()"
|
|
6962
|
-
(scrollToCompetitive)="scrollToCompetitiveSection()" />
|
|
6963
|
-
</div>
|
|
6964
|
-
}
|
|
6965
|
-
</div>
|
|
6966
|
-
}
|
|
6689
|
+
template: `
|
|
6690
|
+
@if (isLoading()) {
|
|
6691
|
+
<div [class]="containerClass()" class="rounded-2xl p-4 sm:p-6 lg:p-8 border shadow-xl backdrop-blur-lg">
|
|
6692
|
+
<div class="space-y-6">
|
|
6693
|
+
<div class="flex items-start justify-between gap-4">
|
|
6694
|
+
<div class="flex-1 space-y-3">
|
|
6695
|
+
<symphiq-skeleton-loader [width]="'60%'" [height]="'32px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6696
|
+
<symphiq-skeleton-loader [width]="'80%'" [height]="'16px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6697
|
+
</div>
|
|
6698
|
+
<div class="flex gap-3 justify-end">
|
|
6699
|
+
<symphiq-skeleton-loader [width]="'100px'" [height]="'70px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6700
|
+
</div>
|
|
6701
|
+
</div>
|
|
6702
|
+
<div class="grid grid-cols-2 gap-4">
|
|
6703
|
+
@for (i of [1,2,3,4]; track i) {
|
|
6704
|
+
<div class="space-y-2">
|
|
6705
|
+
<symphiq-skeleton-loader [width]="'50%'" [height]="'14px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6706
|
+
<symphiq-skeleton-loader [width]="'70%'" [height]="'24px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6707
|
+
</div>
|
|
6708
|
+
}
|
|
6709
|
+
</div>
|
|
6710
|
+
<symphiq-skeleton-loader [width]="'100%'" [height]="'200px'" [isLightMode]="isLightMode()"></symphiq-skeleton-loader>
|
|
6711
|
+
</div>
|
|
6712
|
+
</div>
|
|
6713
|
+
} @else {
|
|
6714
|
+
<div [class]="containerClass()" class="rounded-2xl p-4 sm:p-6 lg:p-8 border shadow-xl transition-all duration-500 hover:shadow-2xl group backdrop-blur-lg">
|
|
6715
|
+
<div class="flex flex-col sm:flex-row items-start justify-between gap-4 mb-4 sm:mb-6">
|
|
6716
|
+
<div class="flex-1">
|
|
6717
|
+
<h2 [class]="titleClass()" class="text-2xl sm:text-3xl font-bold mb-2">Overall Performance</h2>
|
|
6718
|
+
<p [class]="subtitleClass()" class="text-sm sm:text-base">{{ assessment().targetPacingStatus }}</p>
|
|
6719
|
+
</div>
|
|
6720
|
+
<div class="flex items-center gap-3 sm:gap-4 w-full sm:w-auto justify-end">
|
|
6721
|
+
<div
|
|
6722
|
+
[class]="gradeBadgeClass()"
|
|
6723
|
+
[class.animate-pulse]="shouldPulseGrade()"
|
|
6724
|
+
class="flex-1 sm:flex-initial transition-all duration-300 hover:scale-110"
|
|
6725
|
+
[libSymphiqTooltip]="gradeTooltip()"
|
|
6726
|
+
tooltipType="badge"
|
|
6727
|
+
[tooltipPosition]="'bottom'">
|
|
6728
|
+
<div [class]="badgeLabelClass()" class="text-xs font-semibold uppercase tracking-wider mb-1">Grade</div>
|
|
6729
|
+
<div class="text-3xl sm:text-4xl font-bold">{{ assessment().grade }}</div>
|
|
6730
|
+
</div>
|
|
6731
|
+
</div>
|
|
6732
|
+
</div>
|
|
6733
|
+
|
|
6734
|
+
@if (isCompactMode()) {
|
|
6735
|
+
<div class="flex flex-wrap gap-4 mb-6 sm:mb-8">
|
|
6736
|
+
@if (revenueMetric()) {
|
|
6737
|
+
<div [class]="revenueCardClass()" class="flex-shrink-0 rounded-xl p-6 sm:p-8 border-2 transition-all duration-500 hover:scale-[1.01]">
|
|
6738
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6739
|
+
<div [class]="revenueIconBgClass()" class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6740
|
+
<svg [class]="revenueIconClass()" class="w-6 h-6 sm:w-7 sm:h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6741
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6742
|
+
</svg>
|
|
6743
|
+
</div>
|
|
6744
|
+
<div class="min-w-0 flex-1">
|
|
6745
|
+
<h3 [class]="badgeLabelClass()" class="text-xs sm:text-sm font-semibold uppercase tracking-wider">Your Revenue</h3>
|
|
6746
|
+
<p
|
|
6747
|
+
[class]="titleClass()"
|
|
6748
|
+
class="text-2xl sm:text-3xl lg:text-4xl font-bold truncate transition-all duration-300 hover:scale-105"
|
|
6749
|
+
[libSymphiqTooltip]="revenueTooltip()"
|
|
6750
|
+
tooltipType="metric"
|
|
6751
|
+
[tooltipPosition]="'bottom'">
|
|
6752
|
+
{{ formattedRevenueValue() }}
|
|
6753
|
+
</p>
|
|
6754
|
+
</div>
|
|
6755
|
+
</div>
|
|
6756
|
+
<div class="flex flex-col gap-2 mb-3">
|
|
6757
|
+
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
|
6758
|
+
<div
|
|
6759
|
+
class="flex items-center gap-2"
|
|
6760
|
+
[libSymphiqTooltip]="revenueTrendTooltip()"
|
|
6761
|
+
tooltipType="trend"
|
|
6762
|
+
[tooltipPosition]="'top'">
|
|
6763
|
+
<svg [class]="trendIconClass()" class="w-4 h-4 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
6764
|
+
<path fill-rule="evenodd" [attr.d]="revenueTrendArrowPath()" clip-rule="evenodd" />
|
|
6765
|
+
</svg>
|
|
6766
|
+
<span [class]="trendValueClass()" class="font-semibold text-base">{{ formattedRevenueTrend() }}%</span>
|
|
6767
|
+
<span [class]="badgeLabelClass()" class="text-xs">vs last year</span>
|
|
6768
|
+
</div>
|
|
6769
|
+
<div class="hidden sm:block h-6 w-px bg-slate-600"></div>
|
|
6770
|
+
<div
|
|
6771
|
+
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6772
|
+
tooltipType="status"
|
|
6773
|
+
[tooltipPosition]="'top'">
|
|
6774
|
+
<span [class]="badgeLabelClass()" class="text-xs">Target: </span>
|
|
6775
|
+
<span [class]="titleClass()" class="font-semibold text-sm">{{ formattedRevenueTarget() }}</span>
|
|
6776
|
+
</div>
|
|
6777
|
+
</div>
|
|
6778
|
+
@if (hasRevenuePacing()) {
|
|
6779
|
+
<div
|
|
6780
|
+
class="flex items-center gap-2"
|
|
6781
|
+
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6782
|
+
tooltipType="status"
|
|
6783
|
+
[tooltipPosition]="'top'">
|
|
6784
|
+
<span [class]="badgeLabelClass()" class="text-xs">{{ currentYear() }} Pacing: </span>
|
|
6785
|
+
<span [class]="titleClass()" class="font-semibold text-sm">{{ formattedRevenuePacing() }}</span>
|
|
6786
|
+
</div>
|
|
6787
|
+
}
|
|
6788
|
+
</div>
|
|
6789
|
+
<div
|
|
6790
|
+
[class]="revenueStatusClass()"
|
|
6791
|
+
[ngStyle]="getRevenueStatusStyle()"
|
|
6792
|
+
class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-lg font-bold text-base sm:text-lg transition-all duration-300"
|
|
6793
|
+
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6794
|
+
tooltipType="status"
|
|
6795
|
+
[tooltipPosition]="'top'">
|
|
6796
|
+
<span class="text-lg">{{ getRevenueStatusIcon() }}</span>
|
|
6797
|
+
<span>{{ revenueStatusLabel() }}</span>
|
|
6798
|
+
</div>
|
|
6799
|
+
</div>
|
|
6800
|
+
}
|
|
6801
|
+
<div
|
|
6802
|
+
[class]="narrativeBoxClass()"
|
|
6803
|
+
class="flex-1 min-w-[300px] rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:shadow-xl hover:scale-[1.01] group">
|
|
6804
|
+
<p [class]="narrativeTextClass()" class="text-sm sm:text-base leading-relaxed">{{ assessment().narrative }}</p>
|
|
6805
|
+
</div>
|
|
6806
|
+
</div>
|
|
6807
|
+
} @else {
|
|
6808
|
+
@if (revenueMetric()) {
|
|
6809
|
+
<div [class]="revenueCardClass()" class="rounded-xl p-6 sm:p-8 mb-6 sm:mb-8 border-2 transition-all duration-500 hover:scale-[1.01]">
|
|
6810
|
+
<div class="flex flex-col md:flex-row items-start md:items-center gap-4 md:gap-0">
|
|
6811
|
+
<div class="flex-1 w-full">
|
|
6812
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6813
|
+
<div [class]="revenueIconBgClass()" class="w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6814
|
+
<svg [class]="revenueIconClass()" class="w-6 h-6 sm:w-7 sm:h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6815
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6816
|
+
</svg>
|
|
6817
|
+
</div>
|
|
6818
|
+
<div class="min-w-0 flex-1">
|
|
6819
|
+
<h3 [class]="badgeLabelClass()" class="text-xs sm:text-sm font-semibold uppercase tracking-wider">Your Revenue</h3>
|
|
6820
|
+
<p
|
|
6821
|
+
[class]="titleClass()"
|
|
6822
|
+
class="text-2xl sm:text-3xl lg:text-4xl font-bold truncate transition-all duration-300 hover:scale-105"
|
|
6823
|
+
[libSymphiqTooltip]="revenueTooltip()"
|
|
6824
|
+
tooltipType="metric"
|
|
6825
|
+
[tooltipPosition]="'bottom'">
|
|
6826
|
+
{{ formattedRevenueValue() }}
|
|
6827
|
+
</p>
|
|
6828
|
+
</div>
|
|
6829
|
+
</div>
|
|
6830
|
+
<div class="flex flex-col gap-2 mt-4">
|
|
6831
|
+
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
|
6832
|
+
<div
|
|
6833
|
+
class="flex items-center gap-2"
|
|
6834
|
+
[libSymphiqTooltip]="revenueTrendTooltip()"
|
|
6835
|
+
tooltipType="trend"
|
|
6836
|
+
[tooltipPosition]="'top'">
|
|
6837
|
+
<svg [class]="trendIconClass()" class="w-4 h-4 sm:w-5 sm:h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
6838
|
+
<path fill-rule="evenodd" [attr.d]="revenueTrendArrowPath()" clip-rule="evenodd" />
|
|
6839
|
+
</svg>
|
|
6840
|
+
<span [class]="trendValueClass()" class="font-semibold text-base sm:text-lg">{{ formattedRevenueTrend() }}%</span>
|
|
6841
|
+
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">vs last year</span>
|
|
6842
|
+
</div>
|
|
6843
|
+
<div class="hidden sm:block h-6 w-px bg-slate-600"></div>
|
|
6844
|
+
<div
|
|
6845
|
+
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6846
|
+
tooltipType="status"
|
|
6847
|
+
[tooltipPosition]="'top'">
|
|
6848
|
+
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">Target: </span>
|
|
6849
|
+
<span [class]="titleClass()" class="font-semibold text-sm sm:text-base">{{ formattedRevenueTarget() }}</span>
|
|
6850
|
+
</div>
|
|
6851
|
+
</div>
|
|
6852
|
+
@if (hasRevenuePacing()) {
|
|
6853
|
+
<div
|
|
6854
|
+
class="flex items-center gap-2"
|
|
6855
|
+
[libSymphiqTooltip]="revenueStatusTooltip()"
|
|
6856
|
+
tooltipType="status"
|
|
6857
|
+
[tooltipPosition]="'top'">
|
|
6858
|
+
<span [class]="badgeLabelClass()" class="text-xs sm:text-sm">{{ currentYear() }} Pacing: </span>
|
|
6859
|
+
<span [class]="titleClass()" class="font-semibold text-sm sm:text-base">{{ formattedRevenuePacing() }}</span>
|
|
6860
|
+
</div>
|
|
6861
|
+
}
|
|
6862
|
+
</div>
|
|
6863
|
+
</div>
|
|
6864
|
+
<div class="w-full md:w-auto md:text-right md:ml-4">
|
|
6865
|
+
<div [class]="badgeLabelClass()" class="text-xs font-semibold uppercase tracking-wider mb-1">Status</div>
|
|
6866
|
+
<div [class]="revenueStatusClass()" [ngStyle]="getRevenueStatusStyle()" class="inline-flex items-center gap-2 px-3 sm:px-4 py-1.5 sm:py-2 rounded-lg font-bold text-base sm:text-lg transition-all duration-300">
|
|
6867
|
+
<span class="text-lg">{{ getRevenueStatusIcon() }}</span>
|
|
6868
|
+
<span>{{ revenueStatusLabel() }}</span>
|
|
6869
|
+
</div>
|
|
6870
|
+
<div [class]="badgeLabelClass()" class="mt-2 text-xs sm:text-sm">{{ revenueMetric()!.description }}</div>
|
|
6871
|
+
</div>
|
|
6872
|
+
</div>
|
|
6873
|
+
</div>
|
|
6874
|
+
}
|
|
6875
|
+
|
|
6876
|
+
<div [class]="narrativeBoxClass()" class="rounded-xl p-4 sm:p-6 mb-4 sm:mb-6 border transition-all duration-300 hover:shadow-xl hover:scale-[1.01] group">
|
|
6877
|
+
<p [class]="narrativeTextClass()" class="text-sm sm:text-base leading-relaxed">{{ assessment().narrative }}</p>
|
|
6878
|
+
</div>
|
|
6879
|
+
}
|
|
6880
|
+
|
|
6881
|
+
@if (charts() && charts().length > 0) {
|
|
6882
|
+
<div class="mb-4 sm:mb-6">
|
|
6883
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
6884
|
+
@for (chart of charts(); track $index) {
|
|
6885
|
+
<symphiq-chart-container [chart]="chart" [isLightMode]="isLightMode()" [isCompactMode]="isCompactMode()" [collapsibleIn]="'compact'" [isLoading]="isChartsLoading()" [currencySymbol]="currencySymbol()" (chartClick)="openChartModal($event)" />
|
|
6886
|
+
}
|
|
6887
|
+
</div>
|
|
6888
|
+
</div>
|
|
6889
|
+
}
|
|
6890
|
+
|
|
6891
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6">
|
|
6892
|
+
<div [class]="strengthsCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6893
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6894
|
+
<div [class]="strengthsIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6895
|
+
<svg [class]="strengthsIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6896
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
6897
|
+
</svg>
|
|
6898
|
+
</div>
|
|
6899
|
+
<h3 [class]="strengthsTitleClass()" class="text-base sm:text-lg font-semibold">Key Strengths</h3>
|
|
6900
|
+
</div>
|
|
6901
|
+
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed mb-4">{{ assessment().keyStrengths }}</p>
|
|
6902
|
+
@if (strengths().length > 0) {
|
|
6903
|
+
<button
|
|
6904
|
+
type="button"
|
|
6905
|
+
(click)="openStrengthsModal()"
|
|
6906
|
+
[class]="strengthsButtonClass()"
|
|
6907
|
+
class="w-full px-4 py-2.5 rounded-lg font-semibold text-sm transition-all duration-300 hover:scale-105 hover:shadow-lg active:scale-95 cursor-pointer">
|
|
6908
|
+
View {{ strengths().length }} {{ strengths().length === 1 ? 'Strength' : 'Strengths' }}
|
|
6909
|
+
</button>
|
|
6910
|
+
}
|
|
6911
|
+
</div>
|
|
6912
|
+
|
|
6913
|
+
<div [class]="improvementCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6914
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6915
|
+
<div [class]="improvementIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6916
|
+
<svg [class]="improvementIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6917
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
6918
|
+
</svg>
|
|
6919
|
+
</div>
|
|
6920
|
+
<h3 [class]="improvementTitleClass()" class="text-base sm:text-lg font-semibold">Areas for Improvement</h3>
|
|
6921
|
+
</div>
|
|
6922
|
+
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed mb-4">{{ assessment().areasForImprovement }}</p>
|
|
6923
|
+
@if (weaknesses().length > 0) {
|
|
6924
|
+
<button
|
|
6925
|
+
type="button"
|
|
6926
|
+
(click)="openWeaknessesModal()"
|
|
6927
|
+
[class]="weaknessesButtonClass()"
|
|
6928
|
+
class="w-full px-4 py-2.5 rounded-lg font-semibold text-sm transition-all duration-300 hover:scale-105 hover:shadow-lg active:scale-95 cursor-pointer">
|
|
6929
|
+
View {{ weaknesses().length }} {{ weaknesses().length === 1 ? 'Weakness' : 'Weaknesses' }}
|
|
6930
|
+
</button>
|
|
6931
|
+
}
|
|
6932
|
+
</div>
|
|
6933
|
+
|
|
6934
|
+
<div [class]="trendCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6935
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6936
|
+
<div [class]="trendIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6937
|
+
<svg [class]="trendIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6938
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
|
6939
|
+
</svg>
|
|
6940
|
+
</div>
|
|
6941
|
+
<h3 [class]="trendTitleClass()" class="text-base sm:text-lg font-semibold">Prior Year Trend</h3>
|
|
6942
|
+
</div>
|
|
6943
|
+
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed">{{ assessment().priorYearTrend }}</p>
|
|
6944
|
+
</div>
|
|
6945
|
+
|
|
6946
|
+
<div [class]="actionCardClass()" class="rounded-xl p-4 sm:p-6 border transition-all duration-300 hover:scale-105 hover:shadow-xl">
|
|
6947
|
+
<div class="flex items-center gap-3 mb-3">
|
|
6948
|
+
<div [class]="actionIconBgClass()" class="w-8 h-8 sm:w-10 sm:h-10 rounded-lg flex items-center justify-center flex-shrink-0">
|
|
6949
|
+
<svg [class]="actionIconClass()" class="w-5 h-5 sm:w-6 sm:h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6950
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4" />
|
|
6951
|
+
</svg>
|
|
6952
|
+
</div>
|
|
6953
|
+
<h3 [class]="actionTitleClass()" class="text-base sm:text-lg font-semibold">Recommended Actions</h3>
|
|
6954
|
+
</div>
|
|
6955
|
+
<p [class]="descriptionTextClass()" class="text-xs sm:text-sm leading-relaxed">{{ assessment().recommendedActions }}</p>
|
|
6956
|
+
</div>
|
|
6957
|
+
</div>
|
|
6958
|
+
|
|
6959
|
+
<!-- Competitive Positioning Summary -->
|
|
6960
|
+
@if (hasCompetitiveData()) {
|
|
6961
|
+
<div class="mt-6 sm:mt-8">
|
|
6962
|
+
<symphiq-competitive-positioning-summary
|
|
6963
|
+
[metrics]="metrics()"
|
|
6964
|
+
[isLightMode]="isLightMode()"
|
|
6965
|
+
[isCompactMode]="isCompactMode()"
|
|
6966
|
+
[overallDescription]="assessment().competitiveBenchmark?.description"
|
|
6967
|
+
[competitiveBenchmark]="assessment().competitiveBenchmark"
|
|
6968
|
+
[currencySymbol]="currencySymbol()"
|
|
6969
|
+
(scrollToCompetitive)="scrollToCompetitiveSection()" />
|
|
6970
|
+
</div>
|
|
6971
|
+
}
|
|
6972
|
+
</div>
|
|
6973
|
+
}
|
|
6967
6974
|
`,
|
|
6968
6975
|
}]
|
|
6969
6976
|
}], null, { assessment: [{ type: i0.Input, args: [{ isSignal: true, alias: "assessment", required: false }] }], revenueMetric: [{ type: i0.Input, args: [{ isSignal: true, alias: "revenueMetric", required: false }] }], charts: [{ type: i0.Input, args: [{ isSignal: true, alias: "charts", required: false }] }], metrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "metrics", required: false }] }], isLightMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLightMode", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], isCompactMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompactMode", required: false }] }], isChartsLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isChartsLoading", required: false }] }], strengths: [{ type: i0.Input, args: [{ isSignal: true, alias: "strengths", required: false }] }], weaknesses: [{ type: i0.Input, args: [{ isSignal: true, alias: "weaknesses", required: false }] }], currencySymbol: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencySymbol", required: false }] }], scrollToSection: [{ type: i0.Output, args: ["scrollToSection"] }] }); })();
|
|
@@ -13556,9 +13563,6 @@ class ProfileContextService {
|
|
|
13556
13563
|
}
|
|
13557
13564
|
}
|
|
13558
13565
|
}
|
|
13559
|
-
console.log('[ProfileContextService] indexProfile - competitors:', index.competitors.length, 'recommendations:', index.recommendations.length);
|
|
13560
|
-
console.log('[ProfileContextService] indexProfile - recommendation IDs:', index.recommendations.map(r => r.id));
|
|
13561
|
-
console.log('[ProfileContextService] indexProfile - recommendations with relatedCompetitorIds:', index.recommendations.filter(r => r.relatedCompetitorIds && r.relatedCompetitorIds.length > 0).map(r => ({ id: r.id, relatedCompetitorIds: r.relatedCompetitorIds })));
|
|
13562
13566
|
this.contextIndex.set(index);
|
|
13563
13567
|
}
|
|
13564
13568
|
addRecommendations(recommendations) {
|
|
@@ -13566,7 +13570,6 @@ class ProfileContextService {
|
|
|
13566
13570
|
const existingIds = new Set(currentIndex.recommendations.map(r => r.id));
|
|
13567
13571
|
const newRecs = recommendations.filter(r => !existingIds.has(r.id));
|
|
13568
13572
|
const mergedRecommendations = [...currentIndex.recommendations, ...newRecs];
|
|
13569
|
-
console.log('[ProfileContextService] addRecommendations - adding', newRecs.length, 'new recommendations, total:', mergedRecommendations.length);
|
|
13570
13573
|
this.contextIndex.set({
|
|
13571
13574
|
...currentIndex,
|
|
13572
13575
|
recommendations: mergedRecommendations
|
|
@@ -15227,19 +15230,15 @@ class RecommendationCardComponent {
|
|
|
15227
15230
|
}, ...(ngDevMode ? [{ debugName: "displayItem" }] : []));
|
|
15228
15231
|
this.detailedRecommendation = computed(() => {
|
|
15229
15232
|
const inputRec = this.recommendation();
|
|
15230
|
-
console.log('[RecommendationCard] detailedRecommendation - inputRec:', inputRec?.id, 'relatedCompetitorIds:', inputRec?.relatedCompetitorIds, 'relatedProfileItemIds:', inputRec?.relatedProfileItemIds);
|
|
15231
15233
|
if (inputRec) {
|
|
15232
15234
|
if (inputRec.id) {
|
|
15233
15235
|
const serviceRec = this.profileContextService.getRecommendationById(inputRec.id);
|
|
15234
|
-
console.log('[RecommendationCard] detailedRecommendation - serviceRec:', serviceRec?.id, 'relatedCompetitorIds:', serviceRec?.relatedCompetitorIds, 'relatedProfileItemIds:', serviceRec?.relatedProfileItemIds);
|
|
15235
|
-
console.log('[RecommendationCard] detailedRecommendation - allCompetitors in service:', this.profileContextService.getCompetitors());
|
|
15236
15236
|
if (serviceRec) {
|
|
15237
15237
|
const merged = {
|
|
15238
15238
|
...inputRec,
|
|
15239
15239
|
relatedCompetitorIds: inputRec.relatedCompetitorIds || serviceRec.relatedCompetitorIds,
|
|
15240
15240
|
relatedProfileItemIds: inputRec.relatedProfileItemIds || serviceRec.relatedProfileItemIds
|
|
15241
15241
|
};
|
|
15242
|
-
console.log('[RecommendationCard] detailedRecommendation - merged result:', merged.relatedCompetitorIds, merged.relatedProfileItemIds);
|
|
15243
15242
|
return merged;
|
|
15244
15243
|
}
|
|
15245
15244
|
}
|
|
@@ -15310,17 +15309,13 @@ class RecommendationCardComponent {
|
|
|
15310
15309
|
const detailed = this.detailedRecommendation();
|
|
15311
15310
|
const hasCompetitors = !!(detailed?.relatedCompetitorIds && detailed.relatedCompetitorIds.length > 0);
|
|
15312
15311
|
const isExpanded = this.isActuallyExpanded();
|
|
15313
|
-
|
|
15314
|
-
console.log('[RecommendationCard] shouldShowRelatedCompetitors - hasCompetitors:', hasCompetitors, 'isExpanded:', isExpanded, 'shouldShow:', shouldShow, 'relatedCompetitorIds:', detailed?.relatedCompetitorIds);
|
|
15315
|
-
return shouldShow;
|
|
15312
|
+
return hasCompetitors && isExpanded;
|
|
15316
15313
|
}, ...(ngDevMode ? [{ debugName: "shouldShowRelatedCompetitors" }] : []));
|
|
15317
15314
|
this.shouldShowRelatedAreas = computed(() => {
|
|
15318
15315
|
const detailed = this.detailedRecommendation();
|
|
15319
15316
|
const hasAreas = !!(detailed?.relatedProfileItemIds && detailed.relatedProfileItemIds.length > 0);
|
|
15320
15317
|
const isExpanded = this.isActuallyExpanded();
|
|
15321
|
-
|
|
15322
|
-
console.log('[RecommendationCard] shouldShowRelatedAreas - hasAreas:', hasAreas, 'isExpanded:', isExpanded, 'shouldShow:', shouldShow, 'relatedProfileItemIds:', detailed?.relatedProfileItemIds);
|
|
15323
|
-
return shouldShow;
|
|
15318
|
+
return hasAreas && isExpanded;
|
|
15324
15319
|
}, ...(ngDevMode ? [{ debugName: "shouldShowRelatedAreas" }] : []));
|
|
15325
15320
|
this.shouldShowRelatedFocusAreas = computed(() => {
|
|
15326
15321
|
const detailed = this.detailedRecommendation();
|
|
@@ -56060,8 +56055,10 @@ class SymphiqFunnelAnalysisPreviewComponent {
|
|
|
56060
56055
|
return undefined;
|
|
56061
56056
|
}
|
|
56062
56057
|
const series = chart.areaChartData.series;
|
|
56063
|
-
const
|
|
56064
|
-
const
|
|
56058
|
+
const currentYear = new Date().getFullYear().toString();
|
|
56059
|
+
const priorYear = (new Date().getFullYear() - 1).toString();
|
|
56060
|
+
const currentSeries = series.find((s) => s.name === currentYear || s.name === 'This Year');
|
|
56061
|
+
const priorSeries = series.find((s) => s.name === priorYear || s.name === 'Last Year');
|
|
56065
56062
|
const current = currentSeries?.data?.map((d) => d.value || 0) || [];
|
|
56066
56063
|
const prior = priorSeries?.data?.map((d) => d.value || 0);
|
|
56067
56064
|
if (current.length === 0)
|
|
@@ -107561,16 +107558,11 @@ class SymphiqProfileAnalysisUnifiedDashboardComponent {
|
|
|
107561
107558
|
}, ...(ngDevMode ? [{ debugName: "embeddedScrollEffect" }] : []));
|
|
107562
107559
|
this.profileIndexEffect = effect(() => {
|
|
107563
107560
|
const profileToUse = this.profile();
|
|
107564
|
-
console.log('[UnifiedDashboard] profileIndexEffect - profile:', !!profileToUse, 'sections:', profileToUse?.profileStructured?.sections?.length, 'recommendations:', profileToUse?.profileStructured?.recommendations?.length);
|
|
107565
107561
|
if (profileToUse?.profileStructured?.sections) {
|
|
107566
107562
|
const recommendations = profileToUse.profileStructured?.recommendations || [];
|
|
107567
|
-
console.log('[UnifiedDashboard] profileIndexEffect - calling indexProfile with', profileToUse.profileStructured.sections.length, 'sections and', recommendations.length, 'recommendations');
|
|
107568
107563
|
this.profileContextService.indexProfile(profileToUse.profileStructured.sections, recommendations);
|
|
107569
107564
|
this.profileItemLookupService.setProfile(profileToUse);
|
|
107570
107565
|
}
|
|
107571
|
-
else {
|
|
107572
|
-
console.log('[UnifiedDashboard] profileIndexEffect - NO profile data to index');
|
|
107573
|
-
}
|
|
107574
107566
|
}, ...(ngDevMode ? [{ debugName: "profileIndexEffect" }] : []));
|
|
107575
107567
|
this.pendingSourceRequestEffect = effect(() => {
|
|
107576
107568
|
const pending = this.pendingSourceRequest();
|
|
@@ -107684,9 +107676,6 @@ class SymphiqProfileAnalysisUnifiedDashboardComponent {
|
|
|
107684
107676
|
if (sourceResult) {
|
|
107685
107677
|
this.modalService.navigateToSourceRecommendation(sourceResult.recommendation, sourceResult.strategy, sourceResult.objective, sourceResult.goal, sourceResult.sourceAnalysisRef, sourceResult.unifiedGoal, this.viewMode());
|
|
107686
107678
|
}
|
|
107687
|
-
else {
|
|
107688
|
-
console.warn('[Priority Actions] Recommendation not found. ID:', recommendationId);
|
|
107689
|
-
}
|
|
107690
107679
|
}
|
|
107691
107680
|
findRecommendationInUnifiedGoals(recommendationId) {
|
|
107692
107681
|
const unifiedGoals = this.unifiedGoals();
|
|
@@ -107819,7 +107808,6 @@ class SymphiqProfileAnalysisUnifiedDashboardComponent {
|
|
|
107819
107808
|
}
|
|
107820
107809
|
}
|
|
107821
107810
|
}
|
|
107822
|
-
console.log('[SourceAnalysis] openSourceGoalModal - adding', recommendations.length, 'source analysis recommendations');
|
|
107823
107811
|
this.profileContextService.addRecommendations(recommendations);
|
|
107824
107812
|
if (goal) {
|
|
107825
107813
|
const currentModalState = this.modalService.getCurrentState();
|
|
@@ -107827,9 +107815,6 @@ class SymphiqProfileAnalysisUnifiedDashboardComponent {
|
|
|
107827
107815
|
this.modalService.openSourceGoalDetailModal(goal, this.viewMode(), analysisType, currentModalState, sourceTypeTitle);
|
|
107828
107816
|
}
|
|
107829
107817
|
}
|
|
107830
|
-
else {
|
|
107831
|
-
console.warn('[SourceAnalysis] Could not find goal with id:', sourceGoalId);
|
|
107832
|
-
}
|
|
107833
107818
|
this.loadingSourceAnalysisId.set(undefined);
|
|
107834
107819
|
this.pendingSourceRequest.set(undefined);
|
|
107835
107820
|
}
|