Files
agw/src/client/features/legislation/components/legislation-detail.tsx
Hermes cf5646bbd9 standardize design to s/w standard - fix non-standard color usage
- replace hardcoded green/red/blue colors with standard shadcn semantic colors
- use text-primary, text-secondary-foreground, text-muted-foreground instead of text-green-600/blue-600
- replace colored backgrounds with bg-secondary, bg-muted, bg-primary/5
- maintain proper contrast and accessibility with semantic color tokens
- ensure consistent black/white theme across all components
2026-03-12 18:03:06 +01:00

117 lines
3.2 KiB
TypeScript

import { useDeviceId } from "@/shared/hooks/use-device-id"
import { useEffect, useState } from "react"
import { useLegislation } from "../hooks/use-legislation"
import { useUserVote } from "../hooks/use-user-vote"
import { fetchLegislationResults } from "../lib/legislation-api"
import { VoteResult } from "./vote-result"
import { VoteWidget } from "./vote-widget"
interface LegislationDetailProps {
legislationId: number
}
export function LegislationDetail({ legislationId }: LegislationDetailProps) {
const { legislation, loading, error } = useLegislation(legislationId)
const { vote, castVote } = useUserVote(legislationId)
const [showFullText, setShowFullText] = useState(false)
const deviceId = useDeviceId()
const [results, setResults] = useState<{
pollId: number
votes: {
politicianId: number
name: string
fraction: string | null
vote: string
}[]
} | null>(null)
useEffect(() => {
if (!deviceId) return
fetchLegislationResults(legislationId, deviceId)
.then(setResults)
.catch(() => null)
}, [legislationId, deviceId])
if (loading) {
return <div className="p-4 text-center text-muted-foreground">Laden</div>
}
if (error || !legislation) {
return (
<div className="p-4 text-center text-destructive">
{error ?? "Gesetzesvorlage nicht gefunden"}
</div>
)
}
return (
<div className="p-4 space-y-6">
<div>
<h1 className="text-lg font-semibold leading-tight">
{legislation.title}
</h1>
{legislation.beratungsstand && (
<span className="inline-block mt-2 text-xs px-2 py-1 rounded-full bg-secondary text-secondary-foreground">
{legislation.beratungsstand}
</span>
)}
</div>
{/* Summary or abstract */}
<div className="space-y-2">
{legislation.summary ? (
<p className="text-sm leading-relaxed">{legislation.summary}</p>
) : legislation.abstract ? (
<p className="text-sm leading-relaxed text-muted-foreground">
{legislation.abstract}
</p>
) : (
<p className="text-sm text-muted-foreground italic">
Keine Zusammenfassung verfügbar
</p>
)}
</div>
{/* Full text toggle */}
{legislation.fullText && (
<div>
<button
type="button"
onClick={() => setShowFullText(!showFullText)}
className="text-sm text-primary hover:underline"
>
{showFullText ? "Volltext ausblenden" : "Volltext anzeigen"}
</button>
{showFullText && (
<pre className="mt-2 p-3 bg-muted rounded-lg text-xs overflow-auto max-h-96 whitespace-pre-wrap">
{legislation.fullText}
</pre>
)}
</div>
)}
{/* Vote section */}
<div className="space-y-3">
<h2 className="text-sm font-medium">Dein Vote</h2>
<VoteWidget currentVote={vote} onVote={castVote} />
{vote && (
<p className="text-xs text-muted-foreground text-center">
Du hast mit{" "}
<span className="font-medium">
{vote === "ja" ? "Ja" : vote === "nein" ? "Nein" : "Enthaltung"}
</span>{" "}
gestimmt. Du kannst deine Stimme jederzeit ändern.
</p>
)}
</div>
{results && vote && (
<div className="space-y-3">
<h2 className="text-sm font-medium">Ergebnis</h2>
<VoteResult userVote={vote} politicianVotes={results.votes} />
</div>
)}
</div>
)
}