feat(products): port missing variant fields from henza and redesign variant modal
This commit is contained in:
@@ -160,10 +160,18 @@
|
||||
<span v-if="record.grams != null">{{ record.grams }} <small class="muted">گرم</small></span>
|
||||
<span v-else class="muted">—</span>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'color'">
|
||||
<span v-if="record.color_str">{{ record.color_str }}</span>
|
||||
<span v-else class="muted">—</span>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'percentage_pay'">
|
||||
<span v-if="record.percentage_pay != null">{{ record.percentage_pay }}<small class="muted">٪</small></span>
|
||||
<span v-else class="muted">—</span>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'rial_pay'">
|
||||
<span v-if="record.rial_pay != null">{{ Number(record.rial_pay).toLocaleString('fa-IR') }} <small class="muted">ریال</small></span>
|
||||
<span v-else class="muted">—</span>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'op'">
|
||||
<div class="pf-table__ops">
|
||||
<a-tooltip v-if="hasPermission('product.list.variants.edit')" title="ویرایش">
|
||||
@@ -319,82 +327,164 @@
|
||||
</a-form>
|
||||
</a-spin>
|
||||
|
||||
<!-- variant add/edit -->
|
||||
<!-- variant add/edit modal (Compact Widescreen Layout - No Page Scroll) -->
|
||||
<a-modal
|
||||
v-model:open="variantModal"
|
||||
:title="editingIndex === null ? 'افزودن تنوع' : 'ویرایش تنوع'"
|
||||
:width="640"
|
||||
:width="860"
|
||||
wrap-class-name="pf-variant-modal"
|
||||
:footer="null"
|
||||
:destroy-on-close="true"
|
||||
centered
|
||||
>
|
||||
<a-form layout="vertical" class="pf-form variant-form">
|
||||
<!--
|
||||
تصویر تنوع — one image, and it must be one of THIS product's images:
|
||||
an upload here is also added to the site gallery, or an existing
|
||||
gallery image can be reused so one photo backs several weights.
|
||||
Unsaved images have no id yet, so the variant carries the URL and the
|
||||
API resolves it after saving the images.
|
||||
-->
|
||||
<div class="variant-form__media">
|
||||
<!-- انتخاب تصویر تنوع (کاملاً طبق توافق PROTECTED §B) -->
|
||||
<a-form-item label="تصویر اختصاصی این تنوع" class="variant-image-item">
|
||||
<div v-if="gallery.length" class="variant-picker">
|
||||
<button
|
||||
type="button"
|
||||
class="variant-picker__item"
|
||||
:class="{ 'is-on': !variantForm.image_id }"
|
||||
title="بدون تصویر اختصاصی"
|
||||
@click="pickVariantImage(null)"
|
||||
>
|
||||
<span class="variant-picker__none">بدون تصویر</span>
|
||||
</button>
|
||||
<button
|
||||
v-for="img in gallery"
|
||||
:key="img.id"
|
||||
type="button"
|
||||
class="variant-picker__item"
|
||||
:class="{ 'is-on': variantForm.image_id === img.id }"
|
||||
@click="pickVariantImage(img)"
|
||||
>
|
||||
<img :src="img.url" alt="" />
|
||||
</button>
|
||||
<template #title>
|
||||
<div class="vmodal-header">
|
||||
<div class="vmodal-header__icon">
|
||||
<AppstoreOutlined />
|
||||
</div>
|
||||
<div class="vmodal-header__text">
|
||||
<h3>{{ editingIndex === null ? 'افزودن تنوع جدید' : 'ویرایش تنوع' }}</h3>
|
||||
<p>مشخصات، قیمتگذاری و تصویر این تنوع را وارد کنید.</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<a-form layout="vertical" class="vmodal-form">
|
||||
<div class="vmodal-cols">
|
||||
<!-- ── ستون راست: مشخصات اصلی و قیمت ── -->
|
||||
<div class="vmodal-col">
|
||||
<div class="vmodal-card">
|
||||
<div class="vmodal-card__head">مشخصات اصلی</div>
|
||||
<div class="vmodal-grid vmodal-grid--2">
|
||||
<a-form-item label="عنوان تنوع" required class="vmodal-item">
|
||||
<a-input v-model:value="variantForm.title" placeholder="مثلاً: ۵ گرمی" />
|
||||
</a-form-item>
|
||||
<a-form-item label="وزن خام" class="vmodal-item">
|
||||
<a-input-number
|
||||
v-model:value="variantForm.grams"
|
||||
class="w-full"
|
||||
:step="0.001"
|
||||
addon-after="گرم"
|
||||
placeholder="۰.۰۰۰"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="vmodal-grid vmodal-grid--2">
|
||||
<a-form-item label="تعداد موجودی" class="vmodal-item">
|
||||
<a-input-number v-model:value="variantForm.qty" class="w-full" :min="0" placeholder="۰" />
|
||||
</a-form-item>
|
||||
<a-form-item label="رنگ طلا" class="vmodal-item">
|
||||
<a-select v-model:value="variantForm.color" placeholder="انتخاب رنگ" allow-clear>
|
||||
<a-select-option v-for="c in colorOptions" :key="c.id" :value="c.id">
|
||||
<div class="color-opt">
|
||||
<span class="color-opt__dot" :class="`color-opt__dot--${c.id}`"></span>
|
||||
<span>{{ c.title }}</span>
|
||||
</div>
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="vmodal-switches">
|
||||
<label class="vmodal-switch-box">
|
||||
<span class="vmodal-switch-label">فعال برای فروش</span>
|
||||
<a-switch v-model:checked="variantForm.is_active" size="small" />
|
||||
</label>
|
||||
<label class="vmodal-switch-box">
|
||||
<span class="vmodal-switch-label">پیشسفارش</span>
|
||||
<a-switch v-model:checked="variantForm.is_pre_order" size="small" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vmodal-card">
|
||||
<div class="vmodal-card__head">اجرت و قیمتگذاری</div>
|
||||
<div class="vmodal-grid vmodal-grid--2">
|
||||
<a-form-item label="اجرت درصدی" class="vmodal-item">
|
||||
<a-input-number
|
||||
v-model:value="variantForm.percentage_pay"
|
||||
class="w-full"
|
||||
:step="0.1"
|
||||
addon-after="٪"
|
||||
placeholder="۰"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="اجرت ریالی" class="vmodal-item">
|
||||
<a-input-number
|
||||
v-model:value="variantForm.rial_pay"
|
||||
class="w-full"
|
||||
:step="50000"
|
||||
addon-after="ریال"
|
||||
placeholder="۰"
|
||||
:formatter="(val: any) => val ? `${val}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',') : ''"
|
||||
:parser="(val: any) => val ? val.replace(/,/g, '') : ''"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── ستون چپ: تصویر و توضیحات ── -->
|
||||
<div class="vmodal-col">
|
||||
<div class="vmodal-card">
|
||||
<div class="vmodal-card__head">تصویر اختصاصی تنوع</div>
|
||||
<div v-if="gallery.length" class="vmodal-picker">
|
||||
<button
|
||||
type="button"
|
||||
class="vmodal-picker__item"
|
||||
:class="{ 'is-active': !variantForm.image_id }"
|
||||
title="بدون تصویر"
|
||||
@click="pickVariantImage(null)"
|
||||
>
|
||||
<PictureOutlined />
|
||||
<span>بدون عکس</span>
|
||||
</button>
|
||||
<button
|
||||
v-for="img in gallery"
|
||||
:key="img.id"
|
||||
type="button"
|
||||
class="vmodal-picker__item"
|
||||
:class="{ 'is-active': variantForm.image_id === img.id }"
|
||||
@click="pickVariantImage(img)"
|
||||
>
|
||||
<img :src="img.url" alt="" />
|
||||
<div v-if="variantForm.image_id === img.id" class="vmodal-picker__check">
|
||||
<CheckOutlined />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="vmodal-picker-empty">
|
||||
تصویری در گالری ثبت نشده است (میتوانید در بخش گالری محصول تصویر بارگذاری کنید).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vmodal-card">
|
||||
<div class="vmodal-card__head">توضیحات تکمیلی</div>
|
||||
<a-form-item label="توضیح مختصر" class="vmodal-item">
|
||||
<a-input v-model:value="variantForm.details" placeholder="مثلاً: طراحی مات با تراش برلیان" />
|
||||
</a-form-item>
|
||||
<a-form-item label="توضیحات کامل" class="vmodal-item mb-0">
|
||||
<a-textarea
|
||||
v-model:value="variantForm.description"
|
||||
style="height: 95px; min-height: 95px; max-height: 95px; resize: none;"
|
||||
placeholder="ویژگیهای خاص این تنوع..."
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<a-alert
|
||||
v-else
|
||||
type="info"
|
||||
show-icon
|
||||
:message="id ? 'برای این محصول تصویری در گالری ثبت نشده است.' : 'ابتدا محصول را ذخیره کنید تا تصاویر گالری برای انتخاب فعال شوند.'"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="variant-form__fields">
|
||||
<a-form-item label="عنوان" required>
|
||||
<a-input v-model:value="variantForm.title" placeholder="مثلاً: ۵ گرمی" />
|
||||
</a-form-item>
|
||||
<div class="pf-grid-3">
|
||||
<a-form-item label="وزن">
|
||||
<a-input-number v-model:value="variantForm.grams" class="w-full" :step="0.001" addon-after="گرم" />
|
||||
</a-form-item>
|
||||
<a-form-item label="اجرت درصدی">
|
||||
<a-input-number v-model:value="variantForm.percentage_pay" class="w-full" :step="0.1" addon-after="٪" />
|
||||
</a-form-item>
|
||||
<a-form-item label="تعداد">
|
||||
<a-input-number v-model:value="variantForm.qty" class="w-full" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item label="وضعیت" class="mb-0">
|
||||
<a-space :size="24">
|
||||
<a-checkbox v-model:checked="variantForm.is_active">فعال</a-checkbox>
|
||||
<a-checkbox v-model:checked="variantForm.is_pre_order">پیش سفارش</a-checkbox>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
<!-- ── دکمههای فوتر ── -->
|
||||
<div class="vmodal-footer">
|
||||
<a-button class="vmodal-footer__cancel" @click="variantModal = false">
|
||||
انصراف
|
||||
</a-button>
|
||||
<a-button type="primary" class="vmodal-footer__submit" @click="saveVariant">
|
||||
<template #icon><CheckOutlined /></template>
|
||||
{{ editingIndex === null ? 'افزودن تنوع' : 'ذخیره تغییرات' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
<p v-if="users.isSuperAdmin" class="variant-form__hint">تصویر بارگذاریشده به گالری سایت محصول هم اضافه میشود.</p>
|
||||
<template #footer>
|
||||
<a-button @click="variantModal = false">انصراف</a-button>
|
||||
<a-button type="primary" @click="saveVariant">ثبت</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -475,10 +565,16 @@ interface VariantRow {
|
||||
qty?: number;
|
||||
is_active: boolean;
|
||||
is_pre_order: boolean;
|
||||
color?: number | null;
|
||||
color_str?: string | null;
|
||||
rial_pay?: number | null;
|
||||
details?: string | null;
|
||||
description?: string | null;
|
||||
image_id?: string | null;
|
||||
image_url?: string | null;
|
||||
}
|
||||
|
||||
const colorOptions = ref<Array<{ id: number; title: string }>>([]);
|
||||
const variants = ref<VariantRow[]>([]);
|
||||
const variantModal = ref(false);
|
||||
const editingIndex = ref<number | null>(null);
|
||||
@@ -490,6 +586,11 @@ const variantForm = reactive<VariantRow>({
|
||||
qty: 0,
|
||||
is_active: true,
|
||||
is_pre_order: false,
|
||||
color: undefined,
|
||||
color_str: undefined,
|
||||
rial_pay: undefined,
|
||||
details: '',
|
||||
description: '',
|
||||
image_id: null,
|
||||
image_url: null,
|
||||
});
|
||||
@@ -503,7 +604,9 @@ const variantColumns = [
|
||||
{ title: 'تصویر', dataIndex: 'image', width: 68, align: 'center' as const },
|
||||
{ title: 'عنوان تنوع', dataIndex: 'title' },
|
||||
{ title: 'وزن', dataIndex: 'grams', align: 'right' as const },
|
||||
{ title: 'رنگ', dataIndex: 'color', align: 'center' as const },
|
||||
{ title: 'اجرت', dataIndex: 'percentage_pay', align: 'right' as const },
|
||||
{ title: 'اجرت ریالی', dataIndex: 'rial_pay', align: 'right' as const },
|
||||
{ title: 'موجودی', dataIndex: 'qty', align: 'center' as const },
|
||||
{ title: 'وضعیت', dataIndex: 'is_active', align: 'center' as const },
|
||||
{ title: 'پیشسفارش', dataIndex: 'is_pre_order', align: 'center' as const },
|
||||
@@ -525,6 +628,11 @@ function showModal(record?: VariantRow, index?: number) {
|
||||
qty: 0,
|
||||
is_active: true,
|
||||
is_pre_order: false,
|
||||
color: undefined,
|
||||
color_str: undefined,
|
||||
rial_pay: undefined,
|
||||
details: '',
|
||||
description: '',
|
||||
image_id: null,
|
||||
image_url: null,
|
||||
});
|
||||
@@ -537,6 +645,9 @@ function saveVariant() {
|
||||
message.error('عنوان تنوع الزامی است');
|
||||
return;
|
||||
}
|
||||
const matchedColor = colorOptions.value.find((c) => c.id === variantForm.color);
|
||||
variantForm.color_str = matchedColor ? matchedColor.title : null;
|
||||
|
||||
const row: VariantRow = { ...variantForm };
|
||||
if (editingIndex.value === null) {
|
||||
variants.value.push(row);
|
||||
@@ -581,6 +692,10 @@ async function handleSubmit() {
|
||||
qty: v.qty,
|
||||
is_active: v.is_active,
|
||||
is_pre_order: v.is_pre_order,
|
||||
color: v.color ?? null,
|
||||
rial_pay: v.rial_pay ?? null,
|
||||
details: v.details || null,
|
||||
description: v.description || null,
|
||||
image_id: v.image_id ?? null,
|
||||
})),
|
||||
};
|
||||
@@ -600,10 +715,11 @@ async function handleSubmit() {
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const [b, c, col] = await Promise.all([
|
||||
const [b, c, col, colorsRes] = await Promise.all([
|
||||
api.get('brand'),
|
||||
api.post('category'),
|
||||
users.isSuperAdmin ? api.get('admin/products/collections') : Promise.resolve({ data: [] }),
|
||||
api.get('admin/products/colors').catch(() => ({ data: [] })),
|
||||
]);
|
||||
brands.value = b.data;
|
||||
categories.value = (c.data.rows ?? c.data).map((x: any) => ({
|
||||
@@ -612,6 +728,7 @@ onMounted(async () => {
|
||||
type: x.type,
|
||||
}));
|
||||
collections.value = col.data;
|
||||
colorOptions.value = colorsRes.data ?? [];
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -646,6 +763,11 @@ onMounted(async () => {
|
||||
qty: v.qty,
|
||||
is_active: v.is_active,
|
||||
is_pre_order: v.is_pre_order,
|
||||
color: v.color != null ? Number(v.color) : undefined,
|
||||
color_str: v.color_str ?? null,
|
||||
rial_pay: v.rial_pay != null ? Number(v.rial_pay) : undefined,
|
||||
details: v.details ?? '',
|
||||
description: v.description ?? '',
|
||||
image_id: v.image_id ?? null,
|
||||
image_url: v.image?.url ?? null,
|
||||
}));
|
||||
@@ -1146,72 +1268,246 @@ onMounted(async () => {
|
||||
color: #595959;
|
||||
}
|
||||
|
||||
/* ── مدال تنوع و انتخابگر تصویر (PROTECTED §B) ── */
|
||||
.form-grid-3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
/* ── استایل مدرن، فشرده و دو ستونه مودال تنوع (بدون اسکرول) ── */
|
||||
.vmodal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 0 10px;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
}
|
||||
.variant-switches-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin: 14px 0 18px;
|
||||
padding: 12px 14px;
|
||||
background: #fafbfc;
|
||||
border: 1px solid #f0f2f5;
|
||||
.vmodal-header__icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.switch-box {
|
||||
background: rgba(28, 45, 86, 0.08);
|
||||
color: #1c2d56;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.switch-box-label {
|
||||
font-size: 13px;
|
||||
color: #262626;
|
||||
.vmodal-header__text h3 {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #1a202c;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.vmodal-header__text p {
|
||||
margin: 2px 0 0;
|
||||
font-size: 11.5px;
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
.variant-picker {
|
||||
.vmodal-form {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.vmodal-cols {
|
||||
display: grid;
|
||||
grid-template-columns: 1.05fr 0.95fr;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.vmodal-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.vmodal-card {
|
||||
background: #fafafa;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
.vmodal-card__head {
|
||||
font-size: 12.5px;
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 4px;
|
||||
border-bottom: 1px dashed #e2e8f0;
|
||||
position: relative;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.vmodal-card__head::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 12px;
|
||||
background: #1c2d56;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.vmodal-grid {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
.vmodal-grid--2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.vmodal-item {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.vmodal-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.vmodal-item :deep(.ant-form-item-label) {
|
||||
padding-bottom: 2px !important;
|
||||
}
|
||||
.vmodal-item :deep(.ant-form-item-label > label) {
|
||||
font-size: 11.5px;
|
||||
font-weight: 600;
|
||||
color: #4a5568;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* سوئیچهای فشرده */
|
||||
.vmodal-switches {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 6px;
|
||||
padding-top: 6px;
|
||||
border-top: 1px dashed #e2e8f0;
|
||||
}
|
||||
.vmodal-switch-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 6px 10px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
.vmodal-switch-box:hover {
|
||||
border-color: #cbd5e0;
|
||||
}
|
||||
.vmodal-switch-label {
|
||||
font-size: 11.5px;
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
/* گزینههای رنگ طلا */
|
||||
.color-opt {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.color-opt__dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
display: inline-block;
|
||||
}
|
||||
.color-opt__dot--0 { background: #fdfdfd; } /* سفید */
|
||||
.color-opt__dot--1 { background: #ffd700; } /* زرد */
|
||||
.color-opt__dot--2 { background: #795548; } /* شکلاتی */
|
||||
.color-opt__dot--3 { background: #b76e79; } /* رزگلد */
|
||||
|
||||
/* انتخابگر تصویر تنوع (فشرده) */
|
||||
.vmodal-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.variant-picker__item {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
max-height: 125px;
|
||||
overflow-y: auto;
|
||||
padding: 2px;
|
||||
border: 2px solid #d9d9d9;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
.vmodal-picker__item {
|
||||
position: relative;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
padding: 2px;
|
||||
border: 1.5px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.15s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 10px;
|
||||
color: #a0aec0;
|
||||
}
|
||||
.variant-picker__item:hover {
|
||||
.vmodal-picker__item:hover {
|
||||
border-color: #1c2d56;
|
||||
}
|
||||
.variant-picker__item img {
|
||||
.vmodal-picker__item img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
}
|
||||
.variant-picker__item.is-on {
|
||||
border-color: #1890ff;
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
.vmodal-picker__item.is-active {
|
||||
border-color: #1c2d56;
|
||||
box-shadow: 0 0 0 2px rgba(28, 45, 86, 0.2);
|
||||
}
|
||||
.variant-picker__none {
|
||||
.vmodal-picker__check {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background: #1c2d56;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 8px;
|
||||
}
|
||||
.vmodal-picker-empty {
|
||||
font-size: 11px;
|
||||
color: #8c8c8c;
|
||||
line-height: 1.3;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
border: 1px dashed #e2e8f0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* فوتر اختصاصی مودال */
|
||||
.vmodal-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding-top: 10px;
|
||||
margin-top: 8px;
|
||||
border-top: 1px solid #edf2f7;
|
||||
}
|
||||
.vmodal-footer__cancel {
|
||||
border-radius: 6px;
|
||||
min-width: 80px;
|
||||
}
|
||||
.vmodal-footer__submit {
|
||||
border-radius: 6px;
|
||||
background: #1c2d56;
|
||||
border-color: #1c2d56;
|
||||
min-width: 110px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.vmodal-footer__submit:hover {
|
||||
background: #2b427a !important;
|
||||
border-color: #2b427a !important;
|
||||
}
|
||||
|
||||
/* ── ریسپانسیو ── */
|
||||
|
||||
Reference in New Issue
Block a user