@dev.smartpricing/message-composer-layer 1.0.13 → 1.0.14
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/components/Composer/BrandList.vue +190 -0
- package/app/components/Composer/EmailComposer.vue +501 -0
- package/app/components/Composer/EmailContent.vue +95 -0
- package/app/components/Composer/EmailTranslations.vue +70 -0
- package/app/components/Composer/ImageGallery.vue +141 -0
- package/app/components/Composer/MessageLibrary.vue +155 -0
- package/app/components/Composer/WhatsappComposer.vue +424 -0
- package/app/components/Composer/WhatsappContent.vue +88 -0
- package/app/components/Composer/WhatsappTranslations.vue +68 -0
- package/app/pages/brands.vue +7 -176
- package/app/pages/images.vue +1 -126
- package/app/pages/index.vue +6 -138
- package/app/pages/template/email/[id].vue +16 -545
- package/app/pages/template/email/create.vue +13 -514
- package/app/pages/template/whatsapp/[id].vue +21 -509
- package/app/pages/template/whatsapp/create.vue +13 -426
- package/app/stores/emailComposer.ts +188 -0
- package/app/stores/whatsappComposer.ts +173 -0
- package/package.json +2 -2
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { ref, computed } from 'vue'
|
|
2
|
+
import type {
|
|
3
|
+
MessageGroupCategory,
|
|
4
|
+
WhatsappMessage,
|
|
5
|
+
PostEntity,
|
|
6
|
+
MessageFromDb,
|
|
7
|
+
MessageGroupWithMessages,
|
|
8
|
+
} from '@dev.smartpricing/message-composer-utils/types'
|
|
9
|
+
import { getWhatsappEmpty } from '@dev.smartpricing/message-composer-utils/utils'
|
|
10
|
+
|
|
11
|
+
type ComposerMode = 'create' | 'edit'
|
|
12
|
+
|
|
13
|
+
export const useWhatsappComposerStore = defineStore('whatsappComposer', () => {
|
|
14
|
+
// ── Core state ────────────────────────────────────────────────────
|
|
15
|
+
const mode = ref<ComposerMode>('create')
|
|
16
|
+
const messageGroupId = ref<string | null>(null)
|
|
17
|
+
const name = ref('')
|
|
18
|
+
const category = ref<MessageGroupCategory>('marketing')
|
|
19
|
+
const isInternal = ref(false)
|
|
20
|
+
const language = ref('en') // base language
|
|
21
|
+
const targetLanguage = ref('en')
|
|
22
|
+
const activeTab = ref<'content' | 'translations'>('content')
|
|
23
|
+
const messages = ref<Record<string, PostEntity<WhatsappMessage> | WhatsappMessage>>({})
|
|
24
|
+
|
|
25
|
+
// Edit-mode original values for change detection
|
|
26
|
+
const originalName = ref('')
|
|
27
|
+
const originalCategory = ref<MessageGroupCategory>('marketing')
|
|
28
|
+
|
|
29
|
+
// Loaded messageGroup data (edit mode)
|
|
30
|
+
const messageGroup = ref<MessageGroupWithMessages | null>(null)
|
|
31
|
+
|
|
32
|
+
// Create mode: draft ID for change tracking
|
|
33
|
+
const draftId = ref('')
|
|
34
|
+
|
|
35
|
+
// ── Computed ──────────────────────────────────────────────────────
|
|
36
|
+
const messageGroupData = computed(() => ({
|
|
37
|
+
name: name.value,
|
|
38
|
+
category: category.value,
|
|
39
|
+
visibility: isInternal.value ? 'internal' : 'public',
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
const messageGroupUpdateData = computed(() => ({
|
|
43
|
+
name: name.value,
|
|
44
|
+
category: category.value,
|
|
45
|
+
}))
|
|
46
|
+
|
|
47
|
+
const currentMessage = computed(
|
|
48
|
+
() =>
|
|
49
|
+
messages.value[language.value] as (PostEntity<WhatsappMessage> | WhatsappMessage) | undefined,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const targetMessage = computed(
|
|
53
|
+
() =>
|
|
54
|
+
messages.value[targetLanguage.value] as
|
|
55
|
+
| (PostEntity<WhatsappMessage> | WhatsappMessage)
|
|
56
|
+
| undefined,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
// Edit mode: status checks for conditional buttons
|
|
60
|
+
const isPending = computed(() =>
|
|
61
|
+
messageGroup.value?.messages?.some((message: MessageFromDb) => message.status === 'pending'),
|
|
62
|
+
)
|
|
63
|
+
const isApproved = computed(() =>
|
|
64
|
+
messageGroup.value?.messages?.some((message: MessageFromDb) => message.status === 'approved'),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
// Change tracking ID: draftId for create, messageGroupId for edit
|
|
68
|
+
const changeTrackingId = computed(() =>
|
|
69
|
+
mode.value === 'create' ? draftId.value : (messageGroupId.value ?? ''),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// ── Init ──────────────────────────────────────────────────────────
|
|
73
|
+
function initCreate(mainLanguage: string) {
|
|
74
|
+
mode.value = 'create'
|
|
75
|
+
messageGroupId.value = null
|
|
76
|
+
name.value = ''
|
|
77
|
+
category.value = 'marketing'
|
|
78
|
+
isInternal.value = false
|
|
79
|
+
language.value = mainLanguage
|
|
80
|
+
targetLanguage.value = mainLanguage
|
|
81
|
+
activeTab.value = 'content'
|
|
82
|
+
messages.value = { [mainLanguage]: getWhatsappEmpty(mainLanguage) }
|
|
83
|
+
messageGroup.value = null
|
|
84
|
+
originalName.value = ''
|
|
85
|
+
originalCategory.value = 'marketing'
|
|
86
|
+
draftId.value = `draft-${Date.now()}`
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function initEdit(data: MessageGroupWithMessages, mainLanguage: string) {
|
|
90
|
+
mode.value = 'edit'
|
|
91
|
+
messageGroupId.value = data.id?.toString() ?? null
|
|
92
|
+
name.value = data.name
|
|
93
|
+
category.value = data.category
|
|
94
|
+
isInternal.value = data.visibility === 'internal'
|
|
95
|
+
activeTab.value = 'content'
|
|
96
|
+
draftId.value = ''
|
|
97
|
+
|
|
98
|
+
// Deep clone to avoid mutating cache
|
|
99
|
+
messageGroup.value = structuredClone(data)
|
|
100
|
+
|
|
101
|
+
// Store originals for change detection
|
|
102
|
+
originalName.value = data.name
|
|
103
|
+
originalCategory.value = data.category
|
|
104
|
+
|
|
105
|
+
// Populate messages
|
|
106
|
+
const msgs: Record<string, WhatsappMessage> = {}
|
|
107
|
+
for (const message of data.messages) {
|
|
108
|
+
if (message.render_type === 'whatsapp_v1') {
|
|
109
|
+
msgs[message.language_id] = structuredClone(message) as WhatsappMessage
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
messages.value = msgs
|
|
113
|
+
|
|
114
|
+
// Resolve language
|
|
115
|
+
const resolved = resolveDefaultLanguage(msgs, mainLanguage)
|
|
116
|
+
language.value = resolved ?? mainLanguage
|
|
117
|
+
targetLanguage.value = language.value
|
|
118
|
+
|
|
119
|
+
// Set initial target language for translations tab
|
|
120
|
+
const langs = Object.keys(msgs)
|
|
121
|
+
if (langs.length > 1) {
|
|
122
|
+
targetLanguage.value = langs.find((l) => l !== language.value) ?? language.value
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ── Reset ─────────────────────────────────────────────────────────
|
|
127
|
+
function $reset() {
|
|
128
|
+
mode.value = 'create'
|
|
129
|
+
messageGroupId.value = null
|
|
130
|
+
name.value = ''
|
|
131
|
+
category.value = 'marketing'
|
|
132
|
+
isInternal.value = false
|
|
133
|
+
language.value = 'en'
|
|
134
|
+
targetLanguage.value = 'en'
|
|
135
|
+
activeTab.value = 'content'
|
|
136
|
+
messages.value = {}
|
|
137
|
+
messageGroup.value = null
|
|
138
|
+
originalName.value = ''
|
|
139
|
+
originalCategory.value = 'marketing'
|
|
140
|
+
draftId.value = ''
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
// State
|
|
145
|
+
mode,
|
|
146
|
+
messageGroupId,
|
|
147
|
+
name,
|
|
148
|
+
category,
|
|
149
|
+
isInternal,
|
|
150
|
+
language,
|
|
151
|
+
targetLanguage,
|
|
152
|
+
activeTab,
|
|
153
|
+
messages,
|
|
154
|
+
messageGroup,
|
|
155
|
+
originalName,
|
|
156
|
+
originalCategory,
|
|
157
|
+
draftId,
|
|
158
|
+
|
|
159
|
+
// Computed
|
|
160
|
+
messageGroupData,
|
|
161
|
+
messageGroupUpdateData,
|
|
162
|
+
currentMessage,
|
|
163
|
+
targetMessage,
|
|
164
|
+
isPending,
|
|
165
|
+
isApproved,
|
|
166
|
+
changeTrackingId,
|
|
167
|
+
|
|
168
|
+
// Actions
|
|
169
|
+
initCreate,
|
|
170
|
+
initEdit,
|
|
171
|
+
$reset,
|
|
172
|
+
}
|
|
173
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev.smartpricing/message-composer-layer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
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.
|
|
42
|
+
"@dev.smartpricing/message-composer-utils": "3.1.14"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@nuxt/eslint": "^1.15.2",
|