@btst/plugin-affiliate 1.0.0-beta.0 → 1.1.1-beta.0
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/api/bridges.cjs +57 -0
- package/dist/api/bridges.mjs +55 -0
- package/dist/api/index.cjs +2 -0
- package/dist/api/index.d.cts +69 -2
- package/dist/api/index.d.mts +69 -2
- package/dist/api/index.d.ts +69 -2
- package/dist/api/index.mjs +1 -0
- package/dist/client/components/pages/affiliate-detail-page.internal.cjs +1 -1
- package/dist/client/components/pages/affiliate-detail-page.internal.mjs +1 -1
- package/dist/client/components/pages/affiliate-portal-page.internal.cjs +1 -1
- package/dist/client/components/pages/affiliate-portal-page.internal.mjs +1 -1
- package/dist/client/components/pages/affiliates-page.internal.cjs +11 -0
- package/dist/client/components/pages/affiliates-page.internal.mjs +11 -0
- package/dist/client/components/shared.cjs +15 -1
- package/dist/client/components/shared.mjs +15 -1
- package/dist/client/index.d.cts +7 -0
- package/dist/client/index.d.mts +7 -0
- package/dist/client/index.d.ts +7 -0
- package/package.json +5 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const attribution = require('../attribution.cjs');
|
|
4
|
+
const schemas = require('../schemas.cjs');
|
|
5
|
+
|
|
6
|
+
function createAffiliateConversionHooks(options) {
|
|
7
|
+
const capturePaymentAttribution = ({ request }) => {
|
|
8
|
+
if (!request) return void 0;
|
|
9
|
+
const parsed = schemas.createConversionSchema.shape.attribution.safeParse(
|
|
10
|
+
attribution.attributionFromRequest(request)
|
|
11
|
+
);
|
|
12
|
+
return parsed.success ? parsed.data : void 0;
|
|
13
|
+
};
|
|
14
|
+
async function paid(source, id, context) {
|
|
15
|
+
const payment = context?.payment;
|
|
16
|
+
if (!payment?.attribution) return;
|
|
17
|
+
await options.recordConversion({
|
|
18
|
+
externalRef: `${source}:${id}`,
|
|
19
|
+
amount: payment.amount,
|
|
20
|
+
currency: payment.currency,
|
|
21
|
+
attribution: payment.attribution
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
ecommerce: {
|
|
26
|
+
capturePaymentAttribution,
|
|
27
|
+
async onAfterOrderPaid(order, context) {
|
|
28
|
+
if (order.paymentStatus !== "paid") return;
|
|
29
|
+
await paid("ecommerce", order.id, {
|
|
30
|
+
payment: {
|
|
31
|
+
amount: order.subtotal - order.discount,
|
|
32
|
+
currency: order.currency,
|
|
33
|
+
attribution: context.attribution
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
school: {
|
|
39
|
+
capturePaymentAttribution,
|
|
40
|
+
async onAfterEnroll(enrollment, _course, context) {
|
|
41
|
+
if (enrollment.status !== "enrolled" && enrollment.status !== "completed")
|
|
42
|
+
return;
|
|
43
|
+
await paid("school", enrollment.id, context);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
calendar: {
|
|
47
|
+
capturePaymentAttribution,
|
|
48
|
+
async onAfterConfirmBooking(booking, context) {
|
|
49
|
+
if (booking.status !== "confirmed" || context?.reason === "rescheduled")
|
|
50
|
+
return;
|
|
51
|
+
await paid("calendar", booking.id, context);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.createAffiliateConversionHooks = createAffiliateConversionHooks;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { attributionFromRequest } from '../attribution.mjs';
|
|
2
|
+
import { createConversionSchema } from '../schemas.mjs';
|
|
3
|
+
|
|
4
|
+
function createAffiliateConversionHooks(options) {
|
|
5
|
+
const capturePaymentAttribution = ({ request }) => {
|
|
6
|
+
if (!request) return void 0;
|
|
7
|
+
const parsed = createConversionSchema.shape.attribution.safeParse(
|
|
8
|
+
attributionFromRequest(request)
|
|
9
|
+
);
|
|
10
|
+
return parsed.success ? parsed.data : void 0;
|
|
11
|
+
};
|
|
12
|
+
async function paid(source, id, context) {
|
|
13
|
+
const payment = context?.payment;
|
|
14
|
+
if (!payment?.attribution) return;
|
|
15
|
+
await options.recordConversion({
|
|
16
|
+
externalRef: `${source}:${id}`,
|
|
17
|
+
amount: payment.amount,
|
|
18
|
+
currency: payment.currency,
|
|
19
|
+
attribution: payment.attribution
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
ecommerce: {
|
|
24
|
+
capturePaymentAttribution,
|
|
25
|
+
async onAfterOrderPaid(order, context) {
|
|
26
|
+
if (order.paymentStatus !== "paid") return;
|
|
27
|
+
await paid("ecommerce", order.id, {
|
|
28
|
+
payment: {
|
|
29
|
+
amount: order.subtotal - order.discount,
|
|
30
|
+
currency: order.currency,
|
|
31
|
+
attribution: context.attribution
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
school: {
|
|
37
|
+
capturePaymentAttribution,
|
|
38
|
+
async onAfterEnroll(enrollment, _course, context) {
|
|
39
|
+
if (enrollment.status !== "enrolled" && enrollment.status !== "completed")
|
|
40
|
+
return;
|
|
41
|
+
await paid("school", enrollment.id, context);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
calendar: {
|
|
45
|
+
capturePaymentAttribution,
|
|
46
|
+
async onAfterConfirmBooking(booking, context) {
|
|
47
|
+
if (booking.status !== "confirmed" || context?.reason === "rescheduled")
|
|
48
|
+
return;
|
|
49
|
+
await paid("calendar", booking.id, context);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { createAffiliateConversionHooks };
|
package/dist/api/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ const getters = require('./getters.cjs');
|
|
|
7
7
|
const mutations = require('./mutations.cjs');
|
|
8
8
|
const attribution = require('../attribution.cjs');
|
|
9
9
|
const commission = require('../commission.cjs');
|
|
10
|
+
const bridges = require('./bridges.cjs');
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
|
|
@@ -47,3 +48,4 @@ exports.referralCodeFromURL = attribution.referralCodeFromURL;
|
|
|
47
48
|
exports.safeLandingPath = attribution.safeLandingPath;
|
|
48
49
|
exports.selectAttributionClick = attribution.selectAttributionClick;
|
|
49
50
|
exports.calculateCommission = commission.calculateCommission;
|
|
51
|
+
exports.createAffiliateConversionHooks = bridges.createAffiliateConversionHooks;
|
package/dist/api/index.d.cts
CHANGED
|
@@ -971,5 +971,72 @@ declare function updatePayout(adapter: DBAdapter, id: string, input: {
|
|
|
971
971
|
/** Amounts are integer minor units; percentage values may have up to two decimals. */
|
|
972
972
|
declare function calculateCommission(amount: number, type: CommissionType, value: number): number;
|
|
973
973
|
|
|
974
|
-
|
|
975
|
-
|
|
974
|
+
/** Application-owned conversion operation; source plugins remain independently installable. */
|
|
975
|
+
interface AffiliateConversionBridgeOptions {
|
|
976
|
+
/** Call the configured stack's trusted.affiliate.createConversion operation. Errors propagate for payment webhook retry. */
|
|
977
|
+
recordConversion: (input: CreateConversionInput) => Promise<unknown>;
|
|
978
|
+
}
|
|
979
|
+
type Attribution = {
|
|
980
|
+
readonly code?: string;
|
|
981
|
+
readonly clickId?: string;
|
|
982
|
+
};
|
|
983
|
+
type PaymentContext = {
|
|
984
|
+
readonly payment?: {
|
|
985
|
+
readonly amount: number;
|
|
986
|
+
readonly currency: string;
|
|
987
|
+
readonly attribution?: Attribution;
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
/**
|
|
991
|
+
* Capture browser attribution before checkout and record only verified paid
|
|
992
|
+
* conversions using the stored snapshot. External references are namespaced by
|
|
993
|
+
* source entity; the Affiliate operation deduplicates retries and commissions.
|
|
994
|
+
*/
|
|
995
|
+
declare function createAffiliateConversionHooks(options: AffiliateConversionBridgeOptions): {
|
|
996
|
+
ecommerce: {
|
|
997
|
+
capturePaymentAttribution: ({ request }: {
|
|
998
|
+
request?: Request;
|
|
999
|
+
}) => {
|
|
1000
|
+
code?: string | undefined;
|
|
1001
|
+
clickId?: string | undefined;
|
|
1002
|
+
} | undefined;
|
|
1003
|
+
onAfterOrderPaid(order: {
|
|
1004
|
+
readonly id: string;
|
|
1005
|
+
readonly paymentStatus: string;
|
|
1006
|
+
readonly subtotal: number;
|
|
1007
|
+
readonly discount: number;
|
|
1008
|
+
readonly currency: string;
|
|
1009
|
+
}, context: {
|
|
1010
|
+
readonly attribution?: Attribution;
|
|
1011
|
+
}): Promise<void>;
|
|
1012
|
+
};
|
|
1013
|
+
school: {
|
|
1014
|
+
capturePaymentAttribution: ({ request }: {
|
|
1015
|
+
request?: Request;
|
|
1016
|
+
}) => {
|
|
1017
|
+
code?: string | undefined;
|
|
1018
|
+
clickId?: string | undefined;
|
|
1019
|
+
} | undefined;
|
|
1020
|
+
onAfterEnroll(enrollment: {
|
|
1021
|
+
readonly id: string;
|
|
1022
|
+
readonly status: string;
|
|
1023
|
+
}, _course: unknown, context?: PaymentContext): Promise<void>;
|
|
1024
|
+
};
|
|
1025
|
+
calendar: {
|
|
1026
|
+
capturePaymentAttribution: ({ request }: {
|
|
1027
|
+
request?: Request;
|
|
1028
|
+
}) => {
|
|
1029
|
+
code?: string | undefined;
|
|
1030
|
+
clickId?: string | undefined;
|
|
1031
|
+
} | undefined;
|
|
1032
|
+
onAfterConfirmBooking(booking: {
|
|
1033
|
+
readonly id: string;
|
|
1034
|
+
readonly status: string;
|
|
1035
|
+
}, context?: PaymentContext & {
|
|
1036
|
+
readonly reason?: "rescheduled";
|
|
1037
|
+
}): Promise<void>;
|
|
1038
|
+
};
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
export { Affiliate, AffiliateOptions, AffiliatePortal, AffiliateStats, AffiliateStatus, Commission, CommissionStatus, CommissionType, Conversion, CreateAffiliateInput, CreateConversionInput, CreatePayoutInput, ListParams, ListResult, MarketingAsset, Payout, PayoutStatus, ReferralClick, TrackClickInput, UpdateAffiliateInput, affiliateBackendPlugin, affiliateSchema, allRows, calculateCommission, createAffiliate, createAffiliateConversionHooks, createConversion, createPayout, deleteAffiliate, exportPayouts, getAffiliate, getAffiliateByCode, getAffiliateByUserId, getAffiliateStats, getCommission, getConversionByExternalRef, getPayout, getPortal, getReferralClick, listAffiliates, listCommissions, listPayouts, serializeAffiliateRecord, trackClick, updateAffiliate, updateCommission, updatePayout, withAffiliateTransaction };
|
|
1042
|
+
export type { AffiliateApiRouter, AffiliateBackendOptions, AffiliateConversionBridgeOptions, AffiliateDataAdapter, AffiliateHookContext, AffiliatePluginHooks };
|
package/dist/api/index.d.mts
CHANGED
|
@@ -971,5 +971,72 @@ declare function updatePayout(adapter: DBAdapter, id: string, input: {
|
|
|
971
971
|
/** Amounts are integer minor units; percentage values may have up to two decimals. */
|
|
972
972
|
declare function calculateCommission(amount: number, type: CommissionType, value: number): number;
|
|
973
973
|
|
|
974
|
-
|
|
975
|
-
|
|
974
|
+
/** Application-owned conversion operation; source plugins remain independently installable. */
|
|
975
|
+
interface AffiliateConversionBridgeOptions {
|
|
976
|
+
/** Call the configured stack's trusted.affiliate.createConversion operation. Errors propagate for payment webhook retry. */
|
|
977
|
+
recordConversion: (input: CreateConversionInput) => Promise<unknown>;
|
|
978
|
+
}
|
|
979
|
+
type Attribution = {
|
|
980
|
+
readonly code?: string;
|
|
981
|
+
readonly clickId?: string;
|
|
982
|
+
};
|
|
983
|
+
type PaymentContext = {
|
|
984
|
+
readonly payment?: {
|
|
985
|
+
readonly amount: number;
|
|
986
|
+
readonly currency: string;
|
|
987
|
+
readonly attribution?: Attribution;
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
/**
|
|
991
|
+
* Capture browser attribution before checkout and record only verified paid
|
|
992
|
+
* conversions using the stored snapshot. External references are namespaced by
|
|
993
|
+
* source entity; the Affiliate operation deduplicates retries and commissions.
|
|
994
|
+
*/
|
|
995
|
+
declare function createAffiliateConversionHooks(options: AffiliateConversionBridgeOptions): {
|
|
996
|
+
ecommerce: {
|
|
997
|
+
capturePaymentAttribution: ({ request }: {
|
|
998
|
+
request?: Request;
|
|
999
|
+
}) => {
|
|
1000
|
+
code?: string | undefined;
|
|
1001
|
+
clickId?: string | undefined;
|
|
1002
|
+
} | undefined;
|
|
1003
|
+
onAfterOrderPaid(order: {
|
|
1004
|
+
readonly id: string;
|
|
1005
|
+
readonly paymentStatus: string;
|
|
1006
|
+
readonly subtotal: number;
|
|
1007
|
+
readonly discount: number;
|
|
1008
|
+
readonly currency: string;
|
|
1009
|
+
}, context: {
|
|
1010
|
+
readonly attribution?: Attribution;
|
|
1011
|
+
}): Promise<void>;
|
|
1012
|
+
};
|
|
1013
|
+
school: {
|
|
1014
|
+
capturePaymentAttribution: ({ request }: {
|
|
1015
|
+
request?: Request;
|
|
1016
|
+
}) => {
|
|
1017
|
+
code?: string | undefined;
|
|
1018
|
+
clickId?: string | undefined;
|
|
1019
|
+
} | undefined;
|
|
1020
|
+
onAfterEnroll(enrollment: {
|
|
1021
|
+
readonly id: string;
|
|
1022
|
+
readonly status: string;
|
|
1023
|
+
}, _course: unknown, context?: PaymentContext): Promise<void>;
|
|
1024
|
+
};
|
|
1025
|
+
calendar: {
|
|
1026
|
+
capturePaymentAttribution: ({ request }: {
|
|
1027
|
+
request?: Request;
|
|
1028
|
+
}) => {
|
|
1029
|
+
code?: string | undefined;
|
|
1030
|
+
clickId?: string | undefined;
|
|
1031
|
+
} | undefined;
|
|
1032
|
+
onAfterConfirmBooking(booking: {
|
|
1033
|
+
readonly id: string;
|
|
1034
|
+
readonly status: string;
|
|
1035
|
+
}, context?: PaymentContext & {
|
|
1036
|
+
readonly reason?: "rescheduled";
|
|
1037
|
+
}): Promise<void>;
|
|
1038
|
+
};
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
export { Affiliate, AffiliateOptions, AffiliatePortal, AffiliateStats, AffiliateStatus, Commission, CommissionStatus, CommissionType, Conversion, CreateAffiliateInput, CreateConversionInput, CreatePayoutInput, ListParams, ListResult, MarketingAsset, Payout, PayoutStatus, ReferralClick, TrackClickInput, UpdateAffiliateInput, affiliateBackendPlugin, affiliateSchema, allRows, calculateCommission, createAffiliate, createAffiliateConversionHooks, createConversion, createPayout, deleteAffiliate, exportPayouts, getAffiliate, getAffiliateByCode, getAffiliateByUserId, getAffiliateStats, getCommission, getConversionByExternalRef, getPayout, getPortal, getReferralClick, listAffiliates, listCommissions, listPayouts, serializeAffiliateRecord, trackClick, updateAffiliate, updateCommission, updatePayout, withAffiliateTransaction };
|
|
1042
|
+
export type { AffiliateApiRouter, AffiliateBackendOptions, AffiliateConversionBridgeOptions, AffiliateDataAdapter, AffiliateHookContext, AffiliatePluginHooks };
|
package/dist/api/index.d.ts
CHANGED
|
@@ -971,5 +971,72 @@ declare function updatePayout(adapter: DBAdapter, id: string, input: {
|
|
|
971
971
|
/** Amounts are integer minor units; percentage values may have up to two decimals. */
|
|
972
972
|
declare function calculateCommission(amount: number, type: CommissionType, value: number): number;
|
|
973
973
|
|
|
974
|
-
|
|
975
|
-
|
|
974
|
+
/** Application-owned conversion operation; source plugins remain independently installable. */
|
|
975
|
+
interface AffiliateConversionBridgeOptions {
|
|
976
|
+
/** Call the configured stack's trusted.affiliate.createConversion operation. Errors propagate for payment webhook retry. */
|
|
977
|
+
recordConversion: (input: CreateConversionInput) => Promise<unknown>;
|
|
978
|
+
}
|
|
979
|
+
type Attribution = {
|
|
980
|
+
readonly code?: string;
|
|
981
|
+
readonly clickId?: string;
|
|
982
|
+
};
|
|
983
|
+
type PaymentContext = {
|
|
984
|
+
readonly payment?: {
|
|
985
|
+
readonly amount: number;
|
|
986
|
+
readonly currency: string;
|
|
987
|
+
readonly attribution?: Attribution;
|
|
988
|
+
};
|
|
989
|
+
};
|
|
990
|
+
/**
|
|
991
|
+
* Capture browser attribution before checkout and record only verified paid
|
|
992
|
+
* conversions using the stored snapshot. External references are namespaced by
|
|
993
|
+
* source entity; the Affiliate operation deduplicates retries and commissions.
|
|
994
|
+
*/
|
|
995
|
+
declare function createAffiliateConversionHooks(options: AffiliateConversionBridgeOptions): {
|
|
996
|
+
ecommerce: {
|
|
997
|
+
capturePaymentAttribution: ({ request }: {
|
|
998
|
+
request?: Request;
|
|
999
|
+
}) => {
|
|
1000
|
+
code?: string | undefined;
|
|
1001
|
+
clickId?: string | undefined;
|
|
1002
|
+
} | undefined;
|
|
1003
|
+
onAfterOrderPaid(order: {
|
|
1004
|
+
readonly id: string;
|
|
1005
|
+
readonly paymentStatus: string;
|
|
1006
|
+
readonly subtotal: number;
|
|
1007
|
+
readonly discount: number;
|
|
1008
|
+
readonly currency: string;
|
|
1009
|
+
}, context: {
|
|
1010
|
+
readonly attribution?: Attribution;
|
|
1011
|
+
}): Promise<void>;
|
|
1012
|
+
};
|
|
1013
|
+
school: {
|
|
1014
|
+
capturePaymentAttribution: ({ request }: {
|
|
1015
|
+
request?: Request;
|
|
1016
|
+
}) => {
|
|
1017
|
+
code?: string | undefined;
|
|
1018
|
+
clickId?: string | undefined;
|
|
1019
|
+
} | undefined;
|
|
1020
|
+
onAfterEnroll(enrollment: {
|
|
1021
|
+
readonly id: string;
|
|
1022
|
+
readonly status: string;
|
|
1023
|
+
}, _course: unknown, context?: PaymentContext): Promise<void>;
|
|
1024
|
+
};
|
|
1025
|
+
calendar: {
|
|
1026
|
+
capturePaymentAttribution: ({ request }: {
|
|
1027
|
+
request?: Request;
|
|
1028
|
+
}) => {
|
|
1029
|
+
code?: string | undefined;
|
|
1030
|
+
clickId?: string | undefined;
|
|
1031
|
+
} | undefined;
|
|
1032
|
+
onAfterConfirmBooking(booking: {
|
|
1033
|
+
readonly id: string;
|
|
1034
|
+
readonly status: string;
|
|
1035
|
+
}, context?: PaymentContext & {
|
|
1036
|
+
readonly reason?: "rescheduled";
|
|
1037
|
+
}): Promise<void>;
|
|
1038
|
+
};
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
export { Affiliate, AffiliateOptions, AffiliatePortal, AffiliateStats, AffiliateStatus, Commission, CommissionStatus, CommissionType, Conversion, CreateAffiliateInput, CreateConversionInput, CreatePayoutInput, ListParams, ListResult, MarketingAsset, Payout, PayoutStatus, ReferralClick, TrackClickInput, UpdateAffiliateInput, affiliateBackendPlugin, affiliateSchema, allRows, calculateCommission, createAffiliate, createAffiliateConversionHooks, createConversion, createPayout, deleteAffiliate, exportPayouts, getAffiliate, getAffiliateByCode, getAffiliateByUserId, getAffiliateStats, getCommission, getConversionByExternalRef, getPayout, getPortal, getReferralClick, listAffiliates, listCommissions, listPayouts, serializeAffiliateRecord, trackClick, updateAffiliate, updateCommission, updatePayout, withAffiliateTransaction };
|
|
1042
|
+
export type { AffiliateApiRouter, AffiliateBackendOptions, AffiliateConversionBridgeOptions, AffiliateDataAdapter, AffiliateHookContext, AffiliatePluginHooks };
|
package/dist/api/index.mjs
CHANGED
|
@@ -5,3 +5,4 @@ export { allRows, exportPayouts, getAffiliate, getAffiliateByCode, getAffiliateB
|
|
|
5
5
|
export { createAffiliate, createConversion, createPayout, deleteAffiliate, trackClick, updateAffiliate, updateCommission, updatePayout, withAffiliateTransaction } from './mutations.mjs';
|
|
6
6
|
export { AFFILIATE_COOKIE_NAME, attributionFromRequest, createReferralLink, createTrackingLink, getReferralRedirect, isClickWithinWindow, referralCodeFromURL, safeLandingPath, selectAttributionClick } from '../attribution.mjs';
|
|
7
7
|
export { calculateCommission } from '../commission.mjs';
|
|
8
|
+
export { createAffiliateConversionHooks } from './bridges.mjs';
|
|
@@ -50,7 +50,7 @@ function AffiliateDetailPage({ id }) {
|
|
|
50
50
|
action: /* @__PURE__ */ jsxRuntime.jsx(shared.Status, { value: affiliate.status }),
|
|
51
51
|
children: [
|
|
52
52
|
/* @__PURE__ */ jsxRuntime.jsx(Link, { href: resolve("affiliate/admin/affiliates").href, children: "Back to affiliates" }),
|
|
53
|
-
/* @__PURE__ */ jsxRuntime.jsx(shared.Stats, { stats }),
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx(shared.Stats, { page: "affiliateDetail", stats }),
|
|
54
54
|
/* @__PURE__ */ jsxRuntime.jsx(shared.ActionNotice, { ...action }),
|
|
55
55
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
56
56
|
context.PermissionAccess,
|
|
@@ -48,7 +48,7 @@ function AffiliateDetailPage({ id }) {
|
|
|
48
48
|
action: /* @__PURE__ */ jsx(Status, { value: affiliate.status }),
|
|
49
49
|
children: [
|
|
50
50
|
/* @__PURE__ */ jsx(Link, { href: resolve("affiliate/admin/affiliates").href, children: "Back to affiliates" }),
|
|
51
|
-
/* @__PURE__ */ jsx(Stats, { stats }),
|
|
51
|
+
/* @__PURE__ */ jsx(Stats, { page: "affiliateDetail", stats }),
|
|
52
52
|
/* @__PURE__ */ jsx(ActionNotice, { ...action }),
|
|
53
53
|
/* @__PURE__ */ jsx(
|
|
54
54
|
PermissionAccess,
|
|
@@ -67,7 +67,7 @@ function AffiliatePortalPage() {
|
|
|
67
67
|
children: [
|
|
68
68
|
/* @__PURE__ */ jsxRuntime.jsx(shared.ActionNotice, { ...action }),
|
|
69
69
|
affiliate.status !== "approved" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "affiliate-notice", children: affiliate.status === "pending" ? "Your application is pending review. Referral tracking starts after approval." : "Your affiliate account is suspended. New referrals are not attributed. Contact the program administrator for help." }),
|
|
70
|
-
/* @__PURE__ */ jsxRuntime.jsx(shared.Stats, { stats }),
|
|
70
|
+
/* @__PURE__ */ jsxRuntime.jsx(shared.Stats, { page: "portal", stats }),
|
|
71
71
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "affiliate-section affiliate-stack", children: [
|
|
72
72
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Your referral link" }),
|
|
73
73
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "affiliate-muted", children: [
|
|
@@ -65,7 +65,7 @@ function AffiliatePortalPage() {
|
|
|
65
65
|
children: [
|
|
66
66
|
/* @__PURE__ */ jsx(ActionNotice, { ...action }),
|
|
67
67
|
affiliate.status !== "approved" && /* @__PURE__ */ jsx("p", { className: "affiliate-notice", children: affiliate.status === "pending" ? "Your application is pending review. Referral tracking starts after approval." : "Your affiliate account is suspended. New referrals are not attributed. Contact the program administrator for help." }),
|
|
68
|
-
/* @__PURE__ */ jsx(Stats, { stats }),
|
|
68
|
+
/* @__PURE__ */ jsx(Stats, { page: "portal", stats }),
|
|
69
69
|
/* @__PURE__ */ jsxs("section", { className: "affiliate-section affiliate-stack", children: [
|
|
70
70
|
/* @__PURE__ */ jsx("h2", { children: "Your referral link" }),
|
|
71
71
|
/* @__PURE__ */ jsxs("p", { className: "affiliate-muted", children: [
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
const react = require('react');
|
|
6
|
+
const pageContext = require('@btst/stack/page-context');
|
|
6
7
|
const context = require('@btst/stack/context');
|
|
7
8
|
const permissions = require('../../../permissions.cjs');
|
|
8
9
|
const client_hooks_index = require('../../hooks/index.cjs');
|
|
@@ -23,6 +24,16 @@ function AffiliatesPage() {
|
|
|
23
24
|
const action = shared.useAffiliateAction();
|
|
24
25
|
const { Link, resolve } = context.usePluginSiteNavigation(constants.AFFILIATE_PLUGIN_ID);
|
|
25
26
|
const { localization } = context.usePluginOverrides(constants.AFFILIATE_PLUGIN_ID);
|
|
27
|
+
pageContext.useRegisterPageAIContext({
|
|
28
|
+
routeName: "affiliate-admin",
|
|
29
|
+
pageDescription: JSON.stringify({
|
|
30
|
+
page: "Read-only Affiliate administration summary. No mutation tools are available.",
|
|
31
|
+
statusFilter: status || "all",
|
|
32
|
+
offset,
|
|
33
|
+
totalAffiliates: data.total,
|
|
34
|
+
visibleAffiliates: data.items.length
|
|
35
|
+
})
|
|
36
|
+
});
|
|
26
37
|
const save = (event) => {
|
|
27
38
|
event.preventDefault();
|
|
28
39
|
const fields = new FormData(event.currentTarget);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
+
import { useRegisterPageAIContext } from '@btst/stack/page-context';
|
|
4
5
|
import { usePluginSiteNavigation, usePluginOverrides, PermissionAccess } from '@btst/stack/context';
|
|
5
6
|
import { affiliatePermissions } from '../../../permissions.mjs';
|
|
6
7
|
import { useAffiliates, useCreateAffiliate, useUpdateAffiliate } from '../../hooks/index.mjs';
|
|
@@ -21,6 +22,16 @@ function AffiliatesPage() {
|
|
|
21
22
|
const action = useAffiliateAction();
|
|
22
23
|
const { Link, resolve } = usePluginSiteNavigation(AFFILIATE_PLUGIN_ID);
|
|
23
24
|
const { localization } = usePluginOverrides(AFFILIATE_PLUGIN_ID);
|
|
25
|
+
useRegisterPageAIContext({
|
|
26
|
+
routeName: "affiliate-admin",
|
|
27
|
+
pageDescription: JSON.stringify({
|
|
28
|
+
page: "Read-only Affiliate administration summary. No mutation tools are available.",
|
|
29
|
+
statusFilter: status || "all",
|
|
30
|
+
offset,
|
|
31
|
+
totalAffiliates: data.total,
|
|
32
|
+
visibleAffiliates: data.items.length
|
|
33
|
+
})
|
|
34
|
+
});
|
|
24
35
|
const save = (event) => {
|
|
25
36
|
event.preventDefault();
|
|
26
37
|
const fields = new FormData(event.currentTarget);
|
|
@@ -224,7 +224,21 @@ function date(value) {
|
|
|
224
224
|
day: "numeric"
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
|
-
function Stats({
|
|
227
|
+
function Stats({
|
|
228
|
+
page,
|
|
229
|
+
stats
|
|
230
|
+
}) {
|
|
231
|
+
return page ? /* @__PURE__ */ jsxRuntime.jsx(PageStats, { page, stats }) : /* @__PURE__ */ jsxRuntime.jsx(DefaultStats, { stats });
|
|
232
|
+
}
|
|
233
|
+
function PageStats({
|
|
234
|
+
page,
|
|
235
|
+
stats
|
|
236
|
+
}) {
|
|
237
|
+
const { pageOverrides } = context.usePluginOverrides(constants.AFFILIATE_PLUGIN_ID);
|
|
238
|
+
const Component = (page ? pageOverrides?.[page]?.Stats : void 0) ?? DefaultStats;
|
|
239
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Component, { stats });
|
|
240
|
+
}
|
|
241
|
+
function DefaultStats({ stats }) {
|
|
228
242
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
229
243
|
"section",
|
|
230
244
|
{
|
|
@@ -222,7 +222,21 @@ function date(value) {
|
|
|
222
222
|
day: "numeric"
|
|
223
223
|
});
|
|
224
224
|
}
|
|
225
|
-
function Stats({
|
|
225
|
+
function Stats({
|
|
226
|
+
page,
|
|
227
|
+
stats
|
|
228
|
+
}) {
|
|
229
|
+
return page ? /* @__PURE__ */ jsx(PageStats, { page, stats }) : /* @__PURE__ */ jsx(DefaultStats, { stats });
|
|
230
|
+
}
|
|
231
|
+
function PageStats({
|
|
232
|
+
page,
|
|
233
|
+
stats
|
|
234
|
+
}) {
|
|
235
|
+
const { pageOverrides } = usePluginOverrides(AFFILIATE_PLUGIN_ID);
|
|
236
|
+
const Component = (page ? pageOverrides?.[page]?.Stats : void 0) ?? DefaultStats;
|
|
237
|
+
return /* @__PURE__ */ jsx(Component, { stats });
|
|
238
|
+
}
|
|
239
|
+
function DefaultStats({ stats }) {
|
|
226
240
|
return /* @__PURE__ */ jsxs(
|
|
227
241
|
"section",
|
|
228
242
|
{
|
package/dist/client/index.d.cts
CHANGED
|
@@ -2,10 +2,17 @@ import * as _btst_stack_client from '@btst/stack/client';
|
|
|
2
2
|
import * as _btst_yar from '@btst/yar';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ComponentType } from 'react';
|
|
5
|
+
import { AffiliateStats } from '../types.cjs';
|
|
5
6
|
import { AffiliatesPageComponent, CommissionsPageComponent, PayoutsPageComponent, AffiliateApplyPageComponent, AffiliatePortalPageComponent } from './components/index.cjs';
|
|
6
7
|
|
|
7
8
|
/** Affiliate-specific page labels; shared services come from StackProvider. */
|
|
8
9
|
interface AffiliatePluginOverrides {
|
|
10
|
+
/** Earnings and referral summary presentation, independently for admin and affiliate pages. */
|
|
11
|
+
pageOverrides?: Partial<Record<"affiliateDetail" | "portal", {
|
|
12
|
+
Stats?: ComponentType<{
|
|
13
|
+
stats: AffiliateStats;
|
|
14
|
+
}>;
|
|
15
|
+
}>>;
|
|
9
16
|
localization?: Partial<{
|
|
10
17
|
affiliates: string;
|
|
11
18
|
commissions: string;
|
package/dist/client/index.d.mts
CHANGED
|
@@ -2,10 +2,17 @@ import * as _btst_stack_client from '@btst/stack/client';
|
|
|
2
2
|
import * as _btst_yar from '@btst/yar';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ComponentType } from 'react';
|
|
5
|
+
import { AffiliateStats } from '../types.mjs';
|
|
5
6
|
import { AffiliatesPageComponent, CommissionsPageComponent, PayoutsPageComponent, AffiliateApplyPageComponent, AffiliatePortalPageComponent } from './components/index.mjs';
|
|
6
7
|
|
|
7
8
|
/** Affiliate-specific page labels; shared services come from StackProvider. */
|
|
8
9
|
interface AffiliatePluginOverrides {
|
|
10
|
+
/** Earnings and referral summary presentation, independently for admin and affiliate pages. */
|
|
11
|
+
pageOverrides?: Partial<Record<"affiliateDetail" | "portal", {
|
|
12
|
+
Stats?: ComponentType<{
|
|
13
|
+
stats: AffiliateStats;
|
|
14
|
+
}>;
|
|
15
|
+
}>>;
|
|
9
16
|
localization?: Partial<{
|
|
10
17
|
affiliates: string;
|
|
11
18
|
commissions: string;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -2,10 +2,17 @@ import * as _btst_stack_client from '@btst/stack/client';
|
|
|
2
2
|
import * as _btst_yar from '@btst/yar';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ComponentType } from 'react';
|
|
5
|
+
import { AffiliateStats } from '../types.js';
|
|
5
6
|
import { AffiliatesPageComponent, CommissionsPageComponent, PayoutsPageComponent, AffiliateApplyPageComponent, AffiliatePortalPageComponent } from './components/index.js';
|
|
6
7
|
|
|
7
8
|
/** Affiliate-specific page labels; shared services come from StackProvider. */
|
|
8
9
|
interface AffiliatePluginOverrides {
|
|
10
|
+
/** Earnings and referral summary presentation, independently for admin and affiliate pages. */
|
|
11
|
+
pageOverrides?: Partial<Record<"affiliateDetail" | "portal", {
|
|
12
|
+
Stats?: ComponentType<{
|
|
13
|
+
stats: AffiliateStats;
|
|
14
|
+
}>;
|
|
15
|
+
}>>;
|
|
9
16
|
localization?: Partial<{
|
|
10
17
|
affiliates: string;
|
|
11
18
|
commissions: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btst/plugin-affiliate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"zod": "^4.2.1"
|
|
135
135
|
},
|
|
136
136
|
"peerDependencies": {
|
|
137
|
-
"@btst/stack": ">=6.
|
|
137
|
+
"@btst/stack": ">=6.2.0-beta.0 <6.2.0",
|
|
138
138
|
"@btst/yar": ">=1.3.2",
|
|
139
139
|
"@tanstack/react-query": "^5.0.0",
|
|
140
140
|
"react": ">=19.2.6",
|
|
@@ -151,12 +151,12 @@
|
|
|
151
151
|
"unbuild": "3.6.1",
|
|
152
152
|
"vitest": "^4.1.12",
|
|
153
153
|
"@btst/adapter-memory": "3.0.1",
|
|
154
|
-
"@btst/stack": "6.
|
|
154
|
+
"@btst/stack": "6.2.0-beta.0"
|
|
155
155
|
},
|
|
156
|
-
"gitHead": "
|
|
156
|
+
"gitHead": "a4bbf36fd6f07909353ea84aa22de491bbefc260",
|
|
157
157
|
"scripts": {
|
|
158
158
|
"build": "unbuild --clean",
|
|
159
|
-
"typecheck": "tsc --project tsconfig.json",
|
|
159
|
+
"typecheck": "tsc --project tsconfig.json && tsc --project tsconfig.typecheck.json",
|
|
160
160
|
"test": "vitest run"
|
|
161
161
|
}
|
|
162
162
|
}
|