feat: complete UI/UX improvements, vuesax icons, media server, and section management
This commit is contained in:
@@ -102,6 +102,8 @@ const groupTitle = (g: Group) => {
|
||||
return count ? `${g.name} (${count} محصول)` : g.name;
|
||||
};
|
||||
|
||||
const mobileTab = ref<"main" | "groups" | "media" | "seo">("main");
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
|
||||
@@ -113,11 +115,50 @@ onMounted(load);
|
||||
</a-button>
|
||||
</PageHeader>
|
||||
|
||||
<!-- Mobile Segmented Workflow Tabs -->
|
||||
<div class="lg:hidden mb-4 overflow-x-auto pb-1 scrollbar-none">
|
||||
<div class="flex items-center gap-1.5 min-w-max bg-gray-100 p-1 rounded-xl">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg px-3 py-1.5 text-xs font-bold transition-all"
|
||||
:class="mobileTab === 'main' ? 'bg-white text-orange-600 shadow-sm' : 'text-gray-600'"
|
||||
@click="mobileTab = 'main'"
|
||||
>
|
||||
اطلاعات اصلی
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg px-3 py-1.5 text-xs font-bold transition-all flex items-center gap-1"
|
||||
:class="mobileTab === 'groups' ? 'bg-white text-orange-600 shadow-sm' : 'text-gray-600'"
|
||||
@click="mobileTab = 'groups'"
|
||||
>
|
||||
<span>زیرگروهها</span>
|
||||
<span class="rounded-full bg-gray-200 px-1.5 py-0.2 text-[10px]">{{ model.groups.length }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg px-3 py-1.5 text-xs font-bold transition-all"
|
||||
:class="mobileTab === 'media' ? 'bg-white text-orange-600 shadow-sm' : 'text-gray-600'"
|
||||
@click="mobileTab = 'media'"
|
||||
>
|
||||
کاور و آیکون
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg px-3 py-1.5 text-xs font-bold transition-all"
|
||||
:class="mobileTab === 'seo' ? 'bg-white text-orange-600 shadow-sm' : 'text-gray-600'"
|
||||
@click="mobileTab = 'seo'"
|
||||
>
|
||||
سئو و انتشار
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-spin :spinning="loading">
|
||||
<a-form layout="vertical" @submit.prevent="save">
|
||||
<a-form layout="vertical" class="pb-20 lg:pb-0" @submit.prevent="save">
|
||||
<div class="grid gap-6 xl:grid-cols-3">
|
||||
<div class="space-y-6 xl:col-span-2">
|
||||
<a-card title="اطلاعات اصلی">
|
||||
<a-card title="اطلاعات اصلی" :class="mobileTab !== 'main' && 'max-lg:hidden'">
|
||||
<div class="grid gap-x-4 md:grid-cols-2">
|
||||
<FormField path="name" label="نام دسته" required>
|
||||
<a-input v-model:value="model.name" />
|
||||
@@ -144,7 +185,7 @@ onMounted(load);
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<a-card title="زیرگروهها" :body-style="{ background: '#fafafa' }">
|
||||
<a-card title="زیرگروهها" :body-style="{ background: '#fafafa' }" :class="mobileTab !== 'groups' && 'max-lg:hidden'">
|
||||
<p class="mb-4 text-sm text-gray-500">
|
||||
زیرگروهها در صفحه دسته بهصورت فیلتر نمایش داده میشوند. با حذف یک زیرگروه، محصولات آن بدون زیرگروه میمانند.
|
||||
</p>
|
||||
@@ -172,23 +213,23 @@ onMounted(load);
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<a-card title="انتشار">
|
||||
<a-card title="انتشار" :class="mobileTab !== 'seo' && 'max-lg:hidden'">
|
||||
<FormField path="isPublished">
|
||||
<a-switch v-model:checked="model.isPublished" />
|
||||
<span class="ms-2">{{ model.isPublished ? "در سایت نمایش داده میشود" : "مخفی" }}</span>
|
||||
</FormField>
|
||||
</a-card>
|
||||
<a-card title="تصویر کاور">
|
||||
<a-card title="تصویر کاور" :class="mobileTab !== 'media' && 'max-lg:hidden'">
|
||||
<FormField path="coverImageId">
|
||||
<ImageField :url="cover?.url" clearable @pick="pickCover" @clear="cover = null; model.coverImageId = null" />
|
||||
</FormField>
|
||||
</a-card>
|
||||
<a-card title="آیکون">
|
||||
<a-card title="آیکون" :class="mobileTab !== 'media' && 'max-lg:hidden'">
|
||||
<FormField path="icon">
|
||||
<IconSelect v-model="model.icon" allow-clear />
|
||||
</FormField>
|
||||
</a-card>
|
||||
<a-card title="سئو">
|
||||
<a-card title="سئو" :class="mobileTab !== 'seo' && 'max-lg:hidden'">
|
||||
<FormField path="seoTitle" label="عنوان صفحه" hint="خالی = نام دسته">
|
||||
<a-input v-model:value="model.seoTitle" :maxlength="120" show-count />
|
||||
</FormField>
|
||||
@@ -200,4 +241,28 @@ onMounted(load);
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
|
||||
<!-- Mobile Sticky Bottom Action Bar -->
|
||||
<div class="lg:hidden fixed bottom-0 inset-x-0 z-30 border-t border-gray-200 bg-white/95 px-4 py-2.5 backdrop-blur-md shadow-lg flex items-center justify-between gap-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<a-switch v-model:checked="model.isPublished" size="small" />
|
||||
<span class="text-xs font-medium text-gray-700">{{ model.isPublished ? "انتشار" : "پیشنویس" }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<a
|
||||
v-if="model.slug"
|
||||
:href="`/categories/${model.slug}`"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<a-button size="middle" class="!px-3" title="مشاهده در سایت">
|
||||
<template #icon><VuesaxIcon name="eye" :size="16" /></template>
|
||||
</a-button>
|
||||
</a>
|
||||
<a-button type="primary" size="middle" class="!font-bold !px-5" :loading="saving" @click="save">
|
||||
<template #icon><VuesaxIcon name="save-2" :size="16" /></template>
|
||||
ذخیره تغییرات
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user