feat: enhance TripChecklist to categorize items if they contain a '/'

This commit is contained in:
Felix Zett 2025-09-01 20:25:28 +02:00
parent 9a55a994a3
commit f390ce80d6

View file

@ -91,6 +91,22 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
// Gruppiere Items nach Kategorie (item.tag)
const itemsWithoutTag = items.filter((item) => !item.tag);
// Split items into "slash" category items and normal items
const slashCategoryMap: Record<string, any[]> = {};
const normalItemsWithoutTag: any[] = [];
itemsWithoutTag.forEach((item) => {
const name = item.name_calculated || "";
if (name.includes("/")) {
const [cat, sub] = name.split("/", 2);
if (!slashCategoryMap[cat]) slashCategoryMap[cat] = [];
slashCategoryMap[cat].push({ ...item, _sub: sub });
} else {
normalItemsWithoutTag.push(item);
}
});
// Map: tagId -> { tag, items: [...] }
const itemsByTag: Record<string, { tag: any; items: any[] }> = {};
items
@ -203,8 +219,8 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
</div>
{/* ...Rest der Checklist... */}
<ul>
{/* Einträge ohne Kategorie */}
{itemsWithoutTag.map((item) => (
{/* Einträge ohne Kategorie und ohne Slash */}
{normalItemsWithoutTag.map((item) => (
<li
key={item.id}
className={
@ -245,7 +261,7 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
</li>
))}
{/* Einträge mit Kategorie */}
{/* Einträge mit Kategorie (item.tag) */}
{sortedTagGroups.map(({ tag, items }) => (
<React.Fragment key={tag.id}>
<li className="mt-4 mb-1 font-semibold text-gray-700 flex items-center gap-2">
@ -295,6 +311,57 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
))}
</React.Fragment>
))}
{/* Slash categories at the end */}
{Object.entries(slashCategoryMap).map(([cat, items]) => (
<React.Fragment key={cat}>
<li className="mt-6 mb-1 font-semibold text-gray-700 flex items-center gap-2">
<h3 className="text-m text-gray-700 px-2 py-0.5 m-0 font-semibold">
{cat.charAt(0).toUpperCase() + cat.slice(1)}
</h3>
</li>
{items.map((item) => (
<li
key={item.id}
className={
"flex items-center gap-2 cursor-pointer select-none px-2 py-1 rounded group " +
(item.checked ? "bg-green-100" : "hover:bg-gray-100")
}
onClick={async () => {
await toggleTripItem(item.id);
const updated = await getTripItems(id!);
setItems(updated);
}}
>
<input
type="checkbox"
checked={item.checked}
readOnly
tabIndex={-1}
className="pointer-events-none"
/>
<span className={item.checked ? "line-through text-gray-400" : ""}>
{item._sub}
</span>
{item.item && item.item.tags && item.item.tags.length > 0 && (
<span className="ml-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
{[...item.item.tags]
.slice()
.sort((a, b) => a.name.localeCompare(b.name))
.map((tag: any) => (
<span
key={tag.id}
className="text-xs text-gray-400 rounded px-1 py-0.5"
>
#{tag.name}
</span>
))}
</span>
)}
</li>
))}
</React.Fragment>
))}
</ul>
</div>
);