feat: teams redesign — cards, filter, user autocomplete

- Teams index: cards with animation, search filter
- Team detail: user autocomplete via AJAX (search on type)
- CSS: card grid styles, autocomplete dropdown
- Backend: searchUsers endpoint, filter support
This commit is contained in:
2026-06-09 18:11:20 -04:00
parent b1fc0e2cfe
commit 13f14416a4
5 changed files with 419 additions and 75 deletions

View File

@@ -2840,3 +2840,234 @@ textarea.form-input {
.nav-sub-item .status-dot-sm {
display: inline-block;
}
/* ═══════════════════════════════════════════════════════════════════════════
Teams — Card Grid
═══════════════════════════════════════════════════════════════════════════ */
.teams-toolbar {
margin-bottom: 1.5rem;
}
.teams-search {
position: relative;
max-width: 400px;
}
.teams-search-icon {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-muted);
font-size: 0.9rem;
}
.teams-search-input {
padding-left: 36px !important;
padding-right: 36px !important;
}
.teams-search-clear {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: var(--text-muted);
font-size: 1.2rem;
cursor: pointer;
padding: 4px 8px;
line-height: 1;
}
.teams-search-clear:hover {
color: var(--text-primary);
}
.teams-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1rem;
}
.team-card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1.25rem;
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
animation: teamCardEnter 0.35s ease both;
display: flex;
flex-direction: column;
}
.team-card:nth-child(1) { animation-delay: 0.00s; }
.team-card:nth-child(2) { animation-delay: 0.05s; }
.team-card:nth-child(3) { animation-delay: 0.10s; }
.team-card:nth-child(4) { animation-delay: 0.15s; }
.team-card:nth-child(5) { animation-delay: 0.20s; }
.team-card:nth-child(6) { animation-delay: 0.25s; }
.team-card:nth-child(7) { animation-delay: 0.30s; }
.team-card:nth-child(8) { animation-delay: 0.35s; }
.team-card:nth-child(9) { animation-delay: 0.40s; }
.team-card:nth-child(10) { animation-delay: 0.45s; }
.team-card:hover {
transform: translateY(-3px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
border-color: var(--accent);
}
@keyframes teamCardEnter {
from {
opacity: 0;
transform: translateY(15px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.team-card-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.team-card-icon {
width: 40px;
height: 40px;
border-radius: 10px;
background: var(--accent-light);
display: flex;
align-items: center;
justify-content: center;
color: var(--accent);
font-size: 1.1rem;
flex-shrink: 0;
}
.team-card-title {
margin: 0;
font-size: 1.05rem;
font-weight: 600;
color: var(--text-primary);
}
.team-card-title a {
color: var(--text-primary);
text-decoration: none;
}
.team-card-title a:hover {
color: var(--accent);
}
.team-card-desc {
margin: 0 0 1rem;
font-size: 0.875rem;
color: var(--text-secondary);
line-height: 1.5;
flex: 1;
}
.team-card-stats {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
font-size: 0.8rem;
color: var(--text-muted);
}
.team-stat {
display: flex;
align-items: center;
gap: 0.35rem;
}
.team-stat i {
font-size: 0.75rem;
}
.team-card-actions {
display: flex;
gap: 0.5rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border-color);
}
/* ═══════════════════════════════════════════════════════════════════════════
Autocomplete — User Search
═══════════════════════════════════════════════════════════════════════════ */
.autocomplete {
position: relative;
}
.autocomplete-input {
width: 100%;
}
.autocomplete-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
z-index: 100;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 0 0 8px 8px;
max-height: 250px;
overflow-y: auto;
display: none;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.autocomplete-dropdown.active {
display: block;
}
.autocomplete-item {
padding: 10px 14px;
cursor: pointer;
transition: background 0.1s;
border-bottom: 1px solid var(--border-color);
}
.autocomplete-item:last-child {
border-bottom: none;
}
.autocomplete-item:hover {
background: var(--accent-light);
}
.autocomplete-item strong {
color: var(--text-primary);
font-size: 0.9rem;
}
.autocomplete-item small {
color: var(--text-muted);
font-size: 0.8rem;
margin-left: 0.5rem;
}
.autocomplete-empty {
padding: 14px;
text-align: center;
color: var(--text-muted);
font-size: 0.85rem;
}
.form-label {
display: block;
margin-bottom: 0.35rem;
font-size: 0.85rem;
font-weight: 500;
color: var(--text-secondary);
}