diff --git a/app/(dashboard)/external-channels/page.tsx b/app/(dashboard)/external-channels/page.tsx index b47509d..3ccf86a 100644 --- a/app/(dashboard)/external-channels/page.tsx +++ b/app/(dashboard)/external-channels/page.tsx @@ -35,9 +35,22 @@ import { Pencil, Trash2, Users, + ArrowUpDown, + ArrowUp, + ArrowDown, + LayoutGrid, + Table2, } from "lucide-react"; import type { ExternalChannel } from "@/lib/types/api"; import { Alert, AlertDescription } from "@/components/ui/alert"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; import { Dialog, DialogContent, @@ -51,6 +64,15 @@ import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { useTargetChannel } from "@/components/providers/target-channel-provider"; +type ViewMode = "table" | "grid"; +type SortField = + | "title" + | "username" + | "subscribers_count" + | "telegram_id" + | null; +type SortDirection = "asc" | "desc" | null; + export default function ExternalChannelsPage() { const { selectedChannel } = useTargetChannel(); const [channels, setChannels] = useState([]); @@ -59,6 +81,9 @@ export default function ExternalChannelsPage() { const [searchQuery, setSearchQuery] = useState(""); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); const [isCreating, setIsCreating] = useState(false); + const [viewMode, setViewMode] = useState("table"); + const [sortField, setSortField] = useState(null); + const [sortDirection, setSortDirection] = useState(null); // Form state const [formData, setFormData] = useState({ @@ -148,11 +173,77 @@ export default function ExternalChannelsPage() { } }; - const filteredChannels = channels.filter( - (channel) => - channel.title.toLowerCase().includes(searchQuery.toLowerCase()) || - channel.username?.toLowerCase().includes(searchQuery.toLowerCase()) - ); + // Обработка сортировки + const handleSort = (field: SortField) => { + if (sortField === field) { + // Переключение: asc -> desc -> null -> asc + if (sortDirection === "asc") { + setSortDirection("desc"); + } else if (sortDirection === "desc") { + setSortField(null); + setSortDirection(null); + } + } else { + setSortField(field); + setSortDirection("asc"); + } + }; + + const getSortIcon = (field: SortField) => { + if (sortField !== field) { + return ; + } + if (sortDirection === "asc") { + return ; + } + return ; + }; + + const filteredChannels = channels + .filter( + (channel) => + channel.title.toLowerCase().includes(searchQuery.toLowerCase()) || + channel.username?.toLowerCase().includes(searchQuery.toLowerCase()) + ) + .sort((a, b) => { + if (!sortField || !sortDirection) return 0; + + let aValue: string | number | null = ""; + let bValue: string | number | null = ""; + + switch (sortField) { + case "title": + aValue = a.title; + bValue = b.title; + break; + case "username": + aValue = a.username || ""; + bValue = b.username || ""; + break; + case "subscribers_count": + aValue = a.subscribers_count || 0; + bValue = b.subscribers_count || 0; + break; + case "telegram_id": + aValue = a.telegram_id; + bValue = b.telegram_id; + break; + } + + // Сравнение строк + if (typeof aValue === "string" && typeof bValue === "string") { + return sortDirection === "asc" + ? aValue.localeCompare(bValue) + : bValue.localeCompare(aValue); + } + + // Сравнение чисел + if (typeof aValue === "number" && typeof bValue === "number") { + return sortDirection === "asc" ? aValue - bValue : bValue - aValue; + } + + return 0; + }); return ( <> @@ -292,19 +383,39 @@ export default function ExternalChannelsPage() { )} -
-
- - setSearchQuery(e.target.value)} - className="pl-8" - /> +
+
+
+ + setSearchQuery(e.target.value)} + className="pl-8 rounded-lg" + /> +
+ + Всего: {formatNumber(filteredChannels.length)} + +
+
+ +
- - Всего: {formatNumber(filteredChannels.length)} -
{loading ? ( @@ -325,7 +436,7 @@ export default function ExternalChannelsPage() {

- ) : ( + ) : viewMode === "grid" ? (
{filteredChannels.map((channel) => (
-
-
- ID: {channel.telegram_id} -
-
- Telegram ID -
-
@@ -404,6 +507,109 @@ export default function ExternalChannelsPage() { ))}
+ ) : ( + + + Список внешних каналов + + Каналы, в которых покупаете рекламу + + + + + + + handleSort("title")} + > + Название + {getSortIcon("title")} + + + Username + + Описание + handleSort("subscribers_count")} + > + Подписчики + {getSortIcon("subscribers_count")} + + + Telegram ID + + + + + + {filteredChannels.map((channel) => ( + + + + + + {channel.username ? ( +
{formatUsername(channel.username)}
+ ) : ( + "—" + )} +
+ +
+ {channel.description || "—"} +
+
+ + {channel.subscribers_count + ? formatNumber(channel.subscribers_count) + : "—"} + + + {channel.telegram_id} + + + + +
+ ))} +
+
+
+
)}