feat: Linear-style UI redesign with improved mobile experience

Major changes:
- Redesign cabinet with Linear-style components and top navigation
- Replace detail modals with dedicated pages (users, broadcasts, email templates)
- Add email channel support for broadcasts
- Remove pull-to-refresh, improve drag-and-drop on touch devices
- Fix Telegram Mini App: fullscreen, back button, scroll restoration
- Unify admin pages color scheme to design system
- Mobile-first improvements: horizontal tabs for settings, better touch targets
This commit is contained in:
c0mrade
2026-01-31 22:06:36 +03:00
parent 929634aac4
commit b953ee0b8c
108 changed files with 11711 additions and 4542 deletions

View File

@@ -10,6 +10,7 @@ import { useNavigate } from 'react-router-dom';
import { useSuccessNotification } from '../store/successNotification';
import { useCurrency } from '../hooks/useCurrency';
import { useTelegramWebApp } from '../hooks/useTelegramWebApp';
import { useBackButton, useHaptic } from '@/platform';
// Icons
const CheckCircleIcon = () => (
@@ -79,7 +80,8 @@ export default function SuccessNotificationModal() {
const navigate = useNavigate();
const { isOpen, data, hide } = useSuccessNotification();
const { formatAmount, currencySymbol } = useCurrency();
const { webApp, safeAreaInset, contentSafeAreaInset, isTelegramWebApp } = useTelegramWebApp();
const { safeAreaInset, contentSafeAreaInset, isTelegramWebApp } = useTelegramWebApp();
const haptic = useHaptic();
const safeBottom = isTelegramWebApp
? Math.max(safeAreaInset.bottom, contentSafeAreaInset.bottom)
@@ -104,18 +106,15 @@ export default function SuccessNotificationModal() {
return () => document.removeEventListener('keydown', handleKeyDown);
}, [isOpen, handleClose]);
// Telegram back button
// Telegram back button - using platform hook
useBackButton(isOpen ? handleClose : null);
// Haptic feedback on open
useEffect(() => {
if (!isOpen || !webApp?.BackButton) return;
webApp.BackButton.show();
webApp.BackButton.onClick(handleClose);
return () => {
webApp.BackButton.offClick(handleClose);
webApp.BackButton.hide();
};
}, [isOpen, webApp, handleClose]);
if (isOpen) {
haptic.notification('success');
}
}, [isOpen, haptic]);
// Scroll lock
useEffect(() => {