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";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { Utensils } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchColonyFeedings, fetchColonyFeedingsSummary } from "@/lib/feedings/api";
|
import { fetchColonyFeedings, fetchColonyFeedingsSummary } from "@/lib/feedings/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
export function ColonyFeedingsCard({ colonyId }: { colonyId: string }) {
|
export function ColonyFeedingsCard({ colonyId }: { colonyId: string }) {
|
||||||
@@ -39,7 +41,11 @@ export function ColonyFeedingsCard({ colonyId }: { colonyId: string }) {
|
|||||||
) : null}
|
) : null}
|
||||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||||
{!isLoading && (!feedings || feedings.length === 0) ? (
|
{!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}
|
) : null}
|
||||||
{feedings?.map((feeding) => (
|
{feedings?.map((feeding) => (
|
||||||
<div key={feeding.id} className="rounded-md border p-3">
|
<div key={feeding.id} className="rounded-md border p-3">
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { History } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchColonyHistory } from "@/lib/colonies/api";
|
import { fetchColonyHistory } from "@/lib/colonies/api";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -31,7 +33,11 @@ export function ColonyHistoryCard({ colonyId }: { colonyId: string }) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-3 text-sm">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{!hasHistory ? (
|
{!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}
|
) : null}
|
||||||
{history.apiaryHistory.map((entry) => (
|
{history.apiaryHistory.map((entry) => (
|
||||||
<p key={entry.id}>
|
<p key={entry.id}>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { ClipboardCheck } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchColonyInspections } from "@/lib/inspections/api";
|
import { fetchColonyInspections } from "@/lib/inspections/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
export function ColonyInspectionsCard({ colonyId }: { colonyId: string }) {
|
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">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||||
{!isLoading && (!inspections || inspections.length === 0) ? (
|
{!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}
|
) : null}
|
||||||
{inspections?.map((inspection) => (
|
{inspections?.map((inspection) => (
|
||||||
<div key={inspection.id} className="rounded-md border p-3">
|
<div key={inspection.id} className="rounded-md border p-3">
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { Syringe } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchColonyTreatments } from "@/lib/treatments/api";
|
import { fetchColonyTreatments } from "@/lib/treatments/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
export function ColonyTreatmentsCard({ colonyId }: { colonyId: string }) {
|
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">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||||
{!isLoading && (!treatments || treatments.length === 0) ? (
|
{!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}
|
) : null}
|
||||||
{treatments?.map((treatment) => (
|
{treatments?.map((treatment) => (
|
||||||
<div key={treatment.id} className="rounded-md border p-3">
|
<div key={treatment.id} className="rounded-md border p-3">
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { Bug } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchColonyVarroaMeasurements } from "@/lib/varroa/api";
|
import { fetchColonyVarroaMeasurements } from "@/lib/varroa/api";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
const CHART_WIDTH = 280;
|
const CHART_WIDTH = 280;
|
||||||
@@ -64,7 +66,11 @@ export function ColonyVarroaCard({ colonyId }: { colonyId: string }) {
|
|||||||
<CardContent className="flex flex-col gap-3 text-sm">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||||
{!isLoading && (!measurements || measurements.length === 0) ? (
|
{!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}
|
) : null}
|
||||||
<VarroaTrendChart values={values} />
|
<VarroaTrendChart values={values} />
|
||||||
{measurements?.map((measurement) => (
|
{measurements?.map((measurement) => (
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { Droplet } from "lucide-react";
|
import { Droplet, FlaskConical } from "lucide-react";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { fetchHoneyBatch, fetchHoneyBatchTraceability } from "@/lib/honey-batches/api";
|
import { fetchHoneyBatch, fetchHoneyBatchTraceability } from "@/lib/honey-batches/api";
|
||||||
import { exportHoneyBatchTraceabilityPdf } from "@/lib/export/api";
|
import { exportHoneyBatchTraceabilityPdf } from "@/lib/export/api";
|
||||||
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
@@ -78,7 +79,11 @@ export default function HoneyBatchDetailPage() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-3 text-sm">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{honeyBatch.measurements.length === 0 ? (
|
{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}
|
) : null}
|
||||||
{honeyBatch.measurements.map((measurement) => (
|
{honeyBatch.measurements.map((measurement) => (
|
||||||
<div key={measurement.id} className="rounded-md border p-3">
|
<div key={measurement.id} className="rounded-md border p-3">
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FormEvent, useState } from "react";
|
import { FormEvent, useState } from "react";
|
||||||
|
import { Star } from "lucide-react";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { addQueenEvaluation, fetchQueenEvaluations } from "@/lib/queens/api";
|
import { addQueenEvaluation, fetchQueenEvaluations } from "@/lib/queens/api";
|
||||||
import { CreateQueenEvaluationInput } from "@/lib/queens/types";
|
import { CreateQueenEvaluationInput } from "@/lib/queens/types";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -131,7 +133,11 @@ export function QueenEvaluationsCard({ queenId }: { queenId: string }) {
|
|||||||
<CardContent className="flex flex-col gap-3 text-sm">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
{isLoading ? <p className="text-muted-foreground">Lädt…</p> : null}
|
||||||
{!isLoading && (!evaluations || evaluations.length === 0) ? (
|
{!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}
|
) : null}
|
||||||
{evaluations?.map((evaluation) => (
|
{evaluations?.map((evaluation) => (
|
||||||
<div key={evaluation.id} className="rounded-md border p-3">
|
<div key={evaluation.id} className="rounded-md border p-3">
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { History } from "lucide-react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { fetchQueenHistory } from "@/lib/queens/api";
|
import { fetchQueenHistory } from "@/lib/queens/api";
|
||||||
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -26,7 +28,11 @@ export function QueenHistoryCard({ queenId }: { queenId: string }) {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex flex-col gap-3 text-sm">
|
<CardContent className="flex flex-col gap-3 text-sm">
|
||||||
{history.length === 0 ? (
|
{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}
|
) : null}
|
||||||
{history.map((entry) => (
|
{history.map((entry) => (
|
||||||
<p key={entry.id}>
|
<p key={entry.id}>
|
||||||
|
|||||||
Reference in new issue
Block a user