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>