Files
hedena_gold/apps/admin-panel/src/views/sms/create.vue
T
s.esmaeiliandClaude Sonnet 5 f0de478940 admin-panel: fix CSS bugs and dedupe scoped grid utilities
Approved departure from the port's byte-faithful rule (docs/ADMIN-PORT-PLAN.md
bug rows 4-6), fixed and logged rather than silently changed:
- farsi.less: bold/700 @font-face blocks now load iran-yekan-700.woff2
  instead of the 400 file, so bold text actually renders bold. No source
  file exists for weight 300, so that face is dropped rather than faked.
- format("woff") corrected to format("woff2") on all faces.
- Removed 'font-weight: inherit' from the body,* reset, which was flattening
  every heading's weight.

Also deduped 24 view files that each redeclared .grid-2/.grid-3/.grid-4 in
a scoped <style> block with drifted minmax values, though utilities.less
already defines all three globally. Removed the scoped copies; kept
PromotionForm's genuinely different 0.5rem gap as a small .grid-4--tight
modifier instead of a full redeclaration.

Verified: pnpm build passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 15:09:11 +03:30

115 lines
4.1 KiB
Vue

<template>
<!--
Ported from legacy henza_admin/src/views/sms/create.vue.
Each audience option is gated by its own rid, exactly as legacy did — the
numeric codes (-1/0/1/2/9) are legacy's own and are preserved on the wire.
NOTE the "تک فروشی" audience has a rid (sms.create.tak) but NO option in the
legacy markup, so it is unreachable. Preserved as absent.
-->
<a-spin :spinning="loading">
<a-card title="ارسال پیامک">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<div class="grid-2">
<a-form-item label="ارسال برای">
<a-select v-model:value="type">
<a-select-option v-if="hasPermission('sms.create.single')" :value="-1">
شماره موبایل
</a-select-option>
<a-select-option v-if="hasPermission('sms.create.all')" :value="0">
همه مشتریان
</a-select-option>
<a-select-option v-if="hasPermission('sms.create.reagent')" :value="1">
کارشناسان فروش
</a-select-option>
<a-select-option v-if="hasPermission('sms.create.omde')" :value="2">
مشتریان عمده
</a-select-option>
<a-select-option v-if="hasPermission('sms.create.multiple')" :value="9">
شماره های موبایل
</a-select-option>
</a-select>
</a-form-item>
<a-form-item
v-if="type === -1 || type === 9"
:label="type === 9 ? 'شماره های موبایل' : 'شماره موبایل'"
:validate-status="err.mobile ? 'error' : ''"
:help="err.mobile"
>
<a-textarea
v-if="type === 9"
v-model:value="mobile"
:auto-size="{ minRows: 2, maxRows: 6 }"
placeholder="هر شماره در یک خط"
/>
<a-input v-else v-model:value="mobile" />
</a-form-item>
</div>
<a-form-item label="متن پیامک" :validate-status="err.text ? 'error' : ''" :help="err.text">
<a-textarea v-model:value="text" :auto-size="{ minRows: 4, maxRows: 8 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ارسال</a-button>
</a-form>
</a-card>
<a-card v-if="hasPermission('sms.list')" title="لیست پیامک ها" class="mt-4">
<XTable ref="tbl" :model="model" />
</a-card>
</a-spin>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { message } from 'ant-design-vue';
import XTable from '../../components/x-table/XTable.vue';
import { buildSmsModel } from './smsTbl';
import { useUsersStore } from '../../stores/users';
import api from '../../api/client';
const users = useUsersStore();
const hasPermission = (rid: string) => Boolean(users.hasPermission(rid));
const model = buildSmsModel();
const tbl = ref<{ fetch: () => Promise<void> } | null>(null);
const loading = ref(false);
const type = ref<number>(-1);
const mobile = ref('');
const text = ref('');
const err = reactive<Record<string, string>>({});
async function handleSubmit() {
Object.keys(err).forEach((k) => delete err[k]);
if (!text.value) err.text = 'متن پیامک الزامی است';
if ((type.value === -1 || type.value === 9) && !mobile.value) {
err.mobile = 'شماره موبایل الزامی است';
}
if (Object.keys(err).length) return;
try {
loading.value = true;
const { data } = await api.post('sms', {
type: type.value,
mobile: mobile.value,
text: text.value,
});
message.success(`پیامک برای ${data.sentCount} شماره ثبت شد`);
text.value = '';
mobile.value = '';
tbl.value?.fetch();
} catch (e: any) {
message.error(e?.response?.data?.message ?? 'خطا در ارسال پیامک');
} finally {
loading.value = false;
}
}
</script>
<style scoped>
/* .grid-2 now comes from the global utilities.less (dedup) */
.mt-4 { margin-top: 1rem; }
</style>