Update files
This commit is contained in:
parent
2bb573b919
commit
f9ff325c8a
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue