This commit is contained in:
michael committed 2026-09-23 08:10:07 +00:00
1 parent d6c8877ed7
commit 008bc8d09c
1 file changed
+27 -36
+27 -36
View File
@@ -12,6 +12,7 @@ import {
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import { Alert } from "@/components/ui/alert"; import { Alert } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -156,14 +157,11 @@ function CrmDayItem({
); );
} }
function TeamspaceDayItem({ item, onNavigate }: { item: StatisticsTeamspaceDay; onNavigate: (to: string) => void }) { function TeamspaceDayItem({ item }: { item: StatisticsTeamspaceDay }) {
const deltaVariant = item.delta_minutes === 0 ? "outline" : item.delta_minutes > 0 ? "success" : "destructive";
return ( return (
<div className="grid gap-3 rounded-md border bg-background px-3 py-2 lg:grid-cols-[minmax(8rem,0.85fr)_minmax(0,1.45fr)_minmax(15rem,1fr)_auto] lg:items-center"> <div className="grid gap-3 rounded-md border bg-background px-3 py-2 lg:grid-cols-[minmax(8rem,0.75fr)_minmax(0,1.65fr)_minmax(8rem,0.6fr)] lg:items-center">
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
<Badge variant="outline">{formatDate(`${item.day}T00:00:00`)}</Badge> <Badge variant="outline">{formatDate(`${item.day}T00:00:00`)}</Badge>
<Badge variant="info">{item.session_count} Session(s)</Badge>
</div> </div>
<div className="min-w-0 space-y-1"> <div className="min-w-0 space-y-1">
<div className="flex min-w-0 flex-wrap items-center gap-2"> <div className="flex min-w-0 flex-wrap items-center gap-2">
@@ -173,15 +171,9 @@ function TeamspaceDayItem({ item, onNavigate }: { item: StatisticsTeamspaceDay;
</div> </div>
<p className="truncate text-sm text-muted-foreground">{item.organization_name}</p> <p className="truncate text-sm text-muted-foreground">{item.organization_name}</p>
</div> </div>
<div className="flex flex-wrap gap-x-3 gap-y-1 text-sm"> <div className="text-sm">
<span className={`font-medium ${trackedTextClass}`}>Abgerechnet {formatMinutes(item.tracked_minutes)}</span> <span className={`font-semibold ${teamspaceTextClass}`}>Teamspace {formatMinutes(item.crm_billed_minutes)}</span>
<span className={`font-medium ${teamspaceTextClass}`}>Teamspace {formatMinutes(item.crm_billed_minutes)}</span>
<Badge variant={deltaVariant}>Diff. {formatTeamspaceDelta(item.delta_minutes)}</Badge>
</div> </div>
<Button className="h-8 justify-self-start lg:justify-self-end" variant="secondary" size="sm" onClick={() => onNavigate(`/tickets/${item.ticket_id}?month=${item.day.slice(0, 7)}`)}>
Tag öffnen
<ExternalLink className="size-4" />
</Button>
</div> </div>
); );
} }
@@ -410,29 +402,6 @@ export function MonthlyClosePage({ onNavigate }: MonthlyClosePageProps) {
</CardContent> </CardContent>
</Card> </Card>
<Card>
<CardHeader className="p-4">
<div className="flex items-start justify-between gap-3">
<div>
<CardTitle>Vergleich abgerechnete Zeiten Teamspace</CardTitle>
<CardDescription>Teamspace-Tageswerte je Ticket mit Datum der abgerechneten Session(s) und Projekt, sofern verfügbar.</CardDescription>
</div>
<Badge variant="outline">{teamspaceDays.length} Eintrag(e)</Badge>
</div>
</CardHeader>
<CardContent className="space-y-2 px-4 pb-4">
{teamspaceDays.length > 0 ? (
<div className="max-h-[28rem] space-y-2 overflow-y-auto pr-1">
{teamspaceDays.map((item) => (
<TeamspaceDayItem key={`${item.ticket_id}-${item.day}`} item={item} onNavigate={onNavigate} />
))}
</div>
) : (
<p className="rounded-md border bg-muted/20 p-3 text-sm text-muted-foreground">Für diesen Monat sind noch keine Teamspace-Werte zu abgerechneten Ticket-Tagen vorhanden.</p>
)}
</CardContent>
</Card>
<Card> <Card>
<CardHeader className="p-4"> <CardHeader className="p-4">
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between"> <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
@@ -488,6 +457,28 @@ export function MonthlyClosePage({ onNavigate }: MonthlyClosePageProps) {
</CardContent> </CardContent>
</Card> </Card>
<Accordion type="single" collapsible className="rounded-md border bg-card px-4">
<AccordionItem value="teamspace-entries" className="border-b-0">
<AccordionTrigger className="py-3 hover:no-underline">
<span className="flex min-w-0 flex-wrap items-center gap-2">
<span>Teamspace-Einträge</span>
<Badge variant="outline">{teamspaceDays.length} Eintrag(e)</Badge>
</span>
</AccordionTrigger>
<AccordionContent className="space-y-2 pb-4">
{teamspaceDays.length > 0 ? (
<div className="max-h-[28rem] space-y-2 overflow-y-auto pr-1">
{teamspaceDays.map((item) => (
<TeamspaceDayItem key={`${item.ticket_id}-${item.day}`} item={item} />
))}
</div>
) : (
<p className="rounded-md border bg-muted/20 p-3 text-sm text-muted-foreground">Für diesen Monat sind noch keine Teamspace-Werte zu abgerechneten Ticket-Tagen vorhanden.</p>
)}
</AccordionContent>
</AccordionItem>
</Accordion>
{stats && stats.totals.sessions === 0 ? ( {stats && stats.totals.sessions === 0 ? (
<Card> <Card>
<CardContent className="grid place-items-center gap-2 p-8 text-center"> <CardContent className="grid place-items-center gap-2 p-8 text-center">