@deallony/shared 1.2.63 → 1.2.67
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/cjs/constants/company/Company.d.ts +12 -0
- package/dist/cjs/constants/company/Company.js +13 -1
- package/dist/cjs/constants/events/Event.js +3 -0
- package/dist/cjs/constants/events/EventPricing.d.ts +44 -0
- package/dist/cjs/constants/events/EventPricing.js +18 -0
- package/dist/cjs/constants/events/index.d.ts +1 -0
- package/dist/cjs/constants/events/index.js +1 -0
- package/dist/cjs/constants/routes/app.d.ts +34 -1
- package/dist/cjs/constants/routes/app.js +8 -1
- package/dist/cjs/dto/ad/Ad.dto.d.ts +2 -1
- package/dist/cjs/dto/analysis/Analysis.dto.d.ts +4 -0
- package/dist/cjs/dto/analysis/Analysis.dto.js +2 -0
- package/dist/cjs/dto/events/Event.dto.d.ts +3 -1
- package/dist/cjs/dto/index.d.ts +1 -0
- package/dist/cjs/dto/index.js +2 -1
- package/dist/cjs/schema/ad/ad-views.schema.d.ts +5 -0
- package/dist/cjs/schema/ad/ad-views.schema.js +6 -1
- package/dist/cjs/schema/ad/save-ad.schema.d.ts +4 -0
- package/dist/cjs/schema/ad/save-ad.schema.js +1 -0
- package/dist/cjs/schema/analysis/analysis-report.schema.d.ts +17 -0
- package/dist/cjs/schema/analysis/analysis-report.schema.js +29 -0
- package/dist/cjs/schema/analysis/index.d.ts +1 -0
- package/dist/cjs/schema/analysis/index.js +17 -0
- package/dist/cjs/schema/communication/support-ticket.schema.d.ts +3 -3
- package/dist/cjs/schema/events/Event.schema.d.ts +20 -0
- package/dist/cjs/schema/events/Event.schema.js +11 -1
- package/dist/cjs/schema/index.d.ts +1 -0
- package/dist/cjs/schema/index.js +2 -1
- package/dist/cjs/types/ad/Ad.d.ts +6 -1
- package/dist/cjs/types/ad/AdDailyViews.d.ts +14 -0
- package/dist/cjs/types/analysis/AnalysisDailySnapshot.d.ts +98 -0
- package/dist/cjs/types/company/Company.d.ts +26 -0
- package/dist/cjs/types/events/Event.d.ts +8 -0
- package/dist/cjs/utils/analysis.d.ts +7 -0
- package/dist/cjs/utils/analysis.js +14 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/esm/constants/company/Company.js +12 -0
- package/dist/esm/constants/events/Event.js +3 -0
- package/dist/esm/constants/events/EventPricing.js +15 -0
- package/dist/esm/constants/events/index.js +1 -0
- package/dist/esm/constants/routes/app.js +8 -1
- package/dist/esm/dto/analysis/Analysis.dto.js +1 -0
- package/dist/esm/dto/index.js +1 -0
- package/dist/esm/schema/ad/ad-views.schema.js +5 -0
- package/dist/esm/schema/ad/save-ad.schema.js +1 -0
- package/dist/esm/schema/analysis/analysis-report.schema.js +26 -0
- package/dist/esm/schema/analysis/index.js +1 -0
- package/dist/esm/schema/events/Event.schema.js +11 -1
- package/dist/esm/schema/index.js +1 -0
- package/dist/esm/utils/analysis.js +10 -0
- package/dist/esm/utils/index.js +1 -0
- package/package.json +1 -1
|
@@ -7,3 +7,15 @@ export declare const CompanyStatusOptions: {
|
|
|
7
7
|
value: string;
|
|
8
8
|
label: string;
|
|
9
9
|
}[];
|
|
10
|
+
/** A user's role inside a company; a company has exactly one owner */
|
|
11
|
+
export declare const COMPANY_MEMBER_ROLE: {
|
|
12
|
+
readonly OWNER: "owner";
|
|
13
|
+
readonly ADMIN: "admin";
|
|
14
|
+
readonly MEMBER: "member";
|
|
15
|
+
};
|
|
16
|
+
/** What the account represents; all three behave the same */
|
|
17
|
+
export declare const COMPANY_TYPE: {
|
|
18
|
+
readonly COMPANY: "company";
|
|
19
|
+
readonly TEAM: "team";
|
|
20
|
+
readonly OTHER: "other";
|
|
21
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CompanyStatusOptions = exports.COMPANY_STATUS = void 0;
|
|
3
|
+
exports.COMPANY_TYPE = exports.COMPANY_MEMBER_ROLE = exports.CompanyStatusOptions = exports.COMPANY_STATUS = void 0;
|
|
4
4
|
exports.COMPANY_STATUS = {
|
|
5
5
|
PENDING: 'pending',
|
|
6
6
|
APPROVED: 'approved',
|
|
@@ -10,3 +10,15 @@ exports.CompanyStatusOptions = Object.values(exports.COMPANY_STATUS).map((status
|
|
|
10
10
|
value: status,
|
|
11
11
|
label: status.charAt(0).toUpperCase() + status.slice(1),
|
|
12
12
|
}));
|
|
13
|
+
/** A user's role inside a company; a company has exactly one owner */
|
|
14
|
+
exports.COMPANY_MEMBER_ROLE = {
|
|
15
|
+
OWNER: 'owner',
|
|
16
|
+
ADMIN: 'admin',
|
|
17
|
+
MEMBER: 'member',
|
|
18
|
+
};
|
|
19
|
+
/** What the account represents; all three behave the same */
|
|
20
|
+
exports.COMPANY_TYPE = {
|
|
21
|
+
COMPANY: 'company',
|
|
22
|
+
TEAM: 'team',
|
|
23
|
+
OTHER: 'other',
|
|
24
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const EVENT_CREATION_PRICE_SETTING = "event_creation_price";
|
|
2
|
+
export type EventCreationPriceSetting = {
|
|
3
|
+
currencyKey: string;
|
|
4
|
+
company_price: number;
|
|
5
|
+
user_price: number;
|
|
6
|
+
loyalty_point_value?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const EventOwnerTypes: {
|
|
9
|
+
readonly COMPANY: {
|
|
10
|
+
readonly value: "company";
|
|
11
|
+
readonly name: {
|
|
12
|
+
readonly en: "Company";
|
|
13
|
+
readonly ar: "شركة";
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
readonly USER: {
|
|
17
|
+
readonly value: "user";
|
|
18
|
+
readonly name: {
|
|
19
|
+
readonly en: "Personal";
|
|
20
|
+
readonly ar: "شخصي";
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare const EventOwnerTypeValues: readonly ["company", "user"];
|
|
25
|
+
export type EventOwnerType = (typeof EventOwnerTypeValues)[number];
|
|
26
|
+
export declare const EventOwnerTypeOptions: {
|
|
27
|
+
value: "company" | "user";
|
|
28
|
+
name: {
|
|
29
|
+
readonly en: "Company";
|
|
30
|
+
readonly ar: "شركة";
|
|
31
|
+
} | {
|
|
32
|
+
readonly en: "Personal";
|
|
33
|
+
readonly ar: "شخصي";
|
|
34
|
+
};
|
|
35
|
+
}[];
|
|
36
|
+
export declare const EventPublishPaymentMethodValues: readonly ["balance", "loyalty", "combined"];
|
|
37
|
+
export type EventPublishPaymentMethod = (typeof EventPublishPaymentMethodValues)[number];
|
|
38
|
+
export type EventPublishPrice = {
|
|
39
|
+
owner_type: EventOwnerType;
|
|
40
|
+
price_syp: number;
|
|
41
|
+
point_value_syp: number;
|
|
42
|
+
rate_badge: string;
|
|
43
|
+
already_paid: boolean;
|
|
44
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventPublishPaymentMethodValues = exports.EventOwnerTypeOptions = exports.EventOwnerTypeValues = exports.EventOwnerTypes = exports.EVENT_CREATION_PRICE_SETTING = void 0;
|
|
4
|
+
exports.EVENT_CREATION_PRICE_SETTING = "event_creation_price";
|
|
5
|
+
exports.EventOwnerTypes = {
|
|
6
|
+
COMPANY: { value: "company", name: { en: "Company", ar: "شركة" } },
|
|
7
|
+
USER: { value: "user", name: { en: "Personal", ar: "شخصي" } },
|
|
8
|
+
};
|
|
9
|
+
exports.EventOwnerTypeValues = ["company", "user"];
|
|
10
|
+
exports.EventOwnerTypeOptions = Object.values(exports.EventOwnerTypes).map((t) => ({
|
|
11
|
+
value: t.value,
|
|
12
|
+
name: t.name,
|
|
13
|
+
}));
|
|
14
|
+
exports.EventPublishPaymentMethodValues = [
|
|
15
|
+
"balance",
|
|
16
|
+
"loyalty",
|
|
17
|
+
"combined",
|
|
18
|
+
];
|
|
@@ -20,3 +20,4 @@ __exportStar(require("./EventWedding"), exports);
|
|
|
20
20
|
__exportStar(require("./EventTemplate"), exports);
|
|
21
21
|
__exportStar(require("./EventTimeline"), exports);
|
|
22
22
|
__exportStar(require("./EventInvitationScanType"), exports);
|
|
23
|
+
__exportStar(require("./EventPricing"), exports);
|
|
@@ -71,6 +71,13 @@ export declare const APP_ROUTES: {
|
|
|
71
71
|
ad_id: string | number;
|
|
72
72
|
};
|
|
73
73
|
};
|
|
74
|
+
/** The owner's views report for an ad */
|
|
75
|
+
readonly viewsReport: (id: number | string) => {
|
|
76
|
+
pathname: string;
|
|
77
|
+
params: {
|
|
78
|
+
id: string | number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
74
81
|
readonly promotionDetails: (params: {
|
|
75
82
|
id: number | string;
|
|
76
83
|
ad_id?: number | string;
|
|
@@ -371,6 +378,13 @@ export declare const APP_ROUTES: {
|
|
|
371
378
|
id: string | number;
|
|
372
379
|
};
|
|
373
380
|
};
|
|
381
|
+
/** Public profile with the company's ads */
|
|
382
|
+
readonly profile: (id: number | string) => {
|
|
383
|
+
pathname: string;
|
|
384
|
+
params: {
|
|
385
|
+
id: string | number;
|
|
386
|
+
};
|
|
387
|
+
};
|
|
374
388
|
};
|
|
375
389
|
readonly venue: {
|
|
376
390
|
readonly new: (companyId: number | string) => {
|
|
@@ -393,10 +407,29 @@ export declare const APP_ROUTES: {
|
|
|
393
407
|
};
|
|
394
408
|
};
|
|
395
409
|
readonly event: {
|
|
396
|
-
readonly new: (venueId
|
|
410
|
+
readonly new: (venueId?: number | string) => {
|
|
397
411
|
pathname: string;
|
|
398
412
|
params: {
|
|
399
413
|
venue_id: string | number;
|
|
414
|
+
personal?: undefined;
|
|
415
|
+
};
|
|
416
|
+
} | {
|
|
417
|
+
pathname: string;
|
|
418
|
+
params: {
|
|
419
|
+
personal: string;
|
|
420
|
+
venue_id?: undefined;
|
|
421
|
+
};
|
|
422
|
+
};
|
|
423
|
+
readonly start: () => {
|
|
424
|
+
pathname: string;
|
|
425
|
+
};
|
|
426
|
+
readonly mine: () => {
|
|
427
|
+
pathname: string;
|
|
428
|
+
};
|
|
429
|
+
readonly publish: (id: number | string) => {
|
|
430
|
+
pathname: string;
|
|
431
|
+
params: {
|
|
432
|
+
id: string | number;
|
|
400
433
|
};
|
|
401
434
|
};
|
|
402
435
|
readonly edit: (id: number | string) => {
|
|
@@ -36,6 +36,8 @@ exports.APP_ROUTES = {
|
|
|
36
36
|
pathname: "/ad/promotions/history/[ad_id]",
|
|
37
37
|
params: { ad_id: params.id },
|
|
38
38
|
}),
|
|
39
|
+
/** The owner's views report for an ad */
|
|
40
|
+
viewsReport: (id) => ({ pathname: "/ad/views-report/[id]", params: { id } }),
|
|
39
41
|
promotionDetails: (params) => ({
|
|
40
42
|
pathname: "/ad/promotions/details/[id]",
|
|
41
43
|
params: {
|
|
@@ -166,6 +168,8 @@ exports.APP_ROUTES = {
|
|
|
166
168
|
new: () => ({ pathname: "/company/new" }),
|
|
167
169
|
edit: (id) => ({ pathname: "/company/new", params: { id } }),
|
|
168
170
|
details: (id) => ({ pathname: "/company/details/[id]", params: { id } }),
|
|
171
|
+
/** Public profile with the company's ads */
|
|
172
|
+
profile: (id) => ({ pathname: "/company/profile/[id]", params: { id } }),
|
|
169
173
|
},
|
|
170
174
|
venue: {
|
|
171
175
|
new: (companyId) => ({ pathname: "/venue/new", params: { company_id: companyId } }),
|
|
@@ -173,7 +177,10 @@ exports.APP_ROUTES = {
|
|
|
173
177
|
details: (id) => ({ pathname: "/venue/details/[id]", params: { id } }),
|
|
174
178
|
},
|
|
175
179
|
event: {
|
|
176
|
-
new: (venueId) =>
|
|
180
|
+
new: (venueId) => venueId ? { pathname: "/event/new", params: { venue_id: venueId } } : { pathname: "/event/new", params: { personal: "1" } },
|
|
181
|
+
start: () => ({ pathname: "/event/start" }),
|
|
182
|
+
mine: () => ({ pathname: "/event/mine" }),
|
|
183
|
+
publish: (id) => ({ pathname: "/event/publish/[id]", params: { id } }),
|
|
177
184
|
edit: (id) => ({ pathname: "/event/new", params: { id } }),
|
|
178
185
|
details: (id) => ({ pathname: "/event/details/[id]", params: { id } }),
|
|
179
186
|
},
|
|
@@ -2,12 +2,13 @@ import { z } from "zod";
|
|
|
2
2
|
import type { IAd } from "../../types/ad/Ad";
|
|
3
3
|
import { createAdSchema, saveAdSchema, updateAdSchema } from "../../schema/ad/save-ad.schema";
|
|
4
4
|
import { findAdSchema } from "../../schema/ad/find-ad.schema";
|
|
5
|
-
import { adDailyViewsSchema } from "../../schema/ad/ad-views.schema";
|
|
5
|
+
import { adDailyViewsSchema, adViewsReportSchema } from "../../schema/ad/ad-views.schema";
|
|
6
6
|
export type CreateAdDto = z.infer<typeof createAdSchema>;
|
|
7
7
|
export type UpdateAdDto = z.infer<typeof updateAdSchema>;
|
|
8
8
|
export type SaveAdDto = z.infer<typeof saveAdSchema>;
|
|
9
9
|
export type FindAdDto = z.input<typeof findAdSchema>;
|
|
10
10
|
export type AdDailyViewsDto = z.input<typeof adDailyViewsSchema>;
|
|
11
|
+
export type AdViewsReportDto = z.input<typeof adViewsReportSchema>;
|
|
11
12
|
export declare const AdDto: (params: {
|
|
12
13
|
ad: IAd;
|
|
13
14
|
}) => IAd;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { analysisRebuildSchema, analysisReportSchema } from "../../schema/analysis/analysis-report.schema";
|
|
3
|
+
export type AnalysisReportDto = z.input<typeof analysisReportSchema>;
|
|
4
|
+
export type AnalysisRebuildDto = z.input<typeof analysisRebuildSchema>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { createEventSchema, getEventsFilterSchema, saveEventSchema, updateEventSchema } from '../../schema/events/Event.schema';
|
|
2
|
+
import { createEventSchema, eventIdSchema, getEventsFilterSchema, publishEventSchema, saveEventSchema, updateEventSchema } from '../../schema/events/Event.schema';
|
|
3
3
|
export type CreateEventDto = z.infer<typeof createEventSchema>;
|
|
4
4
|
export type UpdateEventDto = z.infer<typeof updateEventSchema>;
|
|
5
5
|
export type SaveEventDto = z.infer<typeof saveEventSchema>;
|
|
6
6
|
export type GetEventsFilterDto = z.infer<typeof getEventsFilterSchema>;
|
|
7
|
+
export type PublishEventDto = z.infer<typeof publishEventSchema>;
|
|
8
|
+
export type EventIdDto = z.infer<typeof eventIdSchema>;
|
package/dist/cjs/dto/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export * as GEMINI_API_KEYS from './ai/gemini-api-key.dto';
|
|
|
6
6
|
export * as PAYMENTS from './payments';
|
|
7
7
|
export * as ADDRESSES from './addresses/addresses.dto';
|
|
8
8
|
export * as POTENTIAL_USERS from './potential-users/potential-user-import.dto';
|
|
9
|
+
export * as ANALYSIS from './analysis/Analysis.dto';
|
package/dist/cjs/dto/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.POTENTIAL_USERS = exports.ADDRESSES = exports.PAYMENTS = exports.GEMINI_API_KEYS = exports.Ai = exports.EVENTS = exports.AD = exports.AdDto = void 0;
|
|
36
|
+
exports.ANALYSIS = exports.POTENTIAL_USERS = exports.ADDRESSES = exports.PAYMENTS = exports.GEMINI_API_KEYS = exports.Ai = exports.EVENTS = exports.AD = exports.AdDto = void 0;
|
|
37
37
|
var Ad_dto_1 = require("./ad/Ad.dto");
|
|
38
38
|
Object.defineProperty(exports, "AdDto", { enumerable: true, get: function () { return Ad_dto_1.AdDto; } });
|
|
39
39
|
exports.AD = __importStar(require("./ad/Ad.dto"));
|
|
@@ -43,3 +43,4 @@ exports.GEMINI_API_KEYS = __importStar(require("./ai/gemini-api-key.dto"));
|
|
|
43
43
|
exports.PAYMENTS = __importStar(require("./payments"));
|
|
44
44
|
exports.ADDRESSES = __importStar(require("./addresses/addresses.dto"));
|
|
45
45
|
exports.POTENTIAL_USERS = __importStar(require("./potential-users/potential-user-import.dto"));
|
|
46
|
+
exports.ANALYSIS = __importStar(require("./analysis/Analysis.dto"));
|
|
@@ -5,3 +5,8 @@ export declare const AD_DAILY_VIEWS_MAX_DAYS = 180;
|
|
|
5
5
|
export declare const adDailyViewsSchema: z.ZodObject<{
|
|
6
6
|
days: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
7
7
|
}, z.core.$strip>;
|
|
8
|
+
/** Body of `POST api/v1/ads/views-report/:id`: one page of the owner's daily view records */
|
|
9
|
+
export declare const adViewsReportSchema: z.ZodObject<{
|
|
10
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
11
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
12
|
+
}, z.core.$strip>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.adDailyViewsSchema = exports.AD_DAILY_VIEWS_MAX_DAYS = void 0;
|
|
3
|
+
exports.adViewsReportSchema = exports.adDailyViewsSchema = exports.AD_DAILY_VIEWS_MAX_DAYS = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
/** Most days of per-day views kept on the server (older merged days are deleted) */
|
|
6
6
|
exports.AD_DAILY_VIEWS_MAX_DAYS = 180;
|
|
@@ -8,3 +8,8 @@ exports.AD_DAILY_VIEWS_MAX_DAYS = 180;
|
|
|
8
8
|
exports.adDailyViewsSchema = zod_1.z.object({
|
|
9
9
|
days: zod_1.z.coerce.number().int().min(1).max(exports.AD_DAILY_VIEWS_MAX_DAYS).default(30),
|
|
10
10
|
});
|
|
11
|
+
/** Body of `POST api/v1/ads/views-report/:id`: one page of the owner's daily view records */
|
|
12
|
+
exports.adViewsReportSchema = zod_1.z.object({
|
|
13
|
+
page: zod_1.z.coerce.number().int().min(1).default(1),
|
|
14
|
+
limit: zod_1.z.coerce.number().int().min(1).max(100).default(15),
|
|
15
|
+
});
|
|
@@ -92,6 +92,7 @@ export declare const createAdSchema: z.ZodObject<{
|
|
|
92
92
|
by_call: z.ZodOptional<z.ZodBoolean>;
|
|
93
93
|
}, z.core.$strip>>>;
|
|
94
94
|
selected_phone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
95
|
+
company_id: z.ZodNullable<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
95
96
|
expires_at: z.ZodNullable<z.ZodOptional<z.ZodISODateTime>>;
|
|
96
97
|
adLocations: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
97
98
|
ad_id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -190,6 +191,7 @@ export declare const updateAdSchema: z.ZodObject<{
|
|
|
190
191
|
by_call: z.ZodOptional<z.ZodBoolean>;
|
|
191
192
|
}, z.core.$strip>>>;
|
|
192
193
|
selected_phone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
194
|
+
company_id: z.ZodNullable<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
193
195
|
expires_at: z.ZodNullable<z.ZodOptional<z.ZodISODateTime>>;
|
|
194
196
|
adLocations: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
195
197
|
ad_id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -283,6 +285,7 @@ export declare const saveAdSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
283
285
|
by_call: z.ZodOptional<z.ZodBoolean>;
|
|
284
286
|
}, z.core.$strip>>>;
|
|
285
287
|
selected_phone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
288
|
+
company_id: z.ZodNullable<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
286
289
|
expires_at: z.ZodNullable<z.ZodOptional<z.ZodISODateTime>>;
|
|
287
290
|
adLocations: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
288
291
|
ad_id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -380,6 +383,7 @@ export declare const saveAdSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
380
383
|
by_call: z.ZodOptional<z.ZodBoolean>;
|
|
381
384
|
}, z.core.$strip>>>;
|
|
382
385
|
selected_phone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
386
|
+
company_id: z.ZodNullable<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
383
387
|
expires_at: z.ZodNullable<z.ZodOptional<z.ZodISODateTime>>;
|
|
384
388
|
adLocations: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
385
389
|
ad_id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -194,6 +194,7 @@ const baseAdCommon = zod_1.z.object({
|
|
|
194
194
|
.optional()
|
|
195
195
|
.nullable(),
|
|
196
196
|
selected_phone: zod_1.z.string().trim().optional().nullable(),
|
|
197
|
+
company_id: zod_1.z.coerce.number().int().positive().optional().nullable(),
|
|
197
198
|
expires_at: zod_1.z.iso.datetime().optional().nullable(),
|
|
198
199
|
adLocations: zod_1.z.array(adLocationSchema).optional().nullable(),
|
|
199
200
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** `metrics_version` of snapshots holding daily views (older snapshots held all-time totals) */
|
|
3
|
+
export declare const ANALYSIS_METRICS_VERSION = 2;
|
|
4
|
+
/** Longest period one analysis report covers */
|
|
5
|
+
export declare const ANALYSIS_REPORT_MAX_DAYS = 366;
|
|
6
|
+
/** Longest period rebuilt in one request; daily view records older than 180 days are deleted anyway */
|
|
7
|
+
export declare const ANALYSIS_REBUILD_MAX_DAYS = 180;
|
|
8
|
+
/** Body of `POST admin/analysis/snapshots/report`: one day when `from` equals `to` */
|
|
9
|
+
export declare const analysisReportSchema: z.ZodObject<{
|
|
10
|
+
from: z.ZodString;
|
|
11
|
+
to: z.ZodString;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
/** Body of `POST admin/analysis/snapshots/rebuild`: recalculates the snapshots of these days */
|
|
14
|
+
export declare const analysisRebuildSchema: z.ZodObject<{
|
|
15
|
+
from: z.ZodString;
|
|
16
|
+
to: z.ZodString;
|
|
17
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analysisRebuildSchema = exports.analysisReportSchema = exports.ANALYSIS_REBUILD_MAX_DAYS = exports.ANALYSIS_REPORT_MAX_DAYS = exports.ANALYSIS_METRICS_VERSION = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** `metrics_version` of snapshots holding daily views (older snapshots held all-time totals) */
|
|
6
|
+
exports.ANALYSIS_METRICS_VERSION = 2;
|
|
7
|
+
/** Longest period one analysis report covers */
|
|
8
|
+
exports.ANALYSIS_REPORT_MAX_DAYS = 366;
|
|
9
|
+
/** Longest period rebuilt in one request; daily view records older than 180 days are deleted anyway */
|
|
10
|
+
exports.ANALYSIS_REBUILD_MAX_DAYS = 180;
|
|
11
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
12
|
+
const day = zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Use YYYY-MM-DD')
|
|
16
|
+
.refine((value) => !Number.isNaN(Date.parse(`${value}T00:00:00Z`)), 'Invalid date');
|
|
17
|
+
/** Days in `from`..`to`, both included */
|
|
18
|
+
const spanDays = ({ from, to }) => Math.round((Date.parse(`${to}T00:00:00Z`) - Date.parse(`${from}T00:00:00Z`)) / DAY_MS) + 1;
|
|
19
|
+
const period = (maxDays) => zod_1.z
|
|
20
|
+
.object({ from: day, to: day })
|
|
21
|
+
.refine((value) => value.from <= value.to, { message: '`from` must not be after `to`', path: ['to'] })
|
|
22
|
+
.refine((value) => spanDays(value) <= maxDays, {
|
|
23
|
+
message: `The period can be at most ${maxDays} days`,
|
|
24
|
+
path: ['from'],
|
|
25
|
+
});
|
|
26
|
+
/** Body of `POST admin/analysis/snapshots/report`: one day when `from` equals `to` */
|
|
27
|
+
exports.analysisReportSchema = period(exports.ANALYSIS_REPORT_MAX_DAYS);
|
|
28
|
+
/** Body of `POST admin/analysis/snapshots/rebuild`: recalculates the snapshots of these days */
|
|
29
|
+
exports.analysisRebuildSchema = period(exports.ANALYSIS_REBUILD_MAX_DAYS);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './analysis-report.schema';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./analysis-report.schema"), exports);
|
|
@@ -16,22 +16,22 @@ export declare const SupportTicketPrioritySchema: z.ZodEnum<{
|
|
|
16
16
|
}>;
|
|
17
17
|
export declare const SupportTicketCategorySchema: z.ZodEnum<{
|
|
18
18
|
payment: "payment";
|
|
19
|
+
other: "other";
|
|
19
20
|
technical_issue: "technical_issue";
|
|
20
21
|
account: "account";
|
|
21
22
|
advertisement: "advertisement";
|
|
22
23
|
complaint: "complaint";
|
|
23
|
-
other: "other";
|
|
24
24
|
}>;
|
|
25
25
|
export declare const SupportTicketCreateSchema: z.ZodObject<{
|
|
26
26
|
title: z.ZodString;
|
|
27
27
|
description: z.ZodString;
|
|
28
28
|
category: z.ZodDefault<z.ZodEnum<{
|
|
29
29
|
payment: "payment";
|
|
30
|
+
other: "other";
|
|
30
31
|
technical_issue: "technical_issue";
|
|
31
32
|
account: "account";
|
|
32
33
|
advertisement: "advertisement";
|
|
33
34
|
complaint: "complaint";
|
|
34
|
-
other: "other";
|
|
35
35
|
}>>;
|
|
36
36
|
priority: z.ZodDefault<z.ZodEnum<{
|
|
37
37
|
low: "low";
|
|
@@ -51,11 +51,11 @@ export declare const SupportTicketAiCreateSchema: z.ZodObject<{
|
|
|
51
51
|
description: z.ZodString;
|
|
52
52
|
category: z.ZodDefault<z.ZodEnum<{
|
|
53
53
|
payment: "payment";
|
|
54
|
+
other: "other";
|
|
54
55
|
technical_issue: "technical_issue";
|
|
55
56
|
account: "account";
|
|
56
57
|
advertisement: "advertisement";
|
|
57
58
|
complaint: "complaint";
|
|
58
|
-
other: "other";
|
|
59
59
|
}>>;
|
|
60
60
|
priority: z.ZodDefault<z.ZodEnum<{
|
|
61
61
|
low: "low";
|
|
@@ -28,6 +28,8 @@ export declare const eventBaseSchema: z.ZodObject<{
|
|
|
28
28
|
event_type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
29
29
|
event_template: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
30
|
venue_id: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
31
|
+
venue_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
|
+
location_label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
31
33
|
invitation_scan_type: z.ZodOptional<z.ZodEnum<{
|
|
32
34
|
none: "none";
|
|
33
35
|
qrcode: "qrcode";
|
|
@@ -63,6 +65,8 @@ export declare const createEventSchema: z.ZodObject<{
|
|
|
63
65
|
event_type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
64
66
|
event_template: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
67
|
venue_id: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
68
|
+
venue_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
69
|
+
location_label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
66
70
|
invitation_scan_type: z.ZodOptional<z.ZodEnum<{
|
|
67
71
|
none: "none";
|
|
68
72
|
qrcode: "qrcode";
|
|
@@ -98,6 +102,8 @@ export declare const updateEventSchema: z.ZodObject<{
|
|
|
98
102
|
event_type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
99
103
|
event_template: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
100
104
|
venue_id: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
105
|
+
venue_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
106
|
+
location_label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
101
107
|
invitation_scan_type: z.ZodOptional<z.ZodEnum<{
|
|
102
108
|
none: "none";
|
|
103
109
|
qrcode: "qrcode";
|
|
@@ -134,6 +140,8 @@ export declare const saveEventSchema: z.ZodObject<{
|
|
|
134
140
|
event_type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
141
|
event_template: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
136
142
|
venue_id: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
143
|
+
venue_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
144
|
+
location_label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
137
145
|
invitation_scan_type: z.ZodOptional<z.ZodEnum<{
|
|
138
146
|
none: "none";
|
|
139
147
|
qrcode: "qrcode";
|
|
@@ -141,6 +149,18 @@ export declare const saveEventSchema: z.ZodObject<{
|
|
|
141
149
|
}>>;
|
|
142
150
|
id: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
143
151
|
}, z.core.$strip>;
|
|
152
|
+
export declare const publishEventSchema: z.ZodObject<{
|
|
153
|
+
id: z.ZodCoercedNumber<unknown>;
|
|
154
|
+
method: z.ZodEnum<{
|
|
155
|
+
combined: "combined";
|
|
156
|
+
balance: "balance";
|
|
157
|
+
loyalty: "loyalty";
|
|
158
|
+
}>;
|
|
159
|
+
points_used: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
160
|
+
}, z.core.$strip>;
|
|
161
|
+
export declare const eventIdSchema: z.ZodObject<{
|
|
162
|
+
id: z.ZodCoercedNumber<unknown>;
|
|
163
|
+
}, z.core.$strip>;
|
|
144
164
|
export declare const getEventsFilterSchema: z.ZodObject<{
|
|
145
165
|
is_published: z.ZodOptional<z.ZodBoolean>;
|
|
146
166
|
search: z.ZodOptional<z.ZodString>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getEventsFilterSchema = exports.saveEventSchema = exports.updateEventSchema = exports.createEventSchema = exports.eventBaseSchema = void 0;
|
|
3
|
+
exports.getEventsFilterSchema = exports.eventIdSchema = exports.publishEventSchema = exports.saveEventSchema = exports.updateEventSchema = exports.createEventSchema = exports.eventBaseSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const EventTimeline_schema_1 = require("./EventTimeline.schema");
|
|
6
6
|
const EventWedding_schema_1 = require("./EventWedding.schema");
|
|
@@ -17,6 +17,8 @@ exports.eventBaseSchema = zod_1.z.object({
|
|
|
17
17
|
event_type: zod_1.z.string().trim().max(255).nullable().optional(),
|
|
18
18
|
event_template: zod_1.z.string().trim().max(255).nullable().optional(),
|
|
19
19
|
venue_id: zod_1.z.coerce.number().int().positive().nullable().optional(),
|
|
20
|
+
venue_name: zod_1.z.string().trim().max(255).nullable().optional(),
|
|
21
|
+
location_label: zod_1.z.string().trim().nullable().optional(),
|
|
20
22
|
invitation_scan_type: zod_1.z.enum(events_1.EventInvitationScanTypeValues).optional(),
|
|
21
23
|
});
|
|
22
24
|
exports.createEventSchema = exports.eventBaseSchema;
|
|
@@ -26,6 +28,14 @@ exports.updateEventSchema = exports.eventBaseSchema.extend({
|
|
|
26
28
|
exports.saveEventSchema = exports.eventBaseSchema.extend({
|
|
27
29
|
id: zod_1.z.coerce.number().int().positive().optional(),
|
|
28
30
|
});
|
|
31
|
+
exports.publishEventSchema = zod_1.z.object({
|
|
32
|
+
id: zod_1.z.coerce.number().int().positive(),
|
|
33
|
+
method: zod_1.z.enum(events_1.EventPublishPaymentMethodValues),
|
|
34
|
+
points_used: zod_1.z.coerce.number().int().nonnegative().optional(),
|
|
35
|
+
});
|
|
36
|
+
exports.eventIdSchema = zod_1.z.object({
|
|
37
|
+
id: zod_1.z.coerce.number().int().positive(),
|
|
38
|
+
});
|
|
29
39
|
exports.getEventsFilterSchema = zod_1.z.object({
|
|
30
40
|
is_published: zod_1.z.boolean().optional(),
|
|
31
41
|
search: zod_1.z.string().trim().optional(),
|
package/dist/cjs/schema/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.POTENTIAL_USERS = exports.ADDRESSES = exports.COMMUNICATION = exports.PAYMENTS = exports.EVENTS = exports.COMMON = exports.AI = exports.AD = void 0;
|
|
36
|
+
exports.ANALYSIS = exports.POTENTIAL_USERS = exports.ADDRESSES = exports.COMMUNICATION = exports.PAYMENTS = exports.EVENTS = exports.COMMON = exports.AI = exports.AD = void 0;
|
|
37
37
|
exports.AD = __importStar(require("./ad"));
|
|
38
38
|
exports.AI = __importStar(require("./ai"));
|
|
39
39
|
exports.COMMON = __importStar(require("./common"));
|
|
@@ -42,3 +42,4 @@ exports.PAYMENTS = __importStar(require("./payments"));
|
|
|
42
42
|
exports.COMMUNICATION = __importStar(require("./communication"));
|
|
43
43
|
exports.ADDRESSES = __importStar(require("./addresses/addresses.schema"));
|
|
44
44
|
exports.POTENTIAL_USERS = __importStar(require("./potential-users"));
|
|
45
|
+
exports.ANALYSIS = __importStar(require("./analysis"));
|
|
@@ -8,6 +8,7 @@ import { IService } from "../service/Service";
|
|
|
8
8
|
import { IUsedProduct } from "../used-product/UsedProduct";
|
|
9
9
|
import { Category, Currency } from "..";
|
|
10
10
|
import { IAdminBoundary } from "../geo";
|
|
11
|
+
import type { ICompany } from "../company/Company";
|
|
11
12
|
export type IAd = {
|
|
12
13
|
id?: number;
|
|
13
14
|
user_id?: number;
|
|
@@ -33,6 +34,9 @@ export type IAd = {
|
|
|
33
34
|
by_call?: boolean;
|
|
34
35
|
} | null;
|
|
35
36
|
selected_phone: string | null;
|
|
37
|
+
/** Optional company the ad is published under */
|
|
38
|
+
company_id?: number | null;
|
|
39
|
+
company?: Pick<ICompany, "id" | "name" | "type"> | null;
|
|
36
40
|
user?: IUser;
|
|
37
41
|
media: IMedia[] | null;
|
|
38
42
|
subject_type?: SubjectTable;
|
|
@@ -48,7 +52,7 @@ export type IAd = {
|
|
|
48
52
|
updated_at?: string | Date;
|
|
49
53
|
expires_at?: string | Date | null;
|
|
50
54
|
};
|
|
51
|
-
export type SaveAdDto = Partial<Omit<IAd, "created_at" | "updated_at" | "views" | "user" | "promotions">> & {
|
|
55
|
+
export type SaveAdDto = Partial<Omit<IAd, "created_at" | "updated_at" | "views" | "user" | "promotions" | "company">> & {
|
|
52
56
|
id?: number;
|
|
53
57
|
latitude?: number;
|
|
54
58
|
longitude?: number;
|
|
@@ -62,6 +66,7 @@ export type GetAdsFilterDto = {
|
|
|
62
66
|
boundary_ids?: number[];
|
|
63
67
|
category_id?: number;
|
|
64
68
|
user_id?: number;
|
|
69
|
+
company_id?: number;
|
|
65
70
|
subject_type?: SubjectTable;
|
|
66
71
|
search?: string;
|
|
67
72
|
status?: string;
|
|
@@ -3,3 +3,17 @@ export type IAdDailyViews = {
|
|
|
3
3
|
day: string;
|
|
4
4
|
views: number;
|
|
5
5
|
};
|
|
6
|
+
/** Header of the owner's views report */
|
|
7
|
+
export type IAdViewsReportSummary = {
|
|
8
|
+
/** All-time views, including today's */
|
|
9
|
+
total_views: number;
|
|
10
|
+
today: number;
|
|
11
|
+
last_7_days: number;
|
|
12
|
+
last_30_days: number;
|
|
13
|
+
/** Average views per day over the last 30 days */
|
|
14
|
+
daily_average: number;
|
|
15
|
+
/** The day with the most views among the kept daily records */
|
|
16
|
+
best_day: IAdDailyViews | null;
|
|
17
|
+
/** First day with a daily record (records are kept for 180 days) */
|
|
18
|
+
tracked_since: string | null;
|
|
19
|
+
};
|
|
@@ -17,9 +17,29 @@ type AdInteractions = {
|
|
|
17
17
|
* High-level app engagement and system health
|
|
18
18
|
*/
|
|
19
19
|
type AppMetrics = {
|
|
20
|
+
/** App opens on the snapshot day */
|
|
20
21
|
device_open_count: number;
|
|
21
22
|
chat_messages_count: number;
|
|
22
23
|
chat_rooms_count: number;
|
|
24
|
+
/** Opens of all devices ever, when the snapshot was taken; the day's opens are the difference to the previous day */
|
|
25
|
+
device_open_total?: number;
|
|
26
|
+
};
|
|
27
|
+
/** A number for each subject type */
|
|
28
|
+
export type AnalysisSubjectTypeCounts = {
|
|
29
|
+
services: number;
|
|
30
|
+
products: number;
|
|
31
|
+
properties: number;
|
|
32
|
+
motors: number;
|
|
33
|
+
};
|
|
34
|
+
/** Views of one category on one day, counting only ads placed directly in it (not its sub-categories) */
|
|
35
|
+
export type AnalysisCategoryViews = {
|
|
36
|
+
category_id: number;
|
|
37
|
+
views: number;
|
|
38
|
+
};
|
|
39
|
+
/** What was created on the snapshot day */
|
|
40
|
+
type ContentMetrics = {
|
|
41
|
+
new_ads: AnalysisSubjectTypeCounts;
|
|
42
|
+
new_users: number;
|
|
23
43
|
};
|
|
24
44
|
export type IAnalysisDailySnapshot = {
|
|
25
45
|
id: number;
|
|
@@ -35,5 +55,83 @@ export type IAnalysisDailySnapshot = {
|
|
|
35
55
|
motors: CategoryMetrics;
|
|
36
56
|
/** General app-wide engagement metrics */
|
|
37
57
|
app_metrics: AppMetrics;
|
|
58
|
+
/** Views per category on the day; empty on legacy snapshots */
|
|
59
|
+
category_views: AnalysisCategoryViews[];
|
|
60
|
+
content_metrics: ContentMetrics;
|
|
61
|
+
/**
|
|
62
|
+
* 1: legacy, `views_count` held all-time totals instead of the day's views.
|
|
63
|
+
* 2 (`SCHEMA.ANALYSIS.ANALYSIS_METRICS_VERSION`): daily views, Asia/Damascus days.
|
|
64
|
+
*/
|
|
65
|
+
metrics_version: number;
|
|
66
|
+
};
|
|
67
|
+
/** A snapshot as listed: without the per-category views */
|
|
68
|
+
export type IAnalysisDailySnapshotRow = Omit<IAnalysisDailySnapshot, 'category_views'>;
|
|
69
|
+
/** Sums over a period of daily snapshots */
|
|
70
|
+
export type IAnalysisReportTotals = {
|
|
71
|
+
views: AnalysisSubjectTypeCounts & {
|
|
72
|
+
total: number;
|
|
73
|
+
};
|
|
74
|
+
ad_interactions: AdInteractions;
|
|
75
|
+
app_metrics: Omit<AppMetrics, 'device_open_total'>;
|
|
76
|
+
content_metrics: ContentMetrics;
|
|
77
|
+
/** See `UTILS.analysisEngagementTotal` */
|
|
78
|
+
engagement_total: number;
|
|
79
|
+
/** Days in the period that have a snapshot */
|
|
80
|
+
days_count: number;
|
|
81
|
+
};
|
|
82
|
+
/** A category with the views of its ads and of all its sub-categories' ads */
|
|
83
|
+
export type IAnalysisCategoryNode = {
|
|
84
|
+
id: number;
|
|
85
|
+
name: string;
|
|
86
|
+
parent_id: number | null;
|
|
87
|
+
views: number;
|
|
88
|
+
/** Views in the period just before (`previous_from`..`previous_to`) */
|
|
89
|
+
previous_views: number;
|
|
90
|
+
/** Views in the same days one week earlier (`week_ago_from`..`week_ago_to`) */
|
|
91
|
+
week_ago_views: number;
|
|
92
|
+
children: IAnalysisCategoryNode[];
|
|
93
|
+
};
|
|
94
|
+
/** Top level of the category tree: one subject type with its top-level categories */
|
|
95
|
+
export type IAnalysisSubjectTypeNode = {
|
|
96
|
+
/** Category `type`: services, used_products, motors or properties */
|
|
97
|
+
subject_type: string;
|
|
98
|
+
views: number;
|
|
99
|
+
previous_views: number;
|
|
100
|
+
week_ago_views: number;
|
|
101
|
+
children: IAnalysisCategoryNode[];
|
|
102
|
+
};
|
|
103
|
+
export type IAnalysisTopAd = {
|
|
104
|
+
ad_id: number;
|
|
105
|
+
title: string | null;
|
|
106
|
+
subject_type: string | null;
|
|
107
|
+
category_id: number | null;
|
|
108
|
+
category_name: string | null;
|
|
109
|
+
views: number;
|
|
110
|
+
previous_views: number;
|
|
111
|
+
week_ago_views: number;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Body of `admin/analysis/snapshots/report`: the period `from`..`to` compared with the period of the
|
|
115
|
+
* same length just before it, and with the same days one week earlier
|
|
116
|
+
*/
|
|
117
|
+
export type IAnalysisReport = {
|
|
118
|
+
from: string;
|
|
119
|
+
to: string;
|
|
120
|
+
previous_from: string;
|
|
121
|
+
previous_to: string;
|
|
122
|
+
/** `from`..`to` moved back 7 days, e.g. last Sunday for a Sunday */
|
|
123
|
+
week_ago_from: string;
|
|
124
|
+
week_ago_to: string;
|
|
125
|
+
totals: IAnalysisReportTotals;
|
|
126
|
+
previous_totals: IAnalysisReportTotals;
|
|
127
|
+
week_ago_totals: IAnalysisReportTotals;
|
|
128
|
+
/** Daily rows for the trend chart: the period, extended to at least the last 30 days up to `to` */
|
|
129
|
+
trend: IAnalysisDailySnapshotRow[];
|
|
130
|
+
/** Subject types, each with its top-level categories; sorted by views */
|
|
131
|
+
category_tree: IAnalysisSubjectTypeNode[];
|
|
132
|
+
/** Most viewed ads in the period; empty for days older than the kept daily view records */
|
|
133
|
+
top_ads: IAnalysisTopAd[];
|
|
134
|
+
/** Days in the period whose view counts are legacy all-time totals; their views are left out of the sums */
|
|
135
|
+
legacy_days: string[];
|
|
38
136
|
};
|
|
39
137
|
export {};
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import type { IUser } from '../user/User';
|
|
2
2
|
import type { IEventVenue } from '../events/EventVenue';
|
|
3
|
+
export type CompanyMemberRole = 'owner' | 'admin' | 'member';
|
|
4
|
+
export type CompanyType = 'company' | 'team' | 'other';
|
|
5
|
+
export type ICompanyMember = {
|
|
6
|
+
id?: number;
|
|
7
|
+
company_id: number;
|
|
8
|
+
user_id: number;
|
|
9
|
+
role: CompanyMemberRole;
|
|
10
|
+
added_by_user_id?: number | null;
|
|
11
|
+
user?: IUser | null;
|
|
12
|
+
company?: ICompany | null;
|
|
13
|
+
created_at?: string | Date;
|
|
14
|
+
};
|
|
3
15
|
export type ICompany = {
|
|
4
16
|
id?: number;
|
|
5
17
|
name: string;
|
|
18
|
+
type?: CompanyType;
|
|
6
19
|
user_id?: number | null;
|
|
7
20
|
user?: IUser | null;
|
|
8
21
|
venues?: IEventVenue[];
|
|
22
|
+
members?: ICompanyMember[];
|
|
23
|
+
/** The signed-in user's role, on "my companies" responses */
|
|
24
|
+
my_role?: CompanyMemberRole;
|
|
25
|
+
status: string;
|
|
26
|
+
};
|
|
27
|
+
/** Public company profile: no phone numbers or other private data */
|
|
28
|
+
export type ICompanyProfile = {
|
|
29
|
+
id: number;
|
|
30
|
+
name: string;
|
|
31
|
+
type: CompanyType;
|
|
9
32
|
status: string;
|
|
33
|
+
members_count: number;
|
|
34
|
+
ads_count: number;
|
|
35
|
+
created_at?: string | Date;
|
|
10
36
|
};
|
|
@@ -2,6 +2,7 @@ import type { IEventTimeline } from "./EventTimeline";
|
|
|
2
2
|
import type { IEventRsvp } from "./EventRsvp";
|
|
3
3
|
import type { IEventWedding } from "./EventWedding";
|
|
4
4
|
import type { IEventVenue } from "./EventVenue";
|
|
5
|
+
import type { IUser } from "../user/User";
|
|
5
6
|
import { EventInvitationScanType } from "../../constants/events";
|
|
6
7
|
export type IEvent = {
|
|
7
8
|
id?: number;
|
|
@@ -19,4 +20,11 @@ export type IEvent = {
|
|
|
19
20
|
rsvps?: IEventRsvp[];
|
|
20
21
|
venue_id?: number | null;
|
|
21
22
|
venue?: IEventVenue | null;
|
|
23
|
+
venue_name?: string | null;
|
|
24
|
+
location_label?: string | null;
|
|
25
|
+
user_id?: number | null;
|
|
26
|
+
user?: IUser | null;
|
|
27
|
+
payment_id?: number | null;
|
|
28
|
+
paid_amount?: string | null;
|
|
29
|
+
paid_at?: string | Date | null;
|
|
22
30
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IAnalysisDailySnapshot } from "../types/analysis/AnalysisDailySnapshot";
|
|
2
|
+
type EngagementSource = Pick<IAnalysisDailySnapshot, 'ad_interactions'> & {
|
|
3
|
+
app_metrics: Pick<IAnalysisDailySnapshot['app_metrics'], 'chat_messages_count' | 'chat_rooms_count'>;
|
|
4
|
+
};
|
|
5
|
+
/** Engagement of a day: WhatsApp, call and chat clicks, shares, chat messages and new chat rooms */
|
|
6
|
+
export declare const analysisEngagementTotal: ({ ad_interactions: a, app_metrics: m }: EngagementSource) => number;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analysisEngagementTotal = void 0;
|
|
4
|
+
/** Engagement of a day: WhatsApp, call and chat clicks, shares, chat messages and new chat rooms */
|
|
5
|
+
const analysisEngagementTotal = ({ ad_interactions: a, app_metrics: m }) => {
|
|
6
|
+
var _a, _b, _c, _d, _e, _f;
|
|
7
|
+
return ((_a = a === null || a === void 0 ? void 0 : a.whatsapp_clicks) !== null && _a !== void 0 ? _a : 0) +
|
|
8
|
+
((_b = a === null || a === void 0 ? void 0 : a.call_clicks) !== null && _b !== void 0 ? _b : 0) +
|
|
9
|
+
((_c = a === null || a === void 0 ? void 0 : a.chat_clicks) !== null && _c !== void 0 ? _c : 0) +
|
|
10
|
+
((_d = a === null || a === void 0 ? void 0 : a.shares) !== null && _d !== void 0 ? _d : 0) +
|
|
11
|
+
((_e = m === null || m === void 0 ? void 0 : m.chat_messages_count) !== null && _e !== void 0 ? _e : 0) +
|
|
12
|
+
((_f = m === null || m === void 0 ? void 0 : m.chat_rooms_count) !== null && _f !== void 0 ? _f : 0);
|
|
13
|
+
};
|
|
14
|
+
exports.analysisEngagementTotal = analysisEngagementTotal;
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -7,3 +7,15 @@ export const CompanyStatusOptions = Object.values(COMPANY_STATUS).map((status) =
|
|
|
7
7
|
value: status,
|
|
8
8
|
label: status.charAt(0).toUpperCase() + status.slice(1),
|
|
9
9
|
}));
|
|
10
|
+
/** A user's role inside a company; a company has exactly one owner */
|
|
11
|
+
export const COMPANY_MEMBER_ROLE = {
|
|
12
|
+
OWNER: 'owner',
|
|
13
|
+
ADMIN: 'admin',
|
|
14
|
+
MEMBER: 'member',
|
|
15
|
+
};
|
|
16
|
+
/** What the account represents; all three behave the same */
|
|
17
|
+
export const COMPANY_TYPE = {
|
|
18
|
+
COMPANY: 'company',
|
|
19
|
+
TEAM: 'team',
|
|
20
|
+
OTHER: 'other',
|
|
21
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const EVENT_CREATION_PRICE_SETTING = "event_creation_price";
|
|
2
|
+
export const EventOwnerTypes = {
|
|
3
|
+
COMPANY: { value: "company", name: { en: "Company", ar: "شركة" } },
|
|
4
|
+
USER: { value: "user", name: { en: "Personal", ar: "شخصي" } },
|
|
5
|
+
};
|
|
6
|
+
export const EventOwnerTypeValues = ["company", "user"];
|
|
7
|
+
export const EventOwnerTypeOptions = Object.values(EventOwnerTypes).map((t) => ({
|
|
8
|
+
value: t.value,
|
|
9
|
+
name: t.name,
|
|
10
|
+
}));
|
|
11
|
+
export const EventPublishPaymentMethodValues = [
|
|
12
|
+
"balance",
|
|
13
|
+
"loyalty",
|
|
14
|
+
"combined",
|
|
15
|
+
];
|
|
@@ -33,6 +33,8 @@ export const APP_ROUTES = {
|
|
|
33
33
|
pathname: "/ad/promotions/history/[ad_id]",
|
|
34
34
|
params: { ad_id: params.id },
|
|
35
35
|
}),
|
|
36
|
+
/** The owner's views report for an ad */
|
|
37
|
+
viewsReport: (id) => ({ pathname: "/ad/views-report/[id]", params: { id } }),
|
|
36
38
|
promotionDetails: (params) => ({
|
|
37
39
|
pathname: "/ad/promotions/details/[id]",
|
|
38
40
|
params: {
|
|
@@ -163,6 +165,8 @@ export const APP_ROUTES = {
|
|
|
163
165
|
new: () => ({ pathname: "/company/new" }),
|
|
164
166
|
edit: (id) => ({ pathname: "/company/new", params: { id } }),
|
|
165
167
|
details: (id) => ({ pathname: "/company/details/[id]", params: { id } }),
|
|
168
|
+
/** Public profile with the company's ads */
|
|
169
|
+
profile: (id) => ({ pathname: "/company/profile/[id]", params: { id } }),
|
|
166
170
|
},
|
|
167
171
|
venue: {
|
|
168
172
|
new: (companyId) => ({ pathname: "/venue/new", params: { company_id: companyId } }),
|
|
@@ -170,7 +174,10 @@ export const APP_ROUTES = {
|
|
|
170
174
|
details: (id) => ({ pathname: "/venue/details/[id]", params: { id } }),
|
|
171
175
|
},
|
|
172
176
|
event: {
|
|
173
|
-
new: (venueId) =>
|
|
177
|
+
new: (venueId) => venueId ? { pathname: "/event/new", params: { venue_id: venueId } } : { pathname: "/event/new", params: { personal: "1" } },
|
|
178
|
+
start: () => ({ pathname: "/event/start" }),
|
|
179
|
+
mine: () => ({ pathname: "/event/mine" }),
|
|
180
|
+
publish: (id) => ({ pathname: "/event/publish/[id]", params: { id } }),
|
|
174
181
|
edit: (id) => ({ pathname: "/event/new", params: { id } }),
|
|
175
182
|
details: (id) => ({ pathname: "/event/details/[id]", params: { id } }),
|
|
176
183
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/esm/dto/index.js
CHANGED
|
@@ -6,3 +6,4 @@ export * as GEMINI_API_KEYS from './ai/gemini-api-key.dto.js';
|
|
|
6
6
|
export * as PAYMENTS from './payments/index.js';
|
|
7
7
|
export * as ADDRESSES from './addresses/addresses.dto.js';
|
|
8
8
|
export * as POTENTIAL_USERS from './potential-users/potential-user-import.dto.js';
|
|
9
|
+
export * as ANALYSIS from './analysis/Analysis.dto.js';
|
|
@@ -5,3 +5,8 @@ export const AD_DAILY_VIEWS_MAX_DAYS = 180;
|
|
|
5
5
|
export const adDailyViewsSchema = z.object({
|
|
6
6
|
days: z.coerce.number().int().min(1).max(AD_DAILY_VIEWS_MAX_DAYS).default(30),
|
|
7
7
|
});
|
|
8
|
+
/** Body of `POST api/v1/ads/views-report/:id`: one page of the owner's daily view records */
|
|
9
|
+
export const adViewsReportSchema = z.object({
|
|
10
|
+
page: z.coerce.number().int().min(1).default(1),
|
|
11
|
+
limit: z.coerce.number().int().min(1).max(100).default(15),
|
|
12
|
+
});
|
|
@@ -191,6 +191,7 @@ const baseAdCommon = z.object({
|
|
|
191
191
|
.optional()
|
|
192
192
|
.nullable(),
|
|
193
193
|
selected_phone: z.string().trim().optional().nullable(),
|
|
194
|
+
company_id: z.coerce.number().int().positive().optional().nullable(),
|
|
194
195
|
expires_at: z.iso.datetime().optional().nullable(),
|
|
195
196
|
adLocations: z.array(adLocationSchema).optional().nullable(),
|
|
196
197
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** `metrics_version` of snapshots holding daily views (older snapshots held all-time totals) */
|
|
3
|
+
export const ANALYSIS_METRICS_VERSION = 2;
|
|
4
|
+
/** Longest period one analysis report covers */
|
|
5
|
+
export const ANALYSIS_REPORT_MAX_DAYS = 366;
|
|
6
|
+
/** Longest period rebuilt in one request; daily view records older than 180 days are deleted anyway */
|
|
7
|
+
export const ANALYSIS_REBUILD_MAX_DAYS = 180;
|
|
8
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
9
|
+
const day = z
|
|
10
|
+
.string()
|
|
11
|
+
.trim()
|
|
12
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Use YYYY-MM-DD')
|
|
13
|
+
.refine((value) => !Number.isNaN(Date.parse(`${value}T00:00:00Z`)), 'Invalid date');
|
|
14
|
+
/** Days in `from`..`to`, both included */
|
|
15
|
+
const spanDays = ({ from, to }) => Math.round((Date.parse(`${to}T00:00:00Z`) - Date.parse(`${from}T00:00:00Z`)) / DAY_MS) + 1;
|
|
16
|
+
const period = (maxDays) => z
|
|
17
|
+
.object({ from: day, to: day })
|
|
18
|
+
.refine((value) => value.from <= value.to, { message: '`from` must not be after `to`', path: ['to'] })
|
|
19
|
+
.refine((value) => spanDays(value) <= maxDays, {
|
|
20
|
+
message: `The period can be at most ${maxDays} days`,
|
|
21
|
+
path: ['from'],
|
|
22
|
+
});
|
|
23
|
+
/** Body of `POST admin/analysis/snapshots/report`: one day when `from` equals `to` */
|
|
24
|
+
export const analysisReportSchema = period(ANALYSIS_REPORT_MAX_DAYS);
|
|
25
|
+
/** Body of `POST admin/analysis/snapshots/rebuild`: recalculates the snapshots of these days */
|
|
26
|
+
export const analysisRebuildSchema = period(ANALYSIS_REBUILD_MAX_DAYS);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './analysis-report.schema.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { saveEventTimelineSchema } from "./EventTimeline.schema.js";
|
|
3
3
|
import { saveEventWeddingSchema } from "./EventWedding.schema.js";
|
|
4
|
-
import { EventInvitationScanTypeValues } from "../../constants/events/index.js";
|
|
4
|
+
import { EventInvitationScanTypeValues, EventPublishPaymentMethodValues, } from "../../constants/events/index.js";
|
|
5
5
|
export const eventBaseSchema = z.object({
|
|
6
6
|
lat: z.coerce.number().optional().nullable(),
|
|
7
7
|
long: z.coerce.number().optional().nullable(),
|
|
@@ -14,6 +14,8 @@ export const eventBaseSchema = z.object({
|
|
|
14
14
|
event_type: z.string().trim().max(255).nullable().optional(),
|
|
15
15
|
event_template: z.string().trim().max(255).nullable().optional(),
|
|
16
16
|
venue_id: z.coerce.number().int().positive().nullable().optional(),
|
|
17
|
+
venue_name: z.string().trim().max(255).nullable().optional(),
|
|
18
|
+
location_label: z.string().trim().nullable().optional(),
|
|
17
19
|
invitation_scan_type: z.enum(EventInvitationScanTypeValues).optional(),
|
|
18
20
|
});
|
|
19
21
|
export const createEventSchema = eventBaseSchema;
|
|
@@ -23,6 +25,14 @@ export const updateEventSchema = eventBaseSchema.extend({
|
|
|
23
25
|
export const saveEventSchema = eventBaseSchema.extend({
|
|
24
26
|
id: z.coerce.number().int().positive().optional(),
|
|
25
27
|
});
|
|
28
|
+
export const publishEventSchema = z.object({
|
|
29
|
+
id: z.coerce.number().int().positive(),
|
|
30
|
+
method: z.enum(EventPublishPaymentMethodValues),
|
|
31
|
+
points_used: z.coerce.number().int().nonnegative().optional(),
|
|
32
|
+
});
|
|
33
|
+
export const eventIdSchema = z.object({
|
|
34
|
+
id: z.coerce.number().int().positive(),
|
|
35
|
+
});
|
|
26
36
|
export const getEventsFilterSchema = z.object({
|
|
27
37
|
is_published: z.boolean().optional(),
|
|
28
38
|
search: z.string().trim().optional(),
|
package/dist/esm/schema/index.js
CHANGED
|
@@ -6,3 +6,4 @@ export * as PAYMENTS from './payments/index.js';
|
|
|
6
6
|
export * as COMMUNICATION from './communication/index.js';
|
|
7
7
|
export * as ADDRESSES from './addresses/addresses.schema.js';
|
|
8
8
|
export * as POTENTIAL_USERS from './potential-users/index.js';
|
|
9
|
+
export * as ANALYSIS from './analysis/index.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Engagement of a day: WhatsApp, call and chat clicks, shares, chat messages and new chat rooms */
|
|
2
|
+
export const analysisEngagementTotal = ({ ad_interactions: a, app_metrics: m }) => {
|
|
3
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4
|
+
return ((_a = a === null || a === void 0 ? void 0 : a.whatsapp_clicks) !== null && _a !== void 0 ? _a : 0) +
|
|
5
|
+
((_b = a === null || a === void 0 ? void 0 : a.call_clicks) !== null && _b !== void 0 ? _b : 0) +
|
|
6
|
+
((_c = a === null || a === void 0 ? void 0 : a.chat_clicks) !== null && _c !== void 0 ? _c : 0) +
|
|
7
|
+
((_d = a === null || a === void 0 ? void 0 : a.shares) !== null && _d !== void 0 ? _d : 0) +
|
|
8
|
+
((_e = m === null || m === void 0 ? void 0 : m.chat_messages_count) !== null && _e !== void 0 ? _e : 0) +
|
|
9
|
+
((_f = m === null || m === void 0 ? void 0 : m.chat_rooms_count) !== null && _f !== void 0 ? _f : 0);
|
|
10
|
+
};
|
package/dist/esm/utils/index.js
CHANGED