2025-03-25 03:52:30 -04:00

529 lines
28 KiB
TypeScript

"use client"
import { useState } from "react"
import Link from "next/link"
import { use } from "react"
import {
ArrowLeft,
FileText,
Download,
Calendar,
CheckCircle,
PieChart,
Users,
LucideIcon,
AlertCircle,
BarChart3,
Clock,
FileBarChart,
Share2,
Bookmark
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger
} from "@/components/ui/tabs"
import { Badge } from "@/components/ui/badge"
import { Separator } from "@/components/ui/separator"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
// Mock data for resolutions with detailed content
const mockResolutions = [
{
id: 12,
title: "Education and Community Health Improvements",
description: "A comprehensive set of recommendations for improving education access and community health services",
summary: "This resolution addresses critical gaps in education and healthcare access by recommending the creation of free after-school programs for K-8 students and establishing community health clinics in underserved areas. These measures aim to improve educational outcomes, provide structured environments for children after school hours, and increase healthcare access for vulnerable populations.",
date: "2024-02-15",
contributions: [
{
id: 1,
title: "After-School Programs",
description: "Create free after-school programs for K-8 students in public schools",
category: "Education",
votes: { yes: 312, no: 28 },
perspectives: 42,
},
{
id: 2,
title: "Community Health Clinics",
description: "Establish walk-in clinics in underserved areas with sliding scale fees",
category: "Healthcare",
votes: { yes: 278, no: 42 },
perspectives: 36,
},
{
id: 7,
title: "Teacher Professional Development",
description: "Increase funding for teacher training programs focused on inclusive education",
category: "Education",
votes: { yes: 245, no: 52 },
perspectives: 31,
},
{
id: 8,
title: "Preventive Health Education",
description: "Implement community-based health education programs focused on prevention",
category: "Healthcare",
votes: { yes: 231, no: 38 },
perspectives: 29,
},
],
categories: ["Education", "Healthcare"],
status: "active",
timeline: [
{
date: "2023-09-01",
event: "Perspective Collection Started",
description: "Community members began submitting perspectives on education and healthcare needs"
},
{
date: "2023-10-15",
event: "Insights Generation",
description: "AI-generated insights were derived from collected perspectives"
},
{
date: "2023-11-15",
event: "First Contribution Validated",
description: "After-School Programs contribution reached consensus"
},
{
date: "2023-12-03",
event: "Second Contribution Validated",
description: "Community Health Clinics contribution reached consensus"
},
{
date: "2024-01-20",
event: "Resolution Draft",
description: "Initial resolution draft based on validated contributions"
},
{
date: "2024-02-15",
event: "Resolution Published",
description: "Final resolution published after community review"
}
],
sections: [
{
id: "1",
title: "Background and Context",
content: "Recent community feedback has highlighted significant gaps in both educational support services and healthcare access, particularly in underserved neighborhoods. Data indicates that approximately 45% of K-8 students lack supervision during after-school hours, contributing to concerning trends in academic performance and youth engagement. Additionally, 38% of residents in priority neighborhoods report delaying healthcare due to lack of affordable and accessible services."
},
{
id: "2",
title: "Recommendations",
content: "Based on community consensus, this resolution recommends: 1) Establishing free after-school programs in all public elementary and middle schools, with priority implementation in underserved areas; 2) Creating walk-in community health clinics with sliding scale fee structures in identified healthcare deserts; 3) Increasing funding for teacher professional development programs focused on inclusive education; and 4) Implementing community-based preventive health education programs.",
subsections: [
{
id: "2.1",
title: "Education Initiatives",
content: "After-school programs should operate from 3:00-6:00 PM on school days, offering tutoring, enrichment activities, and physical recreation. Teacher professional development programs should prioritize training in inclusive education practices and trauma-informed approaches."
},
{
id: "2.2",
title: "Healthcare Initiatives",
content: "Community health clinics should offer basic primary care, preventive services, and health education. Sliding scale fees should ensure that no resident is denied care due to inability to pay, with free services available to those meeting income requirements."
}
]
},
{
id: "3",
title: "Implementation Timeline",
content: "Phase 1 (Immediate): Begin planning and resource allocation for both education and healthcare initiatives; Phase 2 (6-12 months): Launch pilot programs in highest-need areas; Phase 3 (12-24 months): Expand to remaining target areas; Phase 4 (Ongoing): Continuous evaluation and improvement."
},
{
id: "4",
title: "Resource Requirements",
content: "Education Initiatives: Estimated annual budget of $4.2M for staffing, materials, and facility usage; Healthcare Initiatives: Estimated annual budget of $5.8M for facilities, medical staff, and supplies. Recommended funding sources include reallocation from existing programs, grant opportunities, and public-private partnerships."
},
{
id: "5",
title: "Expected Outcomes",
content: "1) Improved academic performance and decreased truancy in K-8 students; 2) Reduced emergency room usage for non-emergency conditions; 3) Earlier detection and treatment of health conditions; 4) Increased community satisfaction with public services; 5) Long-term reduction in costs associated with preventable health conditions and educational remediation."
}
],
impactMetrics: {
estimatedBeneficiaries: 25000,
costEfficiency: "High",
implementationComplexity: "Medium",
timeToImpact: "6-12 months",
sustainabilityScore: 8.2,
},
stakeholders: ["School District", "Department of Health", "Community Organizations", "Parent Associations", "Healthcare Providers"]
},
// Other resolutions would be defined here
]
export default function ResolutionPage({ params }: { params: Promise<{ id: string }> }) {
// Properly handle the params with React.use()
const { id } = use(params)
const resolutionId = parseInt(id)
const [activeTab, setActiveTab] = useState("overview")
// Find the resolution from mock data
const resolution = mockResolutions.find(r => r.id === resolutionId)
if (!resolution) {
return (
<div className="container mx-auto px-4 py-16 text-center">
<AlertCircle className="mx-auto h-16 w-16 text-muted-foreground mb-4" />
<h1 className="text-2xl font-bold mb-2">Resolution Not Found</h1>
<p className="text-muted-foreground mb-8">The resolution you're looking for doesn't exist or has been removed.</p>
<Button asChild>
<Link href="/resolutions">
<ArrowLeft className="mr-2 h-4 w-4" />
Return to Resolutions
</Link>
</Button>
</div>
)
}
// Format date for display
const formattedDate = new Date(resolution.date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
return (
<div className="container mx-auto px-4 py-8">
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-8">
<div>
<Button variant="outline" size="sm" className="mb-4" asChild>
<Link href="/resolutions">
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Resolutions
</Link>
</Button>
<div className="flex items-center gap-2 mb-1">
{resolution.categories.map(category => (
<Badge key={category} className="text-xs">{category}</Badge>
))}
<Badge variant="outline" className="text-xs">ID: {resolution.id}</Badge>
</div>
<h1 className="text-3xl font-bold flex items-center gap-2">
<FileText className="h-6 w-6 text-primary" />
Resolution #{resolution.id}
</h1>
<h2 className="text-xl font-semibold mt-2">{resolution.title}</h2>
<p className="mt-2 text-muted-foreground">{resolution.description}</p>
</div>
<div className="flex flex-col gap-2 items-start md:items-end">
<Badge variant={resolution.status === "active" ? "default" : "secondary"} className="mb-2">
{resolution.status === "active" ? "Active" : "Archived"}
</Badge>
<div className="flex items-center gap-1 text-sm">
<Calendar className="h-4 w-4 mr-1 text-muted-foreground" />
<span className="text-muted-foreground">Published: </span>
<span>{formattedDate}</span>
</div>
<Button className="mt-2" size="sm">
<Download className="mr-2 h-4 w-4" />
Download PDF
</Button>
</div>
</div>
<div className="flex flex-wrap gap-2 mb-6">
<Button variant="outline" size="sm">
<Share2 className="mr-2 h-4 w-4" />
Share
</Button>
<Button variant="outline" size="sm">
<Bookmark className="mr-2 h-4 w-4" />
Save
</Button>
</div>
<Tabs defaultValue="overview" value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="content">Full Content</TabsTrigger>
<TabsTrigger value="contributions">Contributions ({resolution.contributions.length})</TabsTrigger>
</TabsList>
{/* Overview Tab */}
<TabsContent value="overview" className="space-y-6">
<Card>
<CardHeader>
<CardTitle>Executive Summary</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm">{resolution.summary}</p>
<div className="mt-6 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4 text-center">
<StatCard
icon={Users}
label="Beneficiaries"
value={resolution.impactMetrics.estimatedBeneficiaries.toLocaleString()}
sublabel="estimated impact"
/>
<StatCard
icon={CheckCircle}
label="Contributions"
value={resolution.contributions.length}
sublabel="consensus-based"
/>
<StatCard
icon={BarChart3}
label="Cost Efficiency"
value={resolution.impactMetrics.costEfficiency}
sublabel="ROI rating"
/>
<StatCard
icon={Clock}
label="Time to Impact"
value={resolution.impactMetrics.timeToImpact}
sublabel="expected timeline"
/>
</div>
<div className="mt-8">
<h3 className="font-medium text-lg mb-4">Key Stakeholders</h3>
<div className="flex flex-wrap gap-2">
{resolution.stakeholders.map((stakeholder, index) => (
<Badge key={index} variant="outline" className="text-sm py-1">
{stakeholder}
</Badge>
))}
</div>
</div>
</CardContent>
</Card>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card className="md:col-span-2">
<CardHeader>
<CardTitle className="text-lg">Timeline</CardTitle>
<CardDescription>Key milestones in the resolution development</CardDescription>
</CardHeader>
<CardContent>
<div className="relative">
{resolution.timeline.map((item, index) => (
<div key={index} className="mb-6 flex gap-4">
<div className="flex flex-col items-center">
<div className="h-8 w-8 rounded-full bg-primary/20 flex items-center justify-center text-primary">
{index === 0 ?
<Users className="h-4 w-4" /> :
index === resolution.timeline.length - 1 ?
<CheckCircle className="h-4 w-4" /> :
<FileBarChart className="h-4 w-4" />
}
</div>
{index < resolution.timeline.length - 1 && (
<div className="w-px h-full bg-border my-1"></div>
)}
</div>
<div>
<p className="font-medium">{item.event}</p>
<p className="text-sm text-muted-foreground">{item.description}</p>
<p className="text-xs text-muted-foreground mt-1">{new Date(item.date).toLocaleDateString()}</p>
</div>
</div>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Impact Assessment</CardTitle>
<CardDescription>Projected outcomes and metrics</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h4 className="text-sm font-medium">Implementation Complexity</h4>
<div className="flex items-center mt-2">
<Badge variant={
resolution.impactMetrics.implementationComplexity === "Low" ? "outline" :
resolution.impactMetrics.implementationComplexity === "Medium" ? "secondary" :
"destructive"
}>
{resolution.impactMetrics.implementationComplexity}
</Badge>
</div>
</div>
<div>
<h4 className="text-sm font-medium">Sustainability Score</h4>
<div className="mt-2 relative pt-1">
<div className="flex mb-2 items-center justify-between">
<div>
<span className="text-xs font-semibold inline-block py-1 px-2 uppercase rounded-full bg-green-200 text-green-800">
{resolution.impactMetrics.sustainabilityScore}/10
</span>
</div>
</div>
<div className="overflow-hidden h-2 mb-4 text-xs flex rounded bg-muted">
<div style={{ width: `${resolution.impactMetrics.sustainabilityScore * 10}%` }}
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-green-500">
</div>
</div>
</div>
<p className="text-xs text-muted-foreground">
Measures long-term viability and environmental impact
</p>
</div>
<div className="pt-4">
<h4 className="text-sm font-medium mb-2">Key Outcomes</h4>
<ul className="text-sm space-y-2">
<li className="flex items-start gap-2">
<CheckCircle className="h-4 w-4 text-green-500 mt-0.5" />
<span>Improved academic performance and decreased truancy</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-4 w-4 text-green-500 mt-0.5" />
<span>Reduced emergency room usage for non-emergency conditions</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-4 w-4 text-green-500 mt-0.5" />
<span>Earlier detection and treatment of health conditions</span>
</li>
</ul>
</div>
</div>
</CardContent>
</Card>
</div>
</TabsContent>
{/* Content Tab */}
<TabsContent value="content" className="space-y-6">
<Card>
<CardHeader>
<CardTitle>Full Resolution Text</CardTitle>
<CardDescription>
Resolution #{resolution.id}: {resolution.title}
</CardDescription>
</CardHeader>
<CardContent>
<Accordion type="single" collapsible className="w-full">
{resolution.sections.map((section) => (
<AccordionItem key={section.id} value={section.id}>
<AccordionTrigger className="font-medium">
{section.id}. {section.title}
</AccordionTrigger>
<AccordionContent>
<div className="text-sm space-y-4">
<p>{section.content}</p>
{section.subsections && section.subsections.length > 0 && (
<div className="pl-4 border-l-2 border-muted mt-4 space-y-4">
{section.subsections.map((subsection) => (
<div key={subsection.id}>
<h4 className="font-medium">{subsection.id} {subsection.title}</h4>
<p className="mt-2">{subsection.content}</p>
</div>
))}
</div>
)}
</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</CardContent>
</Card>
</TabsContent>
{/* Contributions Tab */}
<TabsContent value="contributions" className="space-y-6">
<Card>
<CardHeader>
<CardTitle>Contributing Insights</CardTitle>
<CardDescription>
Consensus-reached contributions that formed this resolution
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6">
{resolution.contributions.map((contribution) => {
const approvalPercentage = Math.round(
(contribution.votes.yes / (contribution.votes.yes + contribution.votes.no)) * 100
)
return (
<div key={contribution.id} className="border rounded-lg p-4">
<div className="flex items-start justify-between gap-4">
<div>
<div className="flex items-center gap-2">
<Badge className="text-xs">{contribution.category}</Badge>
<Badge variant="outline" className="text-xs">ID: {contribution.id}</Badge>
</div>
<h3 className="font-medium mt-2">{contribution.title}</h3>
<p className="text-sm text-muted-foreground mt-1">{contribution.description}</p>
</div>
<div className="text-center min-w-[80px]">
<div className="h-16 w-16 rounded-full border-4 border-green-500 flex items-center justify-center mx-auto">
<span className="text-lg font-bold">{approvalPercentage}%</span>
</div>
<p className="text-xs text-muted-foreground mt-1">Consensus</p>
</div>
</div>
<div className="mt-4 flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div className="text-sm">
<span className="text-muted-foreground">Based on </span>
<span className="font-medium">{contribution.perspectives} perspectives</span>
</div>
<Button size="sm" variant="outline" asChild>
<Link href={`/contributions/${contribution.id}`}>
View Details
</Link>
</Button>
</div>
</div>
)
})}
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
<div className="mt-12 flex justify-center">
<Button variant="outline" asChild>
<Link href="/resolutions">Return to All Resolutions</Link>
</Button>
</div>
</div>
)
}
// Stat card component
function StatCard({
icon: Icon,
label,
value,
sublabel
}: {
icon: LucideIcon;
label: string;
value: string | number;
sublabel: string;
}) {
return (
<div className="p-4 border rounded-lg">
<div className="flex justify-center mb-2">
<div className="h-10 w-10 rounded-full bg-primary/10 flex items-center justify-center text-primary">
<Icon className="h-5 w-5" />
</div>
</div>
<h3 className="text-lg font-bold">{value}</h3>
<p className="font-medium text-sm">{label}</p>
<p className="text-xs text-muted-foreground">{sublabel}</p>
</div>
)
}