feat: add SMS template IDs to dashboard settings

Let SuperAdmin save sms.ir template IDs in the database, creating missing template records on save.
This commit is contained in:
2026-08-15 18:37:44 +03:30
parent 2b3941e41e
commit 717f122eef
2 changed files with 121 additions and 3 deletions
+7
View File
@@ -0,0 +1,7 @@
// /src/api/settingsApi.js
import axiosInstance from './axiosInstance';
export const settingsApi = {
get: () => axiosInstance.get('/settings'),
save: (data) => axiosInstance.put('/settings', data)
};
+114 -3
View File
@@ -3,9 +3,68 @@
<div class="settings-view w-full max-w-3xl mx-auto">
<PageHeader
title="تنظیمات سیستم"
subtitle="عملیات راه‌اندازی و وارد کردن داده‌های دوره‌ها و کاربران"
subtitle="قالب‌های پیامک، راه‌اندازی پایگاه داده و وارد کردن داده‌ها"
/>
<div class="surface-card p-4 sm:p-5 border-round-xl border-1 border-color shadow-sm mb-4">
<div class="flex align-items-start gap-3 mb-4">
<div class="w-3rem h-3rem border-round-xl flex align-items-center justify-content-center flex-shrink-0 bg-primary-light text-primary">
<i class="pi pi-send text-xl"></i>
</div>
<div class="flex-grow-1">
<h2 class="text-lg font-bold text-color m-0 mb-1">قالبهای پیامک</h2>
<p class="text-sm text-muted m-0 line-height-3">
شناسه قالبهای sms.ir را وارد کنید. اگر قالبی در پایگاه داده نباشد، با ذخیره ایجاد میشود.
</p>
</div>
</div>
<div v-if="isSettingsLoading" class="flex align-items-center gap-2 text-muted text-sm">
<i class="pi pi-spin pi-spinner"></i>
<span>در حال بارگذاری تنظیمات پیامک</span>
</div>
<div v-else class="flex flex-column gap-4">
<div
v-for="template in smsTemplates"
:key="template.key"
class="flex flex-column gap-2"
>
<label class="font-semibold text-sm text-color" :for="`sms-template-${template.key}`">
{{ template.label }}
</label>
<InputText
:id="`sms-template-${template.key}`"
v-model.trim="templateForm[template.key]"
class="w-full text-sm"
dir="ltr"
inputmode="numeric"
placeholder="شناسه قالب sms.ir"
/>
<div class="flex flex-wrap align-items-center gap-2">
<span class="text-xs text-muted">متغیرها:</span>
<Tag
v-for="variable in template.variables"
:key="variable"
:value="`#${variable}#`"
severity="secondary"
class="text-xs font-mono"
/>
</div>
</div>
<div class="flex justify-content-end">
<Button
label="ذخیره قالب‌ها"
icon="pi pi-save"
class="font-bold"
:loading="isSavingSettings"
@click="saveSmsTemplates"
/>
</div>
</div>
</div>
<div class="surface-card p-4 sm:p-5 border-round-xl border-1 border-color shadow-sm mb-4">
<div class="flex align-items-start gap-3 mb-4">
<div class="w-3rem h-3rem border-round-xl flex align-items-center justify-content-center flex-shrink-0 bg-primary-light text-primary">
@@ -110,16 +169,24 @@
</template>
<script setup>
import { computed, onMounted, ref } from 'vue';
import { computed, onMounted, reactive, ref } from 'vue';
import { useConfirm } from 'primevue/useconfirm';
import Button from 'primevue/button';
import InputText from 'primevue/inputtext';
import Tag from 'primevue/tag';
import PageHeader from '@/components/common/PageHeader.vue';
import { seedApi } from '@/api/seedApi';
import { settingsApi } from '@/api/settingsApi';
import { useToast } from '@/composables/useToast';
const confirm = useConfirm();
const { showSuccess, showError } = useToast();
const isSettingsLoading = ref(true);
const isSavingSettings = ref(false);
const smsTemplates = ref([]);
const templateForm = reactive({});
const isStatusLoading = ref(true);
const isSeeding = ref(false);
const isLocked = ref(false);
@@ -222,7 +289,51 @@ const confirmImport = () => {
});
};
onMounted(loadStatus);
const applySmsTemplates = (payload) => {
const data = payload?.data || payload || {};
const templates = Array.isArray(data.smsTemplates) ? data.smsTemplates : [];
smsTemplates.value = templates;
Object.keys(templateForm).forEach((key) => {
delete templateForm[key];
});
templates.forEach((template) => {
templateForm[template.key] = template.templateId || '';
});
};
const loadSettings = async () => {
isSettingsLoading.value = true;
try {
const response = await settingsApi.get();
applySmsTemplates(response);
} catch (err) {
showError(err);
} finally {
isSettingsLoading.value = false;
}
};
const saveSmsTemplates = async () => {
isSavingSettings.value = true;
try {
const smsTemplateIds = {};
smsTemplates.value.forEach((template) => {
smsTemplateIds[template.key] = templateForm[template.key] || '';
});
const response = await settingsApi.save({ smsTemplates: smsTemplateIds });
applySmsTemplates(response);
showSuccess('قالب‌های پیامک ذخیره شدند.');
} catch (err) {
showError(err);
} finally {
isSavingSettings.value = false;
}
};
onMounted(() => {
loadStatus();
loadSettings();
});
</script>
<style scoped>