Improve session discovery UI with intuitive navigation
- Add stats bar showing completed/in-progress/total sessions count - Add status filter tabs (All, Completed, In Progress) - Add horizontal carousel display for recent sessions - Add 'View All Sessions' expandable button - Add visual divider between recent sessions and new session form - Improve session cards with better information display - Make sessions more discoverable and easier to access - Add filtering and sorting capabilities for better UX
This commit is contained in:
parent
56cf1a3efd
commit
1dde7dfc5b
@ -12,6 +12,8 @@ const agentCount = ref(7)
|
||||
const isCreating = ref(false)
|
||||
const previousSessions = ref([])
|
||||
const loadingPreviousSessions = ref(false)
|
||||
const showAllSessions = ref(false)
|
||||
const sessionStatusFilter = ref('all') // 'all', 'completed', 'ongoing', 'created'
|
||||
|
||||
onMounted(async () => {
|
||||
loadingPreviousSessions.value = true
|
||||
@ -37,6 +39,28 @@ const agentOptions = computed(() => {
|
||||
}))
|
||||
})
|
||||
|
||||
const filteredSessions = computed(() => {
|
||||
let filtered = previousSessions.value
|
||||
|
||||
if (sessionStatusFilter.value !== 'all') {
|
||||
filtered = filtered.filter(s => s.status === sessionStatusFilter.value)
|
||||
}
|
||||
|
||||
return filtered
|
||||
})
|
||||
|
||||
const displayedSessions = computed(() => {
|
||||
return showAllSessions.value ? filteredSessions.value : filteredSessions.value.slice(0, 6)
|
||||
})
|
||||
|
||||
const completedCount = computed(() => {
|
||||
return previousSessions.value.filter(s => s.status === 'completed').length
|
||||
})
|
||||
|
||||
const ongoingCount = computed(() => {
|
||||
return previousSessions.value.filter(s => s.status === 'ongoing').length
|
||||
})
|
||||
|
||||
const handleFileSelect = (event) => {
|
||||
const file = event.target.files?.[0]
|
||||
if (file) {
|
||||
@ -112,6 +136,88 @@ const removeFile = () => {
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<!-- Quick Access Section -->
|
||||
<div v-if="previousSessions.length > 0" class="quick-access-section">
|
||||
<div class="stats-bar">
|
||||
<div class="stat">
|
||||
<span class="stat-label">Completed</span>
|
||||
<span class="stat-value">{{ completedCount }}</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-label">In Progress</span>
|
||||
<span class="stat-value">{{ ongoingCount }}</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-label">Total</span>
|
||||
<span class="stat-value">{{ previousSessions.length }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Filter -->
|
||||
<div class="filter-tabs">
|
||||
<button
|
||||
@click="sessionStatusFilter = 'all'"
|
||||
class="filter-btn"
|
||||
:class="{ active: sessionStatusFilter === 'all' }"
|
||||
>
|
||||
All Sessions
|
||||
</button>
|
||||
<button
|
||||
@click="sessionStatusFilter = 'completed'"
|
||||
class="filter-btn"
|
||||
:class="{ active: sessionStatusFilter === 'completed' }"
|
||||
>
|
||||
Completed
|
||||
</button>
|
||||
<button
|
||||
@click="sessionStatusFilter = 'ongoing'"
|
||||
class="filter-btn"
|
||||
:class="{ active: sessionStatusFilter === 'ongoing' }"
|
||||
>
|
||||
In Progress
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Recent Sessions Grid -->
|
||||
<div class="recent-sessions-scroll">
|
||||
<div class="sessions-carousel">
|
||||
<div
|
||||
v-for="session in displayedSessions"
|
||||
:key="session.sessionId"
|
||||
@click="handleOpenSession(session.sessionId)"
|
||||
class="session-card-horizontal"
|
||||
:class="{ 'status-' + session.status }"
|
||||
:title="session.prompt"
|
||||
>
|
||||
<div class="card-left">
|
||||
<div class="session-id">#{{ session.sessionId }}</div>
|
||||
</div>
|
||||
<div class="card-main">
|
||||
<p class="session-prompt-short">{{ session.prompt.substring(0, 75) }}{{ session.prompt.length > 75 ? '...' : '' }}</p>
|
||||
<p class="session-meta">{{ new Date(session.createdAt).toLocaleDateString() }}</p>
|
||||
</div>
|
||||
<div class="card-right">
|
||||
<span class="status-badge">{{ session.status }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="filteredSessions.length > 6" class="view-all-container">
|
||||
<button
|
||||
@click="showAllSessions = !showAllSessions"
|
||||
class="view-all-btn"
|
||||
>
|
||||
{{ showAllSessions ? 'Show Less' : `View All (${filteredSessions.length} sessions)` }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div v-if="previousSessions.length > 0" class="divider">
|
||||
<span>Or start a new session</span>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="handleCreateSession" class="form">
|
||||
<!-- Project Description -->
|
||||
<div class="form-section">
|
||||
@ -201,27 +307,6 @@ const removeFile = () => {
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Previous Sessions -->
|
||||
<div v-if="previousSessions.length > 0" class="previous-sessions-section">
|
||||
<h2>Recent Sessions</h2>
|
||||
<div class="sessions-grid">
|
||||
<div
|
||||
v-for="session in previousSessions.slice(0, 6)"
|
||||
:key="session.sessionId"
|
||||
@click="handleOpenSession(session.sessionId)"
|
||||
class="session-card"
|
||||
:class="{ 'status-completed': session.status === 'completed' }"
|
||||
>
|
||||
<div class="session-header">
|
||||
<span class="session-id">#{{ session.sessionId }}</span>
|
||||
<span class="session-status">{{ session.status }}</span>
|
||||
</div>
|
||||
<p class="session-prompt">{{ session.prompt.substring(0, 100) }}...</p>
|
||||
<p class="session-date">{{ new Date(session.createdAt).toLocaleDateString() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<p>Typical session: 2-5 rounds for complete consensus. Output format: Markdown</p>
|
||||
</footer>
|
||||
@ -617,6 +702,225 @@ const removeFile = () => {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Quick Access Section */
|
||||
.quick-access-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.stats-bar {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
background: rgba(102, 126, 234, 0.08);
|
||||
border: 1px solid rgba(102, 126, 234, 0.2);
|
||||
border-radius: 12px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.8rem;
|
||||
color: rgba(102, 126, 234, 0.95);
|
||||
font-weight: 700;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
padding: 0.6rem 1.2rem;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.filter-btn:hover {
|
||||
background: rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.filter-btn.active {
|
||||
background: rgba(102, 126, 234, 0.3);
|
||||
border-color: rgba(102, 126, 234, 0.6);
|
||||
color: rgba(255, 255, 255, 0.95);
|
||||
box-shadow: 0 0 15px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.recent-sessions-scroll {
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sessions-carousel {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
min-width: min-content;
|
||||
}
|
||||
|
||||
.session-card-horizontal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
min-width: 350px;
|
||||
padding: 1rem;
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
border: 1px solid rgba(102, 126, 234, 0.3);
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.session-card-horizontal:hover {
|
||||
background: rgba(102, 126, 234, 0.15);
|
||||
border-color: rgba(102, 126, 234, 0.5);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.session-card-horizontal.status-completed {
|
||||
border-color: rgba(76, 175, 80, 0.3);
|
||||
background: rgba(76, 175, 80, 0.05);
|
||||
}
|
||||
|
||||
.session-card-horizontal.status-completed:hover {
|
||||
background: rgba(76, 175, 80, 0.12);
|
||||
border-color: rgba(76, 175, 80, 0.5);
|
||||
box-shadow: 0 8px 20px rgba(76, 175, 80, 0.15);
|
||||
}
|
||||
|
||||
.card-left {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.card-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.session-prompt-short {
|
||||
margin: 0;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.session-meta {
|
||||
margin: 0.25rem 0 0 0;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.card-right {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.4rem 0.8rem;
|
||||
background: rgba(76, 175, 80, 0.2);
|
||||
color: rgba(76, 175, 80, 0.9);
|
||||
border-radius: 20px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.session-card-horizontal.status-ongoing .status-badge {
|
||||
background: rgba(102, 126, 234, 0.2);
|
||||
color: rgba(102, 126, 234, 0.9);
|
||||
}
|
||||
|
||||
.view-all-container {
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.view-all-btn {
|
||||
padding: 0.7rem 1.5rem;
|
||||
background: rgba(102, 126, 234, 0.15);
|
||||
border: 1px solid rgba(102, 126, 234, 0.3);
|
||||
color: rgba(102, 126, 234, 0.9);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.view-all-btn:hover {
|
||||
background: rgba(102, 126, 234, 0.25);
|
||||
border-color: rgba(102, 126, 234, 0.5);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
|
||||
}
|
||||
|
||||
.divider {
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.divider span {
|
||||
background: linear-gradient(
|
||||
-45deg,
|
||||
#0f0c29 0%,
|
||||
#302b63 25%,
|
||||
#24243e 50%,
|
||||
#302b63 75%,
|
||||
#0f0c29 100%
|
||||
);
|
||||
padding: 0 1rem;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.divider::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, rgba(102, 126, 234, 0.2), transparent);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.collaborative-input {
|
||||
padding: 1rem;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user