feat: enhance TripChecklist header with dynamic progress gradient and tag colors
This commit is contained in:
parent
a61557f0cc
commit
19099526e1
1 changed files with 40 additions and 54 deletions
|
|
@ -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"
|
||||
>
|
||||
|
|
|
|||
Loading…
Reference in a new issue