Ad Banners/Advert
The Ad Banners page allows admins to view, search, and manage all advertisement banners displayed in the system. It includes support for adding new banners via a modal form and viewing banner details via a reusable component.
File Location: pages/advert.vue (or similar)
Features
✅ Banner listing in a responsive grid
✅ Search functionality with live input binding
✅ Add New Banner modal form
✅ Status indication for banners (e.g., checked/active)
✅ Loading state via BasePageLoading
✅ Modular component architecture using BannerAdvertBanner and BannerAddBanner
<template>
<section class="bg-neutral-10 p-6 rounded-lg min-h-[100%]">
<div class="">
<BasePageLoading v-if="loading" />
<!-- Page Header -->
<div class="flex items-center mb-1">
<h5 class="capitalize">All Ad Banners</h5>
<div
class="flex items-center ml-2 bg-neutral-20 border border-[#D0D5DD] py-[1px] px-[6px] rounded-full b-shadow"
>
<div class="w-[6px] h-[6px] rounded-full bg-[#F2AE2A] mr-[6px]"></div>
<span class="text-neutral-300 body-xsmall">{{ banners.length }} Banners</span>
</div>
</div>
<p class="body-small text-neutral-200 mb-8">Add and manage all advert banners</p>
<!-- Search and Add Button -->
<div class="sm:flex justify-between items-center mb-4">
<div class="sm:w-[274px] w-full max-w-full sm:mb-0 mb-4">
<IconField>
<InputIcon class="pi pi-search" />
<InputText v-model="search" @input="onInput" placeholder="Search" class="w-full" />
</IconField>
</div>
<CommonButton
title="Add New Banner"
bgColor="bg-secondary-300 text-sm"
textColor="text-primary-300 font-medium !h-[40px]"
type="button"
createIcon="plus"
@click="addBanner = true"
/>
</div>
<!-- Advert Banners Grid -->
<div class="grid md:grid-cols-2 xl:grid-cols-3 gap-4">
<BannerAdvertBanner
@onView="onViewDeatails"
v-for="(banner, index) in banners"
:key="index"
:banner="banner"
/>
</div>
<!-- Add Banner Dialog -->
<Dialog
v-model:visible="addBanner"
modal
:show-header="false"
class="w-full max-w-md rounded-lg p-0 custom-modal"
>
<div class="flex items-center justify-between px-6 py-4 bg-neutral-20">
<div class="flex items-center gap-3">
<div class="">
<BaseCustomIcon name="advert" />
</div>
<h5 class="text-base">Add New Banner</h5>
</div>
<button @click="addBanner = false">
<i
class="pi pi-times text-neutral-500 text-base hover:bg-primary-50 p-3 hover:rounded-full"
/>
</button>
</div>
<BannerAddBanner @close="addBanner = false" @proceed="handleProceed" />
</Dialog>
<!-- Add Banner Dialog -->
<Dialog
v-model:visible="addBanner"
modal
:show-header="false"
class="w-full max-w-md rounded-lg p-0 custom-modal"
>
<div class="flex items-center justify-between px-6 py-4 bg-neutral-20">
<div class="flex items-center gap-3">
<div class="">
<BaseCustomIcon name="advert" />
</div>
<h5 class="text-base">Add New Banner</h5>
</div>
<button @click="addBanner = false">
<i
class="pi pi-times text-neutral-500 text-base hover:bg-primary-50 p-3 hover:rounded-full"
/>
</button>
</div>
<BannerAddBanner @close="addBanner = false" @proceed="handleProceed" />
</Dialog>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue'
definePageMeta({
layout: 'default', // Specify the layout to use
customProp: 'Ad Banner' // Define your custom prop
})
useHead({
title: 'Ad Banner | Attafly Admin'
})
const addBanner = ref(false)
const search = ref('')
const loading = ref(false)
// Mock Data for Banners
const banners = ref([
{
image: 'https://res.cloudinary.com/dlzc5sld6/image/upload/v1744122772/image_4_xv23ob.png',
title: 'Sun King Solar Advert 2025',
checked: false,
date: '23 Jan, 2025'
},
{
image: 'https://res.cloudinary.com/dlzc5sld6/image/upload/v1744122772/image_2_q8p7f3.png',
title: 'TotalEnergy Solar Advert',
checked: true,
date: '1 Feb, 2025'
},
{
image: 'https://res.cloudinary.com/dlzc5sld6/image/upload/v1744122772/image_3_qmzwk0.png',
title: 'Solyn Energy Advert',
checked: false,
date: '10 Feb, 2025'
}
])
const onInput = () => {
console.log('Search input:', search.value)
}
</script>