250 lines
11 KiB
TypeScript
Raw Normal View History

2025-03-25 03:52:30 -04:00
"use client"
import { useState } from "react"
import Link from "next/link"
import { Search, Filter, ArrowUpDown, Plus } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
// Mock data for issues
const mockIssues = [
{
id: "climate-action",
title: "Climate Action Policies",
description: "Discussion on policies to address climate change and reduce carbon emissions.",
category: "Environmental Policy",
status: "active",
metrics: {
perspectives: 324,
insights: 18,
contributions: 5
},
dateCreated: "2024-01-10"
},
{
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
},
dateCreated: "2024-01-22"
},
{
id: "healthcare-access",
title: "Healthcare Accessibility",
description: "Solutions to make healthcare more affordable and accessible for everyone.",
category: "Healthcare",
status: "active",
metrics: {
perspectives: 256,
insights: 15,
contributions: 4
},
dateCreated: "2024-02-05"
},
{
id: "housing-affordability",
title: "Housing Affordability Crisis",
description: "Addressing the growing housing affordability crisis in urban areas.",
category: "Infrastructure",
status: "active",
metrics: {
perspectives: 210,
insights: 8,
contributions: 2
},
dateCreated: "2024-02-15"
},
{
id: "digital-privacy",
title: "Digital Privacy Regulations",
description: "Balancing innovation with personal privacy in the digital age.",
category: "Technology",
status: "active",
metrics: {
perspectives: 156,
insights: 7,
contributions: 1
},
dateCreated: "2024-02-28"
}
]
// Categories for filtering
const categories = [
"All Categories",
"Environmental Policy",
"Education",
"Healthcare",
"Infrastructure",
"Technology",
"Economy",
"Social Services"
]
export default function IssuesPage() {
const [selectedTab, setSelectedTab] = useState("all")
const [searchQuery, setSearchQuery] = useState("")
const [selectedCategory, setSelectedCategory] = useState("All Categories")
const [sortBy, setSortBy] = useState("latest")
// Filter issues based on search, category, and tab
const filteredIssues = mockIssues.filter(issue => {
// Search filter
const matchesSearch = searchQuery
? issue.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
issue.description.toLowerCase().includes(searchQuery.toLowerCase())
: true
// Category filter
const matchesCategory = selectedCategory === "All Categories" || issue.category === selectedCategory
// Tab filter (all, trending, etc.) - simplified for demo
const matchesTab = selectedTab === "all" ||
(selectedTab === "trending" && issue.metrics.perspectives > 200)
return matchesSearch && matchesCategory && matchesTab
})
// Sort issues
const sortedIssues = [...filteredIssues].sort((a, b) => {
if (sortBy === "latest") {
return new Date(b.dateCreated).getTime() - new Date(a.dateCreated).getTime()
} else if (sortBy === "popular") {
return b.metrics.perspectives - a.metrics.perspectives
} else if (sortBy === "insights") {
return b.metrics.insights - a.metrics.insights
}
return 0
})
return (
<div className="container mx-auto px-4 py-8">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-8">
<div>
<h1 className="text-3xl font-bold tracking-tight">Issues</h1>
<p className="mt-2 text-muted-foreground">
Browse and contribute to active policy discussions
</p>
</div>
<Button className="mt-4 sm:mt-0" asChild>
<Link href="/issues/propose">
<Plus className="mr-2 h-4 w-4" />
Propose New Issue
</Link>
</Button>
</div>
<div className="flex flex-col gap-6">
{/* Filters and Search */}
<div className="flex flex-col sm:flex-row gap-4">
<div className="relative flex-1">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Search issues..."
className="pl-8"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<div className="flex flex-col sm:flex-row gap-2">
<Select
value={selectedCategory}
onValueChange={setSelectedCategory}
>
<SelectTrigger className="w-full sm:w-[180px]">
<SelectValue placeholder="Category" />
</SelectTrigger>
<SelectContent>
{categories.map((category) => (
<SelectItem key={category} value={category}>
{category}
</SelectItem>
))}
</SelectContent>
</Select>
<Select
value={sortBy}
onValueChange={setSortBy}
>
<SelectTrigger className="w-full sm:w-[180px]">
<SelectValue placeholder="Sort by" />
</SelectTrigger>
<SelectContent>
<SelectItem value="latest">Latest</SelectItem>
<SelectItem value="popular">Most Perspectives</SelectItem>
<SelectItem value="insights">Most Insights</SelectItem>
</SelectContent>
</Select>
<Button variant="outline" size="icon">
<Filter className="h-4 w-4" />
</Button>
</div>
</div>
{/* Tabs */}
<Tabs value={selectedTab} onValueChange={setSelectedTab} className="w-full">
<TabsList className="grid w-full sm:w-auto sm:inline-grid grid-cols-3 sm:grid-cols-3">
<TabsTrigger value="all">All Issues</TabsTrigger>
<TabsTrigger value="trending">Trending</TabsTrigger>
<TabsTrigger value="following">Following</TabsTrigger>
</TabsList>
</Tabs>
{/* Results */}
{sortedIssues.length === 0 ? (
<div className="text-center py-12">
<h3 className="text-lg font-medium">No issues found</h3>
<p className="text-muted-foreground mt-2">Try adjusting your filters or search terms</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{sortedIssues.map((issue) => (
<Link key={issue.id} href={`/issues/${issue.id}`} className="transition-transform hover:scale-[1.01]">
<Card className="h-full flex flex-col">
<CardHeader>
<div className="flex justify-between items-start">
<div>
<CardTitle className="line-clamp-2">{issue.title}</CardTitle>
<CardDescription className="mt-1">
<Badge variant="outline">{issue.category}</Badge>
</CardDescription>
</div>
</div>
</CardHeader>
<CardContent className="flex-grow">
<p className="text-muted-foreground line-clamp-3">{issue.description}</p>
</CardContent>
<CardFooter className="border-t pt-4">
<div className="w-full flex justify-between text-sm text-muted-foreground">
<div className="flex gap-4">
<div>{issue.metrics.perspectives} Perspectives</div>
<div>{issue.metrics.insights} Insights</div>
</div>
<div>
{new Date(issue.dateCreated).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
})}
</div>
</div>
</CardFooter>
</Card>
</Link>
))}
</div>
)}
</div>
</div>
)
}