mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
feat: add display mode selector to info page editor
This commit is contained in:
@@ -43,7 +43,7 @@ export interface InfoPageCreateRequest {
|
|||||||
sort_order: number;
|
sort_order: number;
|
||||||
icon: string | null;
|
icon: string | null;
|
||||||
replaces_tab: ReplacesTab | null;
|
replaces_tab: ReplacesTab | null;
|
||||||
display_mode?: InfoPageDisplayMode;
|
display_mode: InfoPageDisplayMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InfoPageUpdateRequest {
|
export interface InfoPageUpdateRequest {
|
||||||
|
|||||||
@@ -4083,7 +4083,8 @@
|
|||||||
"sortOrder": "Sort Order",
|
"sortOrder": "Sort Order",
|
||||||
"icon": "Icon (emoji)",
|
"icon": "Icon (emoji)",
|
||||||
"pageType": "Page Type",
|
"pageType": "Page Type",
|
||||||
"replacesTab": "Replaces Tab"
|
"replacesTab": "Replaces Tab",
|
||||||
|
"displayMode": "Visibility"
|
||||||
},
|
},
|
||||||
"replacesTabNone": "None",
|
"replacesTabNone": "None",
|
||||||
"replacesTabOptions": {
|
"replacesTabOptions": {
|
||||||
@@ -4092,6 +4093,11 @@
|
|||||||
"privacy": "Privacy",
|
"privacy": "Privacy",
|
||||||
"offer": "Offer"
|
"offer": "Offer"
|
||||||
},
|
},
|
||||||
|
"displayModes": {
|
||||||
|
"bot": "Bot only",
|
||||||
|
"web": "Web only",
|
||||||
|
"both": "Bot and web"
|
||||||
|
},
|
||||||
"replacesTabConflict": "already assigned",
|
"replacesTabConflict": "already assigned",
|
||||||
"replacesTabWarning": "Another page already replaces this tab. It will be unassigned on save.",
|
"replacesTabWarning": "Another page already replaces this tab. It will be unassigned on save.",
|
||||||
"filter": {
|
"filter": {
|
||||||
|
|||||||
@@ -4628,7 +4628,8 @@
|
|||||||
"sortOrder": "Порядок сортировки",
|
"sortOrder": "Порядок сортировки",
|
||||||
"icon": "Иконка (эмодзи)",
|
"icon": "Иконка (эмодзи)",
|
||||||
"pageType": "Тип страницы",
|
"pageType": "Тип страницы",
|
||||||
"replacesTab": "Заменяет таб"
|
"replacesTab": "Заменяет таб",
|
||||||
|
"displayMode": "Отображение"
|
||||||
},
|
},
|
||||||
"replacesTabNone": "Не заменяет",
|
"replacesTabNone": "Не заменяет",
|
||||||
"replacesTabOptions": {
|
"replacesTabOptions": {
|
||||||
@@ -4637,6 +4638,11 @@
|
|||||||
"privacy": "Конфиденциальность",
|
"privacy": "Конфиденциальность",
|
||||||
"offer": "Оферта"
|
"offer": "Оферта"
|
||||||
},
|
},
|
||||||
|
"displayModes": {
|
||||||
|
"bot": "Только бот",
|
||||||
|
"web": "Только веб",
|
||||||
|
"both": "Бот и веб"
|
||||||
|
},
|
||||||
"replacesTabConflict": "уже занят",
|
"replacesTabConflict": "уже занят",
|
||||||
"replacesTabWarning": "Другая страница уже заменяет этот таб. При сохранении она будет снята.",
|
"replacesTabWarning": "Другая страница уже заменяет этот таб. При сохранении она будет снята.",
|
||||||
"filter": {
|
"filter": {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import {
|
|||||||
TrashSmallIcon,
|
TrashSmallIcon,
|
||||||
PlusSmallIcon,
|
PlusSmallIcon,
|
||||||
} from '@/components/icons';
|
} from '@/components/icons';
|
||||||
import type { InfoPageType, FaqItem, ReplacesTab } from '../api/infoPages';
|
import type { InfoPageType, FaqItem, ReplacesTab, InfoPageDisplayMode } from '../api/infoPages';
|
||||||
|
|
||||||
const AVAILABLE_LOCALES = ['ru', 'en', 'zh', 'fa'] as const;
|
const AVAILABLE_LOCALES = ['ru', 'en', 'zh', 'fa'] as const;
|
||||||
type LocaleCode = (typeof AVAILABLE_LOCALES)[number];
|
type LocaleCode = (typeof AVAILABLE_LOCALES)[number];
|
||||||
@@ -643,6 +643,7 @@ export default function AdminInfoPageEditor() {
|
|||||||
const [sortOrder, setSortOrder] = useState(0);
|
const [sortOrder, setSortOrder] = useState(0);
|
||||||
const [pageType, setPageType] = useState<InfoPageType>(initialPageType);
|
const [pageType, setPageType] = useState<InfoPageType>(initialPageType);
|
||||||
const [replacesTab, setReplacesTab] = useState<ReplacesTab | null>(null);
|
const [replacesTab, setReplacesTab] = useState<ReplacesTab | null>(null);
|
||||||
|
const [displayMode, setDisplayMode] = useState<InfoPageDisplayMode>('both');
|
||||||
const [saveError, setSaveError] = useState<string | null>(null);
|
const [saveError, setSaveError] = useState<string | null>(null);
|
||||||
|
|
||||||
// FAQ Q&A state per locale
|
// FAQ Q&A state per locale
|
||||||
@@ -857,6 +858,7 @@ export default function AdminInfoPageEditor() {
|
|||||||
setSortOrder(pageData.sort_order);
|
setSortOrder(pageData.sort_order);
|
||||||
setPageType(pageData.page_type ?? 'page');
|
setPageType(pageData.page_type ?? 'page');
|
||||||
setReplacesTab(pageData.replaces_tab ?? null);
|
setReplacesTab(pageData.replaces_tab ?? null);
|
||||||
|
setDisplayMode(pageData.display_mode ?? 'both');
|
||||||
setTitles(pageData.title);
|
setTitles(pageData.title);
|
||||||
|
|
||||||
if (pageData.page_type === 'faq') {
|
if (pageData.page_type === 'faq') {
|
||||||
@@ -927,6 +929,7 @@ export default function AdminInfoPageEditor() {
|
|||||||
sort_order: number;
|
sort_order: number;
|
||||||
icon: string | null;
|
icon: string | null;
|
||||||
replaces_tab: ReplacesTab | null;
|
replaces_tab: ReplacesTab | null;
|
||||||
|
display_mode: InfoPageDisplayMode;
|
||||||
}) => {
|
}) => {
|
||||||
if (isEdit && pageId != null) {
|
if (isEdit && pageId != null) {
|
||||||
return infoPagesApi.updatePage(pageId, data);
|
return infoPagesApi.updatePage(pageId, data);
|
||||||
@@ -976,6 +979,7 @@ export default function AdminInfoPageEditor() {
|
|||||||
sort_order: sortOrder,
|
sort_order: sortOrder,
|
||||||
icon: icon.trim() || null,
|
icon: icon.trim() || null,
|
||||||
replaces_tab: replacesTab,
|
replaces_tab: replacesTab,
|
||||||
|
display_mode: displayMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
haptic.buttonPress();
|
haptic.buttonPress();
|
||||||
@@ -1089,6 +1093,31 @@ export default function AdminInfoPageEditor() {
|
|||||||
<span className="text-sm text-dark-300">{t('admin.infoPages.fields.isActive')}</span>
|
<span className="text-sm text-dark-300">{t('admin.infoPages.fields.isActive')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label id="ip-displaymode-label" className="label">
|
||||||
|
{t('admin.infoPages.fields.displayMode')}
|
||||||
|
</label>
|
||||||
|
<div className="flex gap-1" role="radiogroup" aria-labelledby="ip-displaymode-label">
|
||||||
|
{(['bot', 'web', 'both'] as const).map((mode) => (
|
||||||
|
<button
|
||||||
|
key={mode}
|
||||||
|
type="button"
|
||||||
|
role="radio"
|
||||||
|
aria-checked={displayMode === mode}
|
||||||
|
onClick={() => setDisplayMode(mode)}
|
||||||
|
className={cn(
|
||||||
|
'min-h-[44px] rounded-lg px-4 py-2.5 text-sm font-medium transition-colors',
|
||||||
|
displayMode === mode
|
||||||
|
? 'bg-accent-500 text-white'
|
||||||
|
: 'bg-dark-700 text-dark-300 hover:bg-dark-600 hover:text-dark-100',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{t(`admin.infoPages.displayModes.${mode}`)}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Page type selector */}
|
{/* Page type selector */}
|
||||||
<div>
|
<div>
|
||||||
<label id="ip-pagetype-label" className="label">
|
<label id="ip-pagetype-label" className="label">
|
||||||
|
|||||||
Reference in New Issue
Block a user