@eric-emg/symphiq-components 1.2.199 → 1.2.201
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 +275 -229
- package/fesm2022/symphiq-components.mjs.map +1 -1
- package/index.d.ts +38 -38
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ViewModeEnum, MetricStatusEnum, TrendDirectionEnum, CompetitiveScoreEnum, MetricEnum, DimensionEnum, UiDataPeriodEnum, UiDataComparePeriodEnum, ChartTypeEnum, IconSourceEnum, ProfileAnalysisRecommendationPriorityEnum, ProfileItemTypeEnum, PriceVsCompetitorsEnum, DifferentiationStrengthEnum, ThreatLevelEnum, normalizeToV3, FocusAreaDetailStatusEnum, FocusAreaDomainEnumUtil, FocusAreaDomainEnum, ShopDataLoadStatusEnum, MetricEnumUtil, NumberTypeEnum, AiDynamicContentStatusEnum, FocusAreaHealthEnum, ProfileAnalysisPriorityEnum, CapabilityStateEnum, QuadrantEnum, AdvantageEnum, OverallGradeEnum, OperationalMaturityEnum, ProfileAnalysisEffortLevelEnum, ProfileAnalysisImpactLevelEnum, ProfileAnalysisTypeEnum, LineChartUseCaseEnum, BarChartUseCaseEnum } from '@jebgem/model';
|
|
1
|
+
import { ViewModeEnum, MetricStatusEnum, TrendDirectionEnum, CompetitiveScoreEnum, MetricEnum, DimensionEnum, UiDataPeriodEnum, UiDataComparePeriodEnum, ChartTypeEnum, IconSourceEnum, ProfileAnalysisRecommendationPriorityEnum, ProfileItemTypeEnum, PriceVsCompetitorsEnum, DifferentiationStrengthEnum, ThreatLevelEnum, normalizeToV3, FocusAreaDetailStatusEnum, FocusAreaDomainEnumUtil, FocusAreaDomainEnum, ShopDataLoadStatusEnum, MetricEnumUtil, NumberTypeEnum, FunnelMetricTypeEnum, AiDynamicContentStatusEnum, FocusAreaHealthEnum, ProfileAnalysisPriorityEnum, CapabilityStateEnum, QuadrantEnum, AdvantageEnum, OverallGradeEnum, OperationalMaturityEnum, ProfileAnalysisEffortLevelEnum, ProfileAnalysisImpactLevelEnum, ProfileAnalysisTypeEnum, LineChartUseCaseEnum, BarChartUseCaseEnum } from '@jebgem/model';
|
|
2
2
|
export * from '@jebgem/model';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { Injectable, signal, computed, input, ChangeDetectionStrategy, Component, output, inject, ElementRef, Renderer2, effect, Directive, HostListener, untracked, ViewChild, PLATFORM_ID, Inject, Input } from '@angular/core';
|
|
@@ -56430,26 +56430,49 @@ class InitialTargetSettingComponent {
|
|
|
56430
56430
|
}, ...(ngDevMode ? [{ debugName: "percentageIncrease" }] : []));
|
|
56431
56431
|
this.displayedMetricCalculations = computed(() => {
|
|
56432
56432
|
const response = this.storedResponse();
|
|
56433
|
-
if (!response
|
|
56433
|
+
if (!response) {
|
|
56434
56434
|
return [];
|
|
56435
56435
|
}
|
|
56436
|
-
|
|
56437
|
-
|
|
56438
|
-
|
|
56439
|
-
|
|
56440
|
-
|
|
56441
|
-
|
|
56442
|
-
|
|
56443
|
-
|
|
56444
|
-
|
|
56445
|
-
|
|
56446
|
-
|
|
56447
|
-
|
|
56448
|
-
|
|
56449
|
-
|
|
56450
|
-
|
|
56451
|
-
|
|
56452
|
-
|
|
56436
|
+
const results = [];
|
|
56437
|
+
if (response.funnelMetricValues) {
|
|
56438
|
+
response.funnelMetricValues.forEach((metricValue) => {
|
|
56439
|
+
const metric = metricValue.metric;
|
|
56440
|
+
const funnelMetric = this.funnelMetrics().find(fm => fm.funnelMetric === metric && fm.funnelMetric === fm.relatedMetric);
|
|
56441
|
+
const currentValue = sumMetricFromUiData(this.mainUiData(), metric, 'priorYear');
|
|
56442
|
+
const { targetValue, percentageIncrease } = this.parseMetricValue(metricValue.value);
|
|
56443
|
+
results.push({
|
|
56444
|
+
metric,
|
|
56445
|
+
funnelMetric: metric,
|
|
56446
|
+
currentValue,
|
|
56447
|
+
targetValue,
|
|
56448
|
+
percentageIncrease,
|
|
56449
|
+
isFunnelStage: true,
|
|
56450
|
+
funnelInd: funnelMetric?.funnelInd,
|
|
56451
|
+
relatedInd: 0,
|
|
56452
|
+
description: funnelMetric?.funnelMetricDescription
|
|
56453
|
+
});
|
|
56454
|
+
});
|
|
56455
|
+
}
|
|
56456
|
+
if (response.relatedMetricTargets) {
|
|
56457
|
+
response.relatedMetricTargets.forEach((metricValue) => {
|
|
56458
|
+
const metric = metricValue.metric;
|
|
56459
|
+
const funnelMetric = this.funnelMetrics().find(fm => fm.relatedMetric === metric);
|
|
56460
|
+
const currentValue = sumMetricFromUiData(this.mainUiData(), metric, 'priorYear');
|
|
56461
|
+
const { targetValue, percentageIncrease } = this.parseMetricValue(metricValue.value);
|
|
56462
|
+
results.push({
|
|
56463
|
+
metric,
|
|
56464
|
+
funnelMetric: funnelMetric?.funnelMetric,
|
|
56465
|
+
currentValue,
|
|
56466
|
+
targetValue,
|
|
56467
|
+
percentageIncrease: percentageIncrease || response.equalRelatedMetricIncreasePercent || 0,
|
|
56468
|
+
isFunnelStage: false,
|
|
56469
|
+
funnelInd: funnelMetric?.funnelInd,
|
|
56470
|
+
relatedInd: funnelMetric?.relatedInd,
|
|
56471
|
+
description: funnelMetric?.relatedMetricDescription
|
|
56472
|
+
});
|
|
56473
|
+
});
|
|
56474
|
+
}
|
|
56475
|
+
return results;
|
|
56453
56476
|
}, ...(ngDevMode ? [{ debugName: "displayedMetricCalculations" }] : []));
|
|
56454
56477
|
this.displayedTargetRevenue = computed(() => {
|
|
56455
56478
|
const response = this.storedResponse();
|
|
@@ -56523,6 +56546,28 @@ class InitialTargetSettingComponent {
|
|
|
56523
56546
|
}
|
|
56524
56547
|
}, { allowSignalWrites: true });
|
|
56525
56548
|
}
|
|
56549
|
+
parseMetricValue(value) {
|
|
56550
|
+
if (!value)
|
|
56551
|
+
return { targetValue: 0, percentageIncrease: 0 };
|
|
56552
|
+
let targetValue = 0;
|
|
56553
|
+
let percentageIncrease = 0;
|
|
56554
|
+
const arrowMatch = value.match(/\([\d.,]+\s*->\s*([\d.,]+)\)/);
|
|
56555
|
+
if (arrowMatch) {
|
|
56556
|
+
targetValue = parseFloat(arrowMatch[1].replace(/,/g, ''));
|
|
56557
|
+
}
|
|
56558
|
+
const targetMatch = value.match(/target:\s*([\d.,]+)/);
|
|
56559
|
+
if (targetMatch) {
|
|
56560
|
+
targetValue = parseFloat(targetMatch[1].replace(/,/g, ''));
|
|
56561
|
+
}
|
|
56562
|
+
const percentMatch = value.match(/([-\d.]+)%\s*(increase|change|decrease)?/);
|
|
56563
|
+
if (percentMatch) {
|
|
56564
|
+
percentageIncrease = parseFloat(percentMatch[1]);
|
|
56565
|
+
}
|
|
56566
|
+
if (!arrowMatch && !targetMatch) {
|
|
56567
|
+
targetValue = parseFloat(value.replace(/,/g, '')) || 0;
|
|
56568
|
+
}
|
|
56569
|
+
return { targetValue, percentageIncrease };
|
|
56570
|
+
}
|
|
56526
56571
|
ngAfterViewInit() {
|
|
56527
56572
|
setTimeout(() => {
|
|
56528
56573
|
this.absoluteInputRef?.nativeElement?.focus();
|
|
@@ -56574,7 +56619,8 @@ class InitialTargetSettingComponent {
|
|
|
56574
56619
|
this.calculationState.set('calculating');
|
|
56575
56620
|
const request = {
|
|
56576
56621
|
shopId: this.shopId(),
|
|
56577
|
-
targetRevenue: this.calculatedRevenue()
|
|
56622
|
+
targetRevenue: this.calculatedRevenue(),
|
|
56623
|
+
funnelType: FunnelMetricTypeEnum.REVENUE,
|
|
56578
56624
|
};
|
|
56579
56625
|
this.calculateRevenueRequest.emit(request);
|
|
56580
56626
|
}
|
|
@@ -56801,214 +56847,214 @@ class InitialTargetSettingComponent {
|
|
|
56801
56847
|
AreaChartComponent
|
|
56802
56848
|
],
|
|
56803
56849
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
56804
|
-
template: `
|
|
56805
|
-
<div class="space-y-8 pb-32">
|
|
56806
|
-
<div [ngClass]="sectionCardClasses()" class="rounded-2xl border shadow-lg p-8">
|
|
56807
|
-
<h2 [ngClass]="sectionTitleClasses()" class="text-2xl font-bold mb-6">
|
|
56808
|
-
Calculate Your Revenue Target
|
|
56809
|
-
</h2>
|
|
56810
|
-
|
|
56811
|
-
<div class="grid lg:grid-cols-2 gap-8">
|
|
56812
|
-
<div class="space-y-6">
|
|
56813
|
-
<div>
|
|
56814
|
-
<label [ngClass]="labelClasses()" class="block text-sm font-semibold mb-2">
|
|
56815
|
-
{{ currentYear() }} Revenue
|
|
56816
|
-
</label>
|
|
56817
|
-
<div class="space-y-1 mb-4">
|
|
56818
|
-
<p [ngClass]="priorYearLabelClasses()" class="text-xs">
|
|
56819
|
-
{{ priorYear() }} Revenue: {{ formatCurrency(priorYearRevenue()) }}
|
|
56820
|
-
</p>
|
|
56821
|
-
@if (currentPaceProjection() > 0) {
|
|
56822
|
-
<p [ngClass]="priorYearLabelClasses()" class="text-xs">
|
|
56823
|
-
Current Pace Projection: {{ formatCurrency(currentPaceProjection()) }}
|
|
56824
|
-
</p>
|
|
56825
|
-
}
|
|
56826
|
-
</div>
|
|
56827
|
-
|
|
56828
|
-
<div class="flex gap-2 mb-4">
|
|
56829
|
-
<button
|
|
56830
|
-
(click)="setInputMode('absolute')"
|
|
56831
|
-
[ngClass]="inputModeButtonClasses('absolute')"
|
|
56832
|
-
class="flex-1 py-2 px-4 rounded-lg text-sm font-semibold transition-all">
|
|
56833
|
-
Absolute Amount
|
|
56834
|
-
</button>
|
|
56835
|
-
<button
|
|
56836
|
-
(click)="setInputMode('percentage')"
|
|
56837
|
-
[ngClass]="inputModeButtonClasses('percentage')"
|
|
56838
|
-
class="flex-1 py-2 px-4 rounded-lg text-sm font-semibold transition-all">
|
|
56839
|
-
% Increase
|
|
56840
|
-
</button>
|
|
56841
|
-
</div>
|
|
56842
|
-
|
|
56843
|
-
@if (inputMode() === 'absolute') {
|
|
56844
|
-
<div class="relative">
|
|
56845
|
-
<span [ngClass]="inputPrefixClasses()" class="absolute left-4 top-1/2 -translate-y-1/2 text-xl font-bold">
|
|
56846
|
-
$
|
|
56847
|
-
</span>
|
|
56848
|
-
<input
|
|
56849
|
-
#absoluteInputRef
|
|
56850
|
-
type="number"
|
|
56851
|
-
[(ngModel)]="absoluteInput"
|
|
56852
|
-
(ngModelChange)="onAbsoluteInputChange()"
|
|
56853
|
-
[ngClass]="inputClasses()"
|
|
56854
|
-
class="w-full pl-10 pr-4 py-4 rounded-xl text-2xl font-bold border-2 transition-all"
|
|
56855
|
-
placeholder="0"
|
|
56856
|
-
min="0"
|
|
56857
|
-
step="1000">
|
|
56858
|
-
</div>
|
|
56859
|
-
} @else {
|
|
56860
|
-
<div class="relative">
|
|
56861
|
-
<input
|
|
56862
|
-
#percentageInputRef
|
|
56863
|
-
type="number"
|
|
56864
|
-
[(ngModel)]="percentageInput"
|
|
56865
|
-
(ngModelChange)="onPercentageInputChange()"
|
|
56866
|
-
[ngClass]="inputClasses()"
|
|
56867
|
-
class="w-full pr-10 pl-4 py-4 rounded-xl text-2xl font-bold border-2 transition-all"
|
|
56868
|
-
placeholder="0"
|
|
56869
|
-
min="0"
|
|
56870
|
-
max="1000"
|
|
56871
|
-
step="0.1">
|
|
56872
|
-
<span [ngClass]="inputSuffixClasses()" class="absolute right-4 top-1/2 -translate-y-1/2 text-xl font-bold">
|
|
56873
|
-
%
|
|
56874
|
-
</span>
|
|
56875
|
-
</div>
|
|
56876
|
-
}
|
|
56877
|
-
</div>
|
|
56878
|
-
|
|
56879
|
-
@if (calculatedRevenue() > 0) {
|
|
56880
|
-
<div [ngClass]="calculatedValuesCardClasses()" class="p-6 rounded-xl border-2">
|
|
56881
|
-
<div class="space-y-4">
|
|
56882
|
-
<div>
|
|
56883
|
-
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56884
|
-
{{ currentYear() }} Revenue Target
|
|
56885
|
-
</p>
|
|
56886
|
-
<p [ngClass]="calculatedValueClasses()" class="text-3xl font-bold">
|
|
56887
|
-
{{ formatCurrency(calculatedRevenue()) }}
|
|
56888
|
-
</p>
|
|
56889
|
-
</div>
|
|
56890
|
-
<div class="grid grid-cols-2 gap-4 pt-4" [ngClass]="calculatedDividerClasses()">
|
|
56891
|
-
<div>
|
|
56892
|
-
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56893
|
-
Increase Amount
|
|
56894
|
-
</p>
|
|
56895
|
-
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56896
|
-
{{ formatCurrency(calculatedRevenue() - priorYearRevenue()) }}
|
|
56897
|
-
</p>
|
|
56898
|
-
</div>
|
|
56899
|
-
<div>
|
|
56900
|
-
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56901
|
-
% Growth
|
|
56902
|
-
</p>
|
|
56903
|
-
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56904
|
-
+{{ formatPercentage(percentageIncrease(), 1) }}
|
|
56905
|
-
</p>
|
|
56906
|
-
</div>
|
|
56907
|
-
</div>
|
|
56908
|
-
@if (currentPaceProjection() > 0 && gapToClose().amount !== 0) {
|
|
56909
|
-
<div class="grid grid-cols-2 gap-4 pt-4" [ngClass]="calculatedDividerClasses()">
|
|
56910
|
-
<div>
|
|
56911
|
-
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56912
|
-
Gap to Close
|
|
56913
|
-
</p>
|
|
56914
|
-
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56915
|
-
{{ formatCurrency(absValue(gapToClose().amount)) }}
|
|
56916
|
-
</p>
|
|
56917
|
-
</div>
|
|
56918
|
-
<div>
|
|
56919
|
-
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56920
|
-
Additional Growth Needed
|
|
56921
|
-
</p>
|
|
56922
|
-
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56923
|
-
{{ gapToClose().amount > 0 ? '+' : '' }}{{ formatPercentage(gapToClose().percentage, 1) }}
|
|
56924
|
-
</p>
|
|
56925
|
-
</div>
|
|
56926
|
-
</div>
|
|
56927
|
-
}
|
|
56928
|
-
</div>
|
|
56929
|
-
</div>
|
|
56930
|
-
}
|
|
56931
|
-
</div>
|
|
56932
|
-
|
|
56933
|
-
<div>
|
|
56934
|
-
<p [ngClass]="chartTitleClasses()" class="text-sm font-semibold mb-3">
|
|
56935
|
-
Year-over-Year Revenue Trend
|
|
56936
|
-
</p>
|
|
56937
|
-
<div [ngClass]="chartContainerClasses()" class="rounded-xl border p-4">
|
|
56938
|
-
@if (revenueChartData()) {
|
|
56939
|
-
<symphiq-area-chart
|
|
56940
|
-
[chart]="revenueChartData()!"
|
|
56941
|
-
[showAxisLabels]="true"
|
|
56942
|
-
[viewMode]="viewMode()"
|
|
56943
|
-
[currencySymbol]="'$'"
|
|
56944
|
-
[height]="'320px'"
|
|
56945
|
-
/>
|
|
56946
|
-
} @else {
|
|
56947
|
-
<div class="h-64 flex items-center justify-center">
|
|
56948
|
-
<p [ngClass]="noDataClasses()" class="text-sm">
|
|
56949
|
-
No revenue data available
|
|
56950
|
-
</p>
|
|
56951
|
-
</div>
|
|
56952
|
-
}
|
|
56953
|
-
</div>
|
|
56954
|
-
</div>
|
|
56955
|
-
</div>
|
|
56956
|
-
</div>
|
|
56957
|
-
|
|
56958
|
-
@if (showMetricsVisualization()) {
|
|
56959
|
-
<div [ngClass]="sectionCardClasses()" class="rounded-2xl border shadow-lg p-8">
|
|
56960
|
-
<div class="mb-6">
|
|
56961
|
-
<h2 [ngClass]="sectionTitleClasses()" class="text-2xl font-bold mb-2">
|
|
56962
|
-
Contributing Metrics
|
|
56963
|
-
</h2>
|
|
56964
|
-
<p [ngClass]="sectionDescriptionClasses()" class="text-sm">
|
|
56965
|
-
To achieve your revenue target of {{ formatCurrency(displayedTargetRevenue()) }}, the following metrics need to improve by these amounts. These improvements compound through your funnel to drive revenue growth.
|
|
56966
|
-
</p>
|
|
56967
|
-
</div>
|
|
56968
|
-
|
|
56969
|
-
<symphiq-funnel-metrics-visualization
|
|
56970
|
-
[viewMode]="viewMode()"
|
|
56971
|
-
[calculations]="displayedMetricCalculations()"
|
|
56972
|
-
[pacingMetrics]="pacingMetrics()"
|
|
56973
|
-
/>
|
|
56974
|
-
</div>
|
|
56975
|
-
}
|
|
56976
|
-
|
|
56977
|
-
<symphiq-sticky-submit-bar
|
|
56978
|
-
[viewMode]="viewMode()"
|
|
56979
|
-
[isValid]="isValid()"
|
|
56980
|
-
[isSubmitting]="isCalculating()"
|
|
56981
|
-
[validationMessage]="validationMessage()"
|
|
56982
|
-
[buttonText]="submitButtonText()"
|
|
56983
|
-
(submitClick)="handleSubmitClick()"
|
|
56984
|
-
/>
|
|
56985
|
-
|
|
56986
|
-
@if (calculationState() === 'results') {
|
|
56987
|
-
<div class="fixed bottom-24 left-0 right-0 z-40 pb-4 px-4">
|
|
56988
|
-
<div class="max-w-7xl mx-auto flex gap-4 justify-center">
|
|
56989
|
-
<button
|
|
56990
|
-
(click)="handleAdjustTarget()"
|
|
56991
|
-
[ngClass]="secondaryButtonClasses()"
|
|
56992
|
-
class="px-6 py-3 rounded-xl font-semibold transition-all shadow-lg">
|
|
56993
|
-
Adjust Revenue Target
|
|
56994
|
-
</button>
|
|
56995
|
-
</div>
|
|
56996
|
-
</div>
|
|
56997
|
-
}
|
|
56998
|
-
|
|
56999
|
-
@if (calculationState() === 'input' && hasStoredResponse()) {
|
|
57000
|
-
<div class="fixed bottom-32 left-0 right-0 z-40 pb-4 px-4">
|
|
57001
|
-
<div class="max-w-7xl mx-auto flex gap-4 justify-center">
|
|
57002
|
-
<button
|
|
57003
|
-
(click)="handleCancel()"
|
|
57004
|
-
[ngClass]="cancelButtonClasses()"
|
|
57005
|
-
class="px-6 py-3 rounded-xl font-semibold transition-all shadow-lg">
|
|
57006
|
-
Cancel
|
|
57007
|
-
</button>
|
|
57008
|
-
</div>
|
|
57009
|
-
</div>
|
|
57010
|
-
}
|
|
57011
|
-
</div>
|
|
56850
|
+
template: `
|
|
56851
|
+
<div class="space-y-8 pb-32">
|
|
56852
|
+
<div [ngClass]="sectionCardClasses()" class="rounded-2xl border shadow-lg p-8">
|
|
56853
|
+
<h2 [ngClass]="sectionTitleClasses()" class="text-2xl font-bold mb-6">
|
|
56854
|
+
Calculate Your Revenue Target
|
|
56855
|
+
</h2>
|
|
56856
|
+
|
|
56857
|
+
<div class="grid lg:grid-cols-2 gap-8">
|
|
56858
|
+
<div class="space-y-6">
|
|
56859
|
+
<div>
|
|
56860
|
+
<label [ngClass]="labelClasses()" class="block text-sm font-semibold mb-2">
|
|
56861
|
+
{{ currentYear() }} Revenue
|
|
56862
|
+
</label>
|
|
56863
|
+
<div class="space-y-1 mb-4">
|
|
56864
|
+
<p [ngClass]="priorYearLabelClasses()" class="text-xs">
|
|
56865
|
+
{{ priorYear() }} Revenue: {{ formatCurrency(priorYearRevenue()) }}
|
|
56866
|
+
</p>
|
|
56867
|
+
@if (currentPaceProjection() > 0) {
|
|
56868
|
+
<p [ngClass]="priorYearLabelClasses()" class="text-xs">
|
|
56869
|
+
Current Pace Projection: {{ formatCurrency(currentPaceProjection()) }}
|
|
56870
|
+
</p>
|
|
56871
|
+
}
|
|
56872
|
+
</div>
|
|
56873
|
+
|
|
56874
|
+
<div class="flex gap-2 mb-4">
|
|
56875
|
+
<button
|
|
56876
|
+
(click)="setInputMode('absolute')"
|
|
56877
|
+
[ngClass]="inputModeButtonClasses('absolute')"
|
|
56878
|
+
class="flex-1 py-2 px-4 rounded-lg text-sm font-semibold transition-all">
|
|
56879
|
+
Absolute Amount
|
|
56880
|
+
</button>
|
|
56881
|
+
<button
|
|
56882
|
+
(click)="setInputMode('percentage')"
|
|
56883
|
+
[ngClass]="inputModeButtonClasses('percentage')"
|
|
56884
|
+
class="flex-1 py-2 px-4 rounded-lg text-sm font-semibold transition-all">
|
|
56885
|
+
% Increase
|
|
56886
|
+
</button>
|
|
56887
|
+
</div>
|
|
56888
|
+
|
|
56889
|
+
@if (inputMode() === 'absolute') {
|
|
56890
|
+
<div class="relative">
|
|
56891
|
+
<span [ngClass]="inputPrefixClasses()" class="absolute left-4 top-1/2 -translate-y-1/2 text-xl font-bold">
|
|
56892
|
+
$
|
|
56893
|
+
</span>
|
|
56894
|
+
<input
|
|
56895
|
+
#absoluteInputRef
|
|
56896
|
+
type="number"
|
|
56897
|
+
[(ngModel)]="absoluteInput"
|
|
56898
|
+
(ngModelChange)="onAbsoluteInputChange()"
|
|
56899
|
+
[ngClass]="inputClasses()"
|
|
56900
|
+
class="w-full pl-10 pr-4 py-4 rounded-xl text-2xl font-bold border-2 transition-all"
|
|
56901
|
+
placeholder="0"
|
|
56902
|
+
min="0"
|
|
56903
|
+
step="1000">
|
|
56904
|
+
</div>
|
|
56905
|
+
} @else {
|
|
56906
|
+
<div class="relative">
|
|
56907
|
+
<input
|
|
56908
|
+
#percentageInputRef
|
|
56909
|
+
type="number"
|
|
56910
|
+
[(ngModel)]="percentageInput"
|
|
56911
|
+
(ngModelChange)="onPercentageInputChange()"
|
|
56912
|
+
[ngClass]="inputClasses()"
|
|
56913
|
+
class="w-full pr-10 pl-4 py-4 rounded-xl text-2xl font-bold border-2 transition-all"
|
|
56914
|
+
placeholder="0"
|
|
56915
|
+
min="0"
|
|
56916
|
+
max="1000"
|
|
56917
|
+
step="0.1">
|
|
56918
|
+
<span [ngClass]="inputSuffixClasses()" class="absolute right-4 top-1/2 -translate-y-1/2 text-xl font-bold">
|
|
56919
|
+
%
|
|
56920
|
+
</span>
|
|
56921
|
+
</div>
|
|
56922
|
+
}
|
|
56923
|
+
</div>
|
|
56924
|
+
|
|
56925
|
+
@if (calculatedRevenue() > 0) {
|
|
56926
|
+
<div [ngClass]="calculatedValuesCardClasses()" class="p-6 rounded-xl border-2">
|
|
56927
|
+
<div class="space-y-4">
|
|
56928
|
+
<div>
|
|
56929
|
+
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56930
|
+
{{ currentYear() }} Revenue Target
|
|
56931
|
+
</p>
|
|
56932
|
+
<p [ngClass]="calculatedValueClasses()" class="text-3xl font-bold">
|
|
56933
|
+
{{ formatCurrency(calculatedRevenue()) }}
|
|
56934
|
+
</p>
|
|
56935
|
+
</div>
|
|
56936
|
+
<div class="grid grid-cols-2 gap-4 pt-4" [ngClass]="calculatedDividerClasses()">
|
|
56937
|
+
<div>
|
|
56938
|
+
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56939
|
+
Increase Amount
|
|
56940
|
+
</p>
|
|
56941
|
+
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56942
|
+
{{ formatCurrency(calculatedRevenue() - priorYearRevenue()) }}
|
|
56943
|
+
</p>
|
|
56944
|
+
</div>
|
|
56945
|
+
<div>
|
|
56946
|
+
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56947
|
+
% Growth
|
|
56948
|
+
</p>
|
|
56949
|
+
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56950
|
+
+{{ formatPercentage(percentageIncrease(), 1) }}
|
|
56951
|
+
</p>
|
|
56952
|
+
</div>
|
|
56953
|
+
</div>
|
|
56954
|
+
@if (currentPaceProjection() > 0 && gapToClose().amount !== 0) {
|
|
56955
|
+
<div class="grid grid-cols-2 gap-4 pt-4" [ngClass]="calculatedDividerClasses()">
|
|
56956
|
+
<div>
|
|
56957
|
+
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56958
|
+
Gap to Close
|
|
56959
|
+
</p>
|
|
56960
|
+
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56961
|
+
{{ formatCurrency(absValue(gapToClose().amount)) }}
|
|
56962
|
+
</p>
|
|
56963
|
+
</div>
|
|
56964
|
+
<div>
|
|
56965
|
+
<p [ngClass]="calculatedLabelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1">
|
|
56966
|
+
Additional Growth Needed
|
|
56967
|
+
</p>
|
|
56968
|
+
<p [ngClass]="calculatedSecondaryClasses()" class="text-xl font-bold">
|
|
56969
|
+
{{ gapToClose().amount > 0 ? '+' : '' }}{{ formatPercentage(gapToClose().percentage, 1) }}
|
|
56970
|
+
</p>
|
|
56971
|
+
</div>
|
|
56972
|
+
</div>
|
|
56973
|
+
}
|
|
56974
|
+
</div>
|
|
56975
|
+
</div>
|
|
56976
|
+
}
|
|
56977
|
+
</div>
|
|
56978
|
+
|
|
56979
|
+
<div>
|
|
56980
|
+
<p [ngClass]="chartTitleClasses()" class="text-sm font-semibold mb-3">
|
|
56981
|
+
Year-over-Year Revenue Trend
|
|
56982
|
+
</p>
|
|
56983
|
+
<div [ngClass]="chartContainerClasses()" class="rounded-xl border p-4">
|
|
56984
|
+
@if (revenueChartData()) {
|
|
56985
|
+
<symphiq-area-chart
|
|
56986
|
+
[chart]="revenueChartData()!"
|
|
56987
|
+
[showAxisLabels]="true"
|
|
56988
|
+
[viewMode]="viewMode()"
|
|
56989
|
+
[currencySymbol]="'$'"
|
|
56990
|
+
[height]="'320px'"
|
|
56991
|
+
/>
|
|
56992
|
+
} @else {
|
|
56993
|
+
<div class="h-64 flex items-center justify-center">
|
|
56994
|
+
<p [ngClass]="noDataClasses()" class="text-sm">
|
|
56995
|
+
No revenue data available
|
|
56996
|
+
</p>
|
|
56997
|
+
</div>
|
|
56998
|
+
}
|
|
56999
|
+
</div>
|
|
57000
|
+
</div>
|
|
57001
|
+
</div>
|
|
57002
|
+
</div>
|
|
57003
|
+
|
|
57004
|
+
@if (showMetricsVisualization()) {
|
|
57005
|
+
<div [ngClass]="sectionCardClasses()" class="rounded-2xl border shadow-lg p-8">
|
|
57006
|
+
<div class="mb-6">
|
|
57007
|
+
<h2 [ngClass]="sectionTitleClasses()" class="text-2xl font-bold mb-2">
|
|
57008
|
+
Contributing Metrics
|
|
57009
|
+
</h2>
|
|
57010
|
+
<p [ngClass]="sectionDescriptionClasses()" class="text-sm">
|
|
57011
|
+
To achieve your revenue target of {{ formatCurrency(displayedTargetRevenue()) }}, the following metrics need to improve by these amounts. These improvements compound through your funnel to drive revenue growth.
|
|
57012
|
+
</p>
|
|
57013
|
+
</div>
|
|
57014
|
+
|
|
57015
|
+
<symphiq-funnel-metrics-visualization
|
|
57016
|
+
[viewMode]="viewMode()"
|
|
57017
|
+
[calculations]="displayedMetricCalculations()"
|
|
57018
|
+
[pacingMetrics]="pacingMetrics()"
|
|
57019
|
+
/>
|
|
57020
|
+
</div>
|
|
57021
|
+
}
|
|
57022
|
+
|
|
57023
|
+
<symphiq-sticky-submit-bar
|
|
57024
|
+
[viewMode]="viewMode()"
|
|
57025
|
+
[isValid]="isValid()"
|
|
57026
|
+
[isSubmitting]="isCalculating()"
|
|
57027
|
+
[validationMessage]="validationMessage()"
|
|
57028
|
+
[buttonText]="submitButtonText()"
|
|
57029
|
+
(submitClick)="handleSubmitClick()"
|
|
57030
|
+
/>
|
|
57031
|
+
|
|
57032
|
+
@if (calculationState() === 'results') {
|
|
57033
|
+
<div class="fixed bottom-24 left-0 right-0 z-40 pb-4 px-4">
|
|
57034
|
+
<div class="max-w-7xl mx-auto flex gap-4 justify-center">
|
|
57035
|
+
<button
|
|
57036
|
+
(click)="handleAdjustTarget()"
|
|
57037
|
+
[ngClass]="secondaryButtonClasses()"
|
|
57038
|
+
class="px-6 py-3 rounded-xl font-semibold transition-all shadow-lg">
|
|
57039
|
+
Adjust Revenue Target
|
|
57040
|
+
</button>
|
|
57041
|
+
</div>
|
|
57042
|
+
</div>
|
|
57043
|
+
}
|
|
57044
|
+
|
|
57045
|
+
@if (calculationState() === 'input' && hasStoredResponse()) {
|
|
57046
|
+
<div class="fixed bottom-32 left-0 right-0 z-40 pb-4 px-4">
|
|
57047
|
+
<div class="max-w-7xl mx-auto flex gap-4 justify-center">
|
|
57048
|
+
<button
|
|
57049
|
+
(click)="handleCancel()"
|
|
57050
|
+
[ngClass]="cancelButtonClasses()"
|
|
57051
|
+
class="px-6 py-3 rounded-xl font-semibold transition-all shadow-lg">
|
|
57052
|
+
Cancel
|
|
57053
|
+
</button>
|
|
57054
|
+
</div>
|
|
57055
|
+
</div>
|
|
57056
|
+
}
|
|
57057
|
+
</div>
|
|
57012
57058
|
`
|
|
57013
57059
|
}]
|
|
57014
57060
|
}], () => [], { absoluteInputRef: [{
|
|
@@ -57018,7 +57064,7 @@ class InitialTargetSettingComponent {
|
|
|
57018
57064
|
type: ViewChild,
|
|
57019
57065
|
args: ['percentageInputRef']
|
|
57020
57066
|
}], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], funnelMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "funnelMetrics", required: false }] }], mainUiData: [{ type: i0.Input, args: [{ isSignal: true, alias: "mainUiData", required: false }] }], trendUiData: [{ type: i0.Input, args: [{ isSignal: true, alias: "trendUiData", required: false }] }], shopId: [{ type: i0.Input, args: [{ isSignal: true, alias: "shopId", required: false }] }], pacingMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingMetrics", required: false }] }], dataResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataResults", required: false }] }], reverseCalculationResponse: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverseCalculationResponse", required: false }] }], targetsCreated: [{ type: i0.Output, args: ["targetsCreated"] }], calculateRevenueRequest: [{ type: i0.Output, args: ["calculateRevenueRequest"] }] }); })();
|
|
57021
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(InitialTargetSettingComponent, { className: "InitialTargetSettingComponent", filePath: "lib/components/revenue-calculator-dashboard/initial-target-setting.component.ts", lineNumber:
|
|
57067
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(InitialTargetSettingComponent, { className: "InitialTargetSettingComponent", filePath: "lib/components/revenue-calculator-dashboard/initial-target-setting.component.ts", lineNumber: 259 }); })();
|
|
57022
57068
|
|
|
57023
57069
|
function IndeterminateSpinnerComponent_For_5_Template(rf, ctx) { if (rf & 1) {
|
|
57024
57070
|
i0.ɵɵelement(0, "div", 5);
|