@deallony/shared 1.2.80 → 1.2.82
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/events/EventBirthday.d.ts +2 -0
- package/dist/cjs/constants/events/EventBirthday.js +12 -0
- package/dist/cjs/constants/events/EventCustomization.d.ts +21 -0
- package/dist/cjs/constants/events/EventCustomization.js +23 -2
- package/dist/cjs/constants/events/EventDressCode.d.ts +65 -0
- package/dist/cjs/constants/events/EventDressCode.js +56 -0
- package/dist/cjs/constants/events/EventGuests.d.ts +3 -0
- package/dist/cjs/constants/events/EventGuests.js +6 -0
- package/dist/cjs/constants/events/EventHost.d.ts +79 -0
- package/dist/cjs/constants/events/EventHost.js +155 -0
- package/dist/cjs/constants/events/EventOccasion.d.ts +63 -0
- package/dist/cjs/constants/events/EventOccasion.js +242 -0
- package/dist/cjs/constants/events/EventPreview.d.ts +3 -0
- package/dist/cjs/constants/events/EventPreview.js +9 -1
- package/dist/cjs/constants/events/EventTemplate.d.ts +518 -10
- package/dist/cjs/constants/events/EventTemplate.js +81 -11
- package/dist/cjs/constants/events/EventTextPolicy.d.ts +7 -0
- package/dist/cjs/constants/events/EventTextPolicy.js +66 -0
- package/dist/cjs/constants/events/EventType.d.ts +273 -8
- package/dist/cjs/constants/events/EventType.js +38 -2
- package/dist/cjs/constants/events/EventVisibility.d.ts +19 -0
- package/dist/cjs/constants/events/EventVisibility.js +18 -0
- package/dist/cjs/constants/events/EventWedding.js +3 -0
- package/dist/cjs/constants/events/EventWeddingReligion.d.ts +72 -0
- package/dist/cjs/constants/events/EventWeddingReligion.js +126 -0
- package/dist/cjs/constants/events/index.d.ts +8 -0
- package/dist/cjs/constants/events/index.js +8 -0
- package/dist/cjs/constants/routes/app.d.ts +49 -0
- package/dist/cjs/constants/routes/app.js +16 -0
- package/dist/cjs/dto/events/EventBirthday.dto.d.ts +3 -0
- package/dist/cjs/dto/events/EventBirthday.dto.js +2 -0
- package/dist/cjs/dto/events/EventHost.dto.d.ts +7 -0
- package/dist/cjs/dto/events/EventHost.dto.js +2 -0
- package/dist/cjs/dto/events/EventOccasion.dto.d.ts +3 -0
- package/dist/cjs/dto/events/EventOccasion.dto.js +2 -0
- package/dist/cjs/dto/events/index.d.ts +3 -0
- package/dist/cjs/dto/events/index.js +3 -0
- package/dist/cjs/schema/communication/ai-conversation.schema.d.ts +55 -3
- package/dist/cjs/schema/communication/ai-conversation.schema.js +28 -3
- package/dist/cjs/schema/communication/offer.schema.d.ts +3 -3
- package/dist/cjs/schema/communication/support-ticket.schema.d.ts +136 -0
- package/dist/cjs/schema/communication/support-ticket.schema.js +47 -2
- package/dist/cjs/schema/events/Event.schema.d.ts +326 -0
- package/dist/cjs/schema/events/Event.schema.js +55 -1
- package/dist/cjs/schema/events/EventBirthday.schema.d.ts +19 -0
- package/dist/cjs/schema/events/EventBirthday.schema.js +17 -0
- package/dist/cjs/schema/events/EventHost.schema.d.ts +36 -0
- package/dist/cjs/schema/events/EventHost.schema.js +44 -0
- package/dist/cjs/schema/events/EventOccasion.schema.d.ts +22 -0
- package/dist/cjs/schema/events/EventOccasion.schema.js +31 -0
- package/dist/cjs/schema/events/EventRsvp.schema.d.ts +4 -0
- package/dist/cjs/schema/events/EventRsvp.schema.js +1 -0
- package/dist/cjs/schema/events/EventTimeline.schema.d.ts +5 -0
- package/dist/cjs/schema/events/EventTimeline.schema.js +14 -1
- package/dist/cjs/schema/events/EventWedding.schema.d.ts +32 -0
- package/dist/cjs/schema/events/EventWedding.schema.js +11 -0
- package/dist/cjs/schema/events/index.d.ts +3 -0
- package/dist/cjs/schema/events/index.js +3 -0
- package/dist/cjs/types/communication/Notification.d.ts +21 -2
- package/dist/cjs/types/communication/Notification.js +17 -0
- package/dist/cjs/types/events/Event.d.ts +38 -1
- package/dist/cjs/types/events/EventBirthday.d.ts +17 -0
- package/dist/cjs/types/events/EventBirthday.js +2 -0
- package/dist/cjs/types/events/EventCustomization.d.ts +4 -0
- package/dist/cjs/types/events/EventDressCode.d.ts +13 -0
- package/dist/cjs/types/events/EventDressCode.js +2 -0
- package/dist/cjs/types/events/EventHost.d.ts +29 -0
- package/dist/cjs/types/events/EventHost.js +2 -0
- package/dist/cjs/types/events/EventOccasion.d.ts +24 -0
- package/dist/cjs/types/events/EventOccasion.js +2 -0
- package/dist/cjs/types/events/EventRsvp.d.ts +2 -0
- package/dist/cjs/types/events/EventTimeline.d.ts +2 -0
- package/dist/cjs/types/events/EventWedding.d.ts +7 -0
- package/dist/cjs/types/events/index.d.ts +4 -0
- package/dist/cjs/types/events/index.js +4 -0
- package/dist/cjs/types/index.d.ts +4 -0
- package/dist/cjs/types/index.js +6 -2
- package/dist/cjs/types/user/SavedSearch.d.ts +38 -0
- package/dist/cjs/types/user/SavedSearch.js +11 -0
- package/dist/esm/constants/events/EventBirthday.js +9 -0
- package/dist/esm/constants/events/EventCustomization.js +21 -1
- package/dist/esm/constants/events/EventDressCode.js +49 -0
- package/dist/esm/constants/events/EventGuests.js +3 -0
- package/dist/esm/constants/events/EventHost.js +147 -0
- package/dist/esm/constants/events/EventOccasion.js +235 -0
- package/dist/esm/constants/events/EventPreview.js +7 -0
- package/dist/esm/constants/events/EventTemplate.js +78 -10
- package/dist/esm/constants/events/EventTextPolicy.js +61 -0
- package/dist/esm/constants/events/EventType.js +34 -1
- package/dist/esm/constants/events/EventVisibility.js +15 -0
- package/dist/esm/constants/events/EventWedding.js +3 -0
- package/dist/esm/constants/events/EventWeddingReligion.js +118 -0
- package/dist/esm/constants/events/index.js +8 -0
- package/dist/esm/constants/routes/app.js +16 -0
- package/dist/esm/dto/events/EventBirthday.dto.js +1 -0
- package/dist/esm/dto/events/EventHost.dto.js +1 -0
- package/dist/esm/dto/events/EventOccasion.dto.js +1 -0
- package/dist/esm/dto/events/index.js +3 -0
- package/dist/esm/schema/communication/ai-conversation.schema.js +27 -2
- package/dist/esm/schema/communication/support-ticket.schema.js +46 -1
- package/dist/esm/schema/events/Event.schema.js +55 -1
- package/dist/esm/schema/events/EventBirthday.schema.js +14 -0
- package/dist/esm/schema/events/EventHost.schema.js +41 -0
- package/dist/esm/schema/events/EventOccasion.schema.js +28 -0
- package/dist/esm/schema/events/EventRsvp.schema.js +1 -0
- package/dist/esm/schema/events/EventTimeline.schema.js +14 -1
- package/dist/esm/schema/events/EventWedding.schema.js +11 -0
- package/dist/esm/schema/events/index.js +3 -0
- package/dist/esm/types/communication/Notification.js +17 -0
- package/dist/esm/types/events/EventBirthday.js +1 -0
- package/dist/esm/types/events/EventDressCode.js +1 -0
- package/dist/esm/types/events/EventHost.js +1 -0
- package/dist/esm/types/events/EventOccasion.js +1 -0
- package/dist/esm/types/events/index.js +4 -0
- package/dist/esm/types/index.js +4 -0
- package/dist/esm/types/user/SavedSearch.js +8 -0
- package/package.json +1 -1
|
@@ -7,6 +7,12 @@ export const APP_ROUTES = {
|
|
|
7
7
|
list: () => ({ pathname: "/notifications" }),
|
|
8
8
|
settings: () => ({ pathname: "/notifications/settings" }),
|
|
9
9
|
},
|
|
10
|
+
savedSearches: {
|
|
11
|
+
/** The user's saved ad searches ("بحثي المحفوظ") */
|
|
12
|
+
list: () => ({ pathname: "/saved-searches" }),
|
|
13
|
+
/** Opens a saved search's results with its new ads marked, and marks them seen */
|
|
14
|
+
open: (id) => ({ pathname: "/saved-searches/[id]", params: { id: String(id) } }),
|
|
15
|
+
},
|
|
10
16
|
favorites: {
|
|
11
17
|
compare: (ad_ids) => ({
|
|
12
18
|
pathname: "/favorites/compare",
|
|
@@ -181,6 +187,10 @@ export const APP_ROUTES = {
|
|
|
181
187
|
details: (id) => ({ pathname: "/company/details/[id]", params: { id } }),
|
|
182
188
|
/** Public profile with the company's ads */
|
|
183
189
|
profile: (id) => ({ pathname: "/company/profile/[id]", params: { id } }),
|
|
190
|
+
/** Every ad published under the company, for its members */
|
|
191
|
+
ads: (id) => ({ pathname: "/company/ads/[id]", params: { id } }),
|
|
192
|
+
/** This week's most active companies (opened from the home strip) */
|
|
193
|
+
ranking: () => ({ pathname: "/company/ranking" }),
|
|
184
194
|
},
|
|
185
195
|
venue: {
|
|
186
196
|
new: (companyId) => ({ pathname: "/venue/new", params: { company_id: companyId } }),
|
|
@@ -189,10 +199,16 @@ export const APP_ROUTES = {
|
|
|
189
199
|
},
|
|
190
200
|
event: {
|
|
191
201
|
new: (venueId) => venueId ? { pathname: "/event/new", params: { venue_id: venueId } } : { pathname: "/event/new", params: { personal: "1" } },
|
|
202
|
+
/** A new personal event of one type (wedding, birthday), chosen on the start page */
|
|
203
|
+
newOfType: (eventType) => ({ pathname: "/event/new", params: { personal: "1", event_type: eventType } }),
|
|
192
204
|
start: () => ({ pathname: "/event/start" }),
|
|
193
205
|
mine: () => ({ pathname: "/event/mine" }),
|
|
206
|
+
/** Upcoming public events (optionally of one venue) */
|
|
207
|
+
upcoming: (venueId) => venueId ? { pathname: "/event/upcoming", params: { venue_id: venueId } } : { pathname: "/event/upcoming" },
|
|
194
208
|
publish: (id) => ({ pathname: "/event/publish/[id]", params: { id } }),
|
|
195
209
|
edit: (id) => ({ pathname: "/event/new", params: { id } }),
|
|
196
210
|
details: (id) => ({ pathname: "/event/details/[id]", params: { id } }),
|
|
211
|
+
/** People of the event (owner, organisers, guest managers) */
|
|
212
|
+
hosts: (id) => ({ pathname: "/event/hosts/[id]", params: { id } }),
|
|
197
213
|
},
|
|
198
214
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,4 +2,7 @@ export * from './Event.dto.js';
|
|
|
2
2
|
export * from './EventRsvp.dto.js';
|
|
3
3
|
export * from './EventTimeline.dto.js';
|
|
4
4
|
export * from './EventWedding.dto.js';
|
|
5
|
+
export * from './EventBirthday.dto.js';
|
|
6
|
+
export * from './EventOccasion.dto.js';
|
|
5
7
|
export * from './EventVenue.dto.js';
|
|
8
|
+
export * from './EventHost.dto.js';
|
|
@@ -40,6 +40,8 @@ export const AiConversationStatusSchema = z.enum([
|
|
|
40
40
|
'starting',
|
|
41
41
|
/** The opening is written and waits for an admin to approve it */
|
|
42
42
|
'awaiting_approval',
|
|
43
|
+
/** Waits for the sending hours to open: the opening, an approved draft or the AI's reply goes out then */
|
|
44
|
+
'scheduled',
|
|
43
45
|
'waiting_for_reply',
|
|
44
46
|
'chatting',
|
|
45
47
|
'interested',
|
|
@@ -55,6 +57,7 @@ export const AiConversationPurposeSchema = z.enum(['marketing', 'support']);
|
|
|
55
57
|
export const AI_CONVERSATION_ACTIVE_STATUSES = [
|
|
56
58
|
'starting',
|
|
57
59
|
'awaiting_approval',
|
|
60
|
+
'scheduled',
|
|
58
61
|
'waiting_for_reply',
|
|
59
62
|
'chatting',
|
|
60
63
|
'interested',
|
|
@@ -74,10 +77,11 @@ export const AiApprovalSettingsSchema = z.object({
|
|
|
74
77
|
enabled: z.boolean(),
|
|
75
78
|
});
|
|
76
79
|
/**
|
|
77
|
-
* pending: waiting for an admin.
|
|
80
|
+
* pending: waiting for an admin. scheduled: ready, goes out when the sending hours open (send_after).
|
|
81
|
+
* sent: approved and sent. rejected: thrown away by an admin.
|
|
78
82
|
* outdated: the customer wrote again, so a newer draft replaced it. failed: approved but WhatsApp refused it.
|
|
79
83
|
*/
|
|
80
|
-
export const AiDraftStatusSchema = z.enum(['pending', 'sent', 'rejected', 'outdated', 'failed']);
|
|
84
|
+
export const AiDraftStatusSchema = z.enum(['pending', 'scheduled', 'sent', 'rejected', 'outdated', 'failed']);
|
|
81
85
|
/** opening: first messages of a new chat. reply: answer to the customer. opt_out: goodbye after a stop request */
|
|
82
86
|
export const AiDraftKindSchema = z.enum(['opening', 'reply', 'opt_out']);
|
|
83
87
|
export const AiDraftListSchema = z.object({
|
|
@@ -92,7 +96,28 @@ export const AiDraftDecisionSchema = z.object({
|
|
|
92
96
|
/** Edited messages to send instead of the AI's; only with approve */
|
|
93
97
|
replies: z.array(z.string().trim().min(1).max(4000)).min(1).max(4).optional(),
|
|
94
98
|
});
|
|
99
|
+
/** Sends a scheduled draft right away, ignoring the sending hours */
|
|
100
|
+
export const AiDraftSendNowSchema = z.object({
|
|
101
|
+
draft_id: z.coerce.number().int().positive(),
|
|
102
|
+
});
|
|
95
103
|
export const AiDraftApproveAllSchema = z.object({
|
|
96
104
|
/** Approve only these drafts; all pending drafts when left out */
|
|
97
105
|
draft_ids: z.array(z.coerce.number().int().positive()).max(100).optional(),
|
|
98
106
|
});
|
|
107
|
+
/* ---------- Sending hours: AI marketing messages go out only between start and end ---------- */
|
|
108
|
+
const ClockTimeSchema = z
|
|
109
|
+
.string()
|
|
110
|
+
.trim()
|
|
111
|
+
.regex(/^([01]\d|2[0-3]):[0-5]\d$/, 'Use HH:MM, 24-hour clock');
|
|
112
|
+
/**
|
|
113
|
+
* One setting for all AI marketing conversations. Times are on each customer's own clock,
|
|
114
|
+
* picked from the phone code (+963 Syria, +971 UAE); other numbers use default_timezone.
|
|
115
|
+
* end before start means the hours cross midnight (for example 20:00 to 02:00).
|
|
116
|
+
*/
|
|
117
|
+
export const AiSendWindowSettingsSchema = z.object({
|
|
118
|
+
enabled: z.boolean(),
|
|
119
|
+
start: ClockTimeSchema,
|
|
120
|
+
end: ClockTimeSchema,
|
|
121
|
+
/** IANA time zone, for example Asia/Damascus */
|
|
122
|
+
default_timezone: z.string().trim().min(1).max(60),
|
|
123
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export const SupportTicketStatusSchema = z.enum(['open', 'assigned', 'in_progress', 'waiting_customer', 'resolved', 'closed', 'reopened']);
|
|
3
3
|
export const SupportTicketPrioritySchema = z.enum(['low', 'normal', 'high', 'urgent']);
|
|
4
|
-
export const SupportTicketCategorySchema = z.enum(['technical_issue', 'account', 'advertisement', 'payment', 'complaint', 'other']);
|
|
4
|
+
export const SupportTicketCategorySchema = z.enum(['technical_issue', 'account', 'advertisement', 'payment', 'complaint', 'kyc', 'event', 'login', 'other']);
|
|
5
|
+
export const SupportTicketSourceSchema = z.enum(['admin', 'ai', 'app', 'guest', 'report']);
|
|
5
6
|
export const SupportTicketCreateSchema = z.object({
|
|
6
7
|
title: z.string().trim().min(4).max(180),
|
|
7
8
|
description: z.string().trim().min(5).max(5000),
|
|
@@ -26,7 +27,51 @@ export const SupportTicketListSchema = z.object({
|
|
|
26
27
|
status: SupportTicketStatusSchema.optional(),
|
|
27
28
|
priority: SupportTicketPrioritySchema.optional(),
|
|
28
29
|
search: z.string().trim().max(100).optional(),
|
|
30
|
+
source: SupportTicketSourceSchema.optional(),
|
|
31
|
+
screen: z.string().trim().max(40).optional(),
|
|
29
32
|
});
|
|
30
33
|
export const SupportTicketStatusUpdateSchema = SupportTicketIdSchema.extend({ status: SupportTicketStatusSchema });
|
|
31
34
|
export const SupportTicketAssignmentSchema = SupportTicketIdSchema.extend({ assigned_to: z.number().int().positive() });
|
|
32
35
|
export const SupportTicketReplySchema = SupportTicketIdSchema.extend({ message: z.string().trim().min(1).max(4000) });
|
|
36
|
+
// In-app "report a problem" button (create event, create ad, KYC, login)
|
|
37
|
+
export const SupportReportScreenSchema = z.enum(['event.new', 'ad.new', 'kyc', 'auth.login']);
|
|
38
|
+
export const SupportReportReasonSchema = z.enum(['blocked', 'error_message', 'slow', 'other']);
|
|
39
|
+
export const SupportReportAttachmentSchema = z.object({
|
|
40
|
+
url: z.string().trim().url().max(500),
|
|
41
|
+
id: z.number().int().positive().nullable().optional(),
|
|
42
|
+
mimetype: z.string().max(80).nullable().optional(),
|
|
43
|
+
width: z.number().nonnegative().nullable().optional(),
|
|
44
|
+
height: z.number().nonnegative().nullable().optional(),
|
|
45
|
+
});
|
|
46
|
+
export const SupportReportRequestLogSchema = z.object({
|
|
47
|
+
at: z.string(),
|
|
48
|
+
method: z.string().max(10),
|
|
49
|
+
path: z.string().max(300),
|
|
50
|
+
status: z.number().int().nullable(),
|
|
51
|
+
ms: z.number().nullable().optional(),
|
|
52
|
+
message: z.string().max(300).nullable().optional(),
|
|
53
|
+
});
|
|
54
|
+
export const SupportReportErrorLogSchema = z.object({
|
|
55
|
+
at: z.string(),
|
|
56
|
+
source: z.string().max(40),
|
|
57
|
+
message: z.string().max(500),
|
|
58
|
+
});
|
|
59
|
+
export const SupportReportContextSchema = z.object({
|
|
60
|
+
screen: z.object({ route: z.string().max(200), step: z.union([z.string(), z.number()]).nullable().optional(), ids: z.record(z.string(), z.union([z.string(), z.number(), z.null()])).optional(), error_fields: z.array(z.string()).optional() }).optional(),
|
|
61
|
+
device: z.record(z.string(), z.any()).optional(),
|
|
62
|
+
app: z.record(z.string(), z.any()).optional(),
|
|
63
|
+
requests: z.array(SupportReportRequestLogSchema).max(50).optional(),
|
|
64
|
+
errors: z.array(SupportReportErrorLogSchema).max(50).optional(),
|
|
65
|
+
}).passthrough();
|
|
66
|
+
export const SupportReportCreateSchema = z.object({
|
|
67
|
+
description: z.string().trim().min(5).max(5000),
|
|
68
|
+
screen: SupportReportScreenSchema,
|
|
69
|
+
reason: SupportReportReasonSchema.default('other'),
|
|
70
|
+
phone: z.string().trim().min(8).max(30).nullable().optional(),
|
|
71
|
+
device_id: z.string().trim().max(80).nullable().optional(),
|
|
72
|
+
platform: z.string().trim().max(20).nullable().optional(),
|
|
73
|
+
app_version: z.string().trim().max(60).nullable().optional(),
|
|
74
|
+
ad_id: z.number().int().positive().nullable().optional(),
|
|
75
|
+
context: SupportReportContextSchema.nullable().optional(),
|
|
76
|
+
attachments: z.array(SupportReportAttachmentSchema).max(3).optional(),
|
|
77
|
+
});
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { saveEventTimelineSchema } from "./EventTimeline.schema.js";
|
|
3
3
|
import { saveEventWeddingSchema } from "./EventWedding.schema.js";
|
|
4
|
-
import {
|
|
4
|
+
import { saveEventBirthdaySchema } from "./EventBirthday.schema.js";
|
|
5
|
+
import { saveEventOccasionSchema } from "./EventOccasion.schema.js";
|
|
6
|
+
import { eventPersonInputSchema } from "./EventHost.schema.js";
|
|
7
|
+
import { EVENT_CUSTOMIZATION_TEXT_MAX, EVENT_DRESS_CODE_NOTE_MAX, EVENT_EXPECTED_GUESTS_MAX, EVENT_EXPECTED_GUESTS_MIN, EventDressCodeColorModeValues, EventDressCodeColorValues, EventDressCodeStyleValues, EventCustomizationFontValues, EventCustomizationOpeningValues, EventCustomizationPaletteValues, EventCustomizationSectionValues, EventCustomizationTrackValues, EventInvitationScanTypeValues, EventPublishPaymentMethodValues, EventVisibilityValues, } from "../../constants/events/index.js";
|
|
8
|
+
import { BLOCKED_RELIGIOUS_TEXT_MESSAGE, hasBlockedReligiousText } from "../../constants/events/EventTextPolicy.js";
|
|
5
9
|
const customizationText = z
|
|
6
10
|
.string()
|
|
7
11
|
.trim()
|
|
8
12
|
.max(EVENT_CUSTOMIZATION_TEXT_MAX)
|
|
13
|
+
.refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar })
|
|
9
14
|
.transform((v) => (v.length ? v : null))
|
|
10
15
|
.nullable()
|
|
11
16
|
.optional();
|
|
@@ -19,6 +24,32 @@ export const eventCustomizationSchema = z.object({
|
|
|
19
24
|
welcome_message: customizationText,
|
|
20
25
|
rsvp_message: customizationText,
|
|
21
26
|
music: z.enum(EventCustomizationTrackValues).nullable().optional(),
|
|
27
|
+
opening: z.enum(EventCustomizationOpeningValues).nullable().optional(),
|
|
28
|
+
auto_scroll: z.boolean().nullable().optional(),
|
|
29
|
+
});
|
|
30
|
+
export const eventDressCodeSchema = z.object({
|
|
31
|
+
style: z.enum(EventDressCodeStyleValues).nullable().optional(),
|
|
32
|
+
/** Colours guests are asked to wear (any number) */
|
|
33
|
+
colors: z
|
|
34
|
+
.array(z.enum(EventDressCodeColorValues))
|
|
35
|
+
.transform((v) => Array.from(new Set(v)))
|
|
36
|
+
.nullable()
|
|
37
|
+
.optional(),
|
|
38
|
+
/** Colours guests should not wear (any number) */
|
|
39
|
+
avoid_colors: z
|
|
40
|
+
.array(z.enum(EventDressCodeColorValues))
|
|
41
|
+
.transform((v) => Array.from(new Set(v)))
|
|
42
|
+
.nullable()
|
|
43
|
+
.optional(),
|
|
44
|
+
color_mode: z.enum(EventDressCodeColorModeValues).nullable().optional(),
|
|
45
|
+
note: z
|
|
46
|
+
.string()
|
|
47
|
+
.trim()
|
|
48
|
+
.max(EVENT_DRESS_CODE_NOTE_MAX)
|
|
49
|
+
.refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar })
|
|
50
|
+
.transform((v) => (v.length ? v : null))
|
|
51
|
+
.nullable()
|
|
52
|
+
.optional(),
|
|
22
53
|
});
|
|
23
54
|
export const eventBaseSchema = z.object({
|
|
24
55
|
lat: z.coerce.number().optional().nullable(),
|
|
@@ -28,14 +59,26 @@ export const eventBaseSchema = z.object({
|
|
|
28
59
|
is_published: z.boolean().optional(),
|
|
29
60
|
slug: z.string().trim().min(1).max(255),
|
|
30
61
|
wedding: saveEventWeddingSchema,
|
|
62
|
+
/** @deprecated birthdays are saved in `occasion` since 2026-11 */
|
|
63
|
+
birthday: saveEventBirthdaySchema.nullable().optional(),
|
|
64
|
+
/** Details of occasion types (birthday, graduation, newborn, ...) */
|
|
65
|
+
occasion: saveEventOccasionSchema.nullable().optional(),
|
|
31
66
|
timeline: saveEventTimelineSchema,
|
|
32
67
|
event_type: z.string().trim().max(255).nullable().optional(),
|
|
33
68
|
event_template: z.string().trim().max(255).nullable().optional(),
|
|
34
69
|
venue_id: z.coerce.number().int().positive().nullable().optional(),
|
|
35
70
|
venue_name: z.string().trim().max(255).nullable().optional(),
|
|
36
71
|
location_label: z.string().trim().nullable().optional(),
|
|
72
|
+
/** Expected number of guests; the app asks for it on every new event (old events may have none) */
|
|
73
|
+
expected_guests: z.coerce.number().int().min(EVENT_EXPECTED_GUESTS_MIN).max(EVENT_EXPECTED_GUESTS_MAX).nullable().optional(),
|
|
37
74
|
invitation_scan_type: z.enum(EventInvitationScanTypeValues).optional(),
|
|
38
75
|
customization: eventCustomizationSchema.nullable().optional(),
|
|
76
|
+
dress_code: eventDressCodeSchema.nullable().optional(),
|
|
77
|
+
visibility: z.enum(EventVisibilityValues).optional(),
|
|
78
|
+
/** «من أنت في هذه المناسبة؟»: a slot key of the type, "company" or "other" */
|
|
79
|
+
creator_role: z.string().trim().max(40).nullable().optional(),
|
|
80
|
+
/** Suggested people of the type (CONSTANTS.EVENTS.EventPeopleSlots) without their own field */
|
|
81
|
+
people: z.array(eventPersonInputSchema).max(20).optional(),
|
|
39
82
|
});
|
|
40
83
|
export const createEventSchema = eventBaseSchema;
|
|
41
84
|
export const updateEventSchema = eventBaseSchema.extend({
|
|
@@ -54,7 +97,18 @@ export const eventIdSchema = z.object({
|
|
|
54
97
|
});
|
|
55
98
|
export const getEventsFilterSchema = z.object({
|
|
56
99
|
is_published: z.boolean().optional(),
|
|
100
|
+
visibility: z.enum(EventVisibilityValues).optional(),
|
|
57
101
|
search: z.string().trim().optional(),
|
|
58
102
|
page: z.coerce.number().int().positive().optional(),
|
|
59
103
|
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
60
104
|
});
|
|
105
|
+
export const setEventVisibilitySchema = z.object({
|
|
106
|
+
id: z.coerce.number().int().positive(),
|
|
107
|
+
visibility: z.enum(EventVisibilityValues),
|
|
108
|
+
});
|
|
109
|
+
export const publicEventsFilterSchema = z.object({
|
|
110
|
+
venue_id: z.coerce.number().int().positive().optional(),
|
|
111
|
+
company_id: z.coerce.number().int().positive().optional(),
|
|
112
|
+
page: z.coerce.number().int().positive().optional(),
|
|
113
|
+
limit: z.coerce.number().int().positive().max(50).optional(),
|
|
114
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { internationalPhoneSchema } from "../common/Phone.schema.js";
|
|
3
|
+
export const EVENT_BIRTHDAY_AGE_MAX = 120;
|
|
4
|
+
export const eventBirthdayBaseSchema = z.object({
|
|
5
|
+
event_id: z.coerce.number().int().positive().optional(),
|
|
6
|
+
cover: z.record(z.string(), z.any()).nullable().optional(),
|
|
7
|
+
celebrant_name: z.string().trim().max(255).nullable().optional(),
|
|
8
|
+
age: z.coerce.number().int().min(1).max(EVENT_BIRTHDAY_AGE_MAX).nullable().optional(),
|
|
9
|
+
host_name: z.string().trim().max(255).nullable().optional(),
|
|
10
|
+
phone: internationalPhoneSchema.nullable().optional(),
|
|
11
|
+
});
|
|
12
|
+
export const saveEventBirthdaySchema = eventBirthdayBaseSchema.extend({
|
|
13
|
+
id: z.coerce.number().int().positive().optional(),
|
|
14
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { internationalPhoneSchema } from "../common/Phone.schema.js";
|
|
3
|
+
import { EVENT_HOST_LABEL_MAX, EventHostRoleValues } from "../../constants/events/EventHost.js";
|
|
4
|
+
const hostName = z
|
|
5
|
+
.string()
|
|
6
|
+
.trim()
|
|
7
|
+
.max(EVENT_HOST_LABEL_MAX)
|
|
8
|
+
.transform((v) => (v.length ? v : null))
|
|
9
|
+
.nullable()
|
|
10
|
+
.optional();
|
|
11
|
+
/** One suggested person in the create/edit form; an empty phone removes them */
|
|
12
|
+
export const eventPersonInputSchema = z.object({
|
|
13
|
+
slot: z.string().trim().min(1).max(40),
|
|
14
|
+
phone: internationalPhoneSchema.nullable().optional(),
|
|
15
|
+
name: hostName,
|
|
16
|
+
/** Don't tell them or give access before the event ends */
|
|
17
|
+
surprise: z.boolean().optional(),
|
|
18
|
+
});
|
|
19
|
+
/** Add someone to an event by hand */
|
|
20
|
+
export const addEventHostSchema = z.object({
|
|
21
|
+
event_id: z.coerce.number().int().positive(),
|
|
22
|
+
phone: internationalPhoneSchema,
|
|
23
|
+
role: z.enum(EventHostRoleValues),
|
|
24
|
+
/** e.g. «أم العروس» */
|
|
25
|
+
label: hostName,
|
|
26
|
+
name: hostName,
|
|
27
|
+
surprise: z.boolean().optional(),
|
|
28
|
+
});
|
|
29
|
+
export const updateEventHostSchema = z.object({
|
|
30
|
+
host_id: z.coerce.number().int().positive(),
|
|
31
|
+
role: z.enum(EventHostRoleValues).optional(),
|
|
32
|
+
label: hostName,
|
|
33
|
+
name: hostName,
|
|
34
|
+
surprise: z.boolean().optional(),
|
|
35
|
+
});
|
|
36
|
+
export const eventHostIdSchema = z.object({
|
|
37
|
+
host_id: z.coerce.number().int().positive(),
|
|
38
|
+
});
|
|
39
|
+
export const eventHostsListSchema = z.object({
|
|
40
|
+
event_id: z.coerce.number().int().positive(),
|
|
41
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { internationalPhoneSchema } from "../common/Phone.schema.js";
|
|
3
|
+
import { EVENT_OCCASION_LONG_TEXT_MAX, EVENT_OCCASION_TEXT_MAX } from "../../constants/events/EventOccasion.js";
|
|
4
|
+
import { EVENT_TEMPLATE_MAX_PHOTOS } from "../../constants/events/EventTemplate.js";
|
|
5
|
+
import { BLOCKED_RELIGIOUS_TEXT_MESSAGE, hasBlockedReligiousText } from "../../constants/events/EventTextPolicy.js";
|
|
6
|
+
const allowedText = (max) => z.string().trim().max(max).refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar });
|
|
7
|
+
const detailValue = z.union([
|
|
8
|
+
allowedText(EVENT_OCCASION_LONG_TEXT_MAX),
|
|
9
|
+
z.number(),
|
|
10
|
+
z.boolean(),
|
|
11
|
+
z.null(),
|
|
12
|
+
]);
|
|
13
|
+
export const eventOccasionBaseSchema = z.object({
|
|
14
|
+
event_id: z.coerce.number().int().positive().optional(),
|
|
15
|
+
primary_name: z.string().trim().max(EVENT_OCCASION_TEXT_MAX).nullable().optional(),
|
|
16
|
+
secondary_name: z.string().trim().max(EVENT_OCCASION_TEXT_MAX).nullable().optional(),
|
|
17
|
+
host_name: z.string().trim().max(EVENT_OCCASION_TEXT_MAX).nullable().optional(),
|
|
18
|
+
phone: internationalPhoneSchema.nullable().optional(),
|
|
19
|
+
cover: z.record(z.string(), z.any()).nullable().optional(),
|
|
20
|
+
/** Extra pictures after the cover, for designs with several photos */
|
|
21
|
+
/** By slot: an empty slot is null so the next pictures keep their place */
|
|
22
|
+
photos: z.array(z.record(z.string(), z.any()).nullable()).max(EVENT_TEMPLATE_MAX_PHOTOS - 1).nullable().optional(),
|
|
23
|
+
/** Keys come from the type's config; the API keeps only known keys */
|
|
24
|
+
details: z.record(z.string().max(64), detailValue).nullable().optional(),
|
|
25
|
+
});
|
|
26
|
+
export const saveEventOccasionSchema = eventOccasionBaseSchema.extend({
|
|
27
|
+
id: z.coerce.number().int().positive().optional(),
|
|
28
|
+
});
|
|
@@ -12,6 +12,7 @@ export const eventRsvpBaseSchema = z.object({
|
|
|
12
12
|
attendance_status: z.enum(attendanceStatusValues),
|
|
13
13
|
guest_count: z.coerce.number().int().positive().max(100).default(1),
|
|
14
14
|
message: z.string().trim().max(5000).nullable().optional(),
|
|
15
|
+
answers: z.record(z.string().max(64), z.union([z.string().max(100), z.number(), z.boolean()])).nullable().optional(),
|
|
15
16
|
responded_at: z.iso.datetime().optional(),
|
|
16
17
|
});
|
|
17
18
|
export const createEventRsvpSchema = eventRsvpBaseSchema;
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { BLOCKED_RELIGIOUS_TEXT_MESSAGE, hasBlockedReligiousText } from '../../constants/events/EventTextPolicy.js';
|
|
2
3
|
export const timelinePayloadSchema = z.object({
|
|
3
|
-
title: z
|
|
4
|
+
title: z
|
|
5
|
+
.string()
|
|
6
|
+
.trim()
|
|
7
|
+
.min(1)
|
|
8
|
+
.max(255)
|
|
9
|
+
.refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar }),
|
|
4
10
|
start_time: z.string().trim().regex(/^([01]\d|2[0-3]):([0-5]\d)$/),
|
|
11
|
+
place: z
|
|
12
|
+
.string()
|
|
13
|
+
.trim()
|
|
14
|
+
.max(255)
|
|
15
|
+
.refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar })
|
|
16
|
+
.nullable()
|
|
17
|
+
.optional(),
|
|
5
18
|
});
|
|
6
19
|
export const eventTimelineBaseSchema = z.object({
|
|
7
20
|
event_id: z.coerce.number().int().positive().optional(),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { internationalPhoneSchema } from "../common/Phone.schema.js";
|
|
3
|
+
import { EVENT_WEDDING_CUSTOM_VERSE_MAX, EventWeddingReligionValues, EventWeddingVerseValues, } from "../../constants/events/EventWeddingReligion.js";
|
|
4
|
+
import { BLOCKED_RELIGIOUS_TEXT_MESSAGE, hasBlockedReligiousText } from "../../constants/events/EventTextPolicy.js";
|
|
3
5
|
export const eventWeddingBaseSchema = z.object({
|
|
4
6
|
event_id: z.coerce.number().int().positive().optional(),
|
|
5
7
|
cover: z.record(z.string(), z.any()).nullable().optional(),
|
|
@@ -9,6 +11,15 @@ export const eventWeddingBaseSchema = z.object({
|
|
|
9
11
|
last_groom_name: z.string().trim().max(255).nullable().optional(),
|
|
10
12
|
bride_phone: internationalPhoneSchema.nullable().optional(),
|
|
11
13
|
groom_phone: internationalPhoneSchema.nullable().optional(),
|
|
14
|
+
religion: z.enum(EventWeddingReligionValues).nullable().optional(),
|
|
15
|
+
verse_key: z.enum(EventWeddingVerseValues).nullable().optional(),
|
|
16
|
+
custom_verse: z
|
|
17
|
+
.string()
|
|
18
|
+
.trim()
|
|
19
|
+
.max(EVENT_WEDDING_CUSTOM_VERSE_MAX)
|
|
20
|
+
.refine((v) => !hasBlockedReligiousText(v), { message: BLOCKED_RELIGIOUS_TEXT_MESSAGE.ar })
|
|
21
|
+
.nullable()
|
|
22
|
+
.optional(),
|
|
12
23
|
});
|
|
13
24
|
export const createEventWeddingSchema = eventWeddingBaseSchema;
|
|
14
25
|
export const updateEventWeddingSchema = eventWeddingBaseSchema.extend({
|
|
@@ -2,5 +2,8 @@ export * from "./Event.schema.js";
|
|
|
2
2
|
export * from "./EventRsvp.schema.js";
|
|
3
3
|
export * from "./EventTimeline.schema.js";
|
|
4
4
|
export * from "./EventWedding.schema.js";
|
|
5
|
+
export * from "./EventBirthday.schema.js";
|
|
6
|
+
export * from "./EventOccasion.schema.js";
|
|
5
7
|
export * from "./EventVenue.schema.js";
|
|
6
8
|
export { internationalPhoneSchema } from "../common/Phone.schema.js";
|
|
9
|
+
export * from "./EventHost.schema.js";
|
|
@@ -15,6 +15,16 @@ export var NotificationTypeEnum;
|
|
|
15
15
|
NotificationTypeEnum["POINTS_EARNED"] = "points_earned";
|
|
16
16
|
/** Sent by Deallony from the dashboard */
|
|
17
17
|
NotificationTypeEnum["DEALLONY_NEWS"] = "deallony_news";
|
|
18
|
+
/** A guest opened their personal invitation or replied to it */
|
|
19
|
+
NotificationTypeEnum["EVENT_GUESTS"] = "event_guests";
|
|
20
|
+
/** Someone added the user to an event (to accept) */
|
|
21
|
+
NotificationTypeEnum["EVENT_HOST_ADDED"] = "event_host_added";
|
|
22
|
+
/** A person the owner added accepted and joined */
|
|
23
|
+
NotificationTypeEnum["EVENT_HOST_JOINED"] = "event_host_joined";
|
|
24
|
+
/** The user no longer has access to an event */
|
|
25
|
+
NotificationTypeEnum["EVENT_HOST_REMOVED"] = "event_host_removed";
|
|
26
|
+
/** New ads match one of the user's saved searches */
|
|
27
|
+
NotificationTypeEnum["SAVED_SEARCH"] = "saved_search";
|
|
18
28
|
})(NotificationTypeEnum || (NotificationTypeEnum = {}));
|
|
19
29
|
/** How the centre groups types for its filter chips and settings */
|
|
20
30
|
export var NotificationCategoryEnum;
|
|
@@ -23,6 +33,8 @@ export var NotificationCategoryEnum;
|
|
|
23
33
|
NotificationCategoryEnum["MY_ADS"] = "my_ads";
|
|
24
34
|
NotificationCategoryEnum["POINTS"] = "points";
|
|
25
35
|
NotificationCategoryEnum["DEALLONY"] = "deallony";
|
|
36
|
+
NotificationCategoryEnum["EVENTS"] = "events";
|
|
37
|
+
NotificationCategoryEnum["SAVED_SEARCHES"] = "saved_searches";
|
|
26
38
|
})(NotificationCategoryEnum || (NotificationCategoryEnum = {}));
|
|
27
39
|
export const NOTIFICATION_CATEGORY = {
|
|
28
40
|
[NotificationTypeEnum.FAVORITE_PRICE_DROP]: NotificationCategoryEnum.FAVORITES,
|
|
@@ -34,4 +46,9 @@ export const NOTIFICATION_CATEGORY = {
|
|
|
34
46
|
[NotificationTypeEnum.AD_SAVED]: NotificationCategoryEnum.MY_ADS,
|
|
35
47
|
[NotificationTypeEnum.POINTS_EARNED]: NotificationCategoryEnum.POINTS,
|
|
36
48
|
[NotificationTypeEnum.DEALLONY_NEWS]: NotificationCategoryEnum.DEALLONY,
|
|
49
|
+
[NotificationTypeEnum.EVENT_GUESTS]: NotificationCategoryEnum.EVENTS,
|
|
50
|
+
[NotificationTypeEnum.EVENT_HOST_ADDED]: NotificationCategoryEnum.EVENTS,
|
|
51
|
+
[NotificationTypeEnum.EVENT_HOST_JOINED]: NotificationCategoryEnum.EVENTS,
|
|
52
|
+
[NotificationTypeEnum.EVENT_HOST_REMOVED]: NotificationCategoryEnum.EVENTS,
|
|
53
|
+
[NotificationTypeEnum.SAVED_SEARCH]: NotificationCategoryEnum.SAVED_SEARCHES,
|
|
37
54
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,4 +2,8 @@ export * from './Event.js';
|
|
|
2
2
|
export * from './EventRsvp.js';
|
|
3
3
|
export * from './EventTimeline.js';
|
|
4
4
|
export * from './EventWedding.js';
|
|
5
|
+
export * from './EventBirthday.js';
|
|
6
|
+
export * from './EventOccasion.js';
|
|
5
7
|
export * from './EventCustomization.js';
|
|
8
|
+
export * from "./EventDressCode.js";
|
|
9
|
+
export * from './EventHost.js';
|
package/dist/esm/types/index.js
CHANGED
|
@@ -50,13 +50,17 @@ export * as Event from './events/Event.js';
|
|
|
50
50
|
export * as EventRsvp from './events/EventRsvp.js';
|
|
51
51
|
export * as EventTimeline from './events/EventTimeline.js';
|
|
52
52
|
export * as EventWedding from './events/EventWedding.js';
|
|
53
|
+
export * as EventBirthday from './events/EventBirthday.js';
|
|
54
|
+
export * as EventOccasion from './events/EventOccasion.js';
|
|
53
55
|
export * as EventVenue from './events/EventVenue.js';
|
|
56
|
+
export * as EventHost from './events/EventHost.js';
|
|
54
57
|
// user
|
|
55
58
|
export * as User from "./user/User.js";
|
|
56
59
|
export * as Role from "./user/Role.js";
|
|
57
60
|
export * as Permission from "./user/Permission.js";
|
|
58
61
|
export * as Wallet from "./user/Wallet.js";
|
|
59
62
|
export * as Favorite from "./user/Favorite.js";
|
|
63
|
+
export * as SavedSearch from "./user/SavedSearch.js";
|
|
60
64
|
export * as Loyalty from "./user/Loyalty.js";
|
|
61
65
|
export * as PotentialUser from "./user/PotentialUser.js";
|
|
62
66
|
export * as Company from './company/Company.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** How often a saved search alerts: as new ads come in, or one summary each morning */
|
|
2
|
+
export var SavedSearchFrequency;
|
|
3
|
+
(function (SavedSearchFrequency) {
|
|
4
|
+
SavedSearchFrequency["INSTANT"] = "instant";
|
|
5
|
+
SavedSearchFrequency["DAILY"] = "daily";
|
|
6
|
+
})(SavedSearchFrequency || (SavedSearchFrequency = {}));
|
|
7
|
+
/** Most saved searches one user can keep */
|
|
8
|
+
export const SAVED_SEARCH_LIMIT = 20;
|