@dev.smartpricing/message-composer-layer 4.2.5 → 4.2.6-brands.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/api/brands.ts +1 -1
- package/app/components/Brand/BrandDrawer.vue +44 -2
- package/app/components/Brand/Steps/BrandStepContactInfo.vue +87 -0
- package/app/components/Brand/Steps/BrandStepGeneral.vue +37 -4
- package/app/components/Email/Editor/Blocks/ButtonBlock.vue +2 -2
- package/app/components/Email/Editor/Blocks/DiscountCodeBlock.vue +5 -4
- package/app/components/Email/Editor/Blocks/DividerBlock.vue +0 -1
- package/app/components/Email/Editor/Blocks/FooterBlock.vue +1 -1
- package/app/components/Email/Editor/Blocks/GridBlock.vue +6 -10
- package/app/components/Email/Editor/Blocks/HeadingBlock.vue +1 -1
- package/app/components/Email/Editor/Blocks/IndexBlock.vue +14 -3
- package/app/components/Email/Editor/Blocks/ParagraphBlock.vue +1 -1
- package/app/components/Email/Editor/Blocks/UnsubscribeLinkBlock.vue +1 -1
- package/app/components/Email/SendTestEmailModal.vue +11 -1
- package/i18n/locales/de.ts +674 -686
- package/i18n/locales/en.ts +673 -685
- package/i18n/locales/es.ts +678 -690
- package/i18n/locales/fr.ts +681 -693
- package/i18n/locales/it.ts +675 -687
- package/package.json +7 -3
- package/i18n/check-translations.ts +0 -56
package/app/api/brands.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const brandsApi = {
|
|
|
21
21
|
if (options?.sort_by) params.set('sort_by', options.sort_by)
|
|
22
22
|
if (options?.direction) params.set('direction', options.direction)
|
|
23
23
|
const query = params.size ? `?${params.toString()}` : ''
|
|
24
|
-
return apiClient<
|
|
24
|
+
return apiClient<BrandWithProperties[]>(`/brands${query}`)
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
getById: (id: string) => apiClient<BrandWithProperties>(`/brands/${id}`),
|
|
@@ -6,13 +6,15 @@ import type {
|
|
|
6
6
|
BrandDefaultButtonSettings,
|
|
7
7
|
BrandCreateBody,
|
|
8
8
|
BrandSocials,
|
|
9
|
+
BrandData,
|
|
9
10
|
} from '@dev.smartpricing/message-composer-utils/types'
|
|
10
|
-
import { isValidUrl } from '@dev.smartpricing/message-composer-utils/utils'
|
|
11
|
+
import { isValidUrl, isEmail } from '@dev.smartpricing/message-composer-utils/utils'
|
|
11
12
|
import type { BrandCascadeData } from '@dev.smartpricing/message-composer-utils/utils'
|
|
12
13
|
import type { BrandWithProperties } from '~/api/brands'
|
|
13
14
|
import BrandPreview from '~/components/Brand/BrandPreview.vue'
|
|
14
15
|
import BrandStepGeneral from '~/components/Brand/Steps/BrandStepGeneral.vue'
|
|
15
16
|
import BrandStepVisual from '~/components/Brand/Steps/BrandStepVisual.vue'
|
|
17
|
+
import BrandStepContactInfo from '~/components/Brand/Steps/BrandStepContactInfo.vue'
|
|
16
18
|
import BrandStepSocials from '~/components/Brand/Steps/BrandStepSocials.vue'
|
|
17
19
|
import { useBrandQuery, useCreateBrandMutation, useUpdateBrandMutation } from '~/queries'
|
|
18
20
|
import type { BrandCreateResponse } from '~/api/brands'
|
|
@@ -48,7 +50,7 @@ const isSaving = computed(() => isCreating.value || isUpdating.value)
|
|
|
48
50
|
// ============================================================================
|
|
49
51
|
// NAVIGATION
|
|
50
52
|
// ============================================================================
|
|
51
|
-
type Step = 'general' | 'visual' | 'socials'
|
|
53
|
+
type Step = 'general' | 'visual' | 'contact_info' | 'socials'
|
|
52
54
|
const activeStep = ref<Step>('general')
|
|
53
55
|
|
|
54
56
|
const navItems = computed<NavigationMenuItem[]>(() => [
|
|
@@ -68,6 +70,14 @@ const navItems = computed<NavigationMenuItem[]>(() => [
|
|
|
68
70
|
activeStep.value = 'visual'
|
|
69
71
|
},
|
|
70
72
|
},
|
|
73
|
+
{
|
|
74
|
+
label: t('pages.brands.steps.contact_info'),
|
|
75
|
+
icon: 'ph:address-book',
|
|
76
|
+
active: activeStep.value === 'contact_info',
|
|
77
|
+
onSelect: () => {
|
|
78
|
+
activeStep.value = 'contact_info'
|
|
79
|
+
},
|
|
80
|
+
},
|
|
71
81
|
{
|
|
72
82
|
label: t('pages.brands.steps.socials'),
|
|
73
83
|
icon: 'ph:share-network',
|
|
@@ -99,6 +109,7 @@ const defaultButtonSettings = ref<BrandDefaultButtonSettings>({
|
|
|
99
109
|
backgroundColor: '#000000',
|
|
100
110
|
})
|
|
101
111
|
|
|
112
|
+
const data = ref<BrandData>({})
|
|
102
113
|
const socials = ref<BrandSocials>({})
|
|
103
114
|
|
|
104
115
|
// ============================================================================
|
|
@@ -124,6 +135,7 @@ function populateForm(brand: BrandWithProperties) {
|
|
|
124
135
|
colors.value = [...brand.colors]
|
|
125
136
|
defaultEmailSettings.value = { ...brand.default_email_settings }
|
|
126
137
|
defaultButtonSettings.value = { ...brand.default_button_settings }
|
|
138
|
+
data.value = brand.data ? { ...brand.data } : {}
|
|
127
139
|
socials.value = brand.default_socials ? { ...brand.default_socials } : {}
|
|
128
140
|
}
|
|
129
141
|
|
|
@@ -143,6 +155,7 @@ function resetForm() {
|
|
|
143
155
|
textColor: '#FFFFFF',
|
|
144
156
|
backgroundColor: '#000000',
|
|
145
157
|
}
|
|
158
|
+
data.value = {}
|
|
146
159
|
socials.value = {}
|
|
147
160
|
activeStep.value = 'general'
|
|
148
161
|
}
|
|
@@ -151,6 +164,13 @@ watch(isOpen, (val) => {
|
|
|
151
164
|
if (!val) resetForm()
|
|
152
165
|
})
|
|
153
166
|
|
|
167
|
+
// Pre-fill data.name with brand display name on create only
|
|
168
|
+
watch(activeStep, (step) => {
|
|
169
|
+
if (step === 'contact_info' && !isEditMode.value && !data.value.name && name.value.trim()) {
|
|
170
|
+
data.value = { ...data.value, name: name.value.trim() }
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
154
174
|
// ============================================================================
|
|
155
175
|
// PREVIEW DATA
|
|
156
176
|
// ============================================================================
|
|
@@ -159,6 +179,7 @@ const brandCascadeData = computed<BrandCascadeData>(() => ({
|
|
|
159
179
|
default_button_settings: defaultButtonSettings.value,
|
|
160
180
|
default_socials: socials.value,
|
|
161
181
|
logo_url: logoUrl.value || null,
|
|
182
|
+
data: data.value,
|
|
162
183
|
}))
|
|
163
184
|
|
|
164
185
|
// ============================================================================
|
|
@@ -168,6 +189,13 @@ function hasInvalidSocialUrls(): boolean {
|
|
|
168
189
|
return Object.values(socials.value).some((url) => !!url && !isValidUrl(url))
|
|
169
190
|
}
|
|
170
191
|
|
|
192
|
+
function hasInvalidContactInfo(): boolean {
|
|
193
|
+
const d = data.value
|
|
194
|
+
if (d.website && !isValidUrl(d.website)) return true
|
|
195
|
+
if (d.email && !isEmail(d.email)) return true
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
|
|
171
199
|
async function handleSave() {
|
|
172
200
|
if (!name.value.trim()) {
|
|
173
201
|
useToast().add({
|
|
@@ -178,6 +206,15 @@ async function handleSave() {
|
|
|
178
206
|
return
|
|
179
207
|
}
|
|
180
208
|
|
|
209
|
+
if (hasInvalidContactInfo()) {
|
|
210
|
+
useToast().add({
|
|
211
|
+
color: 'error',
|
|
212
|
+
title: t('pages.brands.validation.invalid_contact_info'),
|
|
213
|
+
})
|
|
214
|
+
activeStep.value = 'contact_info'
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
181
218
|
if (hasInvalidSocialUrls()) {
|
|
182
219
|
useToast().add({
|
|
183
220
|
color: 'error',
|
|
@@ -194,6 +231,7 @@ async function handleSave() {
|
|
|
194
231
|
default_email_settings: defaultEmailSettings.value,
|
|
195
232
|
default_button_settings: defaultButtonSettings.value,
|
|
196
233
|
default_socials: socials.value,
|
|
234
|
+
data: data.value,
|
|
197
235
|
property_ids: selectedPropertyIds.value,
|
|
198
236
|
}
|
|
199
237
|
|
|
@@ -221,6 +259,7 @@ async function handleSave() {
|
|
|
221
259
|
changedFields.push('button_settings')
|
|
222
260
|
if (JSON.stringify(payload.default_socials) !== JSON.stringify(brand.default_socials))
|
|
223
261
|
changedFields.push('socials')
|
|
262
|
+
if (JSON.stringify(payload.data) !== JSON.stringify(brand.data)) changedFields.push('data')
|
|
224
263
|
if (
|
|
225
264
|
JSON.stringify(payload.property_ids) !==
|
|
226
265
|
JSON.stringify(brand.properties?.map((bp) => bp.property_id))
|
|
@@ -291,6 +330,7 @@ async function handleSave() {
|
|
|
291
330
|
v-if="activeStep === 'general'"
|
|
292
331
|
v-model:name="name"
|
|
293
332
|
v-model:selected-property-ids="selectedPropertyIds"
|
|
333
|
+
:brand-id="brandId"
|
|
294
334
|
/>
|
|
295
335
|
|
|
296
336
|
<BrandStepVisual
|
|
@@ -302,6 +342,8 @@ async function handleSave() {
|
|
|
302
342
|
v-model:default-button-settings="defaultButtonSettings"
|
|
303
343
|
/>
|
|
304
344
|
|
|
345
|
+
<BrandStepContactInfo v-if="activeStep === 'contact_info'" v-model="data" />
|
|
346
|
+
|
|
305
347
|
<BrandStepSocials v-if="activeStep === 'socials'" v-model="socials" />
|
|
306
348
|
</div>
|
|
307
349
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { BrandData } from '@dev.smartpricing/message-composer-utils/types'
|
|
3
|
+
import { isValidUrl, isEmail } from '@dev.smartpricing/message-composer-utils/utils'
|
|
4
|
+
|
|
5
|
+
const data = defineModel<BrandData>({ required: true })
|
|
6
|
+
|
|
7
|
+
const { t, locale } = useI18n()
|
|
8
|
+
|
|
9
|
+
const touched = ref<Partial<Record<string, boolean>>>({})
|
|
10
|
+
|
|
11
|
+
function update(field: keyof BrandData, value: string) {
|
|
12
|
+
const trimmed = value.trim()
|
|
13
|
+
data.value = {
|
|
14
|
+
...data.value,
|
|
15
|
+
[field]: trimmed || undefined,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function onBlur(field: string) {
|
|
20
|
+
const value = data.value[field as keyof BrandData]
|
|
21
|
+
if (value) {
|
|
22
|
+
touched.value = { ...touched.value, [field]: true }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function fieldError(field: string): string | undefined {
|
|
27
|
+
const value = data.value[field as keyof BrandData]
|
|
28
|
+
if (!value || !touched.value[field]) return undefined
|
|
29
|
+
|
|
30
|
+
if (field === 'website') {
|
|
31
|
+
return isValidUrl(value) ? undefined : t('pages.brands.validation.invalid_url_format')
|
|
32
|
+
}
|
|
33
|
+
if (field === 'email') {
|
|
34
|
+
return isEmail(value) ? undefined : t('pages.brands.validation.invalid_email_format')
|
|
35
|
+
}
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<template>
|
|
41
|
+
<div class="space-y-4">
|
|
42
|
+
<UFormField :label="t('pages.brands.fields.contact_name')">
|
|
43
|
+
<UInput
|
|
44
|
+
:model-value="data.name ?? ''"
|
|
45
|
+
:placeholder="t('pages.brands.fields.contact_name_placeholder')"
|
|
46
|
+
@update:model-value="update('name', $event as string)"
|
|
47
|
+
/>
|
|
48
|
+
</UFormField>
|
|
49
|
+
|
|
50
|
+
<UFormField :label="t('pages.brands.fields.contact_address')">
|
|
51
|
+
<UInput
|
|
52
|
+
:model-value="data.address ?? ''"
|
|
53
|
+
:placeholder="t('pages.brands.fields.contact_address_placeholder')"
|
|
54
|
+
@update:model-value="update('address', $event as string)"
|
|
55
|
+
/>
|
|
56
|
+
</UFormField>
|
|
57
|
+
|
|
58
|
+
<UFormField :label="t('pages.brands.fields.contact_telephone')">
|
|
59
|
+
<SPhoneInput
|
|
60
|
+
class="w-full"
|
|
61
|
+
:model-value="data.telephone ?? ''"
|
|
62
|
+
:locale="locale"
|
|
63
|
+
@update:model-value="update('telephone', $event as string)"
|
|
64
|
+
/>
|
|
65
|
+
</UFormField>
|
|
66
|
+
|
|
67
|
+
<UFormField :label="t('pages.brands.fields.contact_email')" :error="fieldError('email')">
|
|
68
|
+
<UInput
|
|
69
|
+
:model-value="data.email ?? ''"
|
|
70
|
+
:placeholder="t('pages.brands.fields.contact_email_placeholder')"
|
|
71
|
+
:color="fieldError('email') ? 'error' : undefined"
|
|
72
|
+
@update:model-value="update('email', $event as string)"
|
|
73
|
+
@blur="onBlur('email')"
|
|
74
|
+
/>
|
|
75
|
+
</UFormField>
|
|
76
|
+
|
|
77
|
+
<UFormField :label="t('pages.brands.fields.contact_website')" :error="fieldError('website')">
|
|
78
|
+
<UInput
|
|
79
|
+
:model-value="data.website ?? ''"
|
|
80
|
+
:placeholder="t('pages.brands.fields.contact_website_placeholder')"
|
|
81
|
+
:color="fieldError('website') ? 'error' : undefined"
|
|
82
|
+
@update:model-value="update('website', $event as string)"
|
|
83
|
+
@blur="onBlur('website')"
|
|
84
|
+
/>
|
|
85
|
+
</UFormField>
|
|
86
|
+
</div>
|
|
87
|
+
</template>
|
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { Property } from '@dev.smartpricing/message-composer-utils/types'
|
|
3
|
-
import { usePropertiesQuery } from '~/queries'
|
|
3
|
+
import { useBrandsQuery, usePropertiesQuery } from '~/queries'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
brandId?: string
|
|
7
|
+
}>()
|
|
4
8
|
|
|
5
9
|
const name = defineModel<string>('name', { required: true })
|
|
6
10
|
const selectedPropertyIds = defineModel<string[]>('selectedPropertyIds', { required: true })
|
|
7
11
|
|
|
12
|
+
const { t } = useI18n()
|
|
13
|
+
|
|
8
14
|
const { data: properties } = usePropertiesQuery()
|
|
15
|
+
const { data: brands } = useBrandsQuery()
|
|
16
|
+
|
|
17
|
+
/** Map of property_id → brand name, excluding the brand currently being edited */
|
|
18
|
+
const takenPropertyMap = computed(() => {
|
|
19
|
+
const map = new Map<string, string>()
|
|
20
|
+
for (const brand of brands.value ?? []) {
|
|
21
|
+
if (brand.id === props.brandId) continue
|
|
22
|
+
for (const bp of brand.properties ?? []) {
|
|
23
|
+
map.set(bp.property_id, brand.name)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return map
|
|
27
|
+
})
|
|
9
28
|
|
|
10
29
|
const propertyItems = computed(() =>
|
|
11
30
|
(properties.value ?? []).map((p: Property) => ({
|
|
12
31
|
label: p.name,
|
|
13
32
|
value: p.id,
|
|
33
|
+
disabled: takenPropertyMap.value.has(p.id),
|
|
34
|
+
takenByBrand: takenPropertyMap.value.get(p.id),
|
|
14
35
|
})),
|
|
15
36
|
)
|
|
16
37
|
</script>
|
|
@@ -24,7 +45,7 @@ const propertyItems = computed(() =>
|
|
|
24
45
|
/>
|
|
25
46
|
</UFormField>
|
|
26
47
|
|
|
27
|
-
|
|
48
|
+
<UFormField :label="$t('pages.brands.fields.properties')">
|
|
28
49
|
<USelectMenu
|
|
29
50
|
v-model="selectedPropertyIds"
|
|
30
51
|
:items="propertyItems"
|
|
@@ -32,6 +53,18 @@ const propertyItems = computed(() =>
|
|
|
32
53
|
value-key="value"
|
|
33
54
|
:placeholder="$t('pages.brands.fields.properties_placeholder')"
|
|
34
55
|
class="w-full"
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
>
|
|
57
|
+
<template #item-label="{ item }">
|
|
58
|
+
<UTooltip
|
|
59
|
+
v-if="item.disabled"
|
|
60
|
+
:text="t('pages.brands.fields.property_taken_tooltip', { brand: item.takenByBrand })"
|
|
61
|
+
>
|
|
62
|
+
<span class="text-muted">
|
|
63
|
+
{{ item.label }}
|
|
64
|
+
</span>
|
|
65
|
+
</UTooltip>
|
|
66
|
+
<span v-else>{{ item.label }}</span>
|
|
67
|
+
</template>
|
|
68
|
+
</USelectMenu>
|
|
69
|
+
</UFormField>
|
|
37
70
|
</template>
|
|
@@ -44,7 +44,7 @@ const buttonStyles = computed(() => {
|
|
|
44
44
|
props.block.settings.shape === 'square'
|
|
45
45
|
? '0px'
|
|
46
46
|
: props.block.settings.shape === 'rounded'
|
|
47
|
-
? '
|
|
47
|
+
? '4px'
|
|
48
48
|
: '50px',
|
|
49
49
|
padding: '12px 24px',
|
|
50
50
|
border: 'none',
|
|
@@ -69,7 +69,7 @@ const containerStyles = computed(() => ({
|
|
|
69
69
|
: props.block.settings.alignment === 'center'
|
|
70
70
|
? 'center'
|
|
71
71
|
: 'flex-end',
|
|
72
|
-
padding: '
|
|
72
|
+
padding: '0',
|
|
73
73
|
}))
|
|
74
74
|
|
|
75
75
|
defineOptions({
|
|
@@ -35,15 +35,16 @@ const discountCodeStyles = computed(() => {
|
|
|
35
35
|
props.block.settings.style === 'square'
|
|
36
36
|
? '0px'
|
|
37
37
|
: props.block.settings.style === 'rounded'
|
|
38
|
-
? '
|
|
38
|
+
? '4px'
|
|
39
39
|
: '50px',
|
|
40
|
-
padding: '
|
|
40
|
+
padding: '12px 8px',
|
|
41
41
|
textAlign: 'center',
|
|
42
|
-
display: 'inline-block',
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
if (props.block.settings.width === 'full_width') {
|
|
46
45
|
styles.width = '100%'
|
|
46
|
+
} else {
|
|
47
|
+
styles.display = 'inline-block'
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
return styles
|
|
@@ -52,7 +53,7 @@ const discountCodeStyles = computed(() => {
|
|
|
52
53
|
const containerStyles = computed(() => {
|
|
53
54
|
return {
|
|
54
55
|
backgroundColor: props.block.settings.backgroundBlock,
|
|
55
|
-
padding: '
|
|
56
|
+
padding: '0',
|
|
56
57
|
textAlign: 'center' as const,
|
|
57
58
|
}
|
|
58
59
|
})
|
|
@@ -72,22 +72,18 @@ defineOptions({
|
|
|
72
72
|
|
|
73
73
|
<template>
|
|
74
74
|
<div
|
|
75
|
-
class="rounded p-4"
|
|
76
75
|
:style="{ backgroundColor: block.settings.backgroundColor }"
|
|
77
76
|
:data-testid="gridBlockTestIds.container"
|
|
78
77
|
>
|
|
79
|
-
<div
|
|
80
|
-
class="grid gap-4"
|
|
81
|
-
:class="{
|
|
82
|
-
'grid-cols-1': block.settings.columns === 1,
|
|
83
|
-
'grid-cols-2': block.settings.columns === 2,
|
|
84
|
-
'grid-cols-3': block.settings.columns === 3,
|
|
85
|
-
}"
|
|
86
|
-
>
|
|
78
|
+
<div class="flex items-center">
|
|
87
79
|
<div
|
|
88
80
|
v-for="(column, index) in block.settings.columnData"
|
|
89
81
|
:key="column.id"
|
|
90
|
-
class="
|
|
82
|
+
class="overflow-hidden [&_img]:w-full self-stretch flex flex-col justify-center"
|
|
83
|
+
:class="
|
|
84
|
+
column.blocks.length === 0 ? 'min-h-32 border border-dashed border-neutral-300/50' : ''
|
|
85
|
+
"
|
|
86
|
+
:style="{ width: `${100 / block.settings.columns}%` }"
|
|
91
87
|
:data-testid="`${gridBlockTestIds.column}-${column.id}`"
|
|
92
88
|
>
|
|
93
89
|
<!-- Column blocks -->
|
|
@@ -96,10 +96,10 @@ defineOptions({
|
|
|
96
96
|
:data-block-id="block.id"
|
|
97
97
|
:data-block-type="block.type"
|
|
98
98
|
:data-testid="`${indexBlockTestIds.container}-${block.id}`"
|
|
99
|
-
class="group relative
|
|
99
|
+
class="group relative transition-colors"
|
|
100
100
|
:class="{
|
|
101
|
-
'
|
|
102
|
-
'
|
|
101
|
+
'outline-2 outline-primary-500 outline': isSelected,
|
|
102
|
+
'outline-transparent hover:outline-2 hover:outline-neutral-300 hover:outline': !isSelected,
|
|
103
103
|
'cursor-move': showDragHandle,
|
|
104
104
|
}"
|
|
105
105
|
@click.stop="handleClick"
|
|
@@ -153,3 +153,14 @@ defineOptions({
|
|
|
153
153
|
</div>
|
|
154
154
|
</UPopover>
|
|
155
155
|
</template>
|
|
156
|
+
|
|
157
|
+
<style scoped>
|
|
158
|
+
:deep(.ProseMirror ul) {
|
|
159
|
+
list-style-type: disc;
|
|
160
|
+
padding-left: 1.5em;
|
|
161
|
+
}
|
|
162
|
+
:deep(.ProseMirror ol) {
|
|
163
|
+
list-style-type: decimal;
|
|
164
|
+
padding-left: 1.5em;
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -97,7 +97,7 @@ const accommodationName = computed(
|
|
|
97
97
|
|
|
98
98
|
const state = ref<Schema>({
|
|
99
99
|
to: '',
|
|
100
|
-
sender_name:
|
|
100
|
+
sender_name: '',
|
|
101
101
|
from: '',
|
|
102
102
|
})
|
|
103
103
|
|
|
@@ -111,6 +111,16 @@ watch(
|
|
|
111
111
|
{ immediate: true },
|
|
112
112
|
)
|
|
113
113
|
|
|
114
|
+
watch(
|
|
115
|
+
accommodationName,
|
|
116
|
+
(name) => {
|
|
117
|
+
if (!state.value.sender_name) {
|
|
118
|
+
state.value.sender_name = name
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{ immediate: true },
|
|
122
|
+
)
|
|
123
|
+
|
|
114
124
|
const schema = z.object({
|
|
115
125
|
to: z
|
|
116
126
|
.string()
|