feat: update icons and improve loading states in various components
- Updated `hard-drive.vue` and `shield-user.vue` icons to use `currentColor` for better color management. - Enhanced `BaseTable.vue` to support skeleton loading rows and improved loading state rendering. - Refactored notification components to use new icon components (`Inbox`, `Video`, `Credit`, `BellOff`, `BellDot`) instead of icon classes. - Added new icons for `BellDot` and `BellOff`. - Improved the `QuickActions.vue` component for better hover effects. - Updated various settings components to use consistent icon styling and improved accessibility. - Refactored `AdsVastTable.tsx`, `DangerZone.vue`, `DomainsDnsTable.vue`, `PlayerConfigsTable.vue`, and `PopupAdsTable.tsx` to streamline loading states and skeleton rendering.
This commit is contained in:
@@ -6,6 +6,11 @@ import NotificationActions from './components/NotificationActions.vue';
|
||||
import NotificationList from './components/NotificationList.vue';
|
||||
import NotificationTabs from './components/NotificationTabs.vue';
|
||||
import { useNotifications } from '@/composables/useNotifications';
|
||||
import Inbox from '@/components/icons/Inbox.vue';
|
||||
import Video from '@/components/icons/Video.vue';
|
||||
import Credit from '@/components/icons/Credit.vue';
|
||||
import BellOff from '@/components/icons/BellOff.vue';
|
||||
import BellDot from '@/components/icons/BellDot.vue';
|
||||
|
||||
const activeTab = ref('all');
|
||||
const { t } = useTranslation();
|
||||
@@ -18,10 +23,10 @@ onMounted(() => {
|
||||
const unreadCount = computed(() => notificationStore.unreadCount.value);
|
||||
|
||||
const tabs = computed(() => [
|
||||
{ key: 'all', label: t('notification.tabs.all'), icon: 'i-lucide-inbox', count: notificationStore.notifications.value.length },
|
||||
{ key: 'unread', label: t('notification.tabs.unread'), icon: 'i-lucide-bell-dot', count: unreadCount.value },
|
||||
{ key: 'video', label: t('notification.tabs.videos'), icon: 'i-lucide-video', count: notificationStore.notifications.value.filter(n => n.type === 'video').length },
|
||||
{ key: 'payment', label: t('notification.tabs.payments'), icon: 'i-lucide-credit-card', count: notificationStore.notifications.value.filter(n => n.type === 'payment').length },
|
||||
{ key: 'all', label: t('notification.tabs.all'), icon: Inbox, count: notificationStore.notifications.value.length },
|
||||
{ key: 'unread', label: t('notification.tabs.unread'), icon: BellDot, count: unreadCount.value },
|
||||
{ key: 'video', label: t('notification.tabs.videos'), icon: Video, count: notificationStore.notifications.value.filter(n => n.type === 'video').length },
|
||||
{ key: 'payment', label: t('notification.tabs.payments'), icon: Credit, count: notificationStore.notifications.value.filter(n => n.type === 'payment').length },
|
||||
]);
|
||||
|
||||
const filteredNotifications = computed(() => {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import Bell from '@/components/icons/Bell.vue';
|
||||
import CheckIcon from '@/components/icons/CheckIcon.vue';
|
||||
import TrashIcon from '@/components/icons/TrashIcon.vue';
|
||||
import { useTranslation } from 'i18next-vue';
|
||||
|
||||
interface Props {
|
||||
@@ -21,7 +24,7 @@ const { t } = useTranslation();
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="stats flex items-center gap-4">
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<span class="i-lucide-bell w-4 h-4 text-gray-400"></span>
|
||||
<Bell filled class="w-4 h-4 text-gray-400" />
|
||||
<span class="text-gray-600">{{ t('notification.stats.total', { count: totalCount }) }}</span>
|
||||
</div>
|
||||
<div v-if="unreadCount > 0" class="flex items-center gap-2 text-sm">
|
||||
@@ -39,7 +42,7 @@ const { t } = useTranslation();
|
||||
class="px-3 py-2 text-sm font-medium text-gray-600 hover:text-primary
|
||||
hover:bg-gray-100 rounded-lg transition-colors flex items-center gap-2"
|
||||
>
|
||||
<span class="i-lucide-check-check w-4 h-4"></span>
|
||||
<CheckIcon class="w-4 h-4" />
|
||||
{{ t('notification.actions.markAllRead') }}
|
||||
</button>
|
||||
<button
|
||||
@@ -49,7 +52,7 @@ const { t } = useTranslation();
|
||||
class="px-3 py-2 text-sm font-medium text-gray-600 hover:text-red-600
|
||||
hover:bg-red-50 rounded-lg transition-colors flex items-center gap-2"
|
||||
>
|
||||
<span class="i-lucide-trash w-4 h-4"></span>
|
||||
<TrashIcon class="w-4 h-4" />
|
||||
{{ t('notification.actions.clearAll') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useTranslation } from 'i18next-vue';
|
||||
import NotificationItem from './NotificationItem.vue';
|
||||
import BellOff from '@/components/icons/BellOff.vue';
|
||||
|
||||
interface Notification {
|
||||
id: string;
|
||||
@@ -60,7 +61,7 @@ const { t } = useTranslation();
|
||||
class="py-16 text-center"
|
||||
>
|
||||
<div class="w-20 h-20 mx-auto mb-4 rounded-full bg-gray-100 flex items-center justify-center">
|
||||
<span class="i-lucide-bell-off w-10 h-10 text-gray-400"></span>
|
||||
<BellOff class="w-10 h-10 text-gray-400" />
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-1">{{ t('notification.empty.title') }}</h3>
|
||||
<p class="text-gray-500">{{ t('notification.empty.subtitle') }}</p>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
interface Tab {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
icon: any;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ const emit = defineEmits<{
|
||||
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-50'
|
||||
]"
|
||||
>
|
||||
<span :class="[tab.icon, 'w-4 h-4']"></span>
|
||||
<component :is="tab.icon" :filled="activeTab === tab.key" class="w-4 h-4" />
|
||||
{{ tab.label }}
|
||||
<span
|
||||
v-if="tab.count && tab.count > 0"
|
||||
|
||||
Reference in New Issue
Block a user