style: compact layout for TripChecklist header

This commit is contained in:
Felix Zett 2025-09-20 17:13:33 +02:00
parent f263225180
commit 68f2d202f0
2 changed files with 88 additions and 83 deletions

View file

@ -46,7 +46,7 @@ function Navigation() {
const isTripDetail = /^\/trips\/[^/]+$/.test(location.pathname); const isTripDetail = /^\/trips\/[^/]+$/.test(location.pathname);
return ( return (
<nav className="mb-8 flex items-center gap-4 bg-white/80 backdrop-blur border-b border-gray-200 px-2 py-2 rounded-xl shadow-sm"> <nav className="mb-2 flex items-center gap-4 bg-white/80 backdrop-blur border-b border-gray-200 px-2 py-2 rounded-xl shadow-sm">
<button <button
className="text-2xl font-extrabold text-blue-700 tracking-tight mr-4 select-none hover:underline bg-transparent p-0" className="text-2xl font-extrabold text-blue-700 tracking-tight mr-4 select-none hover:underline bg-transparent p-0"
style={{ background: "none", border: "none" }} style={{ background: "none", border: "none" }}

View file

@ -241,112 +241,117 @@ export default function TripChecklist({ trips }: { trips: any[] }) {
return ( return (
<div className="py-4 max-w-5xl mx-auto"> <div className="py-4 max-w-5xl mx-auto">
{/* Trip-Titel und Zeitraum */} {/* Kompakter Header für Trip-Titel und Zeitraum */}
<div className="mb-6 p-6 rounded-xl border-2 border-blue-200 bg-blue-50 shadow flex flex-col gap-2"> <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">
<h2 className="text-2xl font-bold text-blue-900">{trip.name}</h2> <div className="flex flex-col flex-1 min-w-[180px]">
<div className="text-gray-600 text-base"> <div className="flex items-center gap-2">
{trip.start_date} {trip.end_date} <h2 className="text-xl font-bold text-blue-900 m-0">{trip.name}</h2>
</div> <span className="text-xs text-blue-700 bg-blue-100 px-2 py-0.5 rounded font-semibold">
<div className="flex flex-wrap gap-2 items-center"> {trip.start_date} {trip.end_date}
<span className="font-semibold">Tags: </span> </span>
{selectedTags.length === 0 ? ( </div>
<span className="text-gray-400">keine</span> <div className="flex flex-wrap gap-2 items-center mt-2">
) : ( <span className="font-semibold text-sm">Tags:</span>
selectedTags.map((tag: any) => { {selectedTags.length === 0 ? (
const isMarked = markedTags.some((mt: any) => mt.id === tag.id); <span className="text-gray-400 text-sm">keine</span>
return ( ) : (
<span selectedTags.map((tag: any) => {
key={tag.id} const isMarked = markedTags.some((mt: any) => mt.id === tag.id);
className={ return (
"relative px-2 py-0.5 rounded mr-1 text-sm cursor-pointer transition " + <span
(isMarked key={tag.id}
? "bg-yellow-200 text-yellow-900 font-bold" className={
: "bg-blue-100 text-blue-800") "relative px-2 py-0.5 rounded mr-1 text-xs cursor-pointer transition " +
} (isMarked
onClick={() => handleToggleMark(tag.id)} ? "bg-yellow-200 text-yellow-900 font-bold"
onMouseEnter={() => setHoveredTag(tag.id)} : "bg-blue-100 text-blue-800")
onMouseLeave={() => setHoveredTag(null)} }
> onClick={() => handleToggleMark(tag.id)}
#{tag.name} onMouseEnter={() => setHoveredTag(tag.id)}
{hoveredTag === tag.id && ( onMouseLeave={() => setHoveredTag(null)}
<button >
className="absolute -top-2 -right-2 text-xs text-red-500 bg-white rounded-full px-1 shadow" #{tag.name}
onClick={e => { {hoveredTag === tag.id && (
e.stopPropagation(); <button
handleRemoveTag(tag.id); className="absolute -top-2 -right-2 text-xs text-red-500 bg-white rounded-full px-1 shadow"
}} onClick={e => {
> e.stopPropagation();
× handleRemoveTag(tag.id);
</button> }}
)} >
</span> ×
); </button>
}) )}
)} </span>
{/* "+Tag" link and dropdown */} );
{!addingTag ? ( })
<button )}
className="text-blue-500 underline text-sm ml-2" {/* "+Tag" link and dropdown */}
onClick={() => { {!addingTag ? (
setAddingTag(true); <button
setTimeout(() => { className="text-blue-500 underline text-xs ml-2"
inputRef.current?.focus(); onClick={() => {
}, 0); setAddingTag(true);
}}
type="button"
>
+ Tag
</button>
) : (
<TagAutocompleteInput
ref={inputRef}
allTags={allTags}
selectedTags={selectedTags}
onAddTag={(tagId, viaTab) => {
handleAddTag(tagId);
if (viaTab) {
setTimeout(() => { setTimeout(() => {
setAddingTag(true);
inputRef.current?.focus(); inputRef.current?.focus();
}, 0); }, 0);
} else { }}
setAddingTag(false); type="button"
} >
}} + Tag
onEscape={() => setAddingTag(false)} </button>
placeholder="Tag suchen..." ) : (
/> <TagAutocompleteInput
)} ref={inputRef}
allTags={allTags}
selectedTags={selectedTags}
onAddTag={(tagId, viaTab) => {
handleAddTag(tagId);
if (viaTab) {
setTimeout(() => {
setAddingTag(true);
inputRef.current?.focus();
}, 0);
} else {
setAddingTag(false);
}
}}
onEscape={() => setAddingTag(false)}
placeholder="Tag suchen..."
/>
)}
</div>
</div> </div>
{/* Progressbar integriert am unteren Rand */} {/* Fortschrittsbalken kompakt rechts */}
<div className="mt-6"> <div className="flex flex-col items-end min-w-[160px]">
<div className="flex justify-between items-center mb-1"> <div className="flex items-center gap-2 mb-1">
<span className="font-semibold text-gray-700">Fortschritt</span> <span className="font-semibold text-gray-700 text-sm">Fortschritt</span>
<span className="text-sm text-gray-500">{checkedItems} / {totalItems} erledigt</span> <span className="text-xs text-gray-500">{checkedItems} / {totalItems}</span>
</div> </div>
<div <div
className="w-full h-5 rounded-full overflow-hidden shadow" className="w-full h-4 rounded-full overflow-hidden shadow"
style={{ style={{
background: "linear-gradient(90deg, #f59e42 0%, #facc15 50%, #22c55e 100%)", background: "linear-gradient(90deg, #f59e42 0%, #facc15 50%, #22c55e 100%)",
position: "relative", position: "relative",
minWidth: "120px",
maxWidth: "180px",
}} }}
> >
<div <div
className="h-full" className="h-full"
style={{ style={{
width: `${progress}%`, width: `${progress}%`,
background: "none", // inherit the gradient from parent background: "none",
position: "absolute", position: "absolute",
left: 0, left: 0,
top: 0, top: 0,
transition: "width 0.3s", transition: "width 0.3s",
}} }}
/> />
{/* gray overlay for unfilled part */}
<div <div
className="h-full w-full" className="h-full w-full"
style={{ style={{
background: "rgba(243,244,246,0.9)", // tailwind gray-200 with opacity background: "rgba(243,244,246,0.9)",
position: "absolute", position: "absolute",
left: 0, left: 0,
top: 0, top: 0,