fix(ui): unify admin table toolbar layout with search and buttons in single row
Standardize filter bar layout across admin pages to place search/filters on left and action buttons on right within the same row, improving visual consistency and space utilization.
This commit is contained in:
@@ -1,8 +1,27 @@
|
||||
<template>
|
||||
<AppLayout>
|
||||
<TablePageLayout>
|
||||
<template #actions>
|
||||
<div class="flex justify-end gap-3">
|
||||
<template #filters>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<!-- Left: Search + Filters -->
|
||||
<div class="flex-1 sm:max-w-64">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.announcements.searchAnnouncements')"
|
||||
class="input"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="statusFilterOptions"
|
||||
class="w-40"
|
||||
@change="handleStatusChange"
|
||||
/>
|
||||
|
||||
<!-- Right: Action buttons -->
|
||||
<div class="flex flex-1 flex-wrap items-center justify-end gap-2">
|
||||
<button
|
||||
@click="loadAnnouncements"
|
||||
:disabled="loading"
|
||||
@@ -16,27 +35,6 @@
|
||||
{{ t('admin.announcements.createAnnouncement') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #filters>
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="max-w-md flex-1">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.announcements.searchAnnouncements')"
|
||||
class="input"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="statusFilterOptions"
|
||||
class="w-40"
|
||||
@change="handleStatusChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
<template>
|
||||
<AppLayout>
|
||||
<TablePageLayout>
|
||||
<template #actions>
|
||||
<div class="flex justify-end gap-3">
|
||||
<template #filters>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<!-- Left: Search + Filters -->
|
||||
<div class="flex-1 sm:max-w-64">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.promo.searchCodes')"
|
||||
class="input"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="filterStatusOptions"
|
||||
class="w-36"
|
||||
@change="loadCodes"
|
||||
/>
|
||||
|
||||
<!-- Right: Action buttons -->
|
||||
<div class="flex flex-1 flex-wrap items-center justify-end gap-2">
|
||||
<button
|
||||
@click="loadCodes"
|
||||
:disabled="loading"
|
||||
@@ -16,27 +35,6 @@
|
||||
{{ t('admin.promo.createCode') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #filters>
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="max-w-md flex-1">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.promo.searchCodes')"
|
||||
class="input"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="filterStatusOptions"
|
||||
class="w-36"
|
||||
@change="loadCodes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,9 +2,42 @@
|
||||
<AppLayout>
|
||||
<TablePageLayout>
|
||||
<template #filters>
|
||||
<div class="space-y-3">
|
||||
<!-- Row 1: Actions -->
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<!-- Left: Search + Filters -->
|
||||
<div class="relative w-full sm:w-64">
|
||||
<Icon
|
||||
name="search"
|
||||
size="md"
|
||||
class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
|
||||
/>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.proxies.searchProxies')"
|
||||
class="input pl-10"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-full sm:w-40">
|
||||
<Select
|
||||
v-model="filters.protocol"
|
||||
:options="protocolOptions"
|
||||
:placeholder="t('admin.proxies.allProtocols')"
|
||||
@change="loadProxies"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full sm:w-36">
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="statusOptions"
|
||||
:placeholder="t('admin.proxies.allStatus')"
|
||||
@change="loadProxies"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Right: All action buttons -->
|
||||
<div class="flex flex-1 flex-wrap items-center justify-end gap-2">
|
||||
<button
|
||||
@click="loadProxies"
|
||||
:disabled="loading"
|
||||
@@ -42,41 +75,6 @@
|
||||
{{ t('admin.proxies.createProxy') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Row 2: Search + Filters -->
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<div class="relative w-full sm:w-64">
|
||||
<Icon
|
||||
name="search"
|
||||
size="md"
|
||||
class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
|
||||
/>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="t('admin.proxies.searchProxies')"
|
||||
class="input pl-10"
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-full sm:w-40">
|
||||
<Select
|
||||
v-model="filters.protocol"
|
||||
:options="protocolOptions"
|
||||
:placeholder="t('admin.proxies.allProtocols')"
|
||||
@change="loadProxies"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full sm:w-36">
|
||||
<Select
|
||||
v-model="filters.status"
|
||||
:options="statusOptions"
|
||||
:placeholder="t('admin.proxies.allStatus')"
|
||||
@change="loadProxies"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,25 +1,10 @@
|
||||
<template>
|
||||
<AppLayout>
|
||||
<TablePageLayout>
|
||||
<template #actions>
|
||||
<div class="flex justify-end gap-3">
|
||||
<button
|
||||
@click="loadCodes"
|
||||
:disabled="loading"
|
||||
class="btn btn-secondary"
|
||||
:title="t('common.refresh')"
|
||||
>
|
||||
<Icon name="refresh" size="md" :class="loading ? 'animate-spin' : ''" />
|
||||
</button>
|
||||
<button @click="showGenerateDialog = true" class="btn btn-primary">
|
||||
{{ t('admin.redeem.generateCodes') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #filters>
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="max-w-md flex-1">
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<!-- Left: Search + Filters -->
|
||||
<div class="flex-1 sm:max-w-64">
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
@@ -28,7 +13,6 @@
|
||||
@input="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<Select
|
||||
v-model="filters.type"
|
||||
:options="filterTypeOptions"
|
||||
@@ -41,9 +25,23 @@
|
||||
class="w-36"
|
||||
@change="loadCodes"
|
||||
/>
|
||||
|
||||
<!-- Right: Action buttons -->
|
||||
<div class="flex flex-1 flex-wrap items-center justify-end gap-2">
|
||||
<button
|
||||
@click="loadCodes"
|
||||
:disabled="loading"
|
||||
class="btn btn-secondary"
|
||||
:title="t('common.refresh')"
|
||||
>
|
||||
<Icon name="refresh" size="md" :class="loading ? 'animate-spin' : ''" />
|
||||
</button>
|
||||
<button @click="handleExportCodes" class="btn btn-secondary">
|
||||
{{ t('admin.redeem.exportCsv') }}
|
||||
</button>
|
||||
<button @click="showGenerateDialog = true" class="btn btn-primary">
|
||||
{{ t('admin.redeem.generateCodes') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<TablePageLayout>
|
||||
<!-- Single Row: Search, Filters, and Actions -->
|
||||
<template #filters>
|
||||
<div class="flex w-full flex-col gap-3 md:flex-row md:flex-wrap-reverse md:items-center md:justify-between md:gap-4">
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<!-- Left: Search + Active Filters -->
|
||||
<div class="flex min-w-[280px] flex-1 flex-wrap content-start items-center gap-3 md:order-1">
|
||||
<div class="flex flex-1 flex-wrap items-center gap-3">
|
||||
<!-- Search Box -->
|
||||
<div class="relative w-full md:w-64">
|
||||
<Icon
|
||||
@@ -100,7 +100,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Right: Actions and Settings -->
|
||||
<div class="flex w-full items-center justify-between gap-2 md:order-2 md:ml-auto md:max-w-full md:flex-wrap md:justify-end md:gap-3">
|
||||
<div class="flex flex-wrap items-center justify-end gap-2">
|
||||
<!-- Mobile: Secondary buttons (icon only) -->
|
||||
<div class="flex items-center gap-2 md:contents">
|
||||
<!-- Refresh Button -->
|
||||
|
||||
Reference in New Issue
Block a user