feat(ServerGroupCard): implement group selection functionality and improve selection indicator logic
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m53s

This commit is contained in:
2026-02-17 11:17:04 +07:00
parent 804f132d42
commit e09976b64e
@@ -5,7 +5,6 @@ import {
IconChevronUp,
IconRouter,
IconCircleCheck,
IconSquare,
IconNetwork,
IconCloud
} from '@tabler/icons-react';
@@ -41,6 +40,15 @@ export default function ServerGroupCard({
const tunnel = first?.tunnel;
const wanCount = servers.length;
const anySelected = servers.some((s) => selectedSet.has(s.ip));
const allSelected = servers.length > 0 && servers.every((s) => selectedSet.has(s.ip));
const handleGroupSelect = () => {
servers.forEach((s) => {
const selected = selectedSet.has(s.ip);
if (allSelected && selected) onSelect?.(s);
if (!allSelected && !selected) onSelect?.(s);
});
};
return (
<div
@@ -64,11 +72,11 @@ export default function ServerGroupCard({
borderBottomLeftRadius: expanded ? '0' : (anySelected ? '10px' : '11px'),
cursor: 'pointer'
}}
onClick={() => onSelect?.(first)}
onClick={handleGroupSelect}
>
<div className="text-center">
<div className="mb-1">
{anySelected ? (
{allSelected ? (
<IconCircleCheck size={20} className="text-green" />
) : (
<IconRouter size={20} className="text-green" />
@@ -171,27 +179,27 @@ export default function ServerGroupCard({
className={`d-flex align-items-stretch rounded mb-1 overflow-hidden ${isSelected ? 'bg-primary-lt' : 'bg-white'}`}
style={{ boxShadow: '0 0 0 1px rgba(0,0,0,0.06)' }}
>
{/* Бейдж HOME у вложенного роутера */}
{/* Бейдж HOME — клик как у обычной карточки, без явной галочки */}
<div
className="d-flex align-items-center justify-content-center bg-green-lt text-green px-2"
style={{ minWidth: '52px', fontSize: '0.6rem', fontWeight: 700, letterSpacing: '0.5px' }}
style={{
minWidth: '52px',
fontSize: '0.6rem',
fontWeight: 700,
letterSpacing: '0.5px',
cursor: 'pointer'
}}
onClick={() => onSelect?.(server)}
title={isSelected ? 'Снять выбор' : 'Выбрать'}
>
<IconRouter size={14} className="me-1" />
{isSelected ? (
<IconCircleCheck size={14} className="me-1" />
) : (
<IconRouter size={14} className="me-1" />
)}
HOME
</div>
<div className="d-flex align-items-center flex-grow-1 py-2 px-2 min-w-0">
<button
type="button"
className="btn btn-ghost-secondary btn-icon btn-sm p-0 me-2 flex-shrink-0"
onClick={() => onSelect?.(server)}
title={isSelected ? 'Снять выбор' : 'Выбрать'}
>
{isSelected ? (
<IconCircleCheck size={18} className="text-primary" />
) : (
<IconSquare size={18} className="text-muted" />
)}
</button>
<span className="me-2 flex-shrink-0" style={{ fontSize: '1.1rem' }}>{countryToFlag(server.country)}</span>
<div className="min-w-0">
<span className="fw-medium">{serverName}</span>