@deallony/shared 1.2.81 → 1.2.83
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/EventCustomization.d.ts +18 -0
- package/dist/cjs/constants/events/EventCustomization.js +21 -1
- 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/EventTemplate.js +3 -3
- package/dist/cjs/constants/events/EventType.d.ts +21 -90
- package/dist/cjs/constants/events/EventType.js +15 -8
- package/dist/cjs/constants/events/EventWeddingReligion.d.ts +10 -5
- package/dist/cjs/constants/events/EventWeddingReligion.js +12 -27
- package/dist/cjs/constants/events/index.d.ts +2 -0
- package/dist/cjs/constants/events/index.js +2 -0
- package/dist/cjs/constants/routes/app.d.ts +21 -0
- package/dist/cjs/constants/routes/app.js +6 -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/index.d.ts +1 -0
- package/dist/cjs/dto/events/index.js +1 -0
- package/dist/cjs/schema/communication/ai-conversation.schema.d.ts +4 -2
- package/dist/cjs/schema/communication/offer.schema.d.ts +3 -3
- package/dist/cjs/schema/events/Event.schema.d.ts +70 -0
- package/dist/cjs/schema/events/Event.schema.js +34 -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/index.d.ts +1 -0
- package/dist/cjs/schema/events/index.js +1 -0
- package/dist/cjs/types/ad/Ad.d.ts +2 -0
- package/dist/cjs/types/communication/Notification.d.ts +12 -0
- package/dist/cjs/types/communication/Notification.js +15 -0
- package/dist/cjs/types/events/Event.d.ts +28 -0
- package/dist/cjs/types/events/EventCustomization.d.ts +11 -0
- package/dist/cjs/types/events/EventDay.d.ts +89 -0
- package/dist/cjs/types/events/EventDay.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/EventInvited.d.ts +25 -0
- package/dist/cjs/types/events/EventInvited.js +2 -0
- package/dist/cjs/types/events/EventRsvp.d.ts +12 -1
- package/dist/cjs/types/events/index.d.ts +3 -0
- package/dist/cjs/types/events/index.js +3 -0
- package/dist/cjs/types/index.d.ts +3 -0
- package/dist/cjs/types/index.js +5 -2
- package/dist/cjs/utils/adSeoTitle.d.ts +35 -0
- package/dist/cjs/utils/adSeoTitle.js +26 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/esm/constants/events/EventCustomization.js +20 -0
- package/dist/esm/constants/events/EventGuests.js +3 -0
- package/dist/esm/constants/events/EventHost.js +147 -0
- package/dist/esm/constants/events/EventTemplate.js +3 -3
- package/dist/esm/constants/events/EventType.js +14 -7
- package/dist/esm/constants/events/EventWeddingReligion.js +11 -26
- package/dist/esm/constants/events/index.js +2 -0
- package/dist/esm/constants/routes/app.js +6 -0
- package/dist/esm/dto/events/EventHost.dto.js +1 -0
- package/dist/esm/dto/events/index.js +1 -0
- package/dist/esm/schema/events/Event.schema.js +35 -1
- package/dist/esm/schema/events/EventHost.schema.js +41 -0
- package/dist/esm/schema/events/index.js +1 -0
- package/dist/esm/types/communication/Notification.js +15 -0
- package/dist/esm/types/events/EventDay.js +1 -0
- package/dist/esm/types/events/EventHost.js +1 -0
- package/dist/esm/types/events/EventInvited.js +1 -0
- package/dist/esm/types/events/index.js +3 -0
- package/dist/esm/types/index.js +3 -0
- package/dist/esm/utils/adSeoTitle.js +23 -0
- package/dist/esm/utils/index.js +1 -0
- package/package.json +1 -1
|
@@ -17,6 +17,16 @@ export declare enum NotificationTypeEnum {
|
|
|
17
17
|
DEALLONY_NEWS = "deallony_news",
|
|
18
18
|
/** A guest opened their personal invitation or replied to it */
|
|
19
19
|
EVENT_GUESTS = "event_guests",
|
|
20
|
+
/** Someone added the user to an event (to accept) */
|
|
21
|
+
EVENT_HOST_ADDED = "event_host_added",
|
|
22
|
+
/** A person the owner added accepted and joined */
|
|
23
|
+
EVENT_HOST_JOINED = "event_host_joined",
|
|
24
|
+
/** The user no longer has access to an event */
|
|
25
|
+
EVENT_HOST_REMOVED = "event_host_removed",
|
|
26
|
+
/** The user is on an event's guest list («دعواتي») */
|
|
27
|
+
EVENT_INVITED = "event_invited",
|
|
28
|
+
/** A guest's invitation is tomorrow or today («دعواتي») */
|
|
29
|
+
EVENT_REMINDER = "event_reminder",
|
|
20
30
|
/** New ads match one of the user's saved searches */
|
|
21
31
|
SAVED_SEARCH = "saved_search"
|
|
22
32
|
}
|
|
@@ -51,6 +61,8 @@ export type INotificationData = {
|
|
|
51
61
|
/** EVENT_GUESTS: the event and the guest it is about */
|
|
52
62
|
event_id?: number;
|
|
53
63
|
rsvp_id?: number;
|
|
64
|
+
/** EVENT_HOST_*: the host row it is about */
|
|
65
|
+
host_id?: number;
|
|
54
66
|
/** SAVED_SEARCH: the saved search the new ads (ad_ids, count) match */
|
|
55
67
|
saved_search_id?: number;
|
|
56
68
|
};
|
|
@@ -20,6 +20,16 @@ var NotificationTypeEnum;
|
|
|
20
20
|
NotificationTypeEnum["DEALLONY_NEWS"] = "deallony_news";
|
|
21
21
|
/** A guest opened their personal invitation or replied to it */
|
|
22
22
|
NotificationTypeEnum["EVENT_GUESTS"] = "event_guests";
|
|
23
|
+
/** Someone added the user to an event (to accept) */
|
|
24
|
+
NotificationTypeEnum["EVENT_HOST_ADDED"] = "event_host_added";
|
|
25
|
+
/** A person the owner added accepted and joined */
|
|
26
|
+
NotificationTypeEnum["EVENT_HOST_JOINED"] = "event_host_joined";
|
|
27
|
+
/** The user no longer has access to an event */
|
|
28
|
+
NotificationTypeEnum["EVENT_HOST_REMOVED"] = "event_host_removed";
|
|
29
|
+
/** The user is on an event's guest list («دعواتي») */
|
|
30
|
+
NotificationTypeEnum["EVENT_INVITED"] = "event_invited";
|
|
31
|
+
/** A guest's invitation is tomorrow or today («دعواتي») */
|
|
32
|
+
NotificationTypeEnum["EVENT_REMINDER"] = "event_reminder";
|
|
23
33
|
/** New ads match one of the user's saved searches */
|
|
24
34
|
NotificationTypeEnum["SAVED_SEARCH"] = "saved_search";
|
|
25
35
|
})(NotificationTypeEnum || (exports.NotificationTypeEnum = NotificationTypeEnum = {}));
|
|
@@ -44,5 +54,10 @@ exports.NOTIFICATION_CATEGORY = {
|
|
|
44
54
|
[NotificationTypeEnum.POINTS_EARNED]: NotificationCategoryEnum.POINTS,
|
|
45
55
|
[NotificationTypeEnum.DEALLONY_NEWS]: NotificationCategoryEnum.DEALLONY,
|
|
46
56
|
[NotificationTypeEnum.EVENT_GUESTS]: NotificationCategoryEnum.EVENTS,
|
|
57
|
+
[NotificationTypeEnum.EVENT_HOST_ADDED]: NotificationCategoryEnum.EVENTS,
|
|
58
|
+
[NotificationTypeEnum.EVENT_HOST_JOINED]: NotificationCategoryEnum.EVENTS,
|
|
59
|
+
[NotificationTypeEnum.EVENT_HOST_REMOVED]: NotificationCategoryEnum.EVENTS,
|
|
60
|
+
[NotificationTypeEnum.EVENT_INVITED]: NotificationCategoryEnum.EVENTS,
|
|
61
|
+
[NotificationTypeEnum.EVENT_REMINDER]: NotificationCategoryEnum.EVENTS,
|
|
47
62
|
[NotificationTypeEnum.SAVED_SEARCH]: NotificationCategoryEnum.SAVED_SEARCHES,
|
|
48
63
|
};
|
|
@@ -6,9 +6,11 @@ import type { IEventOccasion } from "./EventOccasion";
|
|
|
6
6
|
import type { IEventVenue } from "./EventVenue";
|
|
7
7
|
import type { IEventCustomization } from "./EventCustomization";
|
|
8
8
|
import type { IEventDressCode } from "./EventDressCode";
|
|
9
|
+
import type { IEventHost } from "./EventHost";
|
|
9
10
|
export type { IEventCustomization };
|
|
10
11
|
import type { IUser } from "../user/User";
|
|
11
12
|
import { EventInvitationScanType, EventVisibility } from "../../constants/events";
|
|
13
|
+
import type { EventAccessRole, EventPermission } from "../../constants/events/EventHost";
|
|
12
14
|
export type IEvent = {
|
|
13
15
|
id?: number;
|
|
14
16
|
lat: number | null;
|
|
@@ -37,6 +39,12 @@ export type IEvent = {
|
|
|
37
39
|
venue?: IEventVenue | null;
|
|
38
40
|
venue_name?: string | null;
|
|
39
41
|
location_label?: string | null;
|
|
42
|
+
/** Expected number of guests; null for events created before it was asked */
|
|
43
|
+
expected_guests?: number | null;
|
|
44
|
+
/** Children may come; null for events created before it was asked */
|
|
45
|
+
children_allowed?: boolean | null;
|
|
46
|
+
/** Food is served; null for events created before it was asked */
|
|
47
|
+
food_included?: boolean | null;
|
|
40
48
|
user_id?: number | null;
|
|
41
49
|
user?: IUser | null;
|
|
42
50
|
payment_id?: number | null;
|
|
@@ -48,4 +56,24 @@ export type IEvent = {
|
|
|
48
56
|
preview_url?: string | null;
|
|
49
57
|
/** Couple's secret guest-management page; returned to the owner only */
|
|
50
58
|
manage_url?: string | null;
|
|
59
|
+
/** Who created it: a slot key of the type (bride, groom, graduate...), "company" or "other"; null for old events */
|
|
60
|
+
creator_role?: string | null;
|
|
61
|
+
/** What the signed-in user is on this event (owner, organiser or guests); null when they have no access yet */
|
|
62
|
+
my_role?: EventAccessRole | null;
|
|
63
|
+
/** What the signed-in user may do (CONSTANTS.EVENTS.EventRolePermissions of my_role) */
|
|
64
|
+
my_permissions?: EventPermission[];
|
|
65
|
+
/** The signed-in user's own host row, when they are not the owner (pending rows included) */
|
|
66
|
+
my_host?: IEventHost | null;
|
|
67
|
+
/** The type's suggested people as the form shows them; only for those who manage people */
|
|
68
|
+
people?: {
|
|
69
|
+
slot: string;
|
|
70
|
+
phone: string | null;
|
|
71
|
+
name: string | null;
|
|
72
|
+
surprise: boolean;
|
|
73
|
+
status: string;
|
|
74
|
+
}[];
|
|
75
|
+
/** Owner's display name, for people the event was shared with */
|
|
76
|
+
owner_name?: string | null;
|
|
77
|
+
/** Who saved last (owner or a host), for «آخر تعديل» */
|
|
78
|
+
updated_by_user_id?: number | null;
|
|
51
79
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IFile } from "../media";
|
|
1
2
|
import type { EventCustomizationSectionKey } from "../../constants/events/EventCustomization";
|
|
2
3
|
/** Owner choices for the invitation page; anything left empty keeps the template's own look */
|
|
3
4
|
export type IEventCustomization = {
|
|
@@ -11,10 +12,20 @@ export type IEventCustomization = {
|
|
|
11
12
|
welcome_message?: string | null;
|
|
12
13
|
/** Replaces the template's RSVP invitation line */
|
|
13
14
|
rsvp_message?: string | null;
|
|
15
|
+
/** Replaces «جنة الأطفال منازلهم» when children are not allowed */
|
|
16
|
+
children_message?: string | null;
|
|
17
|
+
/** Replaces «عشاكم بيحلا معنا» when food is included */
|
|
18
|
+
food_message?: string | null;
|
|
14
19
|
/** EventCustomizationTracks value */
|
|
15
20
|
music?: string | null;
|
|
16
21
|
/** EventCustomizationOpening value: how the invitation opens; empty keeps the template's own */
|
|
17
22
|
opening?: string | null;
|
|
18
23
|
/** False stops the page scrolling by itself; empty means on */
|
|
19
24
|
auto_scroll?: boolean | null;
|
|
25
|
+
/** Video shown in its own section after the cover (uploaded through the assets service) */
|
|
26
|
+
cover_video?: (IFile & {
|
|
27
|
+
durationSeconds?: number | null;
|
|
28
|
+
}) | null;
|
|
29
|
+
/** True plays the video without sound (the music then keeps playing) */
|
|
30
|
+
cover_video_muted?: boolean | null;
|
|
20
31
|
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { IEventOccasion } from './EventOccasion';
|
|
2
|
+
import type { IEventWedding } from './EventWedding';
|
|
3
|
+
/**
|
|
4
|
+
* «يوم المناسبة»: the door tools of an event.
|
|
5
|
+
* ready: nobody of the invitation came in yet; partial: some came in; full: everyone came in;
|
|
6
|
+
* other_event: a real invitation for another event; not_found: no such invitation.
|
|
7
|
+
*/
|
|
8
|
+
export type EventDayLookupStatus = 'ready' | 'partial' | 'full' | 'other_event' | 'not_found';
|
|
9
|
+
/** A guest as the door sees them */
|
|
10
|
+
export type IEventDayGuest = {
|
|
11
|
+
id: number;
|
|
12
|
+
full_name: string;
|
|
13
|
+
phone: string | null;
|
|
14
|
+
/** People on the invitation (at least 1) */
|
|
15
|
+
guest_count: number;
|
|
16
|
+
/** People of the invitation who came in so far */
|
|
17
|
+
arrived_count: number;
|
|
18
|
+
remaining: number;
|
|
19
|
+
attendance_status: 'attending' | 'not_attending' | 'maybe';
|
|
20
|
+
responded_at: string | Date | null;
|
|
21
|
+
/** First and latest time someone of the invitation came in */
|
|
22
|
+
arrived_at: string | Date | null;
|
|
23
|
+
last_arrived_at: string | Date | null;
|
|
24
|
+
/** Added at the door without an invitation */
|
|
25
|
+
walk_in: boolean;
|
|
26
|
+
checked_in_by: number | null;
|
|
27
|
+
checked_in_by_name: string | null;
|
|
28
|
+
};
|
|
29
|
+
/** Another event's basics, when the door scans an invitation that isn't for this event */
|
|
30
|
+
export type IEventDayOtherEvent = {
|
|
31
|
+
id: number;
|
|
32
|
+
event_type: string | null;
|
|
33
|
+
start_date: string | Date | null;
|
|
34
|
+
wedding: IEventWedding | null;
|
|
35
|
+
occasion: IEventOccasion | null;
|
|
36
|
+
venue: {
|
|
37
|
+
id: number;
|
|
38
|
+
name: string;
|
|
39
|
+
} | null;
|
|
40
|
+
};
|
|
41
|
+
export type IEventDayLookup = {
|
|
42
|
+
status: EventDayLookupStatus;
|
|
43
|
+
guest?: IEventDayGuest;
|
|
44
|
+
other_event?: IEventDayOtherEvent | null;
|
|
45
|
+
/** checkIn only: false when nobody more could come in (the invitation was already full) */
|
|
46
|
+
checked_in?: boolean;
|
|
47
|
+
};
|
|
48
|
+
export type IEventDayScanner = {
|
|
49
|
+
user_id: number;
|
|
50
|
+
name: string | null;
|
|
51
|
+
invites: number;
|
|
52
|
+
people: number;
|
|
53
|
+
};
|
|
54
|
+
export type IEventDaySummary = {
|
|
55
|
+
/** Invitations sent out (guests added at the door not counted) */
|
|
56
|
+
invites: number;
|
|
57
|
+
/** People expected: everyone on the invitations except those who said they won't come */
|
|
58
|
+
expected_people: number;
|
|
59
|
+
/** People who came in, guests added at the door included */
|
|
60
|
+
arrived_people: number;
|
|
61
|
+
invites_full: number;
|
|
62
|
+
invites_partial: number;
|
|
63
|
+
not_arrived: number;
|
|
64
|
+
declined: number;
|
|
65
|
+
walk_ins: number;
|
|
66
|
+
walk_in_people: number;
|
|
67
|
+
recent: IEventDayGuest[];
|
|
68
|
+
scanners: IEventDayScanner[];
|
|
69
|
+
};
|
|
70
|
+
/** An event of today the user can let guests in for */
|
|
71
|
+
export type IEventDayToday = {
|
|
72
|
+
id: number;
|
|
73
|
+
event_type: string | null;
|
|
74
|
+
start_date: string | Date | null;
|
|
75
|
+
end_date: string | Date | null;
|
|
76
|
+
is_published: boolean;
|
|
77
|
+
invitation_scan_type: 'none' | 'qrcode' | 'barcode';
|
|
78
|
+
wedding: IEventWedding | null;
|
|
79
|
+
occasion: IEventOccasion | null;
|
|
80
|
+
venue: {
|
|
81
|
+
id: number;
|
|
82
|
+
name: string;
|
|
83
|
+
} | null;
|
|
84
|
+
my_role: 'owner' | 'organiser' | 'guests' | null;
|
|
85
|
+
/** Seen because it is at the user's company's venue */
|
|
86
|
+
via_company: boolean;
|
|
87
|
+
expected_people: number;
|
|
88
|
+
arrived_people: number;
|
|
89
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EventHostRole, EventHostStatus } from "../../constants/events/EventHost";
|
|
2
|
+
/** Someone other than the creator who can open and manage an event in the app */
|
|
3
|
+
export type IEventHost = {
|
|
4
|
+
id: number;
|
|
5
|
+
event_id: number;
|
|
6
|
+
/** Normalized number; only people who can manage hosts get it */
|
|
7
|
+
phone?: string | null;
|
|
8
|
+
user_id?: number | null;
|
|
9
|
+
/** The account's name once linked */
|
|
10
|
+
user_name?: string | null;
|
|
11
|
+
role: EventHostRole;
|
|
12
|
+
/** Slot key of the event type (CONSTANTS.EVENTS.EventPeopleSlots) or "manual" */
|
|
13
|
+
source: string;
|
|
14
|
+
/** Free text for people added by hand (e.g. «أم العروس»); slots use their own label */
|
|
15
|
+
label: string | null;
|
|
16
|
+
/** Name typed by the owner */
|
|
17
|
+
name: string | null;
|
|
18
|
+
status: EventHostStatus;
|
|
19
|
+
/** Surprise: they get no notice or access until the event ends */
|
|
20
|
+
surprise: boolean;
|
|
21
|
+
/** Computed: when a surprise person gets access (the event's end); null when not hidden */
|
|
22
|
+
hidden_until?: string | Date | null;
|
|
23
|
+
/** Computed: still hidden from them now */
|
|
24
|
+
is_hidden?: boolean;
|
|
25
|
+
added_by_user_id: number | null;
|
|
26
|
+
linked_at: string | Date | null;
|
|
27
|
+
accepted_at: string | Date | null;
|
|
28
|
+
created_at?: string | Date;
|
|
29
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IEvent } from './Event';
|
|
2
|
+
import type { IEventRsvp } from './EventRsvp';
|
|
3
|
+
/** The signed-in guest's own row on an event's guest list (never other guests) */
|
|
4
|
+
export type IInvitedRsvp = Pick<IEventRsvp, 'id' | 'event_id' | 'attendance_status' | 'guest_count' | 'seats_fixed' | 'message' | 'responded_at' | 'arrived_at' | 'arrived_count'> & {
|
|
5
|
+
full_name: string;
|
|
6
|
+
/** Their personal invitation link token: /invite/<token> on the event site */
|
|
7
|
+
invite_token: string | null;
|
|
8
|
+
/** When this row was matched to the account (by number or by opening the link) */
|
|
9
|
+
linked_at: string | Date | null;
|
|
10
|
+
};
|
|
11
|
+
/** «دعواتي»: an event the user was invited to, as a guest sees it */
|
|
12
|
+
export type IInvitedEvent = {
|
|
13
|
+
/** The public view of the event: no phones, guests, payment or manage links */
|
|
14
|
+
event: IEvent;
|
|
15
|
+
rsvp: IInvitedRsvp;
|
|
16
|
+
/** Who invited them (owner's name), when known */
|
|
17
|
+
host_name: string | null;
|
|
18
|
+
/** Full personal invitation URL on the event site */
|
|
19
|
+
invite_url: string | null;
|
|
20
|
+
};
|
|
21
|
+
export type IInvitedEventsResponse = {
|
|
22
|
+
values: IInvitedEvent[];
|
|
23
|
+
/** Matched since the user last opened «دعواتي» */
|
|
24
|
+
new_count: number;
|
|
25
|
+
};
|
|
@@ -4,13 +4,24 @@ export type IEventRsvp = {
|
|
|
4
4
|
event_id: number;
|
|
5
5
|
first_name: string;
|
|
6
6
|
last_name: string | null;
|
|
7
|
-
|
|
7
|
+
/** null when the host added the guest by name only */
|
|
8
|
+
phone: string | null;
|
|
8
9
|
attendance_status: 'attending' | 'not_attending' | 'maybe';
|
|
9
10
|
guest_count: number;
|
|
11
|
+
/** The host fixed the seats: the guest's personal invitation can't change guest_count */
|
|
12
|
+
seats_fixed?: boolean;
|
|
10
13
|
message: string | null;
|
|
11
14
|
/** Extra answers with the reply, e.g. { gender_guess: 'boy' } for a gender reveal */
|
|
12
15
|
answers?: Record<string, any> | null;
|
|
13
16
|
responded_at: string | Date | null;
|
|
17
|
+
/** Day of event: first time someone of the invitation came in, and how many came in */
|
|
18
|
+
arrived_at?: string | Date | null;
|
|
19
|
+
arrived_count?: number;
|
|
20
|
+
last_arrived_at?: string | Date | null;
|
|
21
|
+
/** The user who last let them in */
|
|
22
|
+
checked_in_by?: number | null;
|
|
23
|
+
/** Added at the door without an invitation */
|
|
24
|
+
walk_in?: boolean;
|
|
14
25
|
created_at?: string | Date;
|
|
15
26
|
updated_at?: string | Date;
|
|
16
27
|
event?: IEvent;
|
|
@@ -22,3 +22,6 @@ __exportStar(require("./EventBirthday"), exports);
|
|
|
22
22
|
__exportStar(require("./EventOccasion"), exports);
|
|
23
23
|
__exportStar(require("./EventCustomization"), exports);
|
|
24
24
|
__exportStar(require("./EventDressCode"), exports);
|
|
25
|
+
__exportStar(require("./EventHost"), exports);
|
|
26
|
+
__exportStar(require("./EventDay"), exports);
|
|
27
|
+
__exportStar(require("./EventInvited"), exports);
|
|
@@ -45,6 +45,9 @@ export * as EventWedding from './events/EventWedding';
|
|
|
45
45
|
export * as EventBirthday from './events/EventBirthday';
|
|
46
46
|
export * as EventOccasion from './events/EventOccasion';
|
|
47
47
|
export * as EventVenue from './events/EventVenue';
|
|
48
|
+
export * as EventHost from './events/EventHost';
|
|
49
|
+
export * as EventDay from './events/EventDay';
|
|
50
|
+
export * as EventInvited from './events/EventInvited';
|
|
48
51
|
export * as User from "./user/User";
|
|
49
52
|
export * as Role from "./user/Role";
|
|
50
53
|
export * as Permission from "./user/Permission";
|
package/dist/cjs/types/index.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.Payment = exports.Analysis = exports.GeminiApiKey = exports.Google = exports.Kyc = exports.SocialMediaProfile = exports.SocialMediaPlatform = exports.Image = exports.Media = exports.File = exports.Notification = exports.NotificationToken = exports.MessageTemplate = exports.Device = exports.Chat = exports.AppStartScreen = exports.MetaData = exports.Company = exports.PotentialUser = exports.Loyalty = exports.SavedSearch = exports.Favorite = exports.Wallet = void 0;
|
|
39
|
+
exports.EventInvited = exports.EventDay = exports.EventHost = exports.EventVenue = exports.EventOccasion = exports.EventBirthday = exports.EventWedding = exports.EventTimeline = exports.EventRsvp = exports.Event = exports.District = exports.City = exports.AdminBoundary = exports.WorkType = exports.UsedProductCondition = exports.UsedProductAge = exports.Unit = exports.Transmission = exports.RegionalSpec = exports.PublisherType = exports.PropertyStatus = exports.PriceType = exports.OfferType = exports.LicenseType = exports.FuelType = exports.Feature = exports.Facility = exports.Currency = exports.Color = exports.CategoryWorkType = exports.Category = exports.CarBody = exports.UsedProduct = exports.Service = exports.PropertySubType = exports.Property = exports.MotorTrim = exports.Motor = exports.AdPromotion = exports.Addresses = exports.AdDailyViews = exports.AdLocation = exports.Ad = exports.FilterParams = exports.ModuleFetchEndpoints = exports.Config = exports.AccessType = exports.Status = exports.Response = exports.LocalizedName = void 0;
|
|
40
|
+
exports.Payment = exports.Analysis = exports.GeminiApiKey = exports.Google = exports.Kyc = exports.SocialMediaProfile = exports.SocialMediaPlatform = exports.Image = exports.Media = exports.File = exports.Notification = exports.NotificationToken = exports.MessageTemplate = exports.Device = exports.Chat = exports.AppStartScreen = exports.MetaData = exports.Company = exports.PotentialUser = exports.Loyalty = exports.SavedSearch = exports.Favorite = exports.Wallet = exports.Permission = exports.Role = exports.User = void 0;
|
|
41
41
|
// common
|
|
42
42
|
exports.LocalizedName = __importStar(require("./common/LocalizedName"));
|
|
43
43
|
exports.Response = __importStar(require("./common/Response"));
|
|
@@ -90,6 +90,9 @@ exports.EventWedding = __importStar(require("./events/EventWedding"));
|
|
|
90
90
|
exports.EventBirthday = __importStar(require("./events/EventBirthday"));
|
|
91
91
|
exports.EventOccasion = __importStar(require("./events/EventOccasion"));
|
|
92
92
|
exports.EventVenue = __importStar(require("./events/EventVenue"));
|
|
93
|
+
exports.EventHost = __importStar(require("./events/EventHost"));
|
|
94
|
+
exports.EventDay = __importStar(require("./events/EventDay"));
|
|
95
|
+
exports.EventInvited = __importStar(require("./events/EventInvited"));
|
|
93
96
|
// user
|
|
94
97
|
exports.User = __importStar(require("./user/User"));
|
|
95
98
|
exports.Role = __importStar(require("./user/Role"));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ad's auto-generated title (the page title, the heading and what Google shows).
|
|
3
|
+
* Ads keep their own title field empty, so the title is built from the ad's details:
|
|
4
|
+
* - property: "<offer type> <category> في <city>"
|
|
5
|
+
* - motor: "<category> | <offer type> سيارة في <city>"
|
|
6
|
+
* - otherwise (or when details are missing): the ad's own title, else the category name
|
|
7
|
+
*
|
|
8
|
+
* The backend saves it in ads.seo_title on add/update, so pages read it without building it.
|
|
9
|
+
*/
|
|
10
|
+
export type AdSeoTitleSource = {
|
|
11
|
+
title?: string | null;
|
|
12
|
+
subject_type?: string | null;
|
|
13
|
+
category?: {
|
|
14
|
+
name?: string | null;
|
|
15
|
+
} | null;
|
|
16
|
+
property?: {
|
|
17
|
+
offerType?: {
|
|
18
|
+
name?: {
|
|
19
|
+
ar?: string | null;
|
|
20
|
+
} | null;
|
|
21
|
+
} | null;
|
|
22
|
+
} | null;
|
|
23
|
+
motor?: {
|
|
24
|
+
offerType?: {
|
|
25
|
+
name?: {
|
|
26
|
+
ar?: string | null;
|
|
27
|
+
} | null;
|
|
28
|
+
} | null;
|
|
29
|
+
} | null;
|
|
30
|
+
/** The ad's city (the second level of its admin boundary path) */
|
|
31
|
+
adminBoundary?: {
|
|
32
|
+
name?: string | null;
|
|
33
|
+
} | null;
|
|
34
|
+
};
|
|
35
|
+
export declare function buildAdSeoTitle(ad?: AdSeoTitleSource | null): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAdSeoTitle = buildAdSeoTitle;
|
|
4
|
+
const rtl = (text) => `${text}`;
|
|
5
|
+
const ltr = (text) => `${text}`;
|
|
6
|
+
function buildAdSeoTitle(ad) {
|
|
7
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
8
|
+
if (!ad)
|
|
9
|
+
return "Deallony";
|
|
10
|
+
const categoryName = (_b = (_a = ad.category) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : undefined;
|
|
11
|
+
let title = ((_c = ad.title) === null || _c === void 0 ? void 0 : _c.trim()) || categoryName;
|
|
12
|
+
if (ad.subject_type === "properties") {
|
|
13
|
+
const offer = (_f = (_e = (_d = ad.property) === null || _d === void 0 ? void 0 : _d.offerType) === null || _e === void 0 ? void 0 : _e.name) === null || _f === void 0 ? void 0 : _f.ar;
|
|
14
|
+
if (offer && categoryName) {
|
|
15
|
+
title = offer + " " + categoryName + " في " + ((_g = ad.adminBoundary) === null || _g === void 0 ? void 0 : _g.name);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (ad.subject_type === "motors") {
|
|
19
|
+
const offer = (_k = (_j = (_h = ad.motor) === null || _h === void 0 ? void 0 : _h.offerType) === null || _j === void 0 ? void 0 : _j.name) === null || _k === void 0 ? void 0 : _k.ar;
|
|
20
|
+
if (offer && categoryName) {
|
|
21
|
+
const arabicMain = rtl(`${offer} سيارة في ${(_l = ad.adminBoundary) === null || _l === void 0 ? void 0 : _l.name}`);
|
|
22
|
+
title = `${ltr(categoryName)} | ${arabicMain}`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return title || "Deallony";
|
|
26
|
+
}
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -29,6 +29,8 @@ export const EventCustomizationSection = {
|
|
|
29
29
|
RSVP: "rsvp",
|
|
30
30
|
MUSIC: "music",
|
|
31
31
|
DRESS_CODE: "dress_code",
|
|
32
|
+
ATTENDANCE: "attendance",
|
|
33
|
+
VIDEO: "video",
|
|
32
34
|
};
|
|
33
35
|
export const EventCustomizationSectionOptions = [
|
|
34
36
|
{ value: "countdown", name: { en: "Countdown", ar: "العد التنازلي" } },
|
|
@@ -38,8 +40,26 @@ export const EventCustomizationSectionOptions = [
|
|
|
38
40
|
{ value: "rsvp", name: { en: "RSVP", ar: "تأكيد الحضور" } },
|
|
39
41
|
{ value: "music", name: { en: "Music", ar: "الموسيقى" } },
|
|
40
42
|
{ value: "dress_code", name: { en: "Dress code", ar: "اللباس المطلوب" } },
|
|
43
|
+
{ value: "attendance", name: { en: "Attendance details", ar: "تفاصيل الحضور" } },
|
|
44
|
+
{ value: "video", name: { en: "Video", ar: "الفيديو" } },
|
|
41
45
|
];
|
|
46
|
+
/** Invitation video (customization.cover_video): one per event, checked in the app before upload */
|
|
47
|
+
export const EVENT_COVER_VIDEO_MAX_SECONDS = 60;
|
|
48
|
+
export const EVENT_COVER_VIDEO_MAX_BYTES = 100 * 1024 * 1024;
|
|
49
|
+
export const EVENT_COVER_VIDEO_TYPES = ["video/mp4", "video/quicktime", "video/webm", "video/x-m4v"];
|
|
42
50
|
export const EVENT_CUSTOMIZATION_TEXT_MAX = 160;
|
|
51
|
+
/** Children / food line on the invitation: defaults, owner text limit and ready phrases */
|
|
52
|
+
export const EVENT_ATTENDANCE_TEXT_MAX = 60;
|
|
53
|
+
export const EventAttendanceTexts = {
|
|
54
|
+
children: {
|
|
55
|
+
default: "جنة الأطفال منازلهم",
|
|
56
|
+
suggestions: ["جنة الأطفال منازلهم", "نعتذر عن اصطحاب الأطفال", "الحفل للكبار فقط", "نتمنى لأطفالكم ليلة هانئة في البيت"],
|
|
57
|
+
},
|
|
58
|
+
food: {
|
|
59
|
+
default: "عشاكم بيحلا معنا",
|
|
60
|
+
suggestions: ["عشاكم بيحلا معنا", "يسعدنا أن تشاركونا العشاء", "بوفيه مفتوح بعد الحفل", "ضيافة وعشاء"],
|
|
61
|
+
},
|
|
62
|
+
};
|
|
43
63
|
/** How the invitation opens for a guest; no value keeps the template's own opening */
|
|
44
64
|
export const EventCustomizationOpening = {
|
|
45
65
|
NONE: "none",
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/** organiser: full control like the owner; guests: the event's guests only */
|
|
2
|
+
export const EventHostRoleValues = ["organiser", "guests"];
|
|
3
|
+
export const EventHostRole = {
|
|
4
|
+
ORGANISER: "organiser",
|
|
5
|
+
GUESTS: "guests",
|
|
6
|
+
};
|
|
7
|
+
export const EventHostRoleNames = {
|
|
8
|
+
organiser: { ar: "منظم", en: "Organiser" },
|
|
9
|
+
guests: { ar: "إدارة المدعوين", en: "Manages guests" },
|
|
10
|
+
};
|
|
11
|
+
export const EventHostRoleHints = {
|
|
12
|
+
organiser: { ar: "يدير المناسبة كاملة", en: "Manages the whole event" },
|
|
13
|
+
guests: { ar: "يدير المدعوين ويرسل الدعوات ويتابع الردود", en: "Manages guests, sends invitations and follows replies" },
|
|
14
|
+
};
|
|
15
|
+
export const EventHostRoleOptions = EventHostRoleValues.map((value) => ({
|
|
16
|
+
value,
|
|
17
|
+
name: EventHostRoleNames[value],
|
|
18
|
+
hint: EventHostRoleHints[value],
|
|
19
|
+
}));
|
|
20
|
+
/** pending: waiting for the person to sign in and accept; active: accepted */
|
|
21
|
+
export const EventHostStatusValues = ["pending", "active", "declined", "left", "removed"];
|
|
22
|
+
export const EventHostStatus = {
|
|
23
|
+
PENDING: "pending",
|
|
24
|
+
ACTIVE: "active",
|
|
25
|
+
DECLINED: "declined",
|
|
26
|
+
LEFT: "left",
|
|
27
|
+
REMOVED: "removed",
|
|
28
|
+
};
|
|
29
|
+
export const EventHostStatusNames = {
|
|
30
|
+
pending: { ar: "بانتظار القبول", en: "Waiting to accept" },
|
|
31
|
+
active: { ar: "انضم", en: "Joined" },
|
|
32
|
+
declined: { ar: "رفض", en: "Declined" },
|
|
33
|
+
left: { ar: "غادر", en: "Left" },
|
|
34
|
+
removed: { ar: "أزيل", en: "Removed" },
|
|
35
|
+
};
|
|
36
|
+
/** Statuses that still hold the number on the event (one row per number) */
|
|
37
|
+
export const EventHostOpenStatusValues = ["pending", "active"];
|
|
38
|
+
/** What the signed-in user is on an event */
|
|
39
|
+
export const EventAccessRoleValues = ["owner", "organiser", "guests"];
|
|
40
|
+
export const EventPermissionValues = [
|
|
41
|
+
/** See the event (drafts included) and its invitation link */
|
|
42
|
+
"event.view",
|
|
43
|
+
/** Details, names, date, timeline, dress code, design, photos, visibility, preview */
|
|
44
|
+
"event.edit",
|
|
45
|
+
/** Publish (pay), unpublish */
|
|
46
|
+
"event.publish",
|
|
47
|
+
"event.delete",
|
|
48
|
+
/** Guests: add, edit, remove, send links, read status, replies, check-in, guest reports */
|
|
49
|
+
"guests.manage",
|
|
50
|
+
/** Add/remove people of the event and change their role */
|
|
51
|
+
"hosts.manage",
|
|
52
|
+
];
|
|
53
|
+
export const EventRolePermissions = {
|
|
54
|
+
owner: EventPermissionValues,
|
|
55
|
+
organiser: EventPermissionValues,
|
|
56
|
+
guests: ["event.view", "guests.manage"],
|
|
57
|
+
};
|
|
58
|
+
export const hasEventPermission = (role, permission) => !!role && EventRolePermissions[role].includes(permission);
|
|
59
|
+
export const EventAccessRoleNames = {
|
|
60
|
+
owner: { ar: "المالك", en: "Owner" },
|
|
61
|
+
organiser: EventHostRoleNames.organiser,
|
|
62
|
+
guests: EventHostRoleNames.guests,
|
|
63
|
+
};
|
|
64
|
+
const slot = (key, ar, en, role, extra = {}) => ({ key, label: { ar, en }, role, ...extra });
|
|
65
|
+
const organiser = (ar = "المنظم", en = "Organiser") => slot("organiser", ar, en, "organiser", { mirrors: "occasion.phone" });
|
|
66
|
+
const weddingPeople = [
|
|
67
|
+
slot("bride", "العروس", "Bride", "guests", { mirrors: "wedding.bride_phone" }),
|
|
68
|
+
slot("groom", "العريس", "Groom", "guests", { mirrors: "wedding.groom_phone" }),
|
|
69
|
+
slot("organiser", "المنظم", "Organiser", "organiser"),
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Suggested people of each event type. The person the event is for manages guests;
|
|
73
|
+
* whoever organises or invites gets full control. Anyone else is added by hand.
|
|
74
|
+
*/
|
|
75
|
+
export const EventPeopleSlots = {
|
|
76
|
+
wedding: weddingPeople,
|
|
77
|
+
engagement: weddingPeople,
|
|
78
|
+
marriage: weddingPeople,
|
|
79
|
+
proposal: [
|
|
80
|
+
slot("proposer", "من سيطلب", "Who is proposing", "organiser"),
|
|
81
|
+
slot("partner", "الشريك", "Partner", "guests", { surprise_when_details_surprise: true }),
|
|
82
|
+
organiser(),
|
|
83
|
+
],
|
|
84
|
+
bachelor: [slot("celebrant", "العروس أو العريس", "Bride or groom", "guests"), organiser()],
|
|
85
|
+
birthday: [slot("celebrant", "صاحب عيد الميلاد", "Birthday person", "guests"), organiser("من يدعو", "Who is inviting")],
|
|
86
|
+
newborn: [slot("mother", "الأم", "Mother", "organiser", { mirrors: "occasion.phone" }), slot("father", "الأب", "Father", "organiser")],
|
|
87
|
+
gender_reveal: [slot("mother", "الأم", "Mother", "organiser", { mirrors: "occasion.phone" }), slot("father", "الأب", "Father", "organiser")],
|
|
88
|
+
circumcision: [slot("mother", "الأم", "Mother", "organiser", { mirrors: "occasion.phone" }), slot("father", "الأب", "Father", "organiser")],
|
|
89
|
+
graduation: [slot("graduate", "الخريج", "Graduate", "guests"), organiser("من يدعو", "Who is inviting")],
|
|
90
|
+
hajj: [
|
|
91
|
+
slot("pilgrim", "الحاج أو الحاجة", "Pilgrim", "guests"),
|
|
92
|
+
slot("pilgrim2", "الحاج الثاني", "Second pilgrim", "guests"),
|
|
93
|
+
organiser("من يدعو", "Who is inviting"),
|
|
94
|
+
],
|
|
95
|
+
mothers_day: [slot("mother", "الأم", "Mother", "guests"), organiser("من يدعو", "Who is inviting")],
|
|
96
|
+
valentine: [
|
|
97
|
+
slot("first", "الشخص الأول", "First person", "guests"),
|
|
98
|
+
slot("second", "الشخص الثاني", "Second person", "guests"),
|
|
99
|
+
organiser("من يدعو", "Who is inviting"),
|
|
100
|
+
],
|
|
101
|
+
opening: [slot("shop_owner", "صاحب المحل", "Business owner", "organiser", { mirrors: "occasion.phone" })],
|
|
102
|
+
general: [organiser()],
|
|
103
|
+
};
|
|
104
|
+
const DEFAULT_PEOPLE = [organiser()];
|
|
105
|
+
/** Suggested people of a type (a type without its own list gets the organiser only) */
|
|
106
|
+
export const findEventPeopleSlots = (eventType) => (eventType && EventPeopleSlots[eventType]) || DEFAULT_PEOPLE;
|
|
107
|
+
export const findEventPeopleSlot = (eventType, key) => key ? findEventPeopleSlots(eventType).find((s) => s.key === key) : undefined;
|
|
108
|
+
/** Answers to «من أنت في هذه المناسبة؟» besides the type's slots */
|
|
109
|
+
export const EventCreatorRoleExtra = {
|
|
110
|
+
COMPANY: "company",
|
|
111
|
+
OTHER: "other",
|
|
112
|
+
};
|
|
113
|
+
export const EventCreatorRoleExtraNames = {
|
|
114
|
+
company: { ar: "شركة", en: "A company" },
|
|
115
|
+
other: { ar: "شخص آخر", en: "Someone else" },
|
|
116
|
+
};
|
|
117
|
+
/** Label of the person a host row (or the creator) is: slot label, or the free text */
|
|
118
|
+
export const eventPersonLabel = (eventType, slotKey, fallback) => {
|
|
119
|
+
const s = findEventPeopleSlot(eventType, slotKey);
|
|
120
|
+
if (s)
|
|
121
|
+
return s.label;
|
|
122
|
+
if (slotKey === "company" || slotKey === "other")
|
|
123
|
+
return EventCreatorRoleExtraNames[slotKey];
|
|
124
|
+
return fallback ? { ar: fallback, en: fallback } : null;
|
|
125
|
+
};
|
|
126
|
+
export const EVENT_HOST_LABEL_MAX = 60;
|
|
127
|
+
/**
|
|
128
|
+
* One spelling for a phone number so numbers typed differently still match:
|
|
129
|
+
* digits only with a leading +, 00 → +, and no 0 right after a known country code.
|
|
130
|
+
*/
|
|
131
|
+
export const normalizeEventPhone = (value) => {
|
|
132
|
+
if (!value)
|
|
133
|
+
return null;
|
|
134
|
+
let digits = String(value).trim().replace(/[^\d+]/g, "");
|
|
135
|
+
if (digits.startsWith("00"))
|
|
136
|
+
digits = "+" + digits.slice(2);
|
|
137
|
+
if (!digits.startsWith("+"))
|
|
138
|
+
digits = "+" + digits.replace(/\+/g, "");
|
|
139
|
+
digits = "+" + digits.slice(1).replace(/\+/g, "");
|
|
140
|
+
for (const code of ["+963", "+971", "+965", "+961", "+90", "+966", "+962", "+974"]) {
|
|
141
|
+
if (digits.startsWith(code + "0")) {
|
|
142
|
+
digits = code + digits.slice(code.length + 1);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return digits.length > 4 ? digits : null;
|
|
147
|
+
};
|