@passly-nl/data 1.0.1 → 1.0.3
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/index.d.mts +185 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +11 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/adapter/EmailTemplateAdapter.ts +25 -0
- package/src/adapter/EventAdapter.ts +6 -1
- package/src/adapter/MerchantAdapter.ts +1 -0
- package/src/adapter/ProductAdapter.ts +3 -2
- package/src/adapter/PublicShopAdapter.ts +11 -2
- package/src/adapter/index.ts +1 -0
- package/src/dto/emailTemplate/EmailTemplateDto.ts +80 -0
- package/src/dto/emailTemplate/RenderedMailDto.ts +28 -0
- package/src/dto/emailTemplate/index.ts +2 -0
- package/src/dto/event/ShopElementInformationDto.ts +9 -0
- package/src/dto/event/index.ts +1 -0
- package/src/dto/index.ts +1 -0
- package/src/dto/merchant/MerchantUserDto.ts +12 -1
- package/src/dto/product/ProductDto.ts +12 -1
- package/src/dto/publicShop/PublicShopElementInformationDto.ts +9 -0
- package/src/dto/publicShop/PublicShopEventDto.ts +42 -1
- package/src/dto/publicShop/index.ts +1 -0
- package/src/service/AdminMerchantService.ts +15 -0
- package/src/service/AdminMerchantsService.ts +17 -0
- package/src/service/AdminService.ts +4 -0
- package/src/service/EmailTemplateEditorService.ts +285 -0
- package/src/service/MerchantContractService.ts +60 -0
- package/src/service/MerchantEmailTemplateService.ts +43 -0
- package/src/service/MerchantEmailTemplatesService.ts +31 -0
- package/src/service/MerchantEventEmailTemplateService.ts +43 -0
- package/src/service/MerchantEventEmailTemplatesService.ts +31 -0
- package/src/service/MerchantEventProductService.ts +3 -1
- package/src/service/MerchantEventProductsService.ts +4 -2
- package/src/service/MerchantUserService.ts +38 -0
- package/src/service/index.ts +10 -0
- package/src/types/auth.ts +3 -0
- package/src/types/emailTemplate.ts +10 -0
- package/src/types/emailTemplateEditor.ts +63 -0
- package/src/types/event.ts +1 -0
- package/src/types/index.ts +2 -0
- package/src/types/publicShop.ts +1 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import type { EmailTemplateType } from '../types/emailTemplate';
|
|
2
|
+
import type {
|
|
3
|
+
EmailTemplateEditorBlock,
|
|
4
|
+
EmailTemplateEditorButtonBlock,
|
|
5
|
+
EmailTemplateEditorCondition,
|
|
6
|
+
EmailTemplateEditorContext,
|
|
7
|
+
EmailTemplateEditorH1Block,
|
|
8
|
+
EmailTemplateEditorHeaderBlock,
|
|
9
|
+
EmailTemplateEditorIfBlock,
|
|
10
|
+
EmailTemplateEditorParagraphBlock,
|
|
11
|
+
EmailTemplateEditorVariable
|
|
12
|
+
} from '../types/emailTemplateEditor';
|
|
13
|
+
|
|
14
|
+
const SHARED_VARIABLES: EmailTemplateEditorVariable[] = [
|
|
15
|
+
{label: 'variable.merchantName', path: 'merchant.name'},
|
|
16
|
+
{label: 'variable.weekDay', path: 'weekDay'}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const BUYER_VARIABLES: EmailTemplateEditorVariable[] = [
|
|
20
|
+
{label: 'variable.buyerFirstName', path: 'buyer.firstName'},
|
|
21
|
+
{label: 'variable.buyerLastName', path: 'buyer.lastName'},
|
|
22
|
+
{label: 'variable.buyerFullName', path: 'buyer.fullName'},
|
|
23
|
+
{label: 'variable.buyerInitials', path: 'buyer.initials'},
|
|
24
|
+
{label: 'variable.buyerEmail', path: 'buyer.email'},
|
|
25
|
+
{label: 'variable.buyerPhoneNumber', path: 'buyer.phoneNumber'},
|
|
26
|
+
{label: 'variable.buyerDateOfBirth', path: 'buyer.dateOfBirth'},
|
|
27
|
+
{label: 'variable.buyerGender', path: 'buyer.gender'},
|
|
28
|
+
{label: 'variable.buyerLanguage', path: 'buyer.language'},
|
|
29
|
+
{label: 'variable.buyerAddressStreet', path: 'buyer.address.street'},
|
|
30
|
+
{label: 'variable.buyerAddressNumber', path: 'buyer.address.number'},
|
|
31
|
+
{label: 'variable.buyerAddressPostalCode', path: 'buyer.address.postalCode'},
|
|
32
|
+
{label: 'variable.buyerAddressCity', path: 'buyer.address.city'},
|
|
33
|
+
{label: 'variable.buyerAddressCountry', path: 'buyer.address.country'}
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const EVENT_VARIABLES: EmailTemplateEditorVariable[] = [
|
|
37
|
+
{label: 'variable.eventName', path: 'event.name'},
|
|
38
|
+
{label: 'variable.eventStartDate', path: 'event.startDate'},
|
|
39
|
+
{label: 'variable.eventStartTime', path: 'event.startTime'}
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const ORDER_VARIABLES: EmailTemplateEditorVariable[] = [
|
|
43
|
+
{label: 'variable.orderCode', path: 'order.code'}
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const HEADER_CONDITION: EmailTemplateEditorCondition = {label: 'condition.eventHasHeaderImage', condition: 'event.headerFile'};
|
|
47
|
+
|
|
48
|
+
export const EMAIL_TEMPLATE_EDITOR_CONTEXTS: Record<EmailTemplateType, EmailTemplateEditorContext> = {
|
|
49
|
+
merchant_invite: {
|
|
50
|
+
variables: [
|
|
51
|
+
...SHARED_VARIABLES,
|
|
52
|
+
{label: 'variable.userFirstName', path: 'user.firstName'},
|
|
53
|
+
{label: 'variable.userLastName', path: 'user.lastName'},
|
|
54
|
+
{label: 'variable.acceptUrl', path: 'acceptUrl'}
|
|
55
|
+
],
|
|
56
|
+
conditions: []
|
|
57
|
+
},
|
|
58
|
+
order_confirmation: {
|
|
59
|
+
variables: [...SHARED_VARIABLES, ...BUYER_VARIABLES, ...EVENT_VARIABLES, ...ORDER_VARIABLES],
|
|
60
|
+
conditions: [
|
|
61
|
+
{label: 'condition.hasNormalTicketsOnly', condition: 'hasNormalTicketsOnly'},
|
|
62
|
+
{label: 'condition.hasPersonalizableTickets', condition: 'hasPersonalizableTickets'},
|
|
63
|
+
{label: 'condition.hasSealedTickets', condition: 'hasSealedTickets'},
|
|
64
|
+
HEADER_CONDITION
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
personalization_invite: {
|
|
68
|
+
variables: [...SHARED_VARIABLES, ...BUYER_VARIABLES, ...EVENT_VARIABLES, {label: 'variable.personalizeUrl', path: 'personalizeUrl'}],
|
|
69
|
+
conditions: [HEADER_CONDITION]
|
|
70
|
+
},
|
|
71
|
+
personalization_request: {
|
|
72
|
+
variables: [...SHARED_VARIABLES, ...BUYER_VARIABLES, ...EVENT_VARIABLES, ...ORDER_VARIABLES, {label: 'variable.personalizeUrl', path: 'personalizeUrl'}],
|
|
73
|
+
conditions: [HEADER_CONDITION]
|
|
74
|
+
},
|
|
75
|
+
tickets: {
|
|
76
|
+
variables: [...SHARED_VARIABLES, ...BUYER_VARIABLES, ...EVENT_VARIABLES, ...ORDER_VARIABLES],
|
|
77
|
+
conditions: [HEADER_CONDITION]
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
interface ScanResult {
|
|
82
|
+
blocks: EmailTemplateEditorBlock[];
|
|
83
|
+
consumed: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Parses quoted or unquoted arguments from a Handlebars helper argument string.
|
|
88
|
+
* Returns an array of string values.
|
|
89
|
+
*/
|
|
90
|
+
function parseArgs(args: string): string[] {
|
|
91
|
+
const result: string[] = [];
|
|
92
|
+
let remaining = args.trim();
|
|
93
|
+
|
|
94
|
+
while (remaining.length > 0) {
|
|
95
|
+
if (remaining[0] === '"') {
|
|
96
|
+
const end = remaining.indexOf('"', 1);
|
|
97
|
+
if (end === -1) break;
|
|
98
|
+
result.push(remaining.slice(1, end));
|
|
99
|
+
remaining = remaining.slice(end + 1).trim();
|
|
100
|
+
} else {
|
|
101
|
+
const spaceIdx = remaining.search(/\s/);
|
|
102
|
+
if (spaceIdx === -1) {
|
|
103
|
+
result.push(remaining);
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
result.push(remaining.slice(0, spaceIdx));
|
|
107
|
+
remaining = remaining.slice(spaceIdx + 1).trim();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Builds a single EmailTemplateEditorBlock from a parsed Handlebars block.
|
|
116
|
+
*/
|
|
117
|
+
function buildBlock(
|
|
118
|
+
type: string,
|
|
119
|
+
args: string,
|
|
120
|
+
children: EmailTemplateEditorBlock[],
|
|
121
|
+
rawContent: string
|
|
122
|
+
): EmailTemplateEditorBlock | null {
|
|
123
|
+
const content = rawContent.trim().split('\n').map(line => line.replace(/^ {4}/, '')).join('\n');
|
|
124
|
+
|
|
125
|
+
switch (type) {
|
|
126
|
+
case 'h1':
|
|
127
|
+
return {type: 'h1', content} satisfies EmailTemplateEditorH1Block;
|
|
128
|
+
|
|
129
|
+
case 'paragraph':
|
|
130
|
+
return {type: 'paragraph', content} satisfies EmailTemplateEditorParagraphBlock;
|
|
131
|
+
|
|
132
|
+
case 'divider':
|
|
133
|
+
return {type: 'divider'};
|
|
134
|
+
|
|
135
|
+
case 'spacer':
|
|
136
|
+
return {type: 'spacer'};
|
|
137
|
+
|
|
138
|
+
case 'logo':
|
|
139
|
+
return {type: 'logo'};
|
|
140
|
+
|
|
141
|
+
case 'button': {
|
|
142
|
+
const [label = '', url = ''] = parseArgs(args);
|
|
143
|
+
return {type: 'button', label, url} satisfies EmailTemplateEditorButtonBlock;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
case 'header': {
|
|
147
|
+
const [src = ''] = parseArgs(args);
|
|
148
|
+
return {type: 'header', src} satisfies EmailTemplateEditorHeaderBlock;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
case 'if':
|
|
152
|
+
return {type: 'if', condition: args, children} satisfies EmailTemplateEditorIfBlock;
|
|
153
|
+
|
|
154
|
+
default:
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Recursively scans the template string starting from startPos, building blocks
|
|
161
|
+
* until a closing tag is found or the end of the string is reached.
|
|
162
|
+
*/
|
|
163
|
+
function scan(template: string, startPos: number = 0): ScanResult {
|
|
164
|
+
const blocks: EmailTemplateEditorBlock[] = [];
|
|
165
|
+
let pos = startPos;
|
|
166
|
+
|
|
167
|
+
while (pos < template.length) {
|
|
168
|
+
const tokenStart = template.indexOf('{{', pos);
|
|
169
|
+
if (tokenStart === -1) break;
|
|
170
|
+
|
|
171
|
+
const ch = template[tokenStart + 2];
|
|
172
|
+
|
|
173
|
+
// Partial {{> ...}} — skip
|
|
174
|
+
if (ch === '>') {
|
|
175
|
+
const end = template.indexOf('}}', tokenStart);
|
|
176
|
+
if (end === -1) break;
|
|
177
|
+
pos = end + 2;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Comment {{!-- ... --}} or {{! ...}} — skip
|
|
182
|
+
if (ch === '!') {
|
|
183
|
+
const end = template.indexOf('}}', tokenStart);
|
|
184
|
+
if (end === -1) break;
|
|
185
|
+
pos = end + 2;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Closing tag {{/type}} — return to parent scanner
|
|
190
|
+
if (ch === '/') {
|
|
191
|
+
return {blocks, consumed: tokenStart};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Opening block tag {{#type args}}
|
|
195
|
+
if (ch === '#') {
|
|
196
|
+
const closeTag = template.indexOf('}}', tokenStart);
|
|
197
|
+
if (closeTag === -1) break;
|
|
198
|
+
|
|
199
|
+
const tagContent = template.slice(tokenStart + 3, closeTag).trim();
|
|
200
|
+
const spaceIdx = tagContent.search(/\s/);
|
|
201
|
+
const type = spaceIdx === -1 ? tagContent : tagContent.slice(0, spaceIdx);
|
|
202
|
+
const args = spaceIdx === -1 ? '' : tagContent.slice(spaceIdx + 1).trim();
|
|
203
|
+
|
|
204
|
+
const innerStart = closeTag + 2;
|
|
205
|
+
const {blocks: children, consumed: innerEnd} = scan(template, innerStart);
|
|
206
|
+
const rawContent = template.slice(innerStart, innerEnd);
|
|
207
|
+
|
|
208
|
+
// Advance past the closing {{/type}} tag
|
|
209
|
+
const expectedClose = `{{/${type}}}`;
|
|
210
|
+
pos = innerEnd + expectedClose.length;
|
|
211
|
+
|
|
212
|
+
const block = buildBlock(type, args, children, rawContent);
|
|
213
|
+
if (block !== null) {
|
|
214
|
+
blocks.push(block);
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Variable or other expression — skip
|
|
220
|
+
const end = template.indexOf('}}', tokenStart);
|
|
221
|
+
if (end === -1) break;
|
|
222
|
+
pos = end + 2;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return {blocks, consumed: pos};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Serializes a single block back to its Handlebars string representation.
|
|
230
|
+
*/
|
|
231
|
+
function serializeBlock(block: EmailTemplateEditorBlock): string {
|
|
232
|
+
switch (block.type) {
|
|
233
|
+
case 'h1': {
|
|
234
|
+
const indented = block.content.split('\n').map(line => ` ${line}`).join('\n');
|
|
235
|
+
return `{{#h1}}\n${indented}\n{{/h1}}`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
case 'paragraph': {
|
|
239
|
+
const indented = block.content.split('\n').map(line => ` ${line}`).join('\n');
|
|
240
|
+
return `{{#paragraph}}\n${indented}\n{{/paragraph}}`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
case 'divider':
|
|
244
|
+
return `{{#divider}}{{/divider}}`;
|
|
245
|
+
|
|
246
|
+
case 'spacer':
|
|
247
|
+
return `{{#spacer}}{{/spacer}}`;
|
|
248
|
+
|
|
249
|
+
case 'logo':
|
|
250
|
+
return `{{#logo}}{{/logo}}`;
|
|
251
|
+
|
|
252
|
+
case 'button':
|
|
253
|
+
return `{{#button "${block.label}" "${block.url}"}}{{/button}}`;
|
|
254
|
+
|
|
255
|
+
case 'header': {
|
|
256
|
+
const srcArg = block.src.includes('://') ? `"${block.src}"` : block.src;
|
|
257
|
+
return `{{#header ${srcArg}}}{{/header}}`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
case 'if': {
|
|
261
|
+
const indented = serializeBlocks(block.children)
|
|
262
|
+
.split('\n')
|
|
263
|
+
.map(line => ` ${line}`)
|
|
264
|
+
.join('\n');
|
|
265
|
+
return `{{#if ${block.condition}}}\n${indented}\n{{/if}}`;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Parses a Handlebars template string into an array of editor blocks.
|
|
272
|
+
* Strips structure partials; only content blocks are returned.
|
|
273
|
+
*/
|
|
274
|
+
export function parseEmailTemplate(template: string): EmailTemplateEditorBlock[] {
|
|
275
|
+
const {blocks} = scan(template);
|
|
276
|
+
return blocks;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Serializes an array of editor blocks back into a Handlebars content string.
|
|
281
|
+
* Does not include structure partials — those are added by the backend automatically.
|
|
282
|
+
*/
|
|
283
|
+
export function serializeBlocks(blocks: EmailTemplateEditorBlock[]): string {
|
|
284
|
+
return blocks.map(serializeBlock).join('\n\n');
|
|
285
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { BaseResponse, BaseService, Paginated, QueryString } from '@basmilius/http-client';
|
|
2
|
+
import { MerchantAdapter } from '#data/adapter';
|
|
3
|
+
import type { ContractDto } from '#data/dto';
|
|
4
|
+
import type { DateTime } from 'luxon';
|
|
5
|
+
|
|
6
|
+
export class MerchantContractService extends BaseService {
|
|
7
|
+
async get(merchantId: string, offset: number, limit: number): Promise<BaseResponse<Paginated<ContractDto>>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/contracts`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.queryString(QueryString.builder()
|
|
13
|
+
.append('language', 'nl')
|
|
14
|
+
.append('offset', offset)
|
|
15
|
+
.append('limit', limit))
|
|
16
|
+
.runPaginatedAdapter(MerchantAdapter.parseContract);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async getSingle(merchantId: string, contractId: string): Promise<BaseResponse<ContractDto>> {
|
|
20
|
+
return await this
|
|
21
|
+
.request(`/merchants/${merchantId}/contracts/${contractId}`)
|
|
22
|
+
.method('get')
|
|
23
|
+
.bearerToken()
|
|
24
|
+
.queryString(QueryString.builder()
|
|
25
|
+
.append('language', 'nl'))
|
|
26
|
+
.runAdapter(MerchantAdapter.parseContract);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async post(merchantId: string, startsOn: DateTime, endsOn: DateTime, feeCents: number, remark: string): Promise<BaseResponse<ContractDto>> {
|
|
30
|
+
return await this
|
|
31
|
+
.request(`/merchants/${merchantId}/contracts`)
|
|
32
|
+
.method('post')
|
|
33
|
+
.bearerToken()
|
|
34
|
+
.queryString(QueryString.builder()
|
|
35
|
+
.append('language', 'nl'))
|
|
36
|
+
.body({
|
|
37
|
+
starts_on: startsOn.toISO(),
|
|
38
|
+
ends_on: endsOn.toISO(),
|
|
39
|
+
fee_cents: feeCents,
|
|
40
|
+
remark: remark || undefined
|
|
41
|
+
})
|
|
42
|
+
.runAdapter(MerchantAdapter.parseContract);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async put(merchantId: string, contractId: string, startsOn: DateTime, endsOn: DateTime, feeCents: number, remark: string): Promise<BaseResponse<ContractDto>> {
|
|
46
|
+
return await this
|
|
47
|
+
.request(`/merchants/${merchantId}/contracts/${contractId}`)
|
|
48
|
+
.method('put')
|
|
49
|
+
.bearerToken()
|
|
50
|
+
.queryString(QueryString.builder()
|
|
51
|
+
.append('language', 'nl'))
|
|
52
|
+
.body({
|
|
53
|
+
starts_on: startsOn.toISO(),
|
|
54
|
+
ends_on: endsOn.toISO(),
|
|
55
|
+
fee_cents: feeCents,
|
|
56
|
+
remark: remark || undefined
|
|
57
|
+
})
|
|
58
|
+
.runAdapter(MerchantAdapter.parseContract);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BaseResponse, BaseService } from '@basmilius/http-client';
|
|
2
|
+
import { CommonAdapter, EmailTemplateAdapter } from '#data/adapter';
|
|
3
|
+
import type { EmailTemplateDto, RenderedMailDto, StatusResponseDto } from '#data/dto';
|
|
4
|
+
import type { EmailTemplateLanguage } from '#data/types';
|
|
5
|
+
|
|
6
|
+
export class MerchantEmailTemplateService extends BaseService {
|
|
7
|
+
async getPreview(merchantId: string, emailTemplateId: string): Promise<BaseResponse<RenderedMailDto>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/email-templates/${emailTemplateId}/preview`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.runAdapter(EmailTemplateAdapter.parseRenderedMail);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async get(merchantId: string, emailTemplateId: string): Promise<BaseResponse<EmailTemplateDto>> {
|
|
16
|
+
return await this
|
|
17
|
+
.request(`/merchants/${merchantId}/email-templates/${emailTemplateId}`)
|
|
18
|
+
.method('get')
|
|
19
|
+
.bearerToken()
|
|
20
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async patch(merchantId: string, emailTemplateId: string, subject: string, content: string, language: EmailTemplateLanguage | null = null): Promise<BaseResponse<EmailTemplateDto>> {
|
|
24
|
+
return await this
|
|
25
|
+
.request(`/merchants/${merchantId}/email-templates/${emailTemplateId}`)
|
|
26
|
+
.method('patch')
|
|
27
|
+
.bearerToken()
|
|
28
|
+
.body({
|
|
29
|
+
subject,
|
|
30
|
+
content,
|
|
31
|
+
language
|
|
32
|
+
})
|
|
33
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async delete(merchantId: string, emailTemplateId: string): Promise<BaseResponse<StatusResponseDto>> {
|
|
37
|
+
return await this
|
|
38
|
+
.request(`/merchants/${merchantId}/email-templates/${emailTemplateId}`)
|
|
39
|
+
.method('delete')
|
|
40
|
+
.bearerToken()
|
|
41
|
+
.runAdapter(CommonAdapter.parseStatusResponse);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseResponse, BaseService, Paginated, QueryString } from '@basmilius/http-client';
|
|
2
|
+
import { EmailTemplateAdapter } from '#data/adapter';
|
|
3
|
+
import type { EmailTemplateDto } from '#data/dto';
|
|
4
|
+
import type { EmailTemplateLanguage, EmailTemplateType } from '#data/types';
|
|
5
|
+
|
|
6
|
+
export class MerchantEmailTemplatesService extends BaseService {
|
|
7
|
+
async get(merchantId: string, offset: number, limit: number): Promise<BaseResponse<Paginated<EmailTemplateDto>>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/email-templates`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.queryString(QueryString.builder()
|
|
13
|
+
.append('offset', offset)
|
|
14
|
+
.append('limit', limit))
|
|
15
|
+
.runPaginatedAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async post(merchantId: string, type: EmailTemplateType, subject: string, content: string, language: EmailTemplateLanguage | null = null): Promise<BaseResponse<EmailTemplateDto>> {
|
|
19
|
+
return await this
|
|
20
|
+
.request(`/merchants/${merchantId}/email-templates`)
|
|
21
|
+
.method('post')
|
|
22
|
+
.bearerToken()
|
|
23
|
+
.body({
|
|
24
|
+
type,
|
|
25
|
+
subject,
|
|
26
|
+
content,
|
|
27
|
+
language
|
|
28
|
+
})
|
|
29
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BaseResponse, BaseService } from '@basmilius/http-client';
|
|
2
|
+
import { CommonAdapter, EmailTemplateAdapter } from '#data/adapter';
|
|
3
|
+
import type { EmailTemplateDto, RenderedMailDto, StatusResponseDto } from '#data/dto';
|
|
4
|
+
import type { EmailTemplateLanguage } from '#data/types';
|
|
5
|
+
|
|
6
|
+
export class MerchantEventEmailTemplateService extends BaseService {
|
|
7
|
+
async getPreview(merchantId: string, eventId: string, emailTemplateId: string): Promise<BaseResponse<RenderedMailDto>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates/${emailTemplateId}/preview`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.runAdapter(EmailTemplateAdapter.parseRenderedMail);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async get(merchantId: string, eventId: string, emailTemplateId: string): Promise<BaseResponse<EmailTemplateDto>> {
|
|
16
|
+
return await this
|
|
17
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates/${emailTemplateId}`)
|
|
18
|
+
.method('get')
|
|
19
|
+
.bearerToken()
|
|
20
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async patch(merchantId: string, eventId: string, emailTemplateId: string, subject: string, content: string, language: EmailTemplateLanguage | null = null): Promise<BaseResponse<EmailTemplateDto>> {
|
|
24
|
+
return await this
|
|
25
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates/${emailTemplateId}`)
|
|
26
|
+
.method('patch')
|
|
27
|
+
.bearerToken()
|
|
28
|
+
.body({
|
|
29
|
+
subject,
|
|
30
|
+
content,
|
|
31
|
+
language
|
|
32
|
+
})
|
|
33
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async delete(merchantId: string, eventId: string, emailTemplateId: string): Promise<BaseResponse<StatusResponseDto>> {
|
|
37
|
+
return await this
|
|
38
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates/${emailTemplateId}`)
|
|
39
|
+
.method('delete')
|
|
40
|
+
.bearerToken()
|
|
41
|
+
.runAdapter(CommonAdapter.parseStatusResponse);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseResponse, BaseService, Paginated, QueryString } from '@basmilius/http-client';
|
|
2
|
+
import { EmailTemplateAdapter } from '#data/adapter';
|
|
3
|
+
import type { EmailTemplateDto } from '#data/dto';
|
|
4
|
+
import type { EmailTemplateLanguage, EmailTemplateType } from '#data/types';
|
|
5
|
+
|
|
6
|
+
export class MerchantEventEmailTemplatesService extends BaseService {
|
|
7
|
+
async get(merchantId: string, eventId: string, offset: number, limit: number): Promise<BaseResponse<Paginated<EmailTemplateDto>>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.queryString(QueryString.builder()
|
|
13
|
+
.append('offset', offset)
|
|
14
|
+
.append('limit', limit))
|
|
15
|
+
.runPaginatedAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async post(merchantId: string, eventId: string, type: EmailTemplateType, subject: string, content: string, language: EmailTemplateLanguage | null = null): Promise<BaseResponse<EmailTemplateDto>> {
|
|
19
|
+
return await this
|
|
20
|
+
.request(`/merchants/${merchantId}/events/${eventId}/email-templates`)
|
|
21
|
+
.method('post')
|
|
22
|
+
.bearerToken()
|
|
23
|
+
.body({
|
|
24
|
+
type,
|
|
25
|
+
subject,
|
|
26
|
+
content,
|
|
27
|
+
language
|
|
28
|
+
})
|
|
29
|
+
.runAdapter(EmailTemplateAdapter.parseEmailTemplate);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseResponse, BaseService, QueryString } from '@basmilius/http-client';
|
|
2
|
+
import type { DateTime } from 'luxon';
|
|
2
3
|
import { ProductAdapter } from '#data/adapter';
|
|
3
4
|
import type { ProductDto } from '#data/dto';
|
|
4
5
|
|
|
@@ -39,7 +40,8 @@ export class MerchantEventProductService extends BaseService {
|
|
|
39
40
|
description: product.description,
|
|
40
41
|
price: product.price.cents,
|
|
41
42
|
max_quantity: product.maxQuantity,
|
|
42
|
-
is_swappable: product.isSwappable
|
|
43
|
+
is_swappable: product.isSwappable,
|
|
44
|
+
tickets_released_on: product.ticketsReleasedOn?.toISO() ?? null
|
|
43
45
|
})
|
|
44
46
|
.runAdapter(ProductAdapter.parseProduct);
|
|
45
47
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseResponse, BaseService, Paginated, QueryString } from '@basmilius/http-client';
|
|
2
2
|
import type { FluxFormSelectEntry } from '@flux-ui/types';
|
|
3
|
+
import type { DateTime } from 'luxon';
|
|
3
4
|
import { FluxAdapter, ProductAdapter } from '#data/adapter';
|
|
4
5
|
import type { ProductDto } from '#data/dto';
|
|
5
6
|
|
|
@@ -28,7 +29,7 @@ export class MerchantEventProductsService extends BaseService {
|
|
|
28
29
|
.runArrayAdapter(FluxAdapter.parseFluxFormSelectEntry);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
async post(merchantId: string, eventId: string, name: string, description: string, price: number, maxQuantity: number, stock: number | null, stockPoolId: string | null): Promise<BaseResponse<ProductDto>> {
|
|
32
|
+
async post(merchantId: string, eventId: string, name: string, description: string, price: number, maxQuantity: number, stock: number | null, stockPoolId: string | null, ticketsReleasedOn: DateTime | null = null): Promise<BaseResponse<ProductDto>> {
|
|
32
33
|
return await this
|
|
33
34
|
.request(`/merchants/${merchantId}/events/${eventId}/products`)
|
|
34
35
|
.method('post')
|
|
@@ -41,7 +42,8 @@ export class MerchantEventProductsService extends BaseService {
|
|
|
41
42
|
price,
|
|
42
43
|
stock,
|
|
43
44
|
max_quantity: maxQuantity,
|
|
44
|
-
stock_pool_id: stockPoolId
|
|
45
|
+
stock_pool_id: stockPoolId,
|
|
46
|
+
tickets_released_on: ticketsReleasedOn?.toISO() ?? null
|
|
45
47
|
})
|
|
46
48
|
.runAdapter(ProductAdapter.parseProduct);
|
|
47
49
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BaseResponse, BaseService, QueryString } from '@basmilius/http-client';
|
|
2
|
+
import { MerchantAdapter } from '#data/adapter';
|
|
3
|
+
import type { MerchantUserDto } from '#data/dto';
|
|
4
|
+
import type { Claim } from '#data/types';
|
|
5
|
+
|
|
6
|
+
export class MerchantUserService extends BaseService {
|
|
7
|
+
async get(merchantId: string, userId: string): Promise<BaseResponse<MerchantUserDto>> {
|
|
8
|
+
return await this
|
|
9
|
+
.request(`/merchants/${merchantId}/users/${userId}`)
|
|
10
|
+
.method('get')
|
|
11
|
+
.bearerToken()
|
|
12
|
+
.queryString(QueryString.builder()
|
|
13
|
+
.append('language', 'nl'))
|
|
14
|
+
.runAdapter(MerchantAdapter.parseMerchantUser);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async put(merchantId: string, userId: string, isManager: boolean, claims: Claim[]): Promise<BaseResponse<MerchantUserDto>> {
|
|
18
|
+
return await this
|
|
19
|
+
.request(`/merchants/${merchantId}/users/${userId}`)
|
|
20
|
+
.method('put')
|
|
21
|
+
.bearerToken()
|
|
22
|
+
.queryString(QueryString.builder()
|
|
23
|
+
.append('language', 'nl'))
|
|
24
|
+
.body({
|
|
25
|
+
is_manager: isManager,
|
|
26
|
+
claims
|
|
27
|
+
})
|
|
28
|
+
.runAdapter(MerchantAdapter.parseMerchantUser);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async remove(merchantId: string, userId: string): Promise<BaseResponse<void>> {
|
|
32
|
+
return await this
|
|
33
|
+
.request(`/merchants/${merchantId}/users/${userId}`)
|
|
34
|
+
.method('delete')
|
|
35
|
+
.bearerToken()
|
|
36
|
+
.runEmpty();
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/service/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
export * from './AdminService';
|
|
2
|
+
export * from './AdminMerchantService';
|
|
3
|
+
export * from './AdminMerchantsService';
|
|
1
4
|
export * from './AuthService';
|
|
2
5
|
export * from './InvitationService';
|
|
3
6
|
export * from './MerchantService';
|
|
4
7
|
export * from './MerchantsService';
|
|
8
|
+
export * from './MerchantContractService';
|
|
5
9
|
export * from './MerchantBuyerService';
|
|
6
10
|
export * from './MerchantBuyersService';
|
|
7
11
|
export * from './MerchantDashboardService';
|
|
@@ -16,6 +20,10 @@ export * from './MerchantEventShopsService';
|
|
|
16
20
|
export * from './MerchantEventStockPoolsService';
|
|
17
21
|
export * from './MerchantEventTicketTemplateService';
|
|
18
22
|
export * from './MerchantEventTicketTemplatesService';
|
|
23
|
+
export * from './MerchantEmailTemplateService';
|
|
24
|
+
export * from './MerchantEmailTemplatesService';
|
|
25
|
+
export * from './MerchantEventEmailTemplateService';
|
|
26
|
+
export * from './MerchantEventEmailTemplatesService';
|
|
19
27
|
export * from './MerchantEventsService';
|
|
20
28
|
export * from './MerchantFinanceInvoiceService';
|
|
21
29
|
export * from './MerchantFinanceInvoicesService';
|
|
@@ -31,10 +39,12 @@ export * from './MerchantStatisticsOverviewService';
|
|
|
31
39
|
export * from './MerchantStatisticsSalesService';
|
|
32
40
|
export * from './MerchantTicketService';
|
|
33
41
|
export * from './MerchantTicketsService';
|
|
42
|
+
export * from './MerchantUserService';
|
|
34
43
|
export * from './MerchantUsersService';
|
|
35
44
|
export * from './MeService';
|
|
36
45
|
export * from './PublicOrderService';
|
|
37
46
|
export * from './PublicShopService';
|
|
38
47
|
export * from './ReservationService';
|
|
39
48
|
export * from './ServicesService';
|
|
49
|
+
export * from './EmailTemplateEditorService';
|
|
40
50
|
export * from './UiSelectOptionsService';
|
package/src/types/auth.ts
CHANGED