added notif 2
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<a-form :model="form" ref="formRef" layout="vertical" autocomplete="off">
|
||||
<a-form-item label="عنوان" name="title" :rules="inputRules()">
|
||||
<BasicInput v-model:value="form.title" placeholder="عنوان اعلان" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="توضیح" name="body" :rules="inputRules()">
|
||||
<a-textarea
|
||||
v-model:value="form.body"
|
||||
:rows="5"
|
||||
placeholder="متن اعلان برای مشتری"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="اهمیت" name="severity" :rules="inputRules()">
|
||||
<BasicSelect
|
||||
v-model:value="form.severity"
|
||||
:items="severityItems"
|
||||
key-name="value"
|
||||
value-name="label"
|
||||
placeholder="انتخاب اهمیت"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="وضعیت" name="is_active">
|
||||
<a-switch
|
||||
v-model:checked="form.is_active"
|
||||
checked-children="فعال"
|
||||
un-checked-children="غیرفعال"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import type { FormInstance } from 'ant-design-vue'
|
||||
import type { AppNotification } from '@/model/appNotifications'
|
||||
import { APP_NOTIFICATION_SEVERITIES } from '@/model/appNotifications'
|
||||
import { inputRules } from '@/utils/inputRules'
|
||||
import BasicInput from '@/components/BasicInput.vue'
|
||||
import BasicSelect from '@/components/BasicSelect.vue'
|
||||
|
||||
defineProps<{
|
||||
form: Partial<AppNotification>
|
||||
}>()
|
||||
|
||||
const severityItems = [...APP_NOTIFICATION_SEVERITIES]
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
defineExpose({
|
||||
validateFields: () => formRef.value?.validateFields(),
|
||||
resetFields: () => formRef.value?.resetFields(),
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicShowContext title="اعلانهای اپ">
|
||||
<template #extra>
|
||||
<div class="flex items-center gap-2">
|
||||
<AdminFieldHelp
|
||||
text="اعلانهای ثبتشده برای همهٔ مشتریان فعال در اپ نمایش داده میشود. فقط وقتی سوییچ «اعلان داخل اپ» روشن باشد."
|
||||
/>
|
||||
<BaseButton type="primary" size="small" @click="emits('add')">
|
||||
<span>افزودن اعلان</span>
|
||||
<BaseIcon icon="vuesax-linear:add" size="16" />
|
||||
</BaseButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
|
||||
<template #action="{ record }">
|
||||
<div class="flex justify-center gap-2">
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>ویرایش</template>
|
||||
<Icon
|
||||
icon="vuesax-linear:edit"
|
||||
color="#4572E9"
|
||||
class="cursor-pointer"
|
||||
@click="emits('edit', record)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>{{ record.is_active ? 'غیرفعال کردن' : 'فعال کردن' }}</template>
|
||||
<Icon
|
||||
:icon="record.is_active ? 'vuesax-linear:eye-slash' : 'vuesax-linear:eye'"
|
||||
:color="record.is_active ? '#C53030' : '#25855A'"
|
||||
class="cursor-pointer"
|
||||
@click="emits('toggle', record)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom">
|
||||
<template #title>حذف</template>
|
||||
<Icon
|
||||
icon="vuesax-linear:trash"
|
||||
color="#C53030"
|
||||
class="cursor-pointer"
|
||||
@click="emits('delete', record.id)"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</BaseTable>
|
||||
</BasicShowContext>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
import useBaseTable from '@core/components/BaseTableOld/hooks/useBaseTable'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import { cols } from '../hooks/appNotificationsColumns'
|
||||
import { getAppNotificationsTable } from '@/api/appNotifications'
|
||||
import AdminFieldHelp from '@/components/AdminFieldHelp.vue'
|
||||
|
||||
const [submit, reload] = useBaseTable()
|
||||
|
||||
const emits = defineEmits<{
|
||||
add: []
|
||||
edit: [record: Record<string, unknown>]
|
||||
toggle: [record: Record<string, unknown>]
|
||||
delete: [id: number]
|
||||
}>()
|
||||
|
||||
const tblProps = {
|
||||
columns: cols,
|
||||
api: (params: TableInput) => getAppNotificationsTable(params),
|
||||
}
|
||||
|
||||
function fetch() {
|
||||
reload()
|
||||
}
|
||||
|
||||
defineExpose({ fetch })
|
||||
</script>
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { BaseTableColumn } from '@core/type/baseTable'
|
||||
import { toJalali } from '@core/utils/useDataTime'
|
||||
import CustomTag from '@/components/CustomTag.vue'
|
||||
|
||||
const severityLabel: Record<string, string> = {
|
||||
info: 'اطلاعات',
|
||||
success: 'موفق',
|
||||
warning: 'هشدار',
|
||||
danger: 'مهم',
|
||||
}
|
||||
|
||||
const severityColor: Record<string, string> = {
|
||||
info: 'blue',
|
||||
success: 'green',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
}
|
||||
|
||||
export const cols: BaseTableColumn[] = [
|
||||
{
|
||||
title: 'ردیف',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
customRender: (record: any) => record.index + 1,
|
||||
},
|
||||
{
|
||||
title: 'عنوان',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
type: 'Text',
|
||||
},
|
||||
{
|
||||
title: 'اهمیت',
|
||||
dataIndex: 'severity',
|
||||
key: 'severity',
|
||||
customRender: ({ record }) => (
|
||||
<CustomTag color={severityColor[record.severity] || 'default'}>
|
||||
{severityLabel[record.severity] || record.severity}
|
||||
</CustomTag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'وضعیت',
|
||||
dataIndex: 'is_active',
|
||||
key: 'is_active',
|
||||
customRender: ({ record }) => (
|
||||
<CustomTag color={record.is_active ? 'green' : 'red'}>
|
||||
{record.is_active ? 'فعال' : 'غیرفعال'}
|
||||
</CustomTag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'تاریخ',
|
||||
dataIndex: 'created_at',
|
||||
key: 'created_at',
|
||||
customRender: ({ record }) => (record.created_at ? toJalali(record.created_at) : '-'),
|
||||
},
|
||||
{
|
||||
title: 'عملیات',
|
||||
dataIndex: 'action',
|
||||
key: 'action',
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="flex h-full w-full">
|
||||
<tbl
|
||||
ref="tableRef"
|
||||
class="h-full w-full"
|
||||
@add="openAdd"
|
||||
@edit="openEdit"
|
||||
@toggle="toggleActive"
|
||||
@delete="deleteItem"
|
||||
/>
|
||||
|
||||
<BasicActionSheet
|
||||
v-model:visible="editorVisible"
|
||||
:title="sheetTitle"
|
||||
modal-width="32rem"
|
||||
drawer-height="85vh"
|
||||
:loading="loading"
|
||||
:show-button="true"
|
||||
:show-cancel="true"
|
||||
:show-ok="true"
|
||||
ok-text="ذخیره"
|
||||
cancel-text="انصراف"
|
||||
@ok="submitForm"
|
||||
@close="closeEditor"
|
||||
@cancel="closeEditor"
|
||||
>
|
||||
<div v-if="isMobile" class="mb-3 text-base font-bold">{{ sheetTitle }}</div>
|
||||
<AppNotificationEditorFormBody ref="editorRef" :form="form" />
|
||||
</BasicActionSheet>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import tbl from './components/table.vue'
|
||||
import BasicActionSheet from '@/components/BasicActionSheet.vue'
|
||||
import AppNotificationEditorFormBody from './components/AppNotificationEditorFormBody.vue'
|
||||
import type { AppNotification } from '@/model/appNotifications'
|
||||
import {
|
||||
createAppNotification,
|
||||
deleteAppNotification,
|
||||
toggleAppNotificationActive,
|
||||
updateAppNotification,
|
||||
} from '@/api/appNotifications'
|
||||
import { confirmDeleteItem } from '@/utils/confirmModal'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
|
||||
const tableRef = ref<null | { fetch: () => void }>(null)
|
||||
const editorRef = ref<{
|
||||
validateFields?: () => Promise<unknown>
|
||||
resetFields?: () => void
|
||||
}>()
|
||||
|
||||
const loading = ref(false)
|
||||
const editorVisible = ref(false)
|
||||
const editId = ref<number | undefined>()
|
||||
|
||||
const defaultForm = (): Partial<AppNotification> => ({
|
||||
title: '',
|
||||
body: '',
|
||||
severity: 'info',
|
||||
is_active: true,
|
||||
})
|
||||
|
||||
const form = ref<Partial<AppNotification>>(defaultForm())
|
||||
|
||||
const sheetTitle = computed(() => (editId.value ? 'ویرایش اعلان' : 'افزودن اعلان'))
|
||||
|
||||
function refreshTable() {
|
||||
tableRef.value?.fetch()
|
||||
}
|
||||
|
||||
function closeEditor() {
|
||||
editorVisible.value = false
|
||||
}
|
||||
|
||||
function openAdd() {
|
||||
editId.value = undefined
|
||||
form.value = defaultForm()
|
||||
editorRef.value?.resetFields?.()
|
||||
editorVisible.value = true
|
||||
}
|
||||
|
||||
function openEdit(record: AppNotification) {
|
||||
editId.value = record.id
|
||||
form.value = cloneDeep({
|
||||
title: record.title,
|
||||
body: record.body,
|
||||
severity: record.severity,
|
||||
is_active: record.is_active,
|
||||
})
|
||||
editorVisible.value = true
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
try {
|
||||
await editorRef.value?.validateFields?.()
|
||||
loading.value = true
|
||||
|
||||
const payload = {
|
||||
title: String(form.value.title ?? '').trim(),
|
||||
body: String(form.value.body ?? '').trim(),
|
||||
severity: form.value.severity || 'info',
|
||||
is_active: Boolean(form.value.is_active),
|
||||
}
|
||||
|
||||
if (editId.value) {
|
||||
await updateAppNotification(editId.value, payload)
|
||||
} else {
|
||||
await createAppNotification(payload)
|
||||
}
|
||||
|
||||
message.success('اعلان با موفقیت ذخیره شد')
|
||||
editorVisible.value = false
|
||||
refreshTable()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleActive(record: AppNotification) {
|
||||
if (!record.id) return
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
await toggleAppNotificationActive(record.id)
|
||||
message.success(record.is_active ? 'اعلان غیرفعال شد' : 'اعلان فعال شد')
|
||||
refreshTable()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در تغییر وضعیت')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteItem(id: number) {
|
||||
confirmDeleteItem('اعلان', id, deleteAppNotification, refreshTable)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user