feat: enhance TripChecklist header with dynamic progress gradient and tag colors

This commit is contained in:
Felix Zett 2025-09-20 20:19:14 +02:00
parent a61557f0cc
commit 19099526e1

View file

@ -3,6 +3,7 @@ import React, { useState, useEffect, useRef } from "react";
import { useParams } from "react-router-dom";
import { getTripItems, toggleTripItem, updateTrip, getTags } from "../api";
import TagAutocompleteInput from "../components/TagAutocompleteInput";
import { getTagColor } from "../utils/tagColors";
export default function TripChecklist({ trips }: { trips: any[] }) {
const { id } = useParams();
@ -239,38 +240,60 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
const checkedItems = items.filter((item) => item.checked).length;
const progress = totalItems > 0 ? Math.round((checkedItems / totalItems) * 100) : 0;
// Progress gradient for header background (always full width)
const progressGradient = `linear-gradient(140deg, #f59e42 0%, #facc15 50%, #22c55e 100%)`;
return (
<div className="py-4 max-w-5xl mx-auto">
{/* Kompakter Header für Trip-Titel und Zeitraum */}
<div className="mb-6 px-4 py-3 rounded-xl border border-blue-200 bg-blue-50 shadow flex flex-wrap items-center gap-4">
<div className="flex flex-col flex-1 min-w-[180px]">
<div className="flex items-center gap-2">
<h2 className="text-xl font-bold text-blue-900 m-0">{trip.name}</h2>
<span className="text-xs text-blue-700 bg-blue-100 px-2 py-0.5 rounded font-semibold">
<div
className="mb-6 px-4 py-3 rounded-xl shadow flex flex-wrap items-center gap-4 relative"
style={{
background: progressGradient,
transition: "background 0.3s",
overflow: "hidden",
}}
>
{/* Overlay: shrinking box from the right */}
<div
style={{
position: "absolute",
top: 0,
right: 0,
bottom: 0,
width: `${100 - progress}%`,
background: "rgba(255, 255, 255, 0.85)",
pointerEvents: "none",
transition: "width 0.3s",
zIndex: 1,
}}
/>
<div className="flex flex-col flex-1 min-w-[180px]" style={{ position: "relative", zIndex: 2 }}>
<div className="flex items-end gap-2">
<h2 className="text-xl text-gray-900 font-bold m-0">{trip.name}</h2>
<span className="text-xs text-gray-500 px-2 py-0.5 rounded font-semibold">
{trip.start_date} {trip.end_date}
</span>
</div>
<div className="flex flex-wrap gap-2 items-center mt-2">
<span className="font-semibold text-sm">Tags:</span>
{selectedTags.length === 0 ? (
<span className="text-gray-400 text-sm">keine</span>
) : (
selectedTags.map((tag: any) => {
const isMarked = markedTags.some((mt: any) => mt.id === tag.id);
const color = getTagColor(tag.id);
return (
<span
key={tag.id}
className={
"relative px-2 py-0.5 rounded mr-1 text-xs cursor-pointer transition " +
(isMarked
? "bg-yellow-200 text-yellow-900 font-bold"
: "bg-blue-100 text-blue-800")
`relative px-2 py-0.5 rounded mr-1 text-xs shadow shadow-md cursor-pointer transition font-medium ${color.bg} ` +
(isMarked ? "ring-2 ring-yellow-400" : "")
}
onClick={() => handleToggleMark(tag.id)}
onMouseEnter={() => setHoveredTag(tag.id)}
onMouseLeave={() => setHoveredTag(null)}
>
#{tag.name}
{tag.mandatory && <span className="text-red-500 font-bold ml-0.5">!</span>}
{hoveredTag === tag.id && (
<button
className="absolute -top-2 -right-2 text-xs text-red-500 bg-white rounded-full px-1 shadow"
@ -322,51 +345,14 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
)}
</div>
</div>
{/* Fortschrittsbalken kompakt rechts */}
<div className="flex flex-col items-end min-w-[160px]">
<div className="flex items-center gap-2 mb-1">
{/* Fortschritt kompakt rechts */}
<div className="flex flex-col items-end min-w-[120px]" style={{ position: "relative", zIndex: 2 }}>
<span className="font-semibold text-gray-700 text-sm">Fortschritt</span>
<span className="text-xs text-gray-500">{checkedItems} / {totalItems}</span>
</div>
<div
className="w-full h-4 rounded-full overflow-hidden shadow"
style={{
background: "linear-gradient(90deg, #f59e42 0%, #facc15 50%, #22c55e 100%)",
position: "relative",
minWidth: "120px",
maxWidth: "180px",
}}
>
<div
className="h-full"
style={{
width: `${progress}%`,
background: "none",
position: "absolute",
left: 0,
top: 0,
transition: "width 0.3s",
}}
/>
<div
className="h-full w-full"
style={{
background: "rgba(243,244,246,0.9)",
position: "absolute",
left: 0,
top: 0,
pointerEvents: "none",
zIndex: 1,
width: `${100 - progress}%`,
marginLeft: `${progress}%`,
transition: "width 0.3s, margin-left 0.3s",
}}
/>
</div>
<div className="text-right text-xs text-gray-500 mt-1">{progress}%</div>
<span className="text-xs text-gray-500">{progress}%</span>
</div>
</div>
{/* ...existing code... */}
{/* ...restliche Seite... */}
<ul
className="grid grid-cols-1 gap-x-8 gap-y-2"
>