Sticky table headers, layout parity, and reuse My Tasks on the shared table/toolbar

Shot/Asset/Task data tables now keep their header row pinned while scrolling
(both the locked two-pane and single-table modes), matching a common data-
table expectation that was missing everywhere.

Brings Asset and Task browsers to full structural parity with Shot's bounded-
height layout (fixed toolbar, internally-scrolling table) instead of their
previous page-scroll model with a sticky-positioned toolbar. AssetsDataTable
gained the synced frozen/movable-pane scrolling it was missing entirely;
TasksDataTable and both browsers/parent views got the same container model.

The global My Tasks page (/tasks) now reuses TaskTableToolbar and
TasksDataTable instead of its own ad hoc filter selects and TaskList,
including the detail panel, bulk status/assignment context menu, and sticky
header for free. Since it spans multiple projects, TaskTableToolbar gained
an optional Project filter (only rendered when a project list is passed in,
so the project-scoped Tasks page is unaffected); episode/assignee filters
populate once a specific project is chosen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 10:15:04 +08:00
parent 442abc3586
commit e628c99498
9 changed files with 525 additions and 163 deletions
+12 -12
View File
@@ -1,9 +1,9 @@
<template>
<div class="relative h-full">
<!-- Main Content (Full Width) -->
<div class="space-y-4">
<!-- Toolbar - Sticky -->
<div class="sticky top-0 z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b pb-4 px-4 sm:px-6 pt-4 sm:pt-6 mb-4">
<div class="relative h-full flex flex-col">
<!-- Main Content -->
<div class="flex flex-col flex-1 min-h-0">
<!-- Toolbar -->
<div class="flex-shrink-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b pb-4 px-4 sm:px-6 pt-4 sm:pt-6 mb-4">
<AssetTableToolbar
v-if="customTaskTypesLoaded"
:view-mode="viewMode"
@@ -36,7 +36,7 @@
</div>
<!-- Loading State -->
<div v-if="isLoading" class="flex items-center justify-center py-12">
<div v-if="isLoading" class="flex items-center justify-center py-12 px-4 sm:px-6">
<div class="flex items-center gap-2">
<div
class="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"
@@ -46,7 +46,7 @@
</div>
<!-- Error State -->
<div v-else-if="error" class="text-center py-12">
<div v-else-if="error" class="text-center py-12 px-4 sm:px-6">
<AlertCircle class="h-12 w-12 mx-auto text-destructive mb-4" />
<h3 class="text-lg font-semibold mb-2">Failed to load assets</h3>
<p class="text-muted-foreground mb-4">{{ error }}</p>
@@ -61,7 +61,7 @@
v-else-if="
filteredAssets.length === 0 && !searchQuery && !selectedCategory
"
class="text-center py-12"
class="text-center py-12 px-4 sm:px-6"
>
<Package class="h-12 w-12 mx-auto text-muted-foreground mb-4" />
<h3 class="text-lg font-semibold mb-2">No assets yet</h3>
@@ -75,7 +75,7 @@
</div>
<!-- No Results State -->
<div v-else-if="filteredAssets.length === 0" class="text-center py-12">
<div v-else-if="filteredAssets.length === 0" class="text-center py-12 px-4 sm:px-6">
<Search class="h-12 w-12 mx-auto text-muted-foreground mb-4" />
<h3 class="text-lg font-semibold mb-2">No assets found</h3>
<p class="text-muted-foreground mb-4">
@@ -85,11 +85,11 @@
</div>
<!-- Assets Grid/List -->
<div v-else>
<div v-else class="flex-1 min-h-0">
<!-- Grid View -->
<div
v-if="viewMode === 'grid'"
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 gap-3"
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 gap-3 px-4 sm:px-6 h-full overflow-auto"
>
<AssetCard
v-for="asset in filteredAssets"
@@ -117,7 +117,7 @@
@update:rowSelection="handleRowSelectionChange"
@row-click="handleRowClick"
/>
<div v-else class="flex items-center justify-center py-12">
<div v-else class="flex items-center justify-center py-12 px-4 sm:px-6">
<div class="flex items-center gap-2">
<div class="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"></div>
<span class="text-muted-foreground">Loading table...</span>