feat(frontend): EmptyState statt Fließtext in verschachtelten Listen
Ersetzt den bisherigen reinen Fließtext ("Noch keine X dokumentiert.")
durch die gemeinsame EmptyState-Komponente (Icon, Titel, Beschreibung)
in allen verschachtelten Listen auf den Volk- und Königin-Detailseiten:
Fütterung, Behandlungen, Varroa, Durchsichten, Historie (Volk und
Königin), Bewertungen und Honigmessungen.
Rundet den bereits umgesetzten EmptyState-Look der Hauptlistenseiten
konsistent auf die Detailseiten-Unterkarten ab.
This commit is contained in:
1 parent
e889edd6c5
commit
c0922387fd
8 files changed
+56
-9
No files matched your search
@@ -1,9 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Utensils } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchColonyFeedings, fetchColonyFeedingsSummary } from "@/lib/feedings/api";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
export function ColonyFeedingsCard({ colonyId }: { colonyId: string }) {
|
||||
@@ -39,7 +41,11 @@ export function ColonyFeedingsCard({ colonyId }: { colonyId: string }) {
|
||||
) : null}
|
||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||
{!isLoading && (!feedings || feedings.length === 0) ? (
|
||||
<p className="text-muted-foreground">Noch keine Fütterung dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={Utensils}
|
||||
title="Noch keine Fütterung"
|
||||
description="Erfasse die erste Fütterung für dieses Volk."
|
||||
/>
|
||||
) : null}
|
||||
{feedings?.map((feeding) => (
|
||||
<div key={feeding.id} className="rounded-md border p-3">
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { History } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchColonyHistory } from "@/lib/colonies/api";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -31,7 +33,11 @@ export function ColonyHistoryCard({ colonyId }: { colonyId: string }) {
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{!hasHistory ? (
|
||||
<p className="text-muted-foreground">Noch keine Historie vorhanden.</p>
|
||||
<EmptyState
|
||||
icon={History}
|
||||
title="Noch keine Historie"
|
||||
description="Standortwechsel und Ableger erscheinen hier."
|
||||
/>
|
||||
) : null}
|
||||
{history.apiaryHistory.map((entry) => (
|
||||
<p key={entry.id}>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { ClipboardCheck } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchColonyInspections } from "@/lib/inspections/api";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
export function ColonyInspectionsCard({ colonyId }: { colonyId: string }) {
|
||||
@@ -27,7 +29,11 @@ export function ColonyInspectionsCard({ colonyId }: { colonyId: string }) {
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||
{!isLoading && (!inspections || inspections.length === 0) ? (
|
||||
<p className="text-muted-foreground">Noch keine Durchsicht dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={ClipboardCheck}
|
||||
title="Noch keine Durchsicht"
|
||||
description="Dokumentiere die erste Durchsicht für dieses Volk."
|
||||
/>
|
||||
) : null}
|
||||
{inspections?.map((inspection) => (
|
||||
<div key={inspection.id} className="rounded-md border p-3">
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Syringe } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchColonyTreatments } from "@/lib/treatments/api";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
export function ColonyTreatmentsCard({ colonyId }: { colonyId: string }) {
|
||||
@@ -27,7 +29,11 @@ export function ColonyTreatmentsCard({ colonyId }: { colonyId: string }) {
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||
{!isLoading && (!treatments || treatments.length === 0) ? (
|
||||
<p className="text-muted-foreground">Noch keine Behandlung dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={Syringe}
|
||||
title="Noch keine Behandlung"
|
||||
description="Dokumentiere die erste Behandlung für dieses Volk."
|
||||
/>
|
||||
) : null}
|
||||
{treatments?.map((treatment) => (
|
||||
<div key={treatment.id} className="rounded-md border p-3">
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Bug } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchColonyVarroaMeasurements } from "@/lib/varroa/api";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
const CHART_WIDTH = 280;
|
||||
@@ -64,7 +66,11 @@ export function ColonyVarroaCard({ colonyId }: { colonyId: string }) {
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||
{!isLoading && (!measurements || measurements.length === 0) ? (
|
||||
<p className="text-muted-foreground">Noch keine Varroamessung dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={Bug}
|
||||
title="Noch keine Varroamessung"
|
||||
description="Erfasse die erste Messung für dieses Volk."
|
||||
/>
|
||||
) : null}
|
||||
<VarroaTrendChart values={values} />
|
||||
{measurements?.map((measurement) => (
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Droplet } from "lucide-react";
|
||||
import { Droplet, FlaskConical } from "lucide-react";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { fetchHoneyBatch, fetchHoneyBatchTraceability } from "@/lib/honey-batches/api";
|
||||
import { exportHoneyBatchTraceabilityPdf } from "@/lib/export/api";
|
||||
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -78,7 +79,11 @@ export default function HoneyBatchDetailPage() {
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{honeyBatch.measurements.length === 0 ? (
|
||||
<p className="text-muted-foreground">Noch keine Messung dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={FlaskConical}
|
||||
title="Noch keine Messung"
|
||||
description="Erfasse die erste Wassergehalt-Messung für diese Charge."
|
||||
/>
|
||||
) : null}
|
||||
{honeyBatch.measurements.map((measurement) => (
|
||||
<div key={measurement.id} className="rounded-md border p-3">
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { FormEvent, useState } from "react";
|
||||
import { Star } from "lucide-react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { addQueenEvaluation, fetchQueenEvaluations } from "@/lib/queens/api";
|
||||
import { CreateQueenEvaluationInput } from "@/lib/queens/types";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -131,7 +133,11 @@ export function QueenEvaluationsCard({ queenId }: { queenId: string }) {
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||
{!isLoading && (!evaluations || evaluations.length === 0) ? (
|
||||
<p className="text-muted-foreground">Noch keine Bewertung dokumentiert.</p>
|
||||
<EmptyState
|
||||
icon={Star}
|
||||
title="Noch keine Bewertung"
|
||||
description="Erfasse die erste Bewertung für diese Königin."
|
||||
/>
|
||||
) : null}
|
||||
{evaluations?.map((evaluation) => (
|
||||
<div key={evaluation.id} className="rounded-md border p-3">
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { History } from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { fetchQueenHistory } from "@/lib/queens/api";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -26,7 +28,11 @@ export function QueenHistoryCard({ queenId }: { queenId: string }) {
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
{history.length === 0 ? (
|
||||
<p className="text-muted-foreground">Noch keine Historie vorhanden.</p>
|
||||
<EmptyState
|
||||
icon={History}
|
||||
title="Noch keine Historie"
|
||||
description="Volkszuordnungen erscheinen hier."
|
||||
/>
|
||||
) : null}
|
||||
{history.map((entry) => (
|
||||
<p key={entry.id}>
|
||||
|
||||
Reference in new issue
Block a user