fix(settings): fix Vue reactivity and form keying on SMS templates save

This commit is contained in:
2026-08-15 22:03:29 +03:30
parent 28b75664ab
commit 9fbaf3c7fe
+15 -14
View File
@@ -86,7 +86,7 @@
<div v-else class="flex flex-column gap-2"> <div v-else class="flex flex-column gap-2">
<div <div
v-for="(variable, vIdx) in templateForm[template.key].variables" v-for="(variable, vIdx) in templateForm[template.key].variables"
:key="vIdx" :key="variable.id || vIdx"
class="flex flex-column sm:flex-row sm:align-items-center gap-2 p-2 border-round surface-card border-1 border-color" class="flex flex-column sm:flex-row sm:align-items-center gap-2 p-2 border-round surface-card border-1 border-color"
> >
<div class="flex align-items-center gap-2 sm:w-14rem flex-shrink-0"> <div class="flex align-items-center gap-2 sm:w-14rem flex-shrink-0">
@@ -248,7 +248,7 @@
</template> </template>
<script setup> <script setup>
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useConfirm } from 'primevue/useconfirm'; import { useConfirm } from 'primevue/useconfirm';
import Button from 'primevue/button'; import Button from 'primevue/button';
import InputText from 'primevue/inputtext'; import InputText from 'primevue/inputtext';
@@ -265,7 +265,7 @@ const { showSuccess, showError } = useToast();
const isSettingsLoading = ref(true); const isSettingsLoading = ref(true);
const isSavingSettings = ref(false); const isSavingSettings = ref(false);
const smsTemplates = ref([]); const smsTemplates = ref([]);
const templateForm = reactive({}); const templateForm = ref({});
const isStatusLoading = ref(true); const isStatusLoading = ref(true);
const isSeeding = ref(false); const isSeeding = ref(false);
@@ -291,7 +291,7 @@ const getSlotDefaultName = (template, slotKey) => {
}; };
const onSlotChange = (templateKey, vIdx) => { const onSlotChange = (templateKey, vIdx) => {
const form = templateForm[templateKey]; const form = templateForm.value[templateKey];
if (!form || !form.variables[vIdx]) return; if (!form || !form.variables[vIdx]) return;
const template = smsTemplates.value.find((t) => t.key === templateKey); const template = smsTemplates.value.find((t) => t.key === templateKey);
const currentVar = form.variables[vIdx]; const currentVar = form.variables[vIdx];
@@ -301,7 +301,7 @@ const onSlotChange = (templateKey, vIdx) => {
}; };
const addVariable = (templateKey) => { const addVariable = (templateKey) => {
const form = templateForm[templateKey]; const form = templateForm.value[templateKey];
if (!form) return; if (!form) return;
const template = smsTemplates.value.find((t) => t.key === templateKey); const template = smsTemplates.value.find((t) => t.key === templateKey);
const availableSlots = template?.availableSlots || []; const availableSlots = template?.availableSlots || [];
@@ -311,20 +311,21 @@ const addVariable = (templateKey) => {
const selectedSlot = unusedSlot || availableSlots[0] || { slot: 'param', defaultName: 'param' }; const selectedSlot = unusedSlot || availableSlots[0] || { slot: 'param', defaultName: 'param' };
form.variables.push({ form.variables.push({
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
slot: selectedSlot.slot, slot: selectedSlot.slot,
name: selectedSlot.defaultName || '' name: selectedSlot.defaultName || ''
}); });
}; };
const removeVariable = (templateKey, index) => { const removeVariable = (templateKey, index) => {
const form = templateForm[templateKey]; const form = templateForm.value[templateKey];
if (form && form.variables) { if (form && form.variables) {
form.variables.splice(index, 1); form.variables.splice(index, 1);
} }
}; };
const applyStatus = (payload) => { const applyStatus = (payload) => {
const status = payload?.data || payload || {}; const status = payload?.data?.data || payload?.data || payload || {};
isLocked.value = Boolean(status.locked); isLocked.value = Boolean(status.locked);
lockedAt.value = status.lockedAt || null; lockedAt.value = status.lockedAt || null;
}; };
@@ -411,6 +412,7 @@ const emptyFormEntry = (template) => ({
templateId: template?.templateId || '', templateId: template?.templateId || '',
variables: Array.isArray(template?.variables) variables: Array.isArray(template?.variables)
? template.variables.map((variable) => ({ ? template.variables.map((variable) => ({
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
slot: variable.slot, slot: variable.slot,
name: variable.name || '' name: variable.name || ''
})) }))
@@ -418,15 +420,14 @@ const emptyFormEntry = (template) => ({
}); });
const applySmsTemplates = (payload) => { const applySmsTemplates = (payload) => {
const data = payload?.data || payload || {}; const data = payload?.data?.data || payload?.data || payload || {};
const templates = Array.isArray(data.smsTemplates) ? data.smsTemplates : []; const templates = Array.isArray(data.smsTemplates) ? data.smsTemplates : [];
smsTemplates.value = templates; smsTemplates.value = templates;
Object.keys(templateForm).forEach((key) => { const newForm = {};
delete templateForm[key];
});
templates.forEach((template) => { templates.forEach((template) => {
templateForm[template.key] = emptyFormEntry(template); newForm[template.key] = emptyFormEntry(template);
}); });
templateForm.value = newForm;
}; };
const loadSettings = async () => { const loadSettings = async () => {
@@ -446,7 +447,7 @@ const saveSmsTemplates = async () => {
try { try {
const smsTemplatesPayload = {}; const smsTemplatesPayload = {};
smsTemplates.value.forEach((template) => { smsTemplates.value.forEach((template) => {
const entry = templateForm[template.key] || emptyFormEntry(template); const entry = templateForm.value[template.key] || emptyFormEntry(template);
smsTemplatesPayload[template.key] = { smsTemplatesPayload[template.key] = {
templateId: entry.templateId || '', templateId: entry.templateId || '',
variables: (entry.variables || []) variables: (entry.variables || [])
@@ -459,7 +460,7 @@ const saveSmsTemplates = async () => {
}); });
const response = await settingsApi.save({ smsTemplates: smsTemplatesPayload }); const response = await settingsApi.save({ smsTemplates: smsTemplatesPayload });
applySmsTemplates(response); applySmsTemplates(response);
showSuccess('قالب‌های پیامک ذخیره شدند.'); showSuccess('قالب‌های پیامک با موفقیت ذخیره شدند.');
} catch (err) { } catch (err) {
showError(err); showError(err);
} finally { } finally {