add news page

This commit is contained in:
2025-12-06 02:26:35 +05:00
parent 3e62bd7c27
commit 2e6b2d7add
7 changed files with 2465 additions and 11 deletions

View File

@ -0,0 +1,69 @@
// components/MarkdownEditor.tsx
import { useEffect, useRef } from 'react';
import EasyMDE from 'easymde';
import 'easymde/dist/easymde.min.css';
interface MarkdownEditorProps {
value: string;
onChange: (value: string) => void;
}
export const MarkdownEditor = ({ value, onChange }: MarkdownEditorProps) => {
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
const editorRef = useRef<EasyMDE | null>(null);
// Один раз создаём EasyMDE поверх textarea
useEffect(() => {
if (!textareaRef.current) return;
if (editorRef.current) return; // уже создан
const instance = new EasyMDE({
element: textareaRef.current,
initialValue: value,
spellChecker: false,
minHeight: '200px',
toolbar: [
'bold',
'italic',
'strikethrough',
'|',
'heading',
'quote',
'unordered-list',
'ordered-list',
'|',
'link',
'image',
'|',
'preview',
'side-by-side',
'fullscreen',
'|',
'guide',
],
status: false,
});
instance.codemirror.on('change', () => {
onChange(instance.value());
});
editorRef.current = instance;
// При анмаунте красиво убрать за собой
return () => {
instance.toTextArea();
editorRef.current = null;
};
}, []);
// Если извне поменяли value — обновляем редактор
useEffect(() => {
if (editorRef.current && editorRef.current.value() !== value) {
editorRef.current.value(value);
}
}, [value]);
// Сам текстариа — просто якорь для EasyMDE
return <textarea ref={textareaRef} />;
};

View File

@ -33,23 +33,44 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
const isRegistrationPage = location.pathname === '/registration';
const navigate = useNavigate();
const [coins, setCoins] = useState<number>(0);
const [value, setValue] = useState(0);
const [value, setValue] = useState(1);
const [activePage, setActivePage] = useState('versions');
const tabsWrapperRef = useRef<HTMLDivElement | null>(null);
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
if (newValue === 0) {
navigate('/');
navigate('/news');
} else if (newValue === 1) {
navigate('/profile');
navigate('/');
} else if (newValue === 2) {
navigate('/shop');
navigate('/profile');
} else if (newValue === 3) {
navigate('/shop');
} else if (newValue === 4) {
navigate('/marketplace');
}
};
useEffect(() => {
if (location.pathname === '/news') {
setValue(0);
setActivePage('news');
} else if (location.pathname === '/') {
setValue(1);
setActivePage('versions');
} else if (location.pathname.startsWith('/profile')) {
setValue(2);
setActivePage('profile');
} else if (location.pathname.startsWith('/shop')) {
setValue(3);
setActivePage('shop');
} else if (location.pathname.startsWith('/marketplace')) {
setValue(4);
setActivePage('marketplace');
}
}, [location.pathname]);
const handleLaunchPage = () => {
navigate('/');
};
@ -62,7 +83,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
// Находим внутренний скроллер MUI Tabs
const scroller = tabsWrapperRef.current.querySelector(
'.MuiTabs-scroller'
'.MuiTabs-scroller',
) as HTMLDivElement | null;
if (!scroller) return;
@ -194,8 +215,27 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
variant="scrollable"
scrollButtons={false}
disableRipple={true}
sx={{ maxWidth: "42vw"}}
sx={{ maxWidth: '42vw' }}
>
<Tab
label="Новости"
disableRipple={true}
onClick={() => {
setActivePage('news');
}}
sx={{
color: 'white',
fontFamily: 'Benzin-Bold',
fontSize: '0.7em',
'&.Mui-selected': {
color: 'rgba(255, 77, 77, 1)',
},
'&:hover': {
color: 'rgb(177, 52, 52)',
},
transition: 'all 0.3s ease',
}}
/>
<Tab
label="Версии"
disableRipple={true}