feat(ServerGroupCard): implement group selection functionality and improve selection indicator logic
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m53s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m53s
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user