Redesign note display as message cards; fix reply and Textarea v-model bugs
- NoteItem.vue: render each note as a rounded card (own notes tinted) instead of a flat list row. - TaskNotes.vue: show a "Replying to X" banner with cancel and auto-focus the composer when Reply is clicked, so replying is actually visible instead of silently setting hidden state. - ShotDetailPanel/ShotBrowser/TaskDetailPanel: carry the target note id through select-task so replying from the shot-level aggregated notes view pre-fills the reply in the destination task's panel instead of just switching tabs. - Textarea.vue: fix v-model, which was never wired up (modelValue/ update:modelValue fell through as dead attrs on the native textarea), so typed content never reached the bound ref anywhere it's used - notes, submissions, and shot/asset/episode/project description fields. - AssetDetailPanel/ShotDetailPanel/TaskDetailPanel: drop the header status badge and switch tab labels to icons (with an unread-style badge on Notes), fixing the TabsTrigger clipping/vertical alignment it introduced.
This commit is contained in:
@@ -12,31 +12,39 @@
|
||||
<!-- Task Details -->
|
||||
<div v-else-if="task" class="flex-1 flex flex-col min-h-0">
|
||||
<DetailPanelHeader class="flex-shrink-0" :title="task.name" @close="emit('close')">
|
||||
<template #badges>
|
||||
<TaskStatusBadge :status="task.status" class="flex-shrink-0" />
|
||||
</template>
|
||||
</DetailPanelHeader>
|
||||
|
||||
<!-- Tabbed Content -->
|
||||
<Tabs :default-value="initialTab || 'infos'" class="flex-1 flex flex-col min-h-0">
|
||||
<!-- Tabs List (Fixed) -->
|
||||
<TabsList class="flex-shrink-0 mx-0 mt-0 grid w-full grid-cols-4 rounded-none border-b">
|
||||
<TabsTrigger value="infos">Infos</TabsTrigger>
|
||||
<TabsTrigger value="notes">
|
||||
Notes
|
||||
<Badge v-if="notes.length > 0" variant="secondary" class="ml-2">
|
||||
{{ notes.length }}
|
||||
</Badge>
|
||||
<TabsTrigger value="infos" title="Infos">
|
||||
<Info class="h-4 w-4" />
|
||||
<span class="sr-only">Infos</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="attachments">
|
||||
Attachments
|
||||
<Badge v-if="attachments.length > 0" variant="secondary" class="ml-2">
|
||||
<TabsTrigger value="notes" title="Notes">
|
||||
<span class="relative inline-flex">
|
||||
<MessageSquare class="h-4 w-4" />
|
||||
<span
|
||||
v-if="notes.length > 0"
|
||||
class="absolute -top-1.5 -right-1.5 h-3.5 w-3.5 rounded-full bg-red-500 text-white text-[9px] leading-none flex items-center justify-center"
|
||||
>
|
||||
{{ notes.length > 99 ? '99+' : notes.length }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="sr-only">Notes</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="attachments" title="Attachments">
|
||||
<Paperclip class="h-4 w-4" />
|
||||
<span class="sr-only">Attachments</span>
|
||||
<Badge v-if="attachments.length > 0" variant="secondary" class="ml-1 h-4 px-1 text-[10px]">
|
||||
{{ attachments.length }}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="submissions">
|
||||
Submissions
|
||||
<Badge v-if="submissions.length > 0" variant="secondary" class="ml-2">
|
||||
<TabsTrigger value="submissions" title="Submissions">
|
||||
<Upload class="h-4 w-4" />
|
||||
<span class="sr-only">Submissions</span>
|
||||
<Badge v-if="submissions.length > 0" variant="secondary" class="ml-1 h-4 px-1 text-[10px]">
|
||||
{{ submissions.length }}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
@@ -178,7 +186,12 @@
|
||||
|
||||
<!-- Notes Tab -->
|
||||
<TabsContent value="notes" class="flex-1 m-0 overflow-hidden">
|
||||
<TaskNotes :task-id="taskId" :notes="notes" @notes-updated="loadNotes" />
|
||||
<TaskNotes
|
||||
:task-id="taskId"
|
||||
:notes="notes"
|
||||
:initial-reply-note-id="initialReplyNoteId"
|
||||
@notes-updated="loadNotes"
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<!-- Attachments Tab -->
|
||||
@@ -262,7 +275,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, computed } from 'vue'
|
||||
import { Play, Upload, UserPlus, Calendar, User } from 'lucide-vue-next'
|
||||
import { Play, Upload, UserPlus, Calendar, User, Info, MessageSquare, Paperclip } from 'lucide-vue-next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Label } from '@/components/ui/label'
|
||||
@@ -299,7 +312,6 @@ import {
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/command'
|
||||
import TaskStatusBadge from './TaskStatusBadge.vue'
|
||||
import TaskNotes from './TaskNotes.vue'
|
||||
import TaskAttachments from './TaskAttachments.vue'
|
||||
import TaskSubmissions from './TaskSubmissions.vue'
|
||||
@@ -311,6 +323,7 @@ import { useToast } from '@/components/ui/toast/use-toast'
|
||||
const props = defineProps<{
|
||||
taskId: number
|
||||
initialTab?: string
|
||||
initialReplyNoteId?: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
Reference in New Issue
Block a user