telegram-invite-automation/src/renderer/components/TasksSidebar.jsx
2026-02-01 14:39:30 +04:00

148 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
export default function TasksSidebar({
createTask,
taskSearch,
setTaskSearch,
taskFilter,
setTaskFilter,
taskSort,
setTaskSort,
filteredTasks,
taskStatusMap,
selectedTaskId,
selectTask,
deleteTask,
hasSelectedTask,
formatCountdown,
formatTimestamp,
accountById,
formatAccountLabel
}) {
return (
<section className="card sticky">
<div className="row-header">
<h3>Задачи</h3>
<button className="ghost" type="button" onClick={createTask}>Новая задача</button>
</div>
<div className="task-controls">
<div className="task-search">
<input
type="text"
value={taskSearch}
onChange={(event) => setTaskSearch(event.target.value)}
placeholder="Поиск по названию или ссылке"
/>
</div>
<div className="task-filters">
<button
type="button"
className={`chip ${taskFilter === "all" ? "active" : ""}`}
onClick={() => setTaskFilter("all")}
>
Все
</button>
<button
type="button"
className={`chip ${taskFilter === "running" ? "active" : ""}`}
onClick={() => setTaskFilter("running")}
>
Запущены
</button>
<button
type="button"
className={`chip ${taskFilter === "stopped" ? "active" : ""}`}
onClick={() => setTaskFilter("stopped")}
>
Остановлены
</button>
</div>
<div className="row-inline">
<label className="select-inline">
<span>Сортировка</span>
<select value={taskSort} onChange={(event) => setTaskSort(event.target.value)}>
<option value="activity">Активные сверху</option>
<option value="queue">По очереди</option>
<option value="limit">По лимиту</option>
<option value="lastMessage">По последнему сообщению</option>
<option value="id">По ID</option>
</select>
</label>
</div>
</div>
<div className="task-list">
{filteredTasks.length === 0 && <div className="empty">Совпадений нет.</div>}
{filteredTasks.map((task) => {
const status = taskStatusMap[task.id];
const statusLabel = status ? (status.running ? "Запущено" : "Остановлено") : "—";
const statusClass = status ? (status.running ? "ok" : "off") : "off";
const unconfirmedCount = status ? Number(status.unconfirmedCount || 0) : 0;
const queueLabel = status ? `Очередь: ${status.queueCount}` : "Очередь: —";
const dailyLabel = status ? `Лимит сегодня: ${status.dailyUsed}/${status.dailyLimit}` : "Лимит сегодня: —";
const cycleLabel = status && status.running ? `Цикл: ${formatCountdown(status.nextRunAt)}` : "Цикл: —";
const lastMessageRaw = status && status.monitorInfo && status.monitorInfo.lastMessageAt
? status.monitorInfo.lastMessageAt
: "";
const lastMessage = formatTimestamp(lastMessageRaw);
const lastSource = status && status.monitorInfo && status.monitorInfo.lastSource
? status.monitorInfo.lastSource
: "—";
const monitoring = Boolean(status && status.monitorInfo && status.monitorInfo.monitoring);
const monitorAccountIds = status && status.monitorInfo && status.monitorInfo.accountIds
? status.monitorInfo.accountIds
: (status && status.monitorInfo && status.monitorInfo.accountId ? [status.monitorInfo.accountId] : []);
const monitorLabels = monitorAccountIds
.map((id) => {
const account = accountById.get(id);
return account ? formatAccountLabel(account) : String(id);
})
.filter(Boolean);
const monitorLabel = monitorLabels.length
? (monitorLabels.length > 2 ? `${monitorLabels.length} аккаунта` : monitorLabels.join(", "))
: "—";
const tooltip = [
`Статус: ${statusLabel}`,
`Очередь: ${status ? status.queueCount : "—"}`,
`Лимит сегодня: ${status ? `${status.dailyUsed}/${status.dailyLimit}` : "—"}`,
`Мониторинг: ${monitoring ? "активен" : "нет"}`,
`Мониторит: ${monitorLabel}`,
`Последнее: ${lastMessage}`,
`Источник: ${lastSource}`
].join(" | ");
return (
<button
key={task.id}
type="button"
className={`task-item ${selectedTaskId === task.id ? "active" : ""}`}
onClick={() => selectTask(task.id)}
title={tooltip}
>
<div className="task-info">
<div className="task-title-row">
<div className="task-title">{task.name || `Задача #${task.id}`}</div>
<div className="task-badge-row">
<div className={`task-badge ${statusClass}`}>{statusLabel}</div>
{unconfirmedCount > 0 && (
<div className="task-badge warn" title={`Не подтверждено: ${unconfirmedCount}`}>
Не подтверждено: {unconfirmedCount}
</div>
)}
</div>
</div>
<div className="task-meta-row">
<span className="task-meta">{queueLabel}</span>
<span className="task-meta">{dailyLabel}</span>
<span className="task-meta">{cycleLabel}</span>
</div>
</div>
</button>
);
})}
</div>
<div className="sidebar-actions">
<button className="danger" type="button" onClick={deleteTask} disabled={!hasSelectedTask}>Удалить задачу</button>
</div>
</section>
);
}