diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json index 82772e0..e69de29 100644 --- a/.eslintrc-auto-import.json +++ b/.eslintrc-auto-import.json @@ -1,84 +0,0 @@ -{ - "globals": { - "Component": true, - "ComponentPublicInstance": true, - "ComputedRef": true, - "EffectScope": true, - "ExtractDefaultPropTypes": true, - "ExtractPropTypes": true, - "ExtractPublicPropTypes": true, - "InjectionKey": true, - "PropType": true, - "Ref": true, - "VNode": true, - "WritableComputedRef": true, - "acceptHMRUpdate": true, - "computed": true, - "createApp": true, - "createPinia": true, - "customRef": true, - "defineAsyncComponent": true, - "defineComponent": true, - "defineStore": true, - "effectScope": true, - "getActivePinia": true, - "getCurrentInstance": true, - "getCurrentScope": true, - "h": true, - "inject": true, - "isProxy": true, - "isReactive": true, - "isReadonly": true, - "isRef": true, - "mapActions": true, - "mapGetters": true, - "mapState": true, - "mapStores": true, - "mapWritableState": true, - "markRaw": true, - "nextTick": true, - "onActivated": true, - "onBeforeMount": true, - "onBeforeRouteLeave": true, - "onBeforeRouteUpdate": true, - "onBeforeUnmount": true, - "onBeforeUpdate": true, - "onDeactivated": true, - "onErrorCaptured": true, - "onMounted": true, - "onRenderTracked": true, - "onRenderTriggered": true, - "onScopeDispose": true, - "onServerPrefetch": true, - "onUnmounted": true, - "onUpdated": true, - "provide": true, - "reactive": true, - "readonly": true, - "ref": true, - "resolveComponent": true, - "setActivePinia": true, - "setMapStoreSuffix": true, - "shallowReactive": true, - "shallowReadonly": true, - "shallowRef": true, - "storeToRefs": true, - "toRaw": true, - "toRef": true, - "toRefs": true, - "toValue": true, - "triggerRef": true, - "unref": true, - "useAttrs": true, - "useCssModule": true, - "useCssVars": true, - "useLink": true, - "useRoute": true, - "useRouter": true, - "useSlots": true, - "watch": true, - "watchEffect": true, - "watchPostEffect": true, - "watchSyncEffect": true - } -} \ No newline at end of file diff --git a/components.d.ts b/components.d.ts index 50acf2e..474c9dd 100644 --- a/components.d.ts +++ b/components.d.ts @@ -16,6 +16,7 @@ declare module '@vue/runtime-core' { AButton: typeof import('ant-design-vue/es')['Button'] ACard: typeof import('ant-design-vue/es')['Card'] ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] + ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup'] ACol: typeof import('ant-design-vue/es')['Col'] ACollapse: typeof import('ant-design-vue/es')['Collapse'] ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel'] @@ -55,11 +56,9 @@ declare module '@vue/runtime-core' { ATable: typeof import('ant-design-vue/es')['Table'] ATabPane: typeof import('ant-design-vue/es')['TabPane'] ATabs: typeof import('ant-design-vue/es')['Tabs'] - ATag: typeof import('ant-design-vue/es')['Tag'] ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATimePicker: typeof import('ant-design-vue/es')['TimePicker'] ATooltip: typeof import('ant-design-vue/es')['Tooltip'] - AUpload: typeof import('ant-design-vue/es')['Upload'] BaseButton: typeof import('./src/core/components/BaseButton/index.ts')['default'] BaseCard: typeof import('./src/core/components/BaseCard/index.ts')['default'] BaseCollapse: typeof import('./src/components/BaseCollapse.vue')['default'] diff --git a/src/api/appNotifications.ts b/src/api/appNotifications.ts index 125b83a..b75163b 100644 --- a/src/api/appNotifications.ts +++ b/src/api/appNotifications.ts @@ -1,6 +1,12 @@ import type { TableInput } from '@core/type/baseTable' import useAxios from '@core/utils/useAxios' -import type { AppNotification, AppNotificationReadersResponse } from '@/model/appNotifications' +import type { + AppNotification, + AppNotificationCustomerOption, + AppNotificationReadersResponse, + AppNotificationRecipientsResponse, + AppNotificationSegmentOption, +} from '@/model/appNotifications' export const getAppNotificationsTable = async (params: TableInput) => await useAxios.post>('/admin/app_notifications/table', params) @@ -20,3 +26,27 @@ export const deleteAppNotification = async (id: number) => export const getAppNotificationReaders = async (id: number) => await useAxios.get(`/admin/app_notifications/${id}/readers`) +export const getAppNotificationRecipients = async (id: number) => + await useAxios.get(`/admin/app_notifications/${id}/recipients`) + +export const getAppNotificationAudienceOptions = async () => + await useAxios.get<{ segments: AppNotificationSegmentOption[] }>( + `/admin/app_notifications/audience-options` + ) + +export const searchAppNotificationCustomers = async (q: string) => + await useAxios.get<{ customers: AppNotificationCustomerOption[] }>( + `/admin/app_notifications/search-customers`, + { params: { q } } + ) + +export const previewAppNotificationAudience = async (payload: { + audience_type: string + segment_keys?: string[] + customer_ids?: number[] +}) => + await useAxios.post<{ + count: number | null + sample: AppNotificationCustomerOption[] + label: string + }>(`/admin/app_notifications/preview-audience`, payload) diff --git a/src/model/appNotifications.ts b/src/model/appNotifications.ts index 1bd36c1..9ac7bcb 100644 --- a/src/model/appNotifications.ts +++ b/src/model/appNotifications.ts @@ -1,3 +1,5 @@ +export type AppNotificationAudienceType = 'all' | 'segment' | 'customers' + export interface AppNotification { id?: number title: string @@ -8,6 +10,12 @@ export interface AppNotification { created_at?: string updated_at?: string reads_count?: number + audience_type?: AppNotificationAudienceType + segment_keys?: string[] | null + audience_label?: string | null + recipients_count?: number + /** فقط هنگام ایجاد — لیست id مشتریان تکی */ + customer_ids?: number[] } export const APP_NOTIFICATION_SEVERITIES = [ @@ -17,6 +25,24 @@ export const APP_NOTIFICATION_SEVERITIES = [ { value: 'danger', label: 'مهم / خطر (danger)' }, ] as const +export const APP_NOTIFICATION_AUDIENCE_TYPES = [ + { value: 'all', label: 'همه کاربران' }, + { value: 'segment', label: 'گروهی' }, + { value: 'customers', label: 'تکی / چندنفره' }, +] as const + +export interface AppNotificationSegmentOption { + key: string + name: string + description: string +} + +export interface AppNotificationCustomerOption { + id: number + name?: string | null + mobile?: string | null +} + export interface AppNotificationReader { customer_id: number name: string @@ -28,3 +54,11 @@ export interface AppNotificationReadersResponse { reads_count: number readers: AppNotificationReader[] } + +export interface AppNotificationRecipientsResponse { + audience_type: AppNotificationAudienceType + audience_label?: string | null + recipients_count: number | null + recipients: Array<{ customer_id: number; name: string; mobile?: string | null }> + note?: string +} diff --git a/src/pages/menuPages/appNotifications/components/AppNotificationEditorFormBody.vue b/src/pages/menuPages/appNotifications/components/AppNotificationEditorFormBody.vue index 3d8a587..c3f1ac5 100644 --- a/src/pages/menuPages/appNotifications/components/AppNotificationEditorFormBody.vue +++ b/src/pages/menuPages/appNotifications/components/AppNotificationEditorFormBody.vue @@ -1,55 +1,541 @@ + + diff --git a/src/pages/menuPages/appNotifications/components/table.vue b/src/pages/menuPages/appNotifications/components/table.vue index ed36d9a..29dae4b 100644 --- a/src/pages/menuPages/appNotifications/components/table.vue +++ b/src/pages/menuPages/appNotifications/components/table.vue @@ -4,7 +4,7 @@