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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user