Update files

This commit is contained in:
glpshchn 2025-11-11 03:54:39 +03:00
parent 2bb573b919
commit f9ff325c8a
2 changed files with 97 additions and 60 deletions

View File

@ -12,7 +12,6 @@ const AdminConfirmationSchema = new mongoose.Schema({
}, },
adminNumber: { adminNumber: {
type: Number, type: Number,
required: true,
min: 1, min: 1,
max: 10 max: 10
}, },

View File

@ -167,6 +167,9 @@ export default function App() {
loadReports(); loadReports();
} else if (tab === 'admins') { } else if (tab === 'admins') {
loadAdmins(); loadAdmins();
} else if (tab === 'publish') {
// Загрузить список админов для проверки прав публикации
loadAdmins();
} else if (tab === 'chat' && user) { } else if (tab === 'chat' && user) {
initChat(); initChat();
} }
@ -278,8 +281,16 @@ export default function App() {
const initChat = () => { const initChat = () => {
if (!user || chatSocketRef.current) return; if (!user || chatSocketRef.current) return;
const socket = io('/mod-chat', {
transports: ['websocket', 'polling'] const API_URL = import.meta.env.VITE_API_URL || (
import.meta.env.PROD ? window.location.origin : 'http://localhost:3000'
);
const socket = io(`${API_URL}/mod-chat`, {
transports: ['websocket', 'polling'],
reconnection: true,
reconnectionDelay: 1000,
reconnectionAttempts: 5
}); });
socket.on('connect', () => { socket.on('connect', () => {
@ -626,11 +637,32 @@ export default function App() {
</div> </div>
); );
const renderPublish = () => ( const renderPublish = () => {
// Найти админа текущего пользователя
const currentAdmin = adminsData.admins.find((admin) => admin.telegramId === user.telegramId);
const canPublish = currentAdmin && currentAdmin.adminNumber >= 1 && currentAdmin.adminNumber <= 10;
return (
<div className="card"> <div className="card">
<div className="section-header"> <div className="section-header">
<h2>Публикация в @reichenbfurry</h2> <h2>Публикация в @reichenbfurry</h2>
</div> </div>
{!canPublish && (
<div style={{ padding: '16px', backgroundColor: 'var(--bg-secondary)', borderRadius: '8px', marginBottom: '16px', color: 'var(--text-secondary)' }}>
Публиковать в канал могут только админы с номерами от 1 до 10.
{currentAdmin ? (
<div style={{ marginTop: '8px' }}>
Ваш номер: <strong>#{currentAdmin.adminNumber}</strong> (доступ запрещён)
</div>
) : (
<div style={{ marginTop: '8px' }}>
Вам не присвоен номер админа. Обратитесь к владельцу.
</div>
)}
</div>
)}
<div className="publish-form"> <div className="publish-form">
<label> <label>
Описание Описание
@ -641,6 +673,7 @@ export default function App() {
} }
maxLength={1024} maxLength={1024}
placeholder="Текст поста" placeholder="Текст поста"
disabled={!canPublish}
/> />
</label> </label>
<label> <label>
@ -650,26 +683,26 @@ export default function App() {
value={publishState.tags} value={publishState.tags}
onChange={(e) => setPublishState((prev) => ({ ...prev, tags: e.target.value }))} onChange={(e) => setPublishState((prev) => ({ ...prev, tags: e.target.value }))}
placeholder="#furry #art" placeholder="#furry #art"
disabled={!canPublish}
/> />
</label> </label>
<label> {currentAdmin && (
Номер администратора (#a1 - #a10) <div style={{ padding: '12px', backgroundColor: 'var(--bg-secondary)', borderRadius: '8px', marginBottom: '8px' }}>
<select Ваш номер админа: <strong>#{currentAdmin.adminNumber}</strong>
value={publishState.slot} <div style={{ fontSize: '12px', color: 'var(--text-secondary)', marginTop: '4px' }}>
onChange={(e) => Автоматически будет добавлен тег #a{currentAdmin.adminNumber}
setPublishState((prev) => ({ ...prev, slot: parseInt(e.target.value, 10) })) </div>
} </div>
> )}
{slotOptions.map((option) => (
<option key={option} value={option}>
#{`a${option}`}
</option>
))}
</select>
</label>
<label> <label>
Медиа (до 10, фото или видео) Медиа (до 10, фото или видео)
<input type="file" accept="image/*,video/*" multiple onChange={handleFileChange} /> <input
type="file"
accept="image/*,video/*"
multiple
onChange={handleFileChange}
disabled={!canPublish}
/>
</label> </label>
{publishState.files.length > 0 && ( {publishState.files.length > 0 && (
<div className="file-list"> <div className="file-list">
@ -680,13 +713,18 @@ export default function App() {
))} ))}
</div> </div>
)} )}
<button className="btn primary" disabled={publishing} onClick={handlePublish}> <button
className="btn primary"
disabled={publishing || !canPublish}
onClick={handlePublish}
>
{publishing ? <Loader2 className="spin" size={18} /> : <SendHorizontal size={18} />} {publishing ? <Loader2 className="spin" size={18} /> : <SendHorizontal size={18} />}
Опубликовать Опубликовать
</button> </button>
</div> </div>
</div> </div>
); );
};
const renderAdmins = () => ( const renderAdmins = () => (
<div className="card"> <div className="card">