From 9d8e80a2bff2ceba37a3b45396e7f2fd004f3a81 Mon Sep 17 00:00:00 2001 From: Timothy Cardoza Date: Thu, 19 Feb 2026 17:36:04 -0600 Subject: [PATCH] tag hiding in buckets to prevent orphaning --- src/components/TaskCard.tsx | 20 +++++++++++++++--- src/components/TaskDetail.tsx | 38 +++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/components/TaskCard.tsx b/src/components/TaskCard.tsx index b20c5f8..773cbc3 100644 --- a/src/components/TaskCard.tsx +++ b/src/components/TaskCard.tsx @@ -1,5 +1,5 @@ import { type Component, createMemo, For } from "solid-js"; -import { type Task, calculateUrgencyFromDate, setActiveTaskId, store, copyTask, updateTask } from "@/store"; +import { type Task, calculateUrgencyFromDate, setActiveTaskId, store, copyTask, updateTask, currentTaskContext } from "@/store"; import { cn } from "@/lib/utils"; import { Clock, ArrowUpCircle, Copy, Users2 } from "lucide-solid"; import { Badge } from "@/components/ui/badge"; @@ -26,6 +26,20 @@ export const TaskCard: Component<{ task: Task }> = (props) => { return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; + // Filter out bucket tags if we are currently INSIDE that bucket view + const visibleTags = createMemo(() => { + const tags = props.task.tags || []; + const ctx = currentTaskContext(); + + if (typeof ctx === 'object' && 'bucketId' in ctx) { + // We are in a bucket view. Hide the tag that matches this bucket's name. + const bucketName = (ctx as { name: string }).name.toLowerCase(); + return tags.filter(t => t.toLowerCase() !== bucketName); + } + + return tags; + }); + return (
= (props) => { })()} {/* Tags */} - {props.task.tags && props.task.tags.length > 0 && ( + {visibleTags().length > 0 && (
- + {(tag) => ( = (props) => { }; const updateTags = (tags: string[]) => { - updateTask(props.task.id, { tags }); + const ctx = currentTaskContext(); + let newTags = [...tags]; + + // If in a bucket view, ensure the bucket tag is preserved (it was hidden from the UI so it's missing from 'tags') + if (typeof ctx === 'object' && 'bucketId' in ctx) { + const bucketName = (ctx as { name: string }).name; + // Check case-insensitive existence + if (!newTags.some(t => t.toLowerCase() === bucketName.toLowerCase())) { + newTags.push(bucketName); + } + } + + updateTask(props.task.id, { tags: newTags }); }; const onDateInputChange = (e: Event) => { @@ -110,6 +122,20 @@ export const TaskDetail: Component = (props) => { // Calculate current urgency level for display const currentUrgency = () => calculateUrgencyFromDate(props.task.dueDate).toString(); + // Filter out bucket tags if we are currently INSIDE that bucket view + const visibleTags = createMemo(() => { + const tags = props.task.tags || []; + const ctx = currentTaskContext(); + + if (typeof ctx === 'object' && 'bucketId' in ctx) { + // We are in a bucket view. Hide the tag that matches this bucket's name. + const bucketName = (ctx as { name: string }).name.toLowerCase(); + return tags.filter(t => t.toLowerCase() !== bucketName); + } + + return tags; + }); + return ( { if (!open) { @@ -333,11 +359,11 @@ export const TaskDetail: Component = (props) => { Tags
- + {(tag) => ( = (props) => { return getThemeAdjustedColor(def?.color, def?.theme, resolvedTheme()) || "inherit"; })() }} - onClick={() => updateTags((props.task.tags || []).filter(t => t !== tag))} + onClick={() => updateTags(visibleTags().filter(t => t !== tag))} >