Initial admin edits
This commit is contained in:
+218
-115
@@ -8,17 +8,22 @@ import BaseEmptyState from '@/components/ui/BaseEmptyState.vue'
|
||||
import ActiveSwitchCell from '@/components/ui/ActiveSwitchCell.vue'
|
||||
import AdminIcon from '@/components/icons/AdminIcon.vue'
|
||||
import AdminSelect from '@/components/ui/AdminSelect.vue'
|
||||
import { brandsApi, companiesApi, productsApi, settingsApi, type Brand } from '@/services/api'
|
||||
import { companiesApi, productsApi, settingsApi } from '@/services/api'
|
||||
import { ApiError } from '@/services/http'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { confirm } from '@/composables/useConfirm'
|
||||
import { formatCurrency, formatNumber } from '@/utils/format'
|
||||
import type { Company, Product } from '@/types'
|
||||
import AdminCurrencyInput from '@/components/ui/AdminCurrencyInput.vue'
|
||||
import { toCssBackgroundUrl } from '@/utils/catalogImage'
|
||||
import {
|
||||
PAYMENT_RECIPIENT_COMPANY_SLUG,
|
||||
productCompanyIdForForm,
|
||||
resolveProductCompanyPayload,
|
||||
} from '@/utils/company'
|
||||
|
||||
const productList = ref<Product[]>([])
|
||||
const companies = ref<Company[]>([])
|
||||
const brands = ref<Brand[]>([])
|
||||
const usageOptions = ref<Array<{ value: string; label: string }>>([
|
||||
{ value: 'trousers', label: 'شلوار' },
|
||||
{ value: 'suit', label: 'کتوشلوار' },
|
||||
@@ -47,25 +52,17 @@ const companyFilterOptions = computed(() => [
|
||||
})),
|
||||
])
|
||||
|
||||
const companyFormOptions = computed(() =>
|
||||
companies.value
|
||||
.filter((c) => c.isActive)
|
||||
.map((company) => ({
|
||||
value: company.id,
|
||||
label: company.name,
|
||||
})),
|
||||
)
|
||||
|
||||
const brandFormOptions = computed(() => [
|
||||
{ value: '', label: 'بدون برند' },
|
||||
...brands.value
|
||||
.filter((b) => b.isActive)
|
||||
.map((b) => ({ value: b.id, label: b.name })),
|
||||
])
|
||||
const companyFormOptions = computed(() => {
|
||||
const opts = [{ value: '', label: 'نادمی تکس (پیشفرض)' }]
|
||||
for (const company of companies.value) {
|
||||
if (!company.isActive || company.slug === PAYMENT_RECIPIENT_COMPANY_SLUG) continue
|
||||
opts.push({ value: company.id, label: company.name })
|
||||
}
|
||||
return opts
|
||||
})
|
||||
|
||||
const emptyForm = () => ({
|
||||
companyId: companies.value[0]?.id ?? '',
|
||||
brandId: '',
|
||||
companyId: '',
|
||||
name: '',
|
||||
color: '',
|
||||
productCode: '',
|
||||
@@ -79,6 +76,7 @@ const emptyForm = () => ({
|
||||
composition: '',
|
||||
weaveType: '',
|
||||
subtitle: '',
|
||||
specs: '',
|
||||
rollMeters: 50,
|
||||
isNew: false,
|
||||
generalImages: [] as string[],
|
||||
@@ -93,7 +91,7 @@ const form = reactive(emptyForm())
|
||||
|
||||
const isModalOpen = computed(() => modalMode.value !== null)
|
||||
const modalTitle = computed(() => (modalMode.value === 'edit' ? 'ویرایش محصول' : 'افزودن محصول'))
|
||||
const isFormValid = computed(() => form.name.trim() && form.companyId && form.minMeterage > 0)
|
||||
const isFormValid = computed(() => form.name.trim() && form.minMeterage > 0)
|
||||
const hasActiveFilters = computed(
|
||||
() => searchQuery.value.trim().length > 0 || companyFilter.value !== 'all',
|
||||
)
|
||||
@@ -119,15 +117,13 @@ const filteredProducts = computed(() => {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [productsData, companiesData, brandsData, settings] = await Promise.all([
|
||||
const [productsData, companiesData, settings] = await Promise.all([
|
||||
productsApi.list(),
|
||||
companiesApi.list(),
|
||||
brandsApi.list(),
|
||||
settingsApi.get().catch(() => null),
|
||||
])
|
||||
productList.value = productsData
|
||||
companies.value = companiesData
|
||||
brands.value = brandsData
|
||||
if (settings?.categoryDefsJson?.usage?.length) {
|
||||
usageOptions.value = [
|
||||
...settings.categoryDefsJson.usage.map((item) => ({
|
||||
@@ -169,8 +165,7 @@ async function openEditModal(product: Product) {
|
||||
} catch {
|
||||
/* از ردیف جدول */
|
||||
}
|
||||
form.companyId = product.companyId ?? companies.value[0]?.id ?? ''
|
||||
form.brandId = product.brandId ?? ''
|
||||
form.companyId = productCompanyIdForForm(product.companyId, companies.value)
|
||||
form.name = product.name
|
||||
form.color = product.color
|
||||
form.productCode = product.productCode
|
||||
@@ -184,10 +179,15 @@ async function openEditModal(product: Product) {
|
||||
form.composition = (product as { composition?: string }).composition ?? ''
|
||||
form.weaveType = (product as { weaveType?: string }).weaveType ?? ''
|
||||
form.subtitle = (product as { subtitle?: string }).subtitle ?? ''
|
||||
form.specs = (product as { specs?: string }).specs ?? ''
|
||||
form.rollMeters = (product as { rollMeters?: number }).rollMeters ?? 50
|
||||
form.isNew = (product as { isNew?: boolean }).isNew ?? false
|
||||
form.generalImages = [...(product.imageUrls ?? [])]
|
||||
const colors = product.colors ?? []
|
||||
const colors = product.colors?.length
|
||||
? product.colors
|
||||
: product.color?.trim()
|
||||
? [product.color.trim()]
|
||||
: []
|
||||
if (colors.length) {
|
||||
form.colorRows = colors.map((name, index) => {
|
||||
const fromList = product.colorVariantImages?.[index]?.[0]
|
||||
@@ -199,7 +199,7 @@ async function openEditModal(product: Product) {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
form.colorRows = [{ id: crypto.randomUUID(), name: product.color || '', imageUrl: '' }]
|
||||
form.colorRows = [{ id: crypto.randomUUID(), name: '', imageUrl: '' }]
|
||||
}
|
||||
formError.value = ''
|
||||
}
|
||||
@@ -270,14 +270,17 @@ function closeModal() {
|
||||
|
||||
async function submitProduct() {
|
||||
if (!isFormValid.value) {
|
||||
formError.value = 'نام محصول، شرکت و حداقل متراژ الزامی هستند.'
|
||||
formError.value = 'نام محصول و حداقل متراژ الزامی هستند.'
|
||||
return
|
||||
}
|
||||
|
||||
const company = companies.value.find((c) => c.id === form.companyId)
|
||||
if (!company) {
|
||||
formError.value = 'شرکت معتبر انتخاب کنید.'
|
||||
return
|
||||
const companyIdPayload = resolveProductCompanyPayload(form.companyId)
|
||||
if (form.companyId.trim()) {
|
||||
const company = companies.value.find((c) => c.id === form.companyId)
|
||||
if (!company?.isActive) {
|
||||
formError.value = 'شرکت معتبر انتخاب کنید.'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const { colorEntries, imageUrls } = buildProductMedia()
|
||||
@@ -287,6 +290,7 @@ async function submitProduct() {
|
||||
composition: form.composition.trim() || null,
|
||||
weaveType: form.weaveType.trim() || null,
|
||||
subtitle: form.subtitle.trim() || null,
|
||||
specs: form.specs.trim() || undefined,
|
||||
rollMeters: form.rollMeters,
|
||||
isNew: form.isNew,
|
||||
colorsJson: colorEntries,
|
||||
@@ -297,6 +301,7 @@ async function submitProduct() {
|
||||
try {
|
||||
if (modalMode.value === 'edit' && editingId.value) {
|
||||
await productsApi.update(editingId.value, {
|
||||
companyId: companyIdPayload,
|
||||
name: form.name.trim(),
|
||||
color: form.color.trim() || colorEntries[0]?.name || '—',
|
||||
code: productCode,
|
||||
@@ -314,7 +319,7 @@ async function submitProduct() {
|
||||
toast.success('اطلاعات محصول بهروزرسانی شد.')
|
||||
} else {
|
||||
const created = await productsApi.create({
|
||||
companyId: company.id,
|
||||
companyId: companyIdPayload,
|
||||
name: form.name.trim(),
|
||||
color: form.color.trim() || colorEntries[0]?.name || '—',
|
||||
code: productCode,
|
||||
@@ -324,7 +329,6 @@ async function submitProduct() {
|
||||
price: form.price,
|
||||
internalStock: form.internalStock,
|
||||
isActive: form.isActive,
|
||||
brandId: form.brandId || null,
|
||||
...catalogPayload,
|
||||
})
|
||||
productList.value.push(created)
|
||||
@@ -345,6 +349,24 @@ async function persistActive(id: string, isActive: boolean) {
|
||||
await productsApi.setActive(id, isActive)
|
||||
}
|
||||
|
||||
async function removeProduct(product: Product) {
|
||||
const ok = await confirm({
|
||||
title: 'حذف محصول',
|
||||
message: `آیا از حذف دائمی «${product.name}» مطمئن هستید؟ این عمل قابل بازگشت نیست.`,
|
||||
confirmLabel: 'حذف',
|
||||
cancelLabel: 'انصراف',
|
||||
tone: 'danger',
|
||||
})
|
||||
if (!ok) return
|
||||
try {
|
||||
await productsApi.remove(product.id)
|
||||
productList.value = productList.value.filter((item) => item.id !== product.id)
|
||||
toast.success('محصول حذف شد.')
|
||||
} catch (err) {
|
||||
toast.error(err instanceof ApiError ? err.message : 'حذف محصول انجام نشد.')
|
||||
}
|
||||
}
|
||||
|
||||
function clearFilters() {
|
||||
searchQuery.value = ''
|
||||
companyFilter.value = 'all'
|
||||
@@ -409,8 +431,6 @@ function clearFilters() {
|
||||
<th>کد محصول</th>
|
||||
<th>نام</th>
|
||||
<th>رنگ</th>
|
||||
<th>برند</th>
|
||||
<th>کد محصول</th>
|
||||
<th>شرکت</th>
|
||||
<th class="numeric">حداقل متراژ</th>
|
||||
<th class="numeric">ضریب</th>
|
||||
@@ -432,8 +452,6 @@ function clearFilters() {
|
||||
<td>{{ product.productCode }}</td>
|
||||
<td>{{ product.name }}</td>
|
||||
<td>{{ product.color }}</td>
|
||||
<td>{{ product.brandName || '—' }}</td>
|
||||
<td dir="ltr">{{ product.productCode }}</td>
|
||||
<td>{{ product.companyName }}</td>
|
||||
<td class="numeric">{{ formatNumber(product.minMeterage) }} متر</td>
|
||||
<td class="numeric">{{ formatNumber(product.orderStep) }}</td>
|
||||
@@ -454,6 +472,13 @@ function clearFilters() {
|
||||
<button type="button" class="admin-btn admin-btn--ghost admin-btn--xs" @click="openEditModal(product)">
|
||||
ویرایش
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-danger admin-btn--xs"
|
||||
@click="removeProduct(product)"
|
||||
>
|
||||
حذف
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -476,6 +501,13 @@ function clearFilters() {
|
||||
<button type="button" class="admin-btn admin-btn--ghost admin-btn--xs" @click="openEditModal(product)">
|
||||
ویرایش
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--outline-danger admin-btn--xs"
|
||||
@click="removeProduct(product)"
|
||||
>
|
||||
حذف
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-card-item__meta">
|
||||
@@ -492,27 +524,16 @@ function clearFilters() {
|
||||
<p v-if="formError" class="admin-form__error" role="alert">{{ formError }}</p>
|
||||
|
||||
<div class="admin-form__field">
|
||||
<label>شرکت <span class="admin-form__required">*</span></label>
|
||||
<label>شرکت مرتبط با محصول</label>
|
||||
<AdminSelect
|
||||
v-model="form.companyId"
|
||||
block
|
||||
aria-label="انتخاب شرکت"
|
||||
placeholder="انتخاب شرکت"
|
||||
aria-label="انتخاب شرکت مرتبط با محصول"
|
||||
placeholder="نادمی تکس (پیشفرض)"
|
||||
:options="companyFormOptions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="admin-form__field">
|
||||
<label>برند</label>
|
||||
<AdminSelect
|
||||
v-model="form.brandId"
|
||||
block
|
||||
aria-label="برند محصول"
|
||||
placeholder="انتخاب برند"
|
||||
:options="brandFormOptions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="admin-form__row">
|
||||
<div class="admin-form__field">
|
||||
<label for="product-name">نام محصول <span class="admin-form__required">*</span></label>
|
||||
@@ -544,9 +565,7 @@ function clearFilters() {
|
||||
<div class="admin-form__field">
|
||||
<label for="product-price">قیمت هر متر (تومان)</label>
|
||||
<AdminCurrencyInput id="product-price" v-model="form.price" placeholder="مثلاً ۲۵۰٬۰۰۰" />
|
||||
<p class="admin-form__hint">
|
||||
مبلغ بهازای هر متر پارچه؛ در سفارش با متراژ تأییدشده ضرب میشود.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="admin-form__field">
|
||||
<label for="product-stock">موجودی داخلی (متر)</label>
|
||||
@@ -557,19 +576,25 @@ function clearFilters() {
|
||||
<div class="admin-form__row">
|
||||
<div class="admin-form__field">
|
||||
<label for="product-usage">کاربرد</label>
|
||||
<select id="product-usage" v-model="form.usageCategory" class="admin-input">
|
||||
<option v-for="opt in usageOptions" :key="opt.value" :value="opt.value">
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
<AdminSelect
|
||||
id="product-usage"
|
||||
v-model="form.usageCategory"
|
||||
block
|
||||
aria-label="کاربرد محصول"
|
||||
placeholder="انتخاب کاربرد"
|
||||
:options="usageOptions"
|
||||
/>
|
||||
</div>
|
||||
<div class="admin-form__field">
|
||||
<label for="product-season">فصل</label>
|
||||
<select id="product-season" v-model="form.season" class="admin-input">
|
||||
<option v-for="opt in seasonOptions" :key="opt.value" :value="opt.value">
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
<AdminSelect
|
||||
id="product-season"
|
||||
v-model="form.season"
|
||||
block
|
||||
aria-label="فصل محصول"
|
||||
placeholder="انتخاب فصل"
|
||||
:options="seasonOptions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -595,30 +620,50 @@ function clearFilters() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-form__field">
|
||||
<label for="product-specs">مشخصات محصول</label>
|
||||
<p class="admin-form__hint">
|
||||
متن آزاد؛ در بخش «مشاهده همه مشخصات» صفحه محصول در اپ نمایش داده میشود.
|
||||
</p>
|
||||
<textarea
|
||||
id="product-specs"
|
||||
v-model="form.specs"
|
||||
class="admin-form__textarea"
|
||||
rows="5"
|
||||
placeholder="مثلاً جنس، عرض، وزن و نکات نگهداری — هر خط یک بند"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="admin-form__field">
|
||||
<label>تصاویر عمومی محصول</label>
|
||||
<p class="color-variants__hint">
|
||||
فقط برای گالری اصلی در اپ کاربر (بدون وابستگی به رنگ). با «ذخیره تغییرات» ثبت میشود.
|
||||
فقط برای گالری اصلی در اپ کاربر (بدون وابستگی به رنگ). با «ثبت تغییرات» ثبت میشود.
|
||||
</p>
|
||||
<div class="general-images">
|
||||
<div
|
||||
v-for="(url, gIdx) in form.generalImages"
|
||||
:key="`general-${gIdx}`"
|
||||
class="general-images__row"
|
||||
class="product-media-row"
|
||||
role="group"
|
||||
:aria-label="`تصویر عمومی ${gIdx + 1}`"
|
||||
>
|
||||
<AdminImagePicker
|
||||
compact
|
||||
:show-remove="false"
|
||||
:model-value="url || null"
|
||||
@update:model-value="form.generalImages[gIdx] = $event ?? ''"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="admin-btn admin-btn--ghost admin-btn--xs"
|
||||
class="product-media-row__delete"
|
||||
aria-label="حذف این ردیف تصویر"
|
||||
title="حذف این ردیف"
|
||||
@click="removeGeneralImage(gIdx)"
|
||||
>
|
||||
حذف تصویر
|
||||
<AdminIcon name="trash" :size="17" />
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="admin-btn admin-btn--outline" @click="addGeneralImageSlot">
|
||||
<button type="button" class="admin-btn admin-btn--outline product-media-add" @click="addGeneralImageSlot">
|
||||
+ افزودن تصویر عمومی
|
||||
</button>
|
||||
</div>
|
||||
@@ -630,25 +675,37 @@ function clearFilters() {
|
||||
برای هر رنگ یک نام و یک تصویر بگذارید. تصویر رنگ در بخش رنگبندی اپ نمایش داده میشود، نه در گالری عمومی.
|
||||
</p>
|
||||
<div class="color-variants">
|
||||
<div v-for="(row, index) in form.colorRows" :key="row.id" class="color-variant">
|
||||
<div
|
||||
v-for="(row, index) in form.colorRows"
|
||||
:key="row.id"
|
||||
class="product-media-row product-media-row--color"
|
||||
role="group"
|
||||
:aria-label="`رنگ ${index + 1}`"
|
||||
>
|
||||
<AdminImagePicker
|
||||
:model-value="row.imageUrl || null"
|
||||
compact
|
||||
:show-remove="false"
|
||||
:model-value="row.imageUrl || null"
|
||||
@update:model-value="row.imageUrl = $event ?? ''"
|
||||
/>
|
||||
<div class="color-variant__fields">
|
||||
<input
|
||||
v-model="row.name"
|
||||
type="text"
|
||||
class="admin-input"
|
||||
:placeholder="`نام رنگ ${index + 1}`"
|
||||
/>
|
||||
<button type="button" class="admin-btn admin-btn--ghost admin-btn--xs" @click="removeColorRow(index)">
|
||||
حذف این رنگ
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
v-model="row.name"
|
||||
type="text"
|
||||
class="admin-input product-media-row__input"
|
||||
:placeholder="`نام رنگ ${index + 1}`"
|
||||
:aria-label="`نام رنگ ${index + 1}`"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="product-media-row__delete"
|
||||
aria-label="حذف این رنگ"
|
||||
title="حذف این رنگ"
|
||||
@click="removeColorRow(index)"
|
||||
>
|
||||
<AdminIcon name="trash" :size="17" />
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="admin-btn admin-btn--outline" @click="addColorRow">
|
||||
<button type="button" class="admin-btn admin-btn--outline product-media-add" @click="addColorRow">
|
||||
+ افزودن رنگ
|
||||
</button>
|
||||
</div>
|
||||
@@ -666,7 +723,7 @@ function clearFilters() {
|
||||
<template #footer>
|
||||
<button type="button" class="admin-btn admin-btn--outline" @click="closeModal">انصراف</button>
|
||||
<button type="button" class="admin-btn admin-btn--primary" :disabled="!isFormValid || saving" @click="submitProduct">
|
||||
{{ modalMode === 'edit' ? 'ذخیره تغییرات' : 'ثبت محصول' }}
|
||||
{{ modalMode === 'edit' ? 'ثبت تغییرات' : 'ثبت محصول' }}
|
||||
</button>
|
||||
</template>
|
||||
</BaseModal>
|
||||
@@ -727,12 +784,6 @@ function clearFilters() {
|
||||
background: #eef1f0;
|
||||
}
|
||||
|
||||
.color-variants {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.color-variants__hint {
|
||||
margin: 0 0 10px;
|
||||
color: var(--color-text-muted);
|
||||
@@ -740,41 +791,93 @@ function clearFilters() {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.general-images {
|
||||
.general-images,
|
||||
.color-variants {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.general-images__row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
.product-media-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
gap: 12px 14px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 12px;
|
||||
background: var(--color-bg, #f7f8f7);
|
||||
border-radius: 14px;
|
||||
background: var(--color-elevated, #fff);
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.color-variant {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
.product-media-row--color {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 12px;
|
||||
background: var(--color-bg, #f7f8f7);
|
||||
}
|
||||
|
||||
.color-variant__fields {
|
||||
flex: 1;
|
||||
min-width: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
.product-media-row :deep(.image-picker) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.product-media-row__input {
|
||||
min-width: 0;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.product-media-row__delete {
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 12px;
|
||||
background: transparent;
|
||||
color: var(--color-text-muted);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color 0.15s ease,
|
||||
background 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.product-media-row__delete:hover {
|
||||
color: #c53030;
|
||||
background: rgba(197, 48, 48, 0.08);
|
||||
border-color: rgba(197, 48, 48, 0.18);
|
||||
}
|
||||
|
||||
.product-media-row__delete:focus-visible {
|
||||
outline: 2px solid var(--color-primary, #2d6a4f);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.product-media-add {
|
||||
align-self: stretch;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.product-media-row--color {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-rows: auto auto;
|
||||
}
|
||||
|
||||
.product-media-row--color :deep(.image-picker) {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.product-media-row--color .product-media-row__delete {
|
||||
grid-row: 2;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.product-media-row--color .product-media-row__input {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user