diff --git a/docs/TASKS/content/008-multi-channel-preview-editor.md b/docs/TASKS/content/008-multi-channel-preview-editor.md index 5b07d231..d0c31ac3 100644 --- a/docs/TASKS/content/008-multi-channel-preview-editor.md +++ b/docs/TASKS/content/008-multi-channel-preview-editor.md @@ -15,12 +15,12 @@ The editor should use one shared content body for every selected target channel, - Keep content item editing in `frontend/src/features/content/views/ContentItemDetailView.vue`. - Replace per-channel caption editing with a shared caption and shared hashtags. - Let configured workspace channels be selected or unselected as targets. -- Show selected targets in a vertical rail and render preview cards that look closer to social platform previews. +- Show target channels as a single vertical tab rail and render preview cards that look closer to social platform previews. - Convert shared hashtags into chip-style entry with suggestions from already used hashtags. - Show a workspace hashtag feed so authors can reuse existing tags. - Keep the editor focused on post text and target channels by removing confusing title, calendar, change summary, and base-caption fields. - Make target preview tabs compact. -- Move the create content entry point into the main app menu. +- Move the create content entry point into the top app menu bar. - Preserve existing save payloads and backend contracts. ## Validation @@ -40,5 +40,5 @@ npm run build - [x] Already used hashtags are available as suggestions. - [x] The editor shows a workspace hashtag feed with usage counts. - [x] The editor no longer shows title, calendar, change summary, or base-caption fields. -- [x] Target channel preview tabs use compact buttons. -- [x] Create content is available from the main app menu. +- [x] Target channel tabs use compact icon-only buttons with channel names as accessible labels and tooltips. +- [x] Create content is available from the top app menu bar. diff --git a/frontend/src/features/content/views/ContentItemDetailView.vue b/frontend/src/features/content/views/ContentItemDetailView.vue index 6af76506..d00bc611 100644 --- a/frontend/src/features/content/views/ContentItemDetailView.vue +++ b/frontend/src/features/content/views/ContentItemDetailView.vue @@ -283,11 +283,11 @@ } } - function toggleChannel(channel) { + function selectTargetChannel(channel) { const existing = form.placements.find(placement => placement.channelId === channel.id); if (existing) { - removePlacement(existing.id); + activePlacementId.value = existing.id; return; } @@ -298,10 +298,6 @@ return form.placements.some(placement => placement.channelId === channelId); } - function setActivePlacement(placement) { - activePlacementId.value = placement.id; - } - function addMedia(placement) { placement.mediaItems.push(blankMedia()); } @@ -1104,7 +1100,7 @@
- +
-
- - - {{ placement.channelName || placement.network }} - -
-
span { - @apply px-2 text-xs font-bold uppercase tracking-[0.16em]; + @apply text-[0.62rem] font-bold uppercase tracking-[0.12em]; color: var(--app-text-muted); } .target-channel { - @apply grid min-h-11 w-full grid-cols-[1rem_1.75rem_minmax(0,1fr)] items-center gap-2 rounded-[0.75rem] border px-2.5 py-1.5 text-left transition; + @apply relative grid h-10 w-10 place-items-center rounded-[0.75rem] border p-0 transition; background: var(--app-control-subtle); border-color: transparent; color: var(--app-color-on-surface); @@ -1864,7 +1843,7 @@ } .target-check { - @apply text-lg; + @apply absolute -right-1 -top-1 text-base; color: var(--app-color-on-tertiary); } @@ -1884,53 +1863,10 @@ color: var(--app-color-on-primary); } - .target-channel span { - @apply flex min-w-0 flex-col gap-0.5; - } - - .target-channel strong, - .target-channel small { - @apply block truncate; - } - - .target-channel strong { - @apply text-xs font-bold; - } - - .target-channel small { - @apply text-[0.68rem]; - color: var(--app-text-muted); - } - - .target-channel.active small { - color: rgba(255, 255, 255, 0.72); - } - .preview-stage { @apply flex min-w-0 flex-col gap-3; } - .selected-preview-tabs { - @apply flex gap-2 overflow-x-auto pb-1; - } - - .selected-preview-tab { - @apply inline-flex min-h-8 max-w-36 shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-bold transition; - background: var(--app-color-on-primary); - border-color: var(--app-border-subtle); - color: var(--app-color-on-surface); - } - - .selected-preview-tab span { - @apply truncate; - } - - .selected-preview-tab.active { - background: var(--app-color-on-surface); - border-color: var(--app-color-on-surface); - color: var(--app-color-on-primary); - } - .social-preview-card { @apply flex min-h-[28rem] flex-col gap-4 rounded-[1.25rem] border p-4 shadow-sm; background: var(--app-color-on-primary); diff --git a/frontend/src/layouts/main/AppBar.vue b/frontend/src/layouts/main/AppBar.vue index 30f727bd..b148ef64 100644 --- a/frontend/src/layouts/main/AppBar.vue +++ b/frontend/src/layouts/main/AppBar.vue @@ -97,6 +97,17 @@ } switch (route.name) { + case 'workspace-dashboard': + case 'content-items': + case 'content-item-detail': + return authStore.isManager || authStore.isProvider + ? [{ + key: 'create-content', + label: t('contentItems.newItem'), + icon: mdiPlus, + route: { name: 'content-item-create' }, + }] + : []; case 'campaigns': return [{ key: 'create-campaign', diff --git a/frontend/src/layouts/main/AppSidebar.vue b/frontend/src/layouts/main/AppSidebar.vue index 47c68d9f..f977b602 100644 --- a/frontend/src/layouts/main/AppSidebar.vue +++ b/frontend/src/layouts/main/AppSidebar.vue @@ -57,7 +57,6 @@ const primaryLinks = [ { to: '/app/dashboard', labelKey: 'nav.overview', icon: mdiHomeOutline }, - { to: { name: 'content-item-create' }, key: 'create-content', labelKey: 'contentItems.newItem', icon: mdiPlus }, { to: '/app/media-library', labelKey: 'nav.mediaLibrary', icon: mdiImageMultipleOutline }, { to: '/app/developer/release-notes', labelKey: 'nav.releaseNotes', icon: mdiSourceCommit, roles: ['developer'], badge: 'commits' }, ];