2026-02-21 20:24:59 +03:30
|
|
|
<template>
|
2026-07-06 19:06:57 +03:30
|
|
|
<div class="banners-page">
|
|
|
|
|
<header class="banners-page__header">
|
|
|
|
|
<div class="banners-page__header-text">
|
|
|
|
|
<div class="banners-page__title-row">
|
|
|
|
|
<h1 class="banners-page__title">بنرهای اسلایدر</h1>
|
|
|
|
|
<AdminFieldHelp :text="bannersPageIntro" size="sm" />
|
|
|
|
|
</div>
|
|
|
|
|
<p class="banners-page__subtitle">تصاویر بالای صفحهٔ اصلی اپ مشتری — هر ردیف یک اسلاید</p>
|
2026-02-21 20:24:59 +03:30
|
|
|
</div>
|
2026-07-06 19:06:57 +03:30
|
|
|
<div class="banners-page__header-actions">
|
|
|
|
|
<BaseButton size="small" type="primary" @click="addRow">
|
|
|
|
|
<span>افزودن اسلاید</span>
|
|
|
|
|
<BaseIcon icon="vuesax-linear:add" size="17" />
|
|
|
|
|
</BaseButton>
|
|
|
|
|
<BaseButton type="primary" :loading="saving" @click="handleSubmit">
|
|
|
|
|
ذخیره تغییرات
|
|
|
|
|
</BaseButton>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
2026-07-06 18:30:21 +03:30
|
|
|
|
2026-07-06 19:06:57 +03:30
|
|
|
<div class="banners-page__body">
|
|
|
|
|
<div v-if="!benefitsList.length" class="banners-page__empty">
|
|
|
|
|
<div class="banners-page__empty-inner">
|
|
|
|
|
<BaseIcon icon="vuesax-linear:image" size="48" class="banners-page__empty-icon" />
|
|
|
|
|
<p class="banners-page__empty-title">هنوز بنری اضافه نشده</p>
|
|
|
|
|
<p class="banners-page__empty-text">اولین اسلاید را بسازید تا در اپ مشتری نمایش داده شود</p>
|
|
|
|
|
<BaseButton type="primary" @click="addRow">
|
|
|
|
|
<span>افزودن اسلاید</span>
|
|
|
|
|
<BaseIcon icon="vuesax-linear:add" size="17" />
|
|
|
|
|
</BaseButton>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-else class="banners-page__list">
|
|
|
|
|
<article
|
|
|
|
|
v-for="(item, index) in benefitsList"
|
|
|
|
|
:key="index"
|
|
|
|
|
class="banner-card"
|
|
|
|
|
:class="{ 'banner-card--hidden': !item.show }"
|
|
|
|
|
>
|
|
|
|
|
<header class="banner-card__head">
|
|
|
|
|
<div class="banner-card__head-start">
|
|
|
|
|
<span class="banner-card__index">{{ index + 1 }}</span>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="banner-card__title">اسلاید {{ index + 1 }}</div>
|
|
|
|
|
<div class="banner-card__meta">
|
|
|
|
|
<span class="banner-card__pill" :class="{ 'banner-card__pill--off': !item.show }">
|
|
|
|
|
{{ item.show ? 'فعال در اپ' : 'مخفی' }}
|
|
|
|
|
</span>
|
|
|
|
|
<span class="banner-card__ratio">۱۶:۹</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="banner-card__head-end">
|
|
|
|
|
<label class="banner-card__switch">
|
|
|
|
|
<span>نمایش</span>
|
|
|
|
|
<a-switch v-model:checked="item.show" size="small" />
|
|
|
|
|
<AdminFieldHelp :text="bannersShowHelp" />
|
|
|
|
|
</label>
|
|
|
|
|
<button type="button" class="banner-card__remove" title="حذف اسلاید" @click="removeRow(index)">
|
|
|
|
|
<BaseIcon icon="vuesax-linear:trash" size="18" />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<div class="banner-card__content">
|
|
|
|
|
<div class="banner-card__preview-wrap">
|
|
|
|
|
<AdminLabelWithHelp label="پیشنمایش تصویر" :help="bannersImageSectionHelp" />
|
|
|
|
|
<div class="banner-card__preview">
|
|
|
|
|
<BannerImageUpload
|
|
|
|
|
:image-url="item.icon"
|
|
|
|
|
@upload="item.icon = $event"
|
|
|
|
|
@remove="item.icon = null"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="banner-card__fields" :class="{ 'banner-card__fields--stack': item.typeClick === 'modal' }">
|
|
|
|
|
<div class="banner-card__field">
|
|
|
|
|
<AdminLabelWithHelp label="بعد از کلیک مشتری" :help="clickEventHelp(item.typeClick)" />
|
|
|
|
|
<BasicSelect
|
|
|
|
|
v-model:value="item.typeClick"
|
|
|
|
|
:items="typeList"
|
|
|
|
|
value-name="lable"
|
|
|
|
|
key-name="value"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="item.typeClick === 'link'" class="banner-card__field banner-card__field--wide">
|
|
|
|
|
<AdminLabelWithHelp label="آدرس لینک" :help="bannersLinkHelp" />
|
|
|
|
|
<BasicInput v-model:value="item.link" placeholder="https://example.com" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="item.typeClick === 'modal'" class="banner-card__field banner-card__field--wide">
|
|
|
|
|
<AdminLabelWithHelp label="متن پیام" :help="bannersModalHelp" />
|
|
|
|
|
<a-textarea
|
|
|
|
|
:value="htmlToPlain(item.modalText)"
|
|
|
|
|
:rows="7"
|
|
|
|
|
class="banner-card__message"
|
|
|
|
|
placeholder="متن پیامی که مشتری در پنجرهٔ بازشو میبیند..."
|
|
|
|
|
@update:value="item.modalText = plainToHtml($event)"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</article>
|
|
|
|
|
</div>
|
2026-02-21 20:24:59 +03:30
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-07-06 19:06:57 +03:30
|
|
|
import { message } from 'ant-design-vue'
|
2026-07-06 18:30:21 +03:30
|
|
|
import type { IBenefits } from '@/model/banner'
|
2026-07-06 19:06:57 +03:30
|
|
|
import BannerImageUpload from './components/BannerImageUpload.vue'
|
2026-07-06 18:30:21 +03:30
|
|
|
import AdminFieldHelp from '@/components/AdminFieldHelp.vue'
|
2026-07-06 19:06:57 +03:30
|
|
|
import AdminLabelWithHelp from '@/components/AdminLabelWithHelp.vue'
|
2026-07-06 18:30:21 +03:30
|
|
|
import { updateBannerConst, getHeaderBannerConst } from '@/api/consts'
|
|
|
|
|
import {
|
|
|
|
|
bannersEventHelp,
|
2026-07-06 19:06:57 +03:30
|
|
|
bannersImageSectionHelp,
|
2026-07-06 18:30:21 +03:30
|
|
|
bannersLinkHelp,
|
|
|
|
|
bannersModalHelp,
|
|
|
|
|
bannersNoEventHelp,
|
|
|
|
|
bannersPageIntro,
|
|
|
|
|
bannersShareHelp,
|
|
|
|
|
bannersShowHelp,
|
|
|
|
|
} from '@/utils/adminHelpCopy'
|
2026-02-21 20:24:59 +03:30
|
|
|
|
|
|
|
|
const benefitsList = ref<IBenefits[]>([])
|
2026-07-06 19:06:57 +03:30
|
|
|
const saving = ref(false)
|
2026-02-21 20:24:59 +03:30
|
|
|
let id: number | null = null
|
2026-07-06 19:06:57 +03:30
|
|
|
|
2026-05-02 13:53:43 +03:30
|
|
|
const typeList = ref([
|
2026-07-06 19:06:57 +03:30
|
|
|
{ lable: 'بدون رویداد', value: null },
|
2026-07-06 18:30:21 +03:30
|
|
|
{ lable: 'باز شدن لینک', value: 'link' },
|
|
|
|
|
{ lable: 'پنجره بازشو', value: 'modal' },
|
2026-07-06 19:06:57 +03:30
|
|
|
{ lable: 'اشتراکگذاری', value: 'share' },
|
2026-05-02 13:53:43 +03:30
|
|
|
])
|
2026-07-06 18:30:21 +03:30
|
|
|
|
2026-07-06 19:06:57 +03:30
|
|
|
function clickEventHelp(typeClick: string | null) {
|
|
|
|
|
if (typeClick === 'link') return `${bannersEventHelp}\n\n${bannersLinkHelp}`
|
|
|
|
|
if (typeClick === 'modal') return `${bannersEventHelp}\n\n${bannersModalHelp}`
|
|
|
|
|
if (typeClick === 'share') return `${bannersEventHelp}\n\n${bannersShareHelp}`
|
|
|
|
|
return `${bannersEventHelp}\n\n${bannersNoEventHelp}`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function htmlToPlain(html: string | null | undefined): string {
|
|
|
|
|
if (!html) return ''
|
|
|
|
|
if (typeof document === 'undefined') {
|
|
|
|
|
return html.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]+>/g, '').trim()
|
|
|
|
|
}
|
|
|
|
|
const el = document.createElement('div')
|
|
|
|
|
el.innerHTML = html
|
|
|
|
|
return (el.textContent ?? el.innerText ?? '').trim()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function plainToHtml(text: string | null | undefined): string | null {
|
|
|
|
|
const trimmed = (text ?? '').trim()
|
|
|
|
|
if (!trimmed) return null
|
|
|
|
|
const escaped = trimmed
|
|
|
|
|
.replace(/&/g, '&')
|
|
|
|
|
.replace(/</g, '<')
|
|
|
|
|
.replace(/>/g, '>')
|
|
|
|
|
return `<p>${escaped.replace(/\n/g, '<br>')}</p>`
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-05 12:05:18 +02:00
|
|
|
function parseBannerList(value: string | null | undefined): IBenefits[] {
|
|
|
|
|
if (!value) return []
|
|
|
|
|
try {
|
|
|
|
|
const parsed = JSON.parse(value)
|
|
|
|
|
return Array.isArray(parsed) ? parsed : []
|
|
|
|
|
} catch {
|
|
|
|
|
return []
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-21 20:24:59 +03:30
|
|
|
|
|
|
|
|
function addRow() {
|
2026-07-05 12:05:18 +02:00
|
|
|
if (!Array.isArray(benefitsList.value)) {
|
|
|
|
|
benefitsList.value = []
|
|
|
|
|
}
|
2026-07-06 18:30:21 +03:30
|
|
|
benefitsList.value.push({
|
|
|
|
|
icon: null,
|
|
|
|
|
show: true,
|
|
|
|
|
caption: null,
|
|
|
|
|
link: null,
|
|
|
|
|
typeClick: null,
|
|
|
|
|
modalText: null,
|
|
|
|
|
})
|
2026-02-21 20:24:59 +03:30
|
|
|
}
|
|
|
|
|
|
2026-07-06 19:06:57 +03:30
|
|
|
function removeRow(index: number) {
|
|
|
|
|
benefitsList.value.splice(index, 1)
|
2026-02-21 20:24:59 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleSubmit() {
|
2026-07-05 16:41:45 +03:30
|
|
|
if (!id) {
|
|
|
|
|
message.error('شناسه بنر یافت نشد؛ صفحه را رفرش کنید')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-21 20:24:59 +03:30
|
|
|
try {
|
2026-07-06 19:06:57 +03:30
|
|
|
saving.value = true
|
2026-02-21 20:24:59 +03:30
|
|
|
await updateBannerConst({
|
2026-07-05 16:41:45 +03:30
|
|
|
id,
|
2026-02-21 20:24:59 +03:30
|
|
|
value: JSON.stringify(benefitsList.value),
|
2026-07-05 16:41:45 +03:30
|
|
|
key: 'header_banner',
|
2026-02-21 20:24:59 +03:30
|
|
|
})
|
2026-07-05 16:41:45 +03:30
|
|
|
message.success('اطلاعات با موفقیت ذخیره شد')
|
2026-02-21 20:24:59 +03:30
|
|
|
} catch (error) {
|
2026-07-05 16:41:45 +03:30
|
|
|
message.error('خطا در ذخیره اطلاعات')
|
2026-07-06 19:06:57 +03:30
|
|
|
} finally {
|
|
|
|
|
saving.value = false
|
2026-02-21 20:24:59 +03:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await getHeaderBannerConst()
|
2026-07-05 16:41:45 +03:30
|
|
|
if (!res) {
|
|
|
|
|
return
|
2026-02-21 20:24:59 +03:30
|
|
|
}
|
2026-07-05 16:41:45 +03:30
|
|
|
|
|
|
|
|
id = res.id ?? res.const_id ?? null
|
|
|
|
|
benefitsList.value = parseBannerList(res.value)
|
2026-02-21 20:24:59 +03:30
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در دریافت بنرها:', error)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
2026-07-06 19:06:57 +03:30
|
|
|
<style scoped lang="less">
|
|
|
|
|
.banners-page {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
width: 100%;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
height: 100%;
|
|
|
|
|
min-height: 0;
|
2026-05-02 13:53:43 +03:30
|
|
|
}
|
|
|
|
|
|
2026-07-06 19:06:57 +03:30
|
|
|
.banners-page__header {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
padding: 1rem 1.25rem;
|
|
|
|
|
border-bottom: 1px solid var(--admin-border);
|
|
|
|
|
background: var(--admin-bg-elevated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__title-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__title {
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-size: 1.25rem;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: var(--admin-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__subtitle {
|
|
|
|
|
margin: 0.35rem 0 0;
|
|
|
|
|
font-size: 0.8125rem;
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__header-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.625rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__body {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-height: 0;
|
2026-05-02 13:53:43 +03:30
|
|
|
overflow-y: auto;
|
2026-07-06 19:06:57 +03:30
|
|
|
padding: 1rem 1.25rem 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__empty {
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
min-height: calc(100vh - 12rem);
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__empty-inner {
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 28rem;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.625rem;
|
|
|
|
|
padding: 3rem 1.5rem;
|
|
|
|
|
border: 1px dashed var(--admin-border);
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
background: var(--admin-bg-elevated);
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__empty-icon {
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
opacity: 0.65;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__empty-title {
|
|
|
|
|
margin: 0.25rem 0 0;
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: var(--admin-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__empty-text {
|
|
|
|
|
margin: 0 0 0.75rem;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banners-page__list {
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card {
|
|
|
|
|
width: 100%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
border: 1px solid var(--admin-border);
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
background: var(--admin-bg-elevated);
|
|
|
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
|
|
|
|
|
|
|
|
&--hidden {
|
|
|
|
|
opacity: 0.88;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__head {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 0.75rem;
|
|
|
|
|
padding: 0.875rem 1rem;
|
|
|
|
|
border-bottom: 1px solid var(--admin-border);
|
|
|
|
|
background: color-mix(in srgb, var(--admin-bg-muted) 70%, transparent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__head-start {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.75rem;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__index {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
width: 2.25rem;
|
|
|
|
|
height: 2.25rem;
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
background: var(--admin-primary, #f5b800);
|
|
|
|
|
color: #1a1a1a;
|
|
|
|
|
font-size: 0.9375rem;
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__title {
|
|
|
|
|
font-size: 0.9375rem;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: var(--admin-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__meta {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
margin-top: 0.2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__pill {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
color: #52c41a;
|
|
|
|
|
|
|
|
|
|
&--off {
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__ratio {
|
|
|
|
|
font-size: 0.6875rem;
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__head-end {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__switch {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.4rem;
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-size: 0.8125rem;
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__remove {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
width: 2.25rem;
|
|
|
|
|
height: 2.25rem;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border: 1px solid rgba(255, 77, 79, 0.35);
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
background: rgba(255, 77, 79, 0.08);
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: background 0.15s ease;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
background: rgba(255, 77, 79, 0.16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__content {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 1.25rem;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
|
|
|
|
|
@media (min-width: 900px) {
|
|
|
|
|
grid-template-columns: minmax(280px, 42%) minmax(0, 1fr);
|
|
|
|
|
padding: 1.125rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__preview-wrap {
|
|
|
|
|
display: flex;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__preview {
|
|
|
|
|
aspect-ratio: 16 / 9;
|
|
|
|
|
min-height: 11rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__fields {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
align-content: start;
|
|
|
|
|
|
|
|
|
|
&--stack {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__field {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
|
|
|
|
&--wide {
|
|
|
|
|
grid-column: 1 / -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-card__message {
|
|
|
|
|
width: 100%;
|
|
|
|
|
min-height: 10.5rem;
|
|
|
|
|
padding: 0.75rem 0.875rem;
|
|
|
|
|
border: 1px solid var(--admin-border) !important;
|
|
|
|
|
border-radius: 10px !important;
|
|
|
|
|
background: var(--admin-bg-muted) !important;
|
|
|
|
|
color: var(--admin-text) !important;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
line-height: 1.7;
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
|
|
|
|
&::placeholder {
|
|
|
|
|
color: var(--admin-text-secondary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
border-color: color-mix(in srgb, var(--admin-primary, #f5b800) 35%, var(--admin-border)) !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
|
border-color: var(--admin-primary, #f5b800) !important;
|
|
|
|
|
box-shadow: 0 0 0 2px color-mix(in srgb, var(--admin-primary, #f5b800) 18%, transparent);
|
|
|
|
|
outline: none;
|
|
|
|
|
}
|
2026-05-02 13:53:43 +03:30
|
|
|
}
|
2026-07-05 16:41:45 +03:30
|
|
|
</style>
|