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

460 lines
23 KiB
TypeScript

"use client"
import { useState, use } from "react"
import { ArrowLeft, MessageSquare, ThumbsUp, ThumbsDown, Share2, FileText, Filter } from "lucide-react"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Textarea } from "@/components/ui/textarea"
import { Separator } from "@/components/ui/separator"
import { Progress } from "@/components/ui/progress"
// Mock data for the issue
const mockIssues = {
"climate-action": {
id: "climate-action",
title: "Climate Action Policies",
description: "Discussion on policies to address climate change and reduce carbon emissions.",
category: "Environmental Policy",
dateCreated: "2024-01-10",
status: "active",
metrics: {
perspectives: 324,
insights: 18,
contributions: 5,
participants: 156
}
},
"education-reform": {
id: "education-reform",
title: "Education System Reform",
description: "Ideas for improving educational outcomes and accessibility for all students.",
category: "Education",
status: "active",
metrics: {
perspectives: 187,
insights: 12,
contributions: 3,
participants: 89
}
}
}
// Mock perspectives for issues
const mockPerspectivesByIssue = {
"climate-action": [
{
id: 1,
userId: "user1",
userName: "Alex Johnson",
userAvatar: "",
content: "We should focus on renewable energy investments. Solar and wind power have become more cost-effective and could replace fossil fuels in many regions.",
dateSubmitted: "2024-03-01",
likes: 45,
dislikes: 3
},
{
id: 2,
userId: "user2",
userName: "Jamie Smith",
userAvatar: "",
content: "Carbon pricing is the most efficient way to reduce emissions. It creates market incentives for businesses to innovate and cut their carbon footprint.",
dateSubmitted: "2024-02-28",
likes: 38,
dislikes: 7
},
{
id: 3,
userId: "user3",
userName: "Taylor Reed",
userAvatar: "",
content: "We need to address transportation emissions through better public transit and EV infrastructure. This sector is a major contributor to greenhouse gases.",
dateSubmitted: "2024-02-25",
likes: 52,
dislikes: 4
}
],
"education-reform": [
{
id: 1,
userId: "user4",
userName: "Morgan Lee",
userAvatar: "",
content: "Teachers need better resources and smaller class sizes to effectively improve student outcomes.",
dateSubmitted: "2024-03-02",
likes: 62,
dislikes: 5
},
{
id: 2,
userId: "user5",
userName: "Casey Wilson",
userAvatar: "",
content: "Access to early childhood education should be a priority as it sets the foundation for all future learning.",
dateSubmitted: "2024-02-27",
likes: 41,
dislikes: 2
}
]
}
// Mock insights for issues
const mockInsightsByIssue = {
"climate-action": [
{
id: 1,
title: "Renewable Energy Investment",
description: "67% of perspectives support increased government funding for renewable energy projects, with solar and wind being the most frequently mentioned technologies.",
votes: { yes: 124, no: 18 },
status: "consensus", // voting, consensus, rejected
perspectives: [1, 5, 8, 12] // Reference to perspective IDs
},
{
id: 2,
title: "Carbon Pricing Mechanism",
description: "A majority of users advocate for carbon pricing policies, with 58% specifically mentioning tax incentives for low-emission businesses.",
votes: { yes: 98, no: 32 },
status: "voting", // voting, consensus, rejected
perspectives: [2, 7, 15] // Reference to perspective IDs
}
],
"education-reform": [
{
id: 1,
title: "Teacher Support Systems",
description: "78% of perspectives emphasize the need for better resources and support for teachers, including smaller class sizes and professional development.",
votes: { yes: 112, no: 15 },
status: "consensus",
perspectives: [1, 3, 7]
},
{
id: 2,
title: "Early Childhood Education Access",
description: "64% of perspectives advocate for universal access to early childhood education to establish a strong foundation for learning.",
votes: { yes: 87, no: 34 },
status: "voting",
perspectives: [2, 8, 10]
}
]
}
export default function IssueDetails({ params }: { params: Promise<{ id: string }> }) {
// Properly unwrap params using React.use()
const { id: issueId } = use(params)
const [activeTab, setActiveTab] = useState("overview")
const [commentText, setCommentText] = useState("")
// Get the issue data from our mock data
const issue = mockIssues[issueId as keyof typeof mockIssues] || mockIssues["climate-action"]
const perspectives = mockPerspectivesByIssue[issueId as keyof typeof mockPerspectivesByIssue] || []
const insights = mockInsightsByIssue[issueId as keyof typeof mockInsightsByIssue] || []
const handleSubmitComment = (e: React.FormEvent) => {
e.preventDefault()
if (commentText.trim()) {
// In a real app, submit the comment to the backend
console.log("Submitting comment:", commentText)
setCommentText("")
}
}
return (
<div className="container mx-auto px-4 py-8">
<div className="mb-6">
<Button variant="ghost" size="sm" asChild className="mb-4">
<Link href="/issues">
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Issues
</Link>
</Button>
<div className="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">{issue.title}</h1>
<div className="flex items-center gap-2 mt-2">
<Badge variant="outline">{issue.category}</Badge>
<Badge variant="secondary" className="capitalize">{issue.status}</Badge>
</div>
</div>
<div className="flex gap-2 mt-4 md:mt-0">
<Button variant="outline" size="sm" className="gap-1">
<Share2 className="h-4 w-4" />
Share
</Button>
<Button variant="default" size="sm" asChild>
<Link href={`/submit?issue=${issueId}`}>
<MessageSquare className="mr-2 h-4 w-4" />
Add Perspective
</Link>
</Button>
</div>
</div>
<p className="text-muted-foreground mb-6">{issue.description}</p>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
<Card>
<CardContent className="pt-6">
<div className="text-2xl font-bold">{issue.metrics.perspectives}</div>
<p className="text-sm text-muted-foreground">Perspectives</p>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="text-2xl font-bold">{issue.metrics.insights}</div>
<p className="text-sm text-muted-foreground">Insights</p>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="text-2xl font-bold">{issue.metrics.contributions}</div>
<p className="text-sm text-muted-foreground">Contributions</p>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="text-2xl font-bold">{issue.metrics.participants}</div>
<p className="text-sm text-muted-foreground">Participants</p>
</CardContent>
</Card>
</div>
</div>
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="perspectives">Perspectives</TabsTrigger>
<TabsTrigger value="insights">Insights</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="pt-6">
<Card>
<CardHeader>
<CardTitle>Issue Summary</CardTitle>
<CardDescription>Key information and progress on this issue</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-6">
<div>
<h3 className="font-medium mb-2">Progress</h3>
<div className="space-y-4">
<div>
<div className="flex justify-between text-sm mb-1">
<span>Perspectives Gathering</span>
<span className="text-muted-foreground">75%</span>
</div>
<Progress value={75} />
</div>
<div>
<div className="flex justify-between text-sm mb-1">
<span>Insight Formation</span>
<span className="text-muted-foreground">45%</span>
</div>
<Progress value={45} />
</div>
<div>
<div className="flex justify-between text-sm mb-1">
<span>Contribution Validation</span>
<span className="text-muted-foreground">20%</span>
</div>
<Progress value={20} />
</div>
</div>
</div>
<Separator />
<div>
<h3 className="font-medium mb-2">Timeline</h3>
<div className="space-y-4">
<div className="flex">
<div className="mr-4 mt-0.5">
<Badge variant="secondary" className="h-8 w-8 rounded-full flex items-center justify-center p-0">1</Badge>
</div>
<div>
<h4 className="font-medium">Perspectives Collection</h4>
<p className="text-sm text-muted-foreground">In progress - Ends Apr 15, 2024</p>
</div>
</div>
<div className="flex">
<div className="mr-4 mt-0.5">
<Badge variant="outline" className="h-8 w-8 rounded-full flex items-center justify-center p-0">2</Badge>
</div>
<div>
<h4 className="font-medium">Insight Voting</h4>
<p className="text-sm text-muted-foreground">Apr 16 - May 1, 2024</p>
</div>
</div>
<div className="flex">
<div className="mr-4 mt-0.5">
<Badge variant="outline" className="h-8 w-8 rounded-full flex items-center justify-center p-0">3</Badge>
</div>
<div>
<h4 className="font-medium">Resolution Formation</h4>
<p className="text-sm text-muted-foreground">May 2 - May 15, 2024</p>
</div>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="perspectives" className="pt-6">
<div className="flex justify-between mb-4">
<h2 className="text-xl font-bold">Recent Perspectives</h2>
<div className="flex gap-2">
<Select defaultValue="recent">
<SelectTrigger className="w-[150px]">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
<SelectItem value="recent">Most Recent</SelectItem>
<SelectItem value="popular">Most Popular</SelectItem>
</SelectContent>
</Select>
<Button variant="outline" size="icon">
<Filter className="h-4 w-4" />
</Button>
</div>
</div>
<div className="space-y-4">
{perspectives.map((perspective) => (
<Card key={perspective.id}>
<CardHeader className="pb-2">
<div className="flex justify-between">
<div className="flex items-center">
<Avatar className="h-8 w-8 mr-2">
<AvatarImage src={perspective.userAvatar} />
<AvatarFallback>{perspective.userName.charAt(0)}</AvatarFallback>
</Avatar>
<div>
<p className="font-medium">{perspective.userName}</p>
<p className="text-xs text-muted-foreground">{perspective.dateSubmitted}</p>
</div>
</div>
</div>
</CardHeader>
<CardContent>
<p>{perspective.content}</p>
</CardContent>
<CardFooter className="border-t pt-4 flex justify-between">
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" className="gap-1">
<ThumbsUp className="h-4 w-4" />
{perspective.likes}
</Button>
<Button variant="ghost" size="sm" className="gap-1">
<ThumbsDown className="h-4 w-4" />
{perspective.dislikes}
</Button>
</div>
<Button variant="ghost" size="sm">Reply</Button>
</CardFooter>
</Card>
))}
</div>
<Card className="mt-6">
<CardHeader>
<CardTitle>Add Your Perspective</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmitComment}>
<Textarea
placeholder="Share your thoughts on this issue..."
value={commentText}
onChange={(e) => setCommentText(e.target.value)}
className="min-h-[100px]"
/>
<div className="flex justify-end mt-4">
<Button type="submit" disabled={!commentText.trim()}>
<MessageSquare className="mr-2 h-4 w-4" />
Submit Perspective
</Button>
</div>
</form>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="insights" className="pt-6">
<div className="flex justify-between mb-4">
<h2 className="text-xl font-bold">Emerging Insights</h2>
<Button variant="outline" size="sm">
<Filter className="mr-2 h-4 w-4" />
Filter
</Button>
</div>
<div className="space-y-4">
{insights.map((insight) => (
<Card key={insight.id}>
<CardHeader>
<div className="flex justify-between">
<CardTitle>{insight.title}</CardTitle>
<Badge
variant={insight.status === "consensus" ? "default" : "outline"}
className={insight.status === "consensus" ? "bg-green-500" : ""}
>
{insight.status === "consensus" ? "Consensus Reached" : "Voting In Progress"}
</Badge>
</div>
</CardHeader>
<CardContent>
<p className="mb-4">{insight.description}</p>
<div className="rounded-md bg-muted p-4">
<div className="text-sm text-muted-foreground mb-2">Voting Progress</div>
<div className="flex justify-between text-sm mb-1">
<span>
<ThumbsUp className="h-3 w-3 inline mr-1" />
{insight.votes.yes} Yes
</span>
<span>
<ThumbsDown className="h-3 w-3 inline mr-1" />
{insight.votes.no} No
</span>
</div>
<Progress
value={(insight.votes.yes / (insight.votes.yes + insight.votes.no)) * 100}
className="h-2"
/>
</div>
</CardContent>
<CardFooter className="border-t pt-4 flex justify-between">
<div>
<Badge variant="outline" className="mr-2">
Based on {insight.perspectives.length} perspectives
</Badge>
</div>
{insight.status === "voting" && (
<div className="flex gap-2">
<Button variant="outline" size="sm" className="gap-1">
<ThumbsDown className="h-4 w-4" />
Vote No
</Button>
<Button variant="default" size="sm" className="gap-1">
<ThumbsUp className="h-4 w-4" />
Vote Yes
</Button>
</div>
)}
</CardFooter>
</Card>
))}
</div>
</TabsContent>
</Tabs>
</div>
)
}