@dev.smartpricing/message-composer-layer 1.0.7 → 1.0.9

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.
@@ -6,6 +6,8 @@ import type {
6
6
  import { apiClient } from './client'
7
7
 
8
8
  export const messagesApi = {
9
+ getById: (id: string) => apiClient<MessageFromDb>(`/messages/${id}`),
10
+
9
11
  create: (data: PostEntity<Message>) =>
10
12
  apiClient<MessageFromDb>('/messages', {
11
13
  method: 'POST',
@@ -1,7 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import type { PostEntity, EmailMessage } from '@dev.smartpricing/message-composer-utils/types'
3
3
  import { isEmail } from '@dev.smartpricing/message-composer-utils/utils'
4
+ import { useQuery } from '@pinia/colada'
4
5
  import { useSendTestEmailMutation } from '~/queries'
6
+ import { messageGroupsApi, messagesApi } from '~/api'
5
7
  import { z } from 'zod'
6
8
 
7
9
  defineOptions({
@@ -9,13 +11,73 @@ defineOptions({
9
11
  })
10
12
 
11
13
  const props = defineProps<{
12
- message: PostEntity<EmailMessage>
14
+ message?: PostEntity<EmailMessage>
15
+ messageId?: string
16
+ messageGroupId?: string
17
+ language?: string
13
18
  }>()
14
19
 
15
20
  const emit = defineEmits<{
16
21
  'test-sent': [payload: { to_recipients: number }]
17
22
  }>()
18
23
 
24
+ // --- Resolve message from props (priority: message > messageId > messageGroupId+language) ---
25
+
26
+ const mode = computed(() => {
27
+ if (props.message) return 'direct' as const
28
+ if (props.messageId) return 'byId' as const
29
+ if (props.messageGroupId) return 'byGroup' as const
30
+ return 'none' as const
31
+ })
32
+
33
+ if (import.meta.dev) {
34
+ const propSources = [props.message, props.messageId, props.messageGroupId].filter(Boolean)
35
+ if (propSources.length > 1) {
36
+ console.warn(
37
+ '[SendTestEmailModal] Multiple message sources provided. Priority: message > messageId > messageGroupId+language',
38
+ )
39
+ }
40
+ }
41
+
42
+ const { data: fetchedMessage, isLoading: isLoadingMessage } = useQuery({
43
+ key: () => ['messages', props.messageId ?? ''],
44
+ query: () => messagesApi.getById(props.messageId!),
45
+ enabled: () => mode.value === 'byId',
46
+ })
47
+
48
+ const { data: messageGroup, isLoading: isLoadingGroup } = useQuery({
49
+ key: () => ['message-groups', props.messageGroupId ?? ''],
50
+ query: () => messageGroupsApi.getById(props.messageGroupId!),
51
+ enabled: () => mode.value === 'byGroup',
52
+ })
53
+
54
+ const resolvedMessage = computed<PostEntity<EmailMessage> | undefined>(() => {
55
+ if (props.message) return props.message
56
+
57
+ if (mode.value === 'byId' && fetchedMessage.value) {
58
+ return fetchedMessage.value as unknown as PostEntity<EmailMessage>
59
+ }
60
+
61
+ if (mode.value === 'byGroup' && messageGroup.value) {
62
+ const messages = messageGroup.value.messages
63
+ const msg =
64
+ messages.find((m) => m.language_id === props.language) ||
65
+ messages.find((m) => m.language_id === 'en') ||
66
+ messages[0]
67
+ return msg as unknown as PostEntity<EmailMessage> | undefined
68
+ }
69
+
70
+ return undefined
71
+ })
72
+
73
+ const isResolvingMessage = computed(
74
+ () =>
75
+ (mode.value === 'byId' && isLoadingMessage.value) ||
76
+ (mode.value === 'byGroup' && isLoadingGroup.value),
77
+ )
78
+
79
+ // --- Form ---
80
+
19
81
  const { t } = useI18n()
20
82
  const toast = useToast()
21
83
  const { mutate: sendTest, isLoading: isSending, status } = useSendTestEmailMutation()
@@ -43,13 +105,14 @@ const schema = z.object({
43
105
  type Schema = z.output<typeof schema>
44
106
 
45
107
  function onSubmit() {
108
+ if (!resolvedMessage.value) return
46
109
  sendTest({
47
- message: props.message,
110
+ message: resolvedMessage.value,
48
111
  to: state.value.to,
49
112
  })
50
113
  }
51
114
 
52
- const open = ref(false)
115
+ const open = defineModel<boolean>('open', { default: false })
53
116
  const formRef = ref()
54
117
 
55
118
  watch(status, (newStatus) => {
@@ -78,14 +141,16 @@ watch(status, (newStatus) => {
78
141
  :close="{ 'data-testid': sendTestEmailModalTestIds.modalCloseButton }"
79
142
  :data-testid="sendTestEmailModalTestIds.modal"
80
143
  >
81
- <UButton
82
- icon="ph:envelope-simple-bold"
83
- :label="$t('pages.email.send_test')"
84
- size="md"
85
- color="primary"
86
- variant="ghost"
87
- :data-testid="sendTestEmailModalTestIds.triggerButton"
88
- />
144
+ <slot name="trigger">
145
+ <UButton
146
+ icon="ph:envelope-simple-bold"
147
+ :label="$t('pages.email.send_test')"
148
+ size="md"
149
+ color="primary"
150
+ variant="ghost"
151
+ :data-testid="sendTestEmailModalTestIds.triggerButton"
152
+ />
153
+ </slot>
89
154
 
90
155
  <template #body>
91
156
  <UForm ref="formRef" :schema="schema" :state="state" @submit="onSubmit">
@@ -112,7 +177,8 @@ watch(status, (newStatus) => {
112
177
  :label="$t('pages.email.send_test')"
113
178
  size="sm"
114
179
  color="primary"
115
- :loading="isSending"
180
+ :loading="isSending || isResolvingMessage"
181
+ :disabled="!resolvedMessage"
116
182
  @click="formRef.submit()"
117
183
  :data-testid="sendTestEmailModalTestIds.sendButton"
118
184
  />
@@ -1,7 +1,19 @@
1
- import { useMutation, useQueryCache } from '@pinia/colada'
1
+ import { useMutation, useQuery, useQueryCache } from '@pinia/colada'
2
2
  import type { Message, PostEntity } from '@dev.smartpricing/message-composer-utils/types'
3
+ import type { MaybeRefOrGetter } from 'vue'
3
4
  import { messagesApi } from '~/api'
4
5
 
6
+ export function useMessageQuery(
7
+ id: MaybeRefOrGetter<string>,
8
+ options?: { enabled?: MaybeRefOrGetter<boolean> },
9
+ ) {
10
+ return useQuery({
11
+ key: () => ['messages', toValue(id)],
12
+ query: () => messagesApi.getById(toValue(id)),
13
+ enabled: options?.enabled,
14
+ })
15
+ }
16
+
5
17
  export function useCreateMessageMutation() {
6
18
  const queryCache = useQueryCache()
7
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.smartpricing/message-composer-layer",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -39,7 +39,7 @@
39
39
  "vue-router": "^5.0.6",
40
40
  "vue3-emoji-picker": "^1.1.8",
41
41
  "zod": "^4.4.1",
42
- "@dev.smartpricing/message-composer-utils": "3.1.7"
42
+ "@dev.smartpricing/message-composer-utils": "3.1.9"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@nuxt/eslint": "^1.15.2",