@embedreach/components 0.3.26 → 0.3.27
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/dist/chunks/index.js +5003 -2648
- package/dist/chunks/sandbox-loading-screen.js +674 -60
- package/dist/index.d.ts +6 -1
- package/dist/index.umd.js +11 -11
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -20760,6 +20760,7 @@ const createPartnerLocationsFactory = (platformConfig, businessId, platformId, c
|
|
|
20760
20760
|
phone: f.phone.number(),
|
|
20761
20761
|
email: f.internet.email(),
|
|
20762
20762
|
website: `https://${platformConfig.name.toLowerCase().replace(/\s+/g, "-")}.com`,
|
|
20763
|
+
googleBusinessProfilePlaceId: null,
|
|
20763
20764
|
businessId,
|
|
20764
20765
|
platformId,
|
|
20765
20766
|
createdAt: f.date.past(),
|
|
@@ -20835,6 +20836,7 @@ const createReputationConfigFactory = (platformConfig, businessId, partnerLocati
|
|
|
20835
20836
|
id: f.string.uuid(),
|
|
20836
20837
|
businessId,
|
|
20837
20838
|
locationMappings,
|
|
20839
|
+
// Backend provides this by reading from partner locations
|
|
20838
20840
|
emailChannelSenderId: null,
|
|
20839
20841
|
// Will be set when user configures
|
|
20840
20842
|
smsChannelSenderId: null,
|
|
@@ -21432,11 +21434,7 @@ const createWebPresenceContentFactory = (platformConfig, businessConfig) => {
|
|
|
21432
21434
|
const createSandboxMeasureAndAcquireData = (platformId, businessId) => {
|
|
21433
21435
|
const platformConfigKey = getPlatformConfigKey(platformId);
|
|
21434
21436
|
const platformConfig = {
|
|
21435
|
-
id: platformConfigKey
|
|
21436
|
-
name: platformConfigKey === "goose" ? "ACME Pet Spa" : platformConfigKey === "renterra" ? "Tomers Rentals" : "Default",
|
|
21437
|
-
brandColors: [],
|
|
21438
|
-
locationNames: [],
|
|
21439
|
-
locationAreas: []
|
|
21437
|
+
id: platformConfigKey
|
|
21440
21438
|
};
|
|
21441
21439
|
const businessConfig = getBusinessConfig(platformId);
|
|
21442
21440
|
const businessesMe = createBusinessDataFactory(
|
|
@@ -21703,7 +21701,7 @@ const native = {
|
|
|
21703
21701
|
randomUUID
|
|
21704
21702
|
};
|
|
21705
21703
|
function v4(options, buf, offset) {
|
|
21706
|
-
if (native.randomUUID &&
|
|
21704
|
+
if (native.randomUUID && true && !options) {
|
|
21707
21705
|
return native.randomUUID();
|
|
21708
21706
|
}
|
|
21709
21707
|
options = options || {};
|
|
@@ -22162,7 +22160,7 @@ const measureAndAcquireHandlers = [
|
|
|
22162
22160
|
locations: []
|
|
22163
22161
|
}
|
|
22164
22162
|
},
|
|
22165
|
-
tracking_template: "{lpurl}?gclid={gclid}&er_campaign_id={campaignid}&utm_source=google&campaignid={campaignid}&adgroupid={adgroupid}&random={random}",
|
|
22163
|
+
tracking_template: "{lpurl}?gclid={gclid}&er_campaign_id={campaignid}&utm_source=google&campaignid={campaignid}&adgroupid={adgroupid}&keyword={keyword}&random={random}",
|
|
22166
22164
|
reach_managed: true,
|
|
22167
22165
|
created_at: now,
|
|
22168
22166
|
updated_at: now
|
|
@@ -22801,7 +22799,7 @@ const generateReviewAnalyticsData = ({
|
|
|
22801
22799
|
const platformConfig = getPlatformConfig(
|
|
22802
22800
|
platformData.businessesMe?.platform_id
|
|
22803
22801
|
);
|
|
22804
|
-
const isAllTimeQuery = !queryParams.start_date || !queryParams.end_date;
|
|
22802
|
+
const isAllTimeQuery = !queryParams.start_date || !queryParams.end_date || queryParams.start_date && queryParams.start_date.startsWith("2020-");
|
|
22805
22803
|
let scalingFactor = 1;
|
|
22806
22804
|
if (!isAllTimeQuery) {
|
|
22807
22805
|
const { requestedDays } = parseDateRange(
|
|
@@ -22816,14 +22814,15 @@ const generateReviewAnalyticsData = ({
|
|
|
22816
22814
|
platformConfig,
|
|
22817
22815
|
scalingFactor,
|
|
22818
22816
|
false,
|
|
22819
|
-
isAllTimeQuery
|
|
22817
|
+
isAllTimeQuery || false
|
|
22820
22818
|
);
|
|
22821
|
-
|
|
22819
|
+
const includeComparison = Boolean(queryParams.include_comparison);
|
|
22820
|
+
if (includeComparison) {
|
|
22822
22821
|
const previousPeriodData = generateReviewPeriodData(
|
|
22823
22822
|
platformConfig,
|
|
22824
22823
|
scalingFactor,
|
|
22825
22824
|
true,
|
|
22826
|
-
isAllTimeQuery
|
|
22825
|
+
isAllTimeQuery || false
|
|
22827
22826
|
);
|
|
22828
22827
|
const comparison = calculateReviewComparison(
|
|
22829
22828
|
currentPeriodData,
|
|
@@ -22846,13 +22845,14 @@ const generateReviewAnalyticsData = ({
|
|
|
22846
22845
|
return basicResponse;
|
|
22847
22846
|
};
|
|
22848
22847
|
function generateReviewPeriodData(platformConfig, scalingFactor, isPrevious = false, isAllTime = false) {
|
|
22849
|
-
const baseMetrics = isAllTime ? getAllTimePlatformReviewMetrics(platformConfig) : getBasePlatformReviewMetrics(platformConfig);
|
|
22848
|
+
const baseMetrics = isAllTime ? getAllTimePlatformReviewMetrics(platformConfig) : getBasePlatformReviewMetrics$1(platformConfig);
|
|
22850
22849
|
const scaledTotalCount = isAllTime ? baseMetrics.totalCount : Math.max(1, Math.round(baseMetrics.totalCount * scalingFactor));
|
|
22851
|
-
const performanceMultiplier = isPrevious ?
|
|
22850
|
+
const performanceMultiplier = isPrevious ? 0.9 : 1;
|
|
22852
22851
|
const adjustedTotalCount = Math.round(
|
|
22853
22852
|
scaledTotalCount * performanceMultiplier
|
|
22854
22853
|
);
|
|
22855
|
-
const
|
|
22854
|
+
const ratingDelta = isPrevious ? -0.2 : 0;
|
|
22855
|
+
const adjustedAverageRating = baseMetrics.averageRating + ratingDelta;
|
|
22856
22856
|
const ratingDistribution = generateRatingDistribution(
|
|
22857
22857
|
adjustedTotalCount,
|
|
22858
22858
|
adjustedAverageRating
|
|
@@ -22863,21 +22863,22 @@ function generateReviewPeriodData(platformConfig, scalingFactor, isPrevious = fa
|
|
|
22863
22863
|
ratingDistribution
|
|
22864
22864
|
};
|
|
22865
22865
|
}
|
|
22866
|
-
function getBasePlatformReviewMetrics(platformConfig) {
|
|
22866
|
+
function getBasePlatformReviewMetrics$1(platformConfig) {
|
|
22867
22867
|
const industryMultipliers = {
|
|
22868
22868
|
// Pet spa industry (Goose) - high customer satisfaction
|
|
22869
22869
|
"ACME Pet Spa": {
|
|
22870
|
-
totalCount:
|
|
22870
|
+
totalCount: 8,
|
|
22871
|
+
// Much lower - reviews are rare compared to emails
|
|
22871
22872
|
averageRating: 4.6
|
|
22872
22873
|
},
|
|
22873
22874
|
// Equipment rental (Renterra) - moderate review volume
|
|
22874
22875
|
"Tomer's Rentals": {
|
|
22875
|
-
totalCount:
|
|
22876
|
+
totalCount: 5,
|
|
22876
22877
|
averageRating: 4.2
|
|
22877
22878
|
},
|
|
22878
22879
|
// Default platform
|
|
22879
22880
|
default: {
|
|
22880
|
-
totalCount:
|
|
22881
|
+
totalCount: 6,
|
|
22881
22882
|
averageRating: 4.3
|
|
22882
22883
|
}
|
|
22883
22884
|
};
|
|
@@ -22888,19 +22889,19 @@ function getAllTimePlatformReviewMetrics(platformConfig) {
|
|
|
22888
22889
|
const industryMultipliers = {
|
|
22889
22890
|
// Pet spa industry (Goose) - high customer satisfaction
|
|
22890
22891
|
"ACME Pet Spa": {
|
|
22891
|
-
totalCount:
|
|
22892
|
-
// Much
|
|
22892
|
+
totalCount: 124,
|
|
22893
|
+
// Much lower - reviews are rare compared to emails
|
|
22893
22894
|
averageRating: 4.3
|
|
22894
22895
|
// Slightly lower all-time average
|
|
22895
22896
|
},
|
|
22896
22897
|
// Equipment rental (Renterra) - moderate review volume
|
|
22897
22898
|
"Tomer's Rentals": {
|
|
22898
|
-
totalCount:
|
|
22899
|
+
totalCount: 78,
|
|
22899
22900
|
averageRating: 4.1
|
|
22900
22901
|
},
|
|
22901
22902
|
// Default platform
|
|
22902
22903
|
default: {
|
|
22903
|
-
totalCount:
|
|
22904
|
+
totalCount: 95,
|
|
22904
22905
|
averageRating: 4.2
|
|
22905
22906
|
}
|
|
22906
22907
|
};
|
|
@@ -23018,58 +23019,89 @@ const generateFeedbackAnalyticsData = ({
|
|
|
23018
23019
|
averageRating: currentPeriodData.averageRating,
|
|
23019
23020
|
responseRate: currentPeriodData.responseRate,
|
|
23020
23021
|
positiveResponses: currentPeriodData.positiveResponses,
|
|
23021
|
-
negativeResponses: currentPeriodData.negativeResponses
|
|
23022
|
+
negativeResponses: currentPeriodData.negativeResponses,
|
|
23023
|
+
passiveResponses: currentPeriodData.passiveResponses,
|
|
23024
|
+
npsScore: currentPeriodData.npsScore
|
|
23022
23025
|
};
|
|
23023
23026
|
return basicResponse;
|
|
23024
23027
|
};
|
|
23025
23028
|
function generateFeedbackPeriodData(platformConfig, scalingFactor, isPrevious = false, isAllTime = false) {
|
|
23026
|
-
const baseMetrics = isAllTime ? getAllTimePlatformFeedbackMetrics(platformConfig) : getBasePlatformFeedbackMetrics(platformConfig);
|
|
23029
|
+
const baseMetrics = isAllTime ? getAllTimePlatformFeedbackMetrics(platformConfig) : getBasePlatformFeedbackMetrics$1(platformConfig);
|
|
23027
23030
|
const scaledTotalSent = isAllTime ? baseMetrics.totalSent : Math.max(1, Math.round(baseMetrics.totalSent * scalingFactor));
|
|
23028
|
-
const performanceMultiplier = isPrevious ?
|
|
23031
|
+
const performanceMultiplier = isPrevious ? 0.82 : 1;
|
|
23029
23032
|
const adjustedTotalSent = Math.round(scaledTotalSent * performanceMultiplier);
|
|
23030
23033
|
const responseRate = baseMetrics.responseRate * performanceMultiplier;
|
|
23031
23034
|
const totalResponded = Math.round(adjustedTotalSent * (responseRate / 100));
|
|
23032
|
-
|
|
23033
|
-
|
|
23034
|
-
|
|
23035
|
-
|
|
23036
|
-
|
|
23037
|
-
|
|
23035
|
+
let promoterRate, passiveRate;
|
|
23036
|
+
if (isPrevious) {
|
|
23037
|
+
promoterRate = 0.5;
|
|
23038
|
+
passiveRate = 0.3;
|
|
23039
|
+
} else {
|
|
23040
|
+
promoterRate = baseMetrics.promoterRate * performanceMultiplier;
|
|
23041
|
+
passiveRate = baseMetrics.passiveRate * performanceMultiplier;
|
|
23042
|
+
}
|
|
23043
|
+
const promoters = Math.round(totalResponded * promoterRate);
|
|
23044
|
+
const passives = Math.round(totalResponded * passiveRate);
|
|
23045
|
+
const detractors = totalResponded - promoters - passives;
|
|
23046
|
+
const npsScore = totalResponded > 0 ? Math.round((promoters - detractors) / totalResponded * 100) : 0;
|
|
23047
|
+
const averageRating = calculateAverageFromNPS(
|
|
23048
|
+
promoters,
|
|
23049
|
+
passives,
|
|
23050
|
+
detractors
|
|
23038
23051
|
);
|
|
23039
23052
|
return {
|
|
23040
23053
|
totalSent: adjustedTotalSent,
|
|
23041
23054
|
totalResponded,
|
|
23042
23055
|
averageRating: parseFloat(averageRating.toFixed(1)),
|
|
23043
23056
|
responseRate: parseFloat(responseRate.toFixed(1)),
|
|
23044
|
-
positiveResponses,
|
|
23045
|
-
|
|
23057
|
+
positiveResponses: promoters,
|
|
23058
|
+
// promoters for backward compatibility
|
|
23059
|
+
negativeResponses: detractors,
|
|
23060
|
+
// detractors for backward compatibility
|
|
23061
|
+
passiveResponses: passives,
|
|
23062
|
+
// new field for passives
|
|
23063
|
+
npsScore
|
|
23064
|
+
// real NPS score
|
|
23046
23065
|
};
|
|
23047
23066
|
}
|
|
23048
|
-
function getBasePlatformFeedbackMetrics(platformConfig) {
|
|
23067
|
+
function getBasePlatformFeedbackMetrics$1(platformConfig) {
|
|
23049
23068
|
const industryMultipliers = {
|
|
23050
23069
|
// Pet spa industry (Goose) - high engagement, positive feedback
|
|
23051
23070
|
"ACME Pet Spa": {
|
|
23052
|
-
totalSent:
|
|
23071
|
+
totalSent: 1250,
|
|
23072
|
+
// Much higher - businesses send way more emails than get reviews
|
|
23053
23073
|
responseRate: 42,
|
|
23054
23074
|
// 42% response rate
|
|
23055
|
-
|
|
23056
|
-
//
|
|
23075
|
+
promoterRate: 0.65,
|
|
23076
|
+
// 65% promoters (9-10) - much higher NPS
|
|
23077
|
+
passiveRate: 0.2,
|
|
23078
|
+
// 20% passives (7-8)
|
|
23079
|
+
detractorRate: 0.15
|
|
23080
|
+
// 15% detractors (1-6) - much lower
|
|
23057
23081
|
},
|
|
23058
23082
|
// Equipment rental (Renterra) - moderate engagement
|
|
23059
23083
|
"Tomer's Rentals": {
|
|
23060
|
-
totalSent:
|
|
23084
|
+
totalSent: 980,
|
|
23061
23085
|
responseRate: 35,
|
|
23062
23086
|
// 35% response rate
|
|
23063
|
-
|
|
23064
|
-
//
|
|
23087
|
+
promoterRate: 0.55,
|
|
23088
|
+
// 55% promoters
|
|
23089
|
+
passiveRate: 0.25,
|
|
23090
|
+
// 25% passives
|
|
23091
|
+
detractorRate: 0.2
|
|
23092
|
+
// 20% detractors
|
|
23065
23093
|
},
|
|
23066
23094
|
// Default platform
|
|
23067
23095
|
default: {
|
|
23068
|
-
totalSent:
|
|
23096
|
+
totalSent: 1100,
|
|
23069
23097
|
responseRate: 38,
|
|
23070
23098
|
// 38% response rate
|
|
23071
|
-
|
|
23072
|
-
//
|
|
23099
|
+
promoterRate: 0.6,
|
|
23100
|
+
// 60% promoters
|
|
23101
|
+
passiveRate: 0.22,
|
|
23102
|
+
// 22% passives
|
|
23103
|
+
detractorRate: 0.18
|
|
23104
|
+
// 18% detractors
|
|
23073
23105
|
}
|
|
23074
23106
|
};
|
|
23075
23107
|
const baseKey = platformConfig.name in industryMultipliers ? platformConfig.name : "default";
|
|
@@ -23079,37 +23111,52 @@ function getAllTimePlatformFeedbackMetrics(platformConfig) {
|
|
|
23079
23111
|
const industryMultipliers = {
|
|
23080
23112
|
// Pet spa industry (Goose) - high engagement, positive feedback
|
|
23081
23113
|
"ACME Pet Spa": {
|
|
23082
|
-
totalSent:
|
|
23083
|
-
//
|
|
23114
|
+
totalSent: 18500,
|
|
23115
|
+
// WAY higher - businesses send tons of emails over time
|
|
23084
23116
|
responseRate: 39,
|
|
23085
23117
|
// Slightly lower all-time response rate
|
|
23086
|
-
|
|
23087
|
-
//
|
|
23118
|
+
promoterRate: 0.61,
|
|
23119
|
+
// 61% promoters - produces NPS of 42
|
|
23120
|
+
passiveRate: 0.2,
|
|
23121
|
+
// 20% passives
|
|
23122
|
+
detractorRate: 0.19
|
|
23123
|
+
// 19% detractors
|
|
23088
23124
|
},
|
|
23089
23125
|
// Equipment rental (Renterra) - moderate engagement
|
|
23090
23126
|
"Tomer's Rentals": {
|
|
23091
|
-
totalSent:
|
|
23127
|
+
totalSent: 14200,
|
|
23092
23128
|
responseRate: 33,
|
|
23093
|
-
|
|
23129
|
+
promoterRate: 0.58,
|
|
23130
|
+
// 58% promoters - good NPS
|
|
23131
|
+
passiveRate: 0.22,
|
|
23132
|
+
// 22% passives
|
|
23133
|
+
detractorRate: 0.2
|
|
23134
|
+
// 20% detractors
|
|
23094
23135
|
},
|
|
23095
23136
|
// Default platform
|
|
23096
23137
|
default: {
|
|
23097
|
-
totalSent:
|
|
23138
|
+
totalSent: 16500,
|
|
23098
23139
|
responseRate: 36,
|
|
23099
|
-
|
|
23140
|
+
promoterRate: 0.62,
|
|
23141
|
+
// 62% promoters - good NPS
|
|
23142
|
+
passiveRate: 0.2,
|
|
23143
|
+
// 20% passives
|
|
23144
|
+
detractorRate: 0.18
|
|
23145
|
+
// 18% detractors
|
|
23100
23146
|
}
|
|
23101
23147
|
};
|
|
23102
23148
|
const baseKey = platformConfig.name in industryMultipliers ? platformConfig.name : "default";
|
|
23103
23149
|
return industryMultipliers[baseKey];
|
|
23104
23150
|
}
|
|
23105
|
-
function
|
|
23106
|
-
|
|
23151
|
+
function calculateAverageFromNPS(promoters, passives, detractors) {
|
|
23152
|
+
const totalResponses = promoters + passives + detractors;
|
|
23153
|
+
if (totalResponses === 0) {
|
|
23107
23154
|
return 0;
|
|
23108
23155
|
}
|
|
23109
|
-
const
|
|
23110
|
-
const
|
|
23111
|
-
const
|
|
23112
|
-
const weightedSum =
|
|
23156
|
+
const promoterAverage = 9.5;
|
|
23157
|
+
const passiveAverage = 7.5;
|
|
23158
|
+
const detractorAverage = 3.5;
|
|
23159
|
+
const weightedSum = promoters * promoterAverage + passives * passiveAverage + detractors * detractorAverage;
|
|
23113
23160
|
return weightedSum / totalResponses;
|
|
23114
23161
|
}
|
|
23115
23162
|
function calculateFeedbackComparison(currentPeriod, previousPeriod) {
|
|
@@ -23135,6 +23182,12 @@ function calculateFeedbackComparison(currentPeriod, previousPeriod) {
|
|
|
23135
23182
|
const responseRateChangePercent = previousPeriod.responseRate > 0 ? parseFloat(
|
|
23136
23183
|
(responseRateChange / previousPeriod.responseRate * 100).toFixed(1)
|
|
23137
23184
|
) : null;
|
|
23185
|
+
const npsScoreChange = currentPeriod.npsScore - previousPeriod.npsScore;
|
|
23186
|
+
const npsScoreChangePercent = previousPeriod.npsScore !== 0 ? parseFloat(
|
|
23187
|
+
(npsScoreChange / Math.abs(previousPeriod.npsScore) * 100).toFixed(
|
|
23188
|
+
1
|
|
23189
|
+
)
|
|
23190
|
+
) : null;
|
|
23138
23191
|
return {
|
|
23139
23192
|
totalSentChange,
|
|
23140
23193
|
totalSentChangePercent,
|
|
@@ -23143,7 +23196,469 @@ function calculateFeedbackComparison(currentPeriod, previousPeriod) {
|
|
|
23143
23196
|
averageRatingChange,
|
|
23144
23197
|
averageRatingChangePercent,
|
|
23145
23198
|
responseRateChange: parseFloat(responseRateChange.toFixed(1)),
|
|
23146
|
-
responseRateChangePercent
|
|
23199
|
+
responseRateChangePercent,
|
|
23200
|
+
npsScoreChange,
|
|
23201
|
+
npsScoreChangePercent
|
|
23202
|
+
};
|
|
23203
|
+
}
|
|
23204
|
+
const generateAuditLogData = ({
|
|
23205
|
+
startDate,
|
|
23206
|
+
endDate,
|
|
23207
|
+
locationIds,
|
|
23208
|
+
cursor,
|
|
23209
|
+
limit,
|
|
23210
|
+
searchTerm,
|
|
23211
|
+
orderBy
|
|
23212
|
+
}) => {
|
|
23213
|
+
const queryStartDate = startDate ? new Date(startDate) : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
23214
|
+
const queryEndDate = endDate ? new Date(endDate) : /* @__PURE__ */ new Date();
|
|
23215
|
+
const queryDays = Math.ceil(
|
|
23216
|
+
(queryEndDate.getTime() - queryStartDate.getTime()) / (1e3 * 60 * 60 * 24)
|
|
23217
|
+
) + 1;
|
|
23218
|
+
const baseLogCount = 100;
|
|
23219
|
+
const scaledLogCount = Math.max(
|
|
23220
|
+
20,
|
|
23221
|
+
Math.round(baseLogCount * queryDays / 30)
|
|
23222
|
+
);
|
|
23223
|
+
const allLogs = generateAuditLogPool(
|
|
23224
|
+
queryStartDate,
|
|
23225
|
+
queryEndDate,
|
|
23226
|
+
scaledLogCount
|
|
23227
|
+
);
|
|
23228
|
+
let filteredLogs = allLogs;
|
|
23229
|
+
if (startDate || endDate) {
|
|
23230
|
+
filteredLogs = filteredLogs.filter((item) => {
|
|
23231
|
+
const itemDate = new Date(item.timestamp);
|
|
23232
|
+
if (startDate && itemDate < new Date(startDate)) return false;
|
|
23233
|
+
if (endDate && itemDate > new Date(endDate)) return false;
|
|
23234
|
+
return true;
|
|
23235
|
+
});
|
|
23236
|
+
}
|
|
23237
|
+
if (searchTerm && searchTerm.length >= 3) {
|
|
23238
|
+
const searchLower = searchTerm.toLowerCase();
|
|
23239
|
+
filteredLogs = filteredLogs.filter(
|
|
23240
|
+
(item) => item.message.toLowerCase().includes(searchLower) || item.user.toLowerCase().includes(searchLower) || item.status.toLowerCase().includes(searchLower) || item.channel.toLowerCase().includes(searchLower) || item.type.toLowerCase().includes(searchLower)
|
|
23241
|
+
);
|
|
23242
|
+
}
|
|
23243
|
+
if (locationIds && locationIds.length > 0) ;
|
|
23244
|
+
filteredLogs.sort((a2, b2) => {
|
|
23245
|
+
const dateA = new Date(a2.timestamp).getTime();
|
|
23246
|
+
const dateB = new Date(b2.timestamp).getTime();
|
|
23247
|
+
return orderBy.includes("desc") || orderBy === "timestamp" ? dateB - dateA : dateA - dateB;
|
|
23248
|
+
});
|
|
23249
|
+
let startIndex = 0;
|
|
23250
|
+
if (cursor) {
|
|
23251
|
+
const cursorIndex = filteredLogs.findIndex((item) => item.id === cursor);
|
|
23252
|
+
if (cursorIndex !== -1) {
|
|
23253
|
+
startIndex = cursorIndex + 1;
|
|
23254
|
+
}
|
|
23255
|
+
}
|
|
23256
|
+
const pageData = filteredLogs.slice(startIndex, startIndex + limit);
|
|
23257
|
+
const hasMore = startIndex + limit < filteredLogs.length;
|
|
23258
|
+
const nextCursor = hasMore && pageData.length > 0 ? pageData[pageData.length - 1].id : void 0;
|
|
23259
|
+
return {
|
|
23260
|
+
data: pageData,
|
|
23261
|
+
total: filteredLogs.length,
|
|
23262
|
+
nextCursor
|
|
23263
|
+
};
|
|
23264
|
+
};
|
|
23265
|
+
function generateAuditLogPool(startDate, endDate, count) {
|
|
23266
|
+
const logs = [];
|
|
23267
|
+
const timeSpan = endDate.getTime() - startDate.getTime();
|
|
23268
|
+
const eventSequences = [
|
|
23269
|
+
// Survey flow
|
|
23270
|
+
{
|
|
23271
|
+
type: "SURVEY_REQUEST",
|
|
23272
|
+
channel: "EMAIL",
|
|
23273
|
+
statuses: ["SENT", "DELIVERED", "OPENED", "COMPLETED"],
|
|
23274
|
+
messages: [
|
|
23275
|
+
"Survey request sent to customer",
|
|
23276
|
+
"Survey request delivered to customer",
|
|
23277
|
+
"Customer opened survey request",
|
|
23278
|
+
"Survey completed by customer"
|
|
23279
|
+
]
|
|
23280
|
+
},
|
|
23281
|
+
// Review flow
|
|
23282
|
+
{
|
|
23283
|
+
type: "REVIEW_REQUEST",
|
|
23284
|
+
channel: "SMS",
|
|
23285
|
+
statuses: ["SENT", "DELIVERED"],
|
|
23286
|
+
messages: ["Review request sent to", "Review request delivered to"]
|
|
23287
|
+
},
|
|
23288
|
+
// Google review flow
|
|
23289
|
+
{
|
|
23290
|
+
type: "GOOGLE_REVIEW",
|
|
23291
|
+
channel: "EMAIL",
|
|
23292
|
+
statuses: ["RECEIVED", "RESPONDED"],
|
|
23293
|
+
messages: [
|
|
23294
|
+
"New Google review received from",
|
|
23295
|
+
"Response sent to Google review from"
|
|
23296
|
+
]
|
|
23297
|
+
},
|
|
23298
|
+
// Reminder flows
|
|
23299
|
+
{
|
|
23300
|
+
type: "SURVEY_REMINDER",
|
|
23301
|
+
channel: "EMAIL",
|
|
23302
|
+
statuses: ["SENT", "DELIVERED"],
|
|
23303
|
+
messages: ["Survey reminder sent to", "Survey reminder delivered to"]
|
|
23304
|
+
},
|
|
23305
|
+
{
|
|
23306
|
+
type: "REVIEW_REMINDER",
|
|
23307
|
+
channel: "SMS",
|
|
23308
|
+
statuses: ["SENT", "DELIVERED"],
|
|
23309
|
+
messages: ["Review reminder sent to", "Review reminder delivered to"]
|
|
23310
|
+
}
|
|
23311
|
+
];
|
|
23312
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
23313
|
+
const sequence = f.helpers.arrayElement(eventSequences);
|
|
23314
|
+
const statusIndex = f.number.int({
|
|
23315
|
+
min: 0,
|
|
23316
|
+
max: sequence.statuses.length - 1
|
|
23317
|
+
});
|
|
23318
|
+
const status = sequence.statuses[statusIndex];
|
|
23319
|
+
const messageTemplate = sequence.messages[statusIndex];
|
|
23320
|
+
const timestamp = new Date(startDate.getTime() + Math.random() * timeSpan);
|
|
23321
|
+
let contactInfo;
|
|
23322
|
+
if (sequence.channel === "EMAIL") {
|
|
23323
|
+
contactInfo = f.internet.email();
|
|
23324
|
+
} else {
|
|
23325
|
+
contactInfo = f.phone.number();
|
|
23326
|
+
}
|
|
23327
|
+
const user = status === "RESPONDED" ? f.internet.email({ provider: "business.com" }) : "system";
|
|
23328
|
+
const customerName = status === "RECEIVED" || status === "RESPONDED" ? `${f.person.firstName()} ${f.person.lastName().charAt(0)}.` : null;
|
|
23329
|
+
let message2;
|
|
23330
|
+
if (customerName) {
|
|
23331
|
+
message2 = `${messageTemplate} ${customerName}`;
|
|
23332
|
+
} else {
|
|
23333
|
+
message2 = `${messageTemplate} ${contactInfo}`;
|
|
23334
|
+
}
|
|
23335
|
+
logs.push({
|
|
23336
|
+
id: f.string.uuid(),
|
|
23337
|
+
timestamp: timestamp.toISOString(),
|
|
23338
|
+
message: message2,
|
|
23339
|
+
user,
|
|
23340
|
+
status,
|
|
23341
|
+
channel: sequence.channel,
|
|
23342
|
+
type: sequence.type
|
|
23343
|
+
});
|
|
23344
|
+
}
|
|
23345
|
+
return logs;
|
|
23346
|
+
}
|
|
23347
|
+
const generateReviewTimeSeriesData = ({
|
|
23348
|
+
platformData,
|
|
23349
|
+
queryParams
|
|
23350
|
+
}) => {
|
|
23351
|
+
const platformConfig = getPlatformConfig(
|
|
23352
|
+
platformData.businessesMe?.platform_id
|
|
23353
|
+
);
|
|
23354
|
+
const { requestedDays, startDate, endDate } = parseDateRange(
|
|
23355
|
+
queryParams.start_date,
|
|
23356
|
+
queryParams.end_date,
|
|
23357
|
+
30
|
|
23358
|
+
);
|
|
23359
|
+
const baseMetrics = getBasePlatformReviewMetrics(platformConfig);
|
|
23360
|
+
const basePeriodDays = 30;
|
|
23361
|
+
const scalingFactor = requestedDays / basePeriodDays;
|
|
23362
|
+
const totalScaledReviews = Math.max(
|
|
23363
|
+
1,
|
|
23364
|
+
Math.round(baseMetrics.totalReviews * scalingFactor)
|
|
23365
|
+
);
|
|
23366
|
+
let intervalDays = 7;
|
|
23367
|
+
if (requestedDays <= 30)
|
|
23368
|
+
intervalDays = 1;
|
|
23369
|
+
else if (requestedDays <= 90) intervalDays = 3;
|
|
23370
|
+
const numDataPoints = Math.max(1, Math.ceil(requestedDays / intervalDays));
|
|
23371
|
+
const dataPoints = generateReviewTimeSeriesPoints({
|
|
23372
|
+
totalScaledReviews,
|
|
23373
|
+
startDate,
|
|
23374
|
+
endDate,
|
|
23375
|
+
numDataPoints,
|
|
23376
|
+
intervalDays
|
|
23377
|
+
});
|
|
23378
|
+
return {
|
|
23379
|
+
data: dataPoints
|
|
23380
|
+
};
|
|
23381
|
+
};
|
|
23382
|
+
function generateReviewTimeSeriesPoints({
|
|
23383
|
+
totalScaledReviews,
|
|
23384
|
+
startDate,
|
|
23385
|
+
endDate,
|
|
23386
|
+
numDataPoints,
|
|
23387
|
+
intervalDays
|
|
23388
|
+
}) {
|
|
23389
|
+
const dataPoints = [];
|
|
23390
|
+
let currentDate = new Date(startDate);
|
|
23391
|
+
let cumulativeReviews = 0;
|
|
23392
|
+
const basePointReviews = totalScaledReviews / numDataPoints;
|
|
23393
|
+
const targetRating = 4.2;
|
|
23394
|
+
const startingRating = 4;
|
|
23395
|
+
const endingRating = 4.2;
|
|
23396
|
+
for (let i2 = 0; i2 < numDataPoints; i2++) {
|
|
23397
|
+
const pointDateStr = currentDate.toISOString().split("T")[0];
|
|
23398
|
+
let currentPointReviews;
|
|
23399
|
+
let currentPointRating;
|
|
23400
|
+
if (i2 < numDataPoints - 1) {
|
|
23401
|
+
currentPointReviews = Math.round(
|
|
23402
|
+
basePointReviews * (1 + (Math.random() - 0.5) * 0.5)
|
|
23403
|
+
);
|
|
23404
|
+
const progress = i2 / (numDataPoints - 1);
|
|
23405
|
+
currentPointRating = startingRating + (endingRating - startingRating) * Math.pow(progress, 1.3);
|
|
23406
|
+
currentPointRating *= 1 + (Math.random() - 0.5) * 0.05;
|
|
23407
|
+
} else {
|
|
23408
|
+
currentPointReviews = Math.max(0, totalScaledReviews - cumulativeReviews);
|
|
23409
|
+
currentPointRating = targetRating;
|
|
23410
|
+
}
|
|
23411
|
+
currentPointReviews = Math.max(0, currentPointReviews);
|
|
23412
|
+
currentPointRating = Math.max(1, Math.min(5, currentPointRating));
|
|
23413
|
+
cumulativeReviews += currentPointReviews;
|
|
23414
|
+
const { promoterCount, detractorCount } = calculatePromoterDetractorSplit(
|
|
23415
|
+
currentPointReviews,
|
|
23416
|
+
currentPointRating
|
|
23417
|
+
);
|
|
23418
|
+
dataPoints.push({
|
|
23419
|
+
date: pointDateStr,
|
|
23420
|
+
totalReviews: currentPointReviews,
|
|
23421
|
+
averageRating: currentPointReviews > 0 ? parseFloat(currentPointRating.toFixed(1)) : null,
|
|
23422
|
+
promoterCount,
|
|
23423
|
+
detractorCount
|
|
23424
|
+
});
|
|
23425
|
+
currentDate.setDate(currentDate.getDate() + intervalDays);
|
|
23426
|
+
if (currentDate > endDate && i2 < numDataPoints - 1) {
|
|
23427
|
+
currentDate = new Date(endDate);
|
|
23428
|
+
if (dataPoints.length > 0 && dataPoints[dataPoints.length - 1].date === currentDate.toISOString().split("T")[0]) {
|
|
23429
|
+
break;
|
|
23430
|
+
}
|
|
23431
|
+
}
|
|
23432
|
+
}
|
|
23433
|
+
return dataPoints;
|
|
23434
|
+
}
|
|
23435
|
+
function getBasePlatformReviewMetrics(platformConfig) {
|
|
23436
|
+
const industryMetrics = {
|
|
23437
|
+
// Pet spa industry (Goose) - high customer satisfaction, more reviews
|
|
23438
|
+
"ACME Pet Spa": {
|
|
23439
|
+
totalReviews: 52,
|
|
23440
|
+
// Slightly higher than analytics factory
|
|
23441
|
+
averageRating: 4.5,
|
|
23442
|
+
promoterRate: 0.65,
|
|
23443
|
+
// 65% 5-star
|
|
23444
|
+
detractorRate: 0.15
|
|
23445
|
+
// 15% 1-3 star
|
|
23446
|
+
},
|
|
23447
|
+
// Equipment rental (Renterra) - moderate review volume, good satisfaction
|
|
23448
|
+
"Tomer's Rentals": {
|
|
23449
|
+
totalReviews: 31,
|
|
23450
|
+
averageRating: 4.2,
|
|
23451
|
+
promoterRate: 0.55,
|
|
23452
|
+
// 55% 5-star
|
|
23453
|
+
detractorRate: 0.2
|
|
23454
|
+
// 20% 1-3 star
|
|
23455
|
+
},
|
|
23456
|
+
// Default platform
|
|
23457
|
+
default: {
|
|
23458
|
+
totalReviews: 95,
|
|
23459
|
+
// Match all-time analytics exactly
|
|
23460
|
+
averageRating: 4.2,
|
|
23461
|
+
// Match all-time analytics exactly
|
|
23462
|
+
promoterRate: 0.6,
|
|
23463
|
+
// 60% 5-star
|
|
23464
|
+
detractorRate: 0.18
|
|
23465
|
+
// 18% 1-3 star
|
|
23466
|
+
}
|
|
23467
|
+
};
|
|
23468
|
+
const baseKey = platformConfig.name in industryMetrics ? platformConfig.name : "default";
|
|
23469
|
+
return industryMetrics[baseKey];
|
|
23470
|
+
}
|
|
23471
|
+
function calculatePromoterDetractorSplit(totalReviews, averageRating) {
|
|
23472
|
+
if (totalReviews === 0) {
|
|
23473
|
+
return { promoterCount: 0, detractorCount: 0 };
|
|
23474
|
+
}
|
|
23475
|
+
let promoterRate = 0.6;
|
|
23476
|
+
let detractorRate = 0.15;
|
|
23477
|
+
if (averageRating >= 4.5) {
|
|
23478
|
+
promoterRate = 0.7;
|
|
23479
|
+
detractorRate = 0.1;
|
|
23480
|
+
} else if (averageRating >= 4.2) {
|
|
23481
|
+
promoterRate = 0.6;
|
|
23482
|
+
detractorRate = 0.15;
|
|
23483
|
+
} else if (averageRating >= 3.8) {
|
|
23484
|
+
promoterRate = 0.45;
|
|
23485
|
+
detractorRate = 0.25;
|
|
23486
|
+
} else {
|
|
23487
|
+
promoterRate = 0.3;
|
|
23488
|
+
detractorRate = 0.4;
|
|
23489
|
+
}
|
|
23490
|
+
promoterRate *= 1 + (Math.random() - 0.5) * 0.2;
|
|
23491
|
+
detractorRate *= 1 + (Math.random() - 0.5) * 0.2;
|
|
23492
|
+
const promoterCount = Math.round(totalReviews * promoterRate);
|
|
23493
|
+
const detractorCount = Math.round(totalReviews * detractorRate);
|
|
23494
|
+
return { promoterCount, detractorCount };
|
|
23495
|
+
}
|
|
23496
|
+
const generateFeedbackTimeSeriesData = ({
|
|
23497
|
+
platformData,
|
|
23498
|
+
queryParams
|
|
23499
|
+
}) => {
|
|
23500
|
+
const platformConfig = getPlatformConfig(
|
|
23501
|
+
platformData.businessesMe?.platform_id
|
|
23502
|
+
);
|
|
23503
|
+
const { requestedDays, startDate, endDate } = parseDateRange(
|
|
23504
|
+
queryParams.start_date,
|
|
23505
|
+
queryParams.end_date,
|
|
23506
|
+
30
|
|
23507
|
+
);
|
|
23508
|
+
const baseMetrics = getBasePlatformFeedbackMetrics(platformConfig);
|
|
23509
|
+
const basePeriodDays = 30;
|
|
23510
|
+
const scalingFactor = requestedDays / basePeriodDays;
|
|
23511
|
+
const totalScaledSent = Math.max(
|
|
23512
|
+
1,
|
|
23513
|
+
Math.round(baseMetrics.totalSent * scalingFactor)
|
|
23514
|
+
);
|
|
23515
|
+
let intervalDays = 7;
|
|
23516
|
+
if (requestedDays <= 30)
|
|
23517
|
+
intervalDays = 1;
|
|
23518
|
+
else if (requestedDays <= 90) intervalDays = 3;
|
|
23519
|
+
const numDataPoints = Math.max(1, Math.ceil(requestedDays / intervalDays));
|
|
23520
|
+
const dataPoints = generateFeedbackTimeSeriesPoints({
|
|
23521
|
+
totalScaledSent,
|
|
23522
|
+
baseMetrics,
|
|
23523
|
+
startDate,
|
|
23524
|
+
endDate,
|
|
23525
|
+
numDataPoints,
|
|
23526
|
+
intervalDays
|
|
23527
|
+
});
|
|
23528
|
+
return {
|
|
23529
|
+
data: dataPoints
|
|
23530
|
+
};
|
|
23531
|
+
};
|
|
23532
|
+
function generateFeedbackTimeSeriesPoints({
|
|
23533
|
+
totalScaledSent,
|
|
23534
|
+
baseMetrics,
|
|
23535
|
+
startDate,
|
|
23536
|
+
endDate,
|
|
23537
|
+
numDataPoints,
|
|
23538
|
+
intervalDays
|
|
23539
|
+
}) {
|
|
23540
|
+
const dataPoints = [];
|
|
23541
|
+
let currentDate = new Date(startDate);
|
|
23542
|
+
let cumulativeSent = 0;
|
|
23543
|
+
const basePointSent = totalScaledSent / numDataPoints;
|
|
23544
|
+
const startingResponseRate = baseMetrics.responseRate * 0.75;
|
|
23545
|
+
const endingResponseRate = baseMetrics.responseRate * 1.15;
|
|
23546
|
+
const startingNPS = 30;
|
|
23547
|
+
const endingNPS = 42;
|
|
23548
|
+
for (let i2 = 0; i2 < numDataPoints; i2++) {
|
|
23549
|
+
const pointDateStr = currentDate.toISOString().split("T")[0];
|
|
23550
|
+
let currentPointSent;
|
|
23551
|
+
let currentPointResponseRate;
|
|
23552
|
+
let currentPointNPS;
|
|
23553
|
+
if (i2 < numDataPoints - 1) {
|
|
23554
|
+
currentPointSent = Math.round(
|
|
23555
|
+
basePointSent * (1 + (Math.random() - 0.5) * 0.5)
|
|
23556
|
+
);
|
|
23557
|
+
const progress = i2 / (numDataPoints - 1);
|
|
23558
|
+
currentPointResponseRate = startingResponseRate + (endingResponseRate - startingResponseRate) * Math.pow(progress, 1.3);
|
|
23559
|
+
currentPointNPS = startingNPS + (endingNPS - startingNPS) * Math.pow(progress, 1.2);
|
|
23560
|
+
currentPointResponseRate *= 1 + (Math.random() - 0.5) * 0.1;
|
|
23561
|
+
currentPointNPS *= 1 + (Math.random() - 0.5) * 0.1;
|
|
23562
|
+
} else {
|
|
23563
|
+
currentPointSent = Math.max(0, totalScaledSent - cumulativeSent);
|
|
23564
|
+
currentPointResponseRate = baseMetrics.responseRate;
|
|
23565
|
+
currentPointNPS = 42;
|
|
23566
|
+
}
|
|
23567
|
+
currentPointSent = Math.max(0, currentPointSent);
|
|
23568
|
+
currentPointResponseRate = Math.max(
|
|
23569
|
+
5,
|
|
23570
|
+
Math.min(80, currentPointResponseRate)
|
|
23571
|
+
);
|
|
23572
|
+
currentPointNPS = Math.max(-100, Math.min(100, currentPointNPS));
|
|
23573
|
+
cumulativeSent += currentPointSent;
|
|
23574
|
+
const currentPointResponded = Math.round(
|
|
23575
|
+
currentPointSent * (currentPointResponseRate / 100)
|
|
23576
|
+
);
|
|
23577
|
+
const { promoterCount, detractorCount, passiveCount } = calculateNPSBreakdown(currentPointResponded, currentPointNPS);
|
|
23578
|
+
dataPoints.push({
|
|
23579
|
+
date: pointDateStr,
|
|
23580
|
+
totalSent: currentPointSent,
|
|
23581
|
+
totalResponded: currentPointResponded,
|
|
23582
|
+
promoterCount,
|
|
23583
|
+
detractorCount,
|
|
23584
|
+
passiveCount,
|
|
23585
|
+
npsScore: parseFloat(currentPointNPS.toFixed(1))
|
|
23586
|
+
// Use the target NPS (30 → 42)
|
|
23587
|
+
});
|
|
23588
|
+
currentDate.setDate(currentDate.getDate() + intervalDays);
|
|
23589
|
+
if (currentDate > endDate && i2 < numDataPoints - 1) {
|
|
23590
|
+
currentDate = new Date(endDate);
|
|
23591
|
+
if (dataPoints.length > 0 && dataPoints[dataPoints.length - 1].date === currentDate.toISOString().split("T")[0]) {
|
|
23592
|
+
break;
|
|
23593
|
+
}
|
|
23594
|
+
}
|
|
23595
|
+
}
|
|
23596
|
+
return dataPoints;
|
|
23597
|
+
}
|
|
23598
|
+
function getBasePlatformFeedbackMetrics(platformConfig) {
|
|
23599
|
+
const industryMetrics = {
|
|
23600
|
+
// Pet spa industry (Goose) - high engagement, positive feedback
|
|
23601
|
+
"ACME Pet Spa": {
|
|
23602
|
+
totalSent: 1200,
|
|
23603
|
+
// Much higher - realistic email volume
|
|
23604
|
+
responseRate: 44,
|
|
23605
|
+
// 44% response rate
|
|
23606
|
+
targetNPS: 42,
|
|
23607
|
+
// Match the all-time NPS score (42)
|
|
23608
|
+
promoterRate: 0.78
|
|
23609
|
+
// 78% promoters
|
|
23610
|
+
},
|
|
23611
|
+
// Equipment rental (Renterra) - moderate engagement
|
|
23612
|
+
"Tomer's Rentals": {
|
|
23613
|
+
totalSent: 950,
|
|
23614
|
+
responseRate: 37,
|
|
23615
|
+
// 37% response rate
|
|
23616
|
+
targetNPS: 55,
|
|
23617
|
+
// Good NPS for B2B
|
|
23618
|
+
promoterRate: 0.72
|
|
23619
|
+
// 72% promoters
|
|
23620
|
+
},
|
|
23621
|
+
// Default platform
|
|
23622
|
+
default: {
|
|
23623
|
+
totalSent: 1050,
|
|
23624
|
+
responseRate: 40,
|
|
23625
|
+
// 40% response rate
|
|
23626
|
+
targetNPS: 60,
|
|
23627
|
+
// Good overall NPS
|
|
23628
|
+
promoterRate: 0.75
|
|
23629
|
+
// 75% promoters
|
|
23630
|
+
}
|
|
23631
|
+
};
|
|
23632
|
+
const baseKey = platformConfig.name in industryMetrics ? platformConfig.name : "default";
|
|
23633
|
+
return industryMetrics[baseKey];
|
|
23634
|
+
}
|
|
23635
|
+
function calculateNPSBreakdown(totalResponses, targetNPS) {
|
|
23636
|
+
if (totalResponses === 0) {
|
|
23637
|
+
return { promoterCount: 0, detractorCount: 0, passiveCount: 0 };
|
|
23638
|
+
}
|
|
23639
|
+
const passiveRate = 0.25;
|
|
23640
|
+
const passiveCount = Math.round(totalResponses * passiveRate);
|
|
23641
|
+
const activeResponses = totalResponses - passiveCount;
|
|
23642
|
+
const npsDecimal = targetNPS / 100;
|
|
23643
|
+
const promoterCount = Math.round(
|
|
23644
|
+
(activeResponses + npsDecimal * totalResponses) / 2
|
|
23645
|
+
);
|
|
23646
|
+
const detractorCount = Math.max(0, activeResponses - promoterCount);
|
|
23647
|
+
const finalPromoterCount = Math.max(
|
|
23648
|
+
0,
|
|
23649
|
+
Math.min(promoterCount, totalResponses - passiveCount)
|
|
23650
|
+
);
|
|
23651
|
+
const finalDetractorCount = Math.max(
|
|
23652
|
+
0,
|
|
23653
|
+
Math.min(
|
|
23654
|
+
detractorCount,
|
|
23655
|
+
totalResponses - passiveCount - finalPromoterCount
|
|
23656
|
+
)
|
|
23657
|
+
);
|
|
23658
|
+
return {
|
|
23659
|
+
promoterCount: finalPromoterCount,
|
|
23660
|
+
detractorCount: finalDetractorCount,
|
|
23661
|
+
passiveCount
|
|
23147
23662
|
};
|
|
23148
23663
|
}
|
|
23149
23664
|
const mockStore = {
|
|
@@ -23221,7 +23736,8 @@ const reputationHandlers = [
|
|
|
23221
23736
|
locationMappings: body.locationMappings || currentConfig.locationMappings,
|
|
23222
23737
|
emailChannelSenderId: body.emailChannelSenderId,
|
|
23223
23738
|
smsChannelSenderId: body.smsChannelSenderId,
|
|
23224
|
-
completedOnboardingAt
|
|
23739
|
+
// Preserve existing completedOnboardingAt if not provided in update
|
|
23740
|
+
completedOnboardingAt: body.completedOnboardingAt || currentConfig.completedOnboardingAt,
|
|
23225
23741
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
23226
23742
|
};
|
|
23227
23743
|
mockStore.reputationConfig = updatedConfig;
|
|
@@ -23306,6 +23822,20 @@ const reputationHandlers = [
|
|
|
23306
23822
|
}
|
|
23307
23823
|
});
|
|
23308
23824
|
}),
|
|
23825
|
+
// OAuth GBP Connection Revoke
|
|
23826
|
+
http.post(`${HOSTNAME}/api/oauth/gbp/revoke`, () => {
|
|
23827
|
+
return HttpResponse.json(
|
|
23828
|
+
{
|
|
23829
|
+
success: false,
|
|
23830
|
+
message: "Error (Sandbox)",
|
|
23831
|
+
data: {
|
|
23832
|
+
success: false,
|
|
23833
|
+
message: "Unable to revoke sandbox account"
|
|
23834
|
+
}
|
|
23835
|
+
},
|
|
23836
|
+
{ status: 400 }
|
|
23837
|
+
);
|
|
23838
|
+
}),
|
|
23309
23839
|
// OAuth GBP Connection Status
|
|
23310
23840
|
http.get(`${HOSTNAME}/api/oauth/gbp/connection`, () => {
|
|
23311
23841
|
const platformData = getSandboxDataForPlatform(currentSandboxPlatformId);
|
|
@@ -23368,7 +23898,6 @@ const reputationHandlers = [
|
|
|
23368
23898
|
const includeComparison = url.searchParams.get("include_comparison") === "true";
|
|
23369
23899
|
const platformData = getSandboxDataForPlatform(currentSandboxPlatformId);
|
|
23370
23900
|
const queryParams = {
|
|
23371
|
-
platform: "google_business_profile",
|
|
23372
23901
|
start_date: startDate || void 0,
|
|
23373
23902
|
end_date: endDate || void 0,
|
|
23374
23903
|
location_ids: locationIds ? locationIds.split(",").filter(Boolean) : void 0,
|
|
@@ -23384,6 +23913,37 @@ const reputationHandlers = [
|
|
|
23384
23913
|
data: analyticsData
|
|
23385
23914
|
});
|
|
23386
23915
|
}),
|
|
23916
|
+
// Review Time-Series
|
|
23917
|
+
http.get(`${HOSTNAME}/api/reviews/time-series`, ({ request }) => {
|
|
23918
|
+
const url = new URL(request.url);
|
|
23919
|
+
const startDate = url.searchParams.get("start_date");
|
|
23920
|
+
const endDate = url.searchParams.get("end_date");
|
|
23921
|
+
const locationIds = url.searchParams.get("location_ids");
|
|
23922
|
+
if (!startDate || !endDate) {
|
|
23923
|
+
return HttpResponse.json(
|
|
23924
|
+
{
|
|
23925
|
+
success: false,
|
|
23926
|
+
message: "Missing required parameters: start_date and end_date"
|
|
23927
|
+
},
|
|
23928
|
+
{ status: 400 }
|
|
23929
|
+
);
|
|
23930
|
+
}
|
|
23931
|
+
const platformData = getSandboxDataForPlatform(currentSandboxPlatformId);
|
|
23932
|
+
const queryParams = {
|
|
23933
|
+
start_date: startDate,
|
|
23934
|
+
end_date: endDate,
|
|
23935
|
+
location_ids: locationIds ? locationIds.split(",").filter(Boolean) : void 0
|
|
23936
|
+
};
|
|
23937
|
+
const timeSeriesData = generateReviewTimeSeriesData({
|
|
23938
|
+
platformData,
|
|
23939
|
+
queryParams
|
|
23940
|
+
});
|
|
23941
|
+
return HttpResponse.json({
|
|
23942
|
+
success: true,
|
|
23943
|
+
message: "Success (Sandbox)",
|
|
23944
|
+
data: timeSeriesData
|
|
23945
|
+
});
|
|
23946
|
+
}),
|
|
23387
23947
|
// Feedback Analytics
|
|
23388
23948
|
http.get(`${HOSTNAME}/api/feedback/analytics`, ({ request }) => {
|
|
23389
23949
|
const url = new URL(request.url);
|
|
@@ -23409,6 +23969,60 @@ const reputationHandlers = [
|
|
|
23409
23969
|
message: "Success (Sandbox)",
|
|
23410
23970
|
data: analyticsData
|
|
23411
23971
|
});
|
|
23972
|
+
}),
|
|
23973
|
+
// Feedback Time-Series
|
|
23974
|
+
http.get(`${HOSTNAME}/api/feedback/time-series`, ({ request }) => {
|
|
23975
|
+
const url = new URL(request.url);
|
|
23976
|
+
const startDate = url.searchParams.get("start_date");
|
|
23977
|
+
const endDate = url.searchParams.get("end_date");
|
|
23978
|
+
if (!startDate || !endDate) {
|
|
23979
|
+
return HttpResponse.json(
|
|
23980
|
+
{
|
|
23981
|
+
success: false,
|
|
23982
|
+
message: "Missing required parameters: start_date and end_date"
|
|
23983
|
+
},
|
|
23984
|
+
{ status: 400 }
|
|
23985
|
+
);
|
|
23986
|
+
}
|
|
23987
|
+
const platformData = getSandboxDataForPlatform(currentSandboxPlatformId);
|
|
23988
|
+
const queryParams = {
|
|
23989
|
+
start_date: startDate,
|
|
23990
|
+
end_date: endDate
|
|
23991
|
+
};
|
|
23992
|
+
const timeSeriesData = generateFeedbackTimeSeriesData({
|
|
23993
|
+
platformData,
|
|
23994
|
+
queryParams
|
|
23995
|
+
});
|
|
23996
|
+
return HttpResponse.json({
|
|
23997
|
+
success: true,
|
|
23998
|
+
message: "Success (Sandbox)",
|
|
23999
|
+
data: timeSeriesData
|
|
24000
|
+
});
|
|
24001
|
+
}),
|
|
24002
|
+
// Reputation Audit Logs
|
|
24003
|
+
http.get(`${HOSTNAME}/api/reputation/audit-logs`, ({ request }) => {
|
|
24004
|
+
const url = new URL(request.url);
|
|
24005
|
+
const startDate = url.searchParams.get("start_date");
|
|
24006
|
+
const endDate = url.searchParams.get("end_date");
|
|
24007
|
+
const locationIds = url.searchParams.getAll("location_ids");
|
|
24008
|
+
const cursor = url.searchParams.get("cursor");
|
|
24009
|
+
const limit = parseInt(url.searchParams.get("limit") || "25", 10);
|
|
24010
|
+
const searchTerm = url.searchParams.get("search_term");
|
|
24011
|
+
const orderBy = url.searchParams.get("order_by") || "timestamp";
|
|
24012
|
+
const auditLogResponse = generateAuditLogData({
|
|
24013
|
+
startDate,
|
|
24014
|
+
endDate,
|
|
24015
|
+
locationIds,
|
|
24016
|
+
cursor,
|
|
24017
|
+
limit,
|
|
24018
|
+
searchTerm,
|
|
24019
|
+
orderBy
|
|
24020
|
+
});
|
|
24021
|
+
return HttpResponse.json({
|
|
24022
|
+
success: true,
|
|
24023
|
+
message: "Success (Sandbox)",
|
|
24024
|
+
data: auditLogResponse
|
|
24025
|
+
});
|
|
23412
24026
|
})
|
|
23413
24027
|
];
|
|
23414
24028
|
const getHandlersByFeatures = (features) => {
|