forked from wishonia/wishonia
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Task Galaxy Visualizer and Impact Tracker Visualizer components, hub …
…for idea submission The tasks are represented in a structured manner where status can be changed and matched with the suitable team based on skills and experience. Impact Tracker Visualizer measures the real-world effects of the efforts. The Idea Submission Hub encourages users to submit new problems, solutions, or tasks.
- Loading branch information
Showing
7 changed files
with
807 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
"use client" | ||
import React, { useState } from 'react'; | ||
import { Lightbulb, AlertCircle, Cog, List, Send } from 'lucide-react'; | ||
|
||
type IdeaType = 'problem' | 'solution' | 'task' | 'other'; | ||
|
||
interface Idea { | ||
type: IdeaType; | ||
title: string; | ||
description: string; | ||
} | ||
|
||
const IdeaSubmissionHub: React.FC = () => { | ||
const [ideaType, setIdeaType] = useState<IdeaType>('problem'); | ||
const [title, setTitle] = useState(''); | ||
const [description, setDescription] = useState(''); | ||
const [submitted, setSubmitted] = useState(false); | ||
const [recentIdeas, setRecentIdeas] = useState<Idea[]>([]); | ||
|
||
const handleSubmit = (e: React.FormEvent) => { | ||
e.preventDefault(); | ||
const newIdea: Idea = { type: ideaType, title, description }; | ||
setRecentIdeas(prev => [newIdea, ...prev.slice(0, 2)]); | ||
setSubmitted(true); | ||
setTimeout(() => { | ||
setSubmitted(false); | ||
setTitle(''); | ||
setDescription(''); | ||
}, 3000); | ||
}; | ||
|
||
const getIcon = (type: IdeaType) => { | ||
switch (type) { | ||
case 'problem': return <AlertCircle size={20} />; | ||
case 'solution': return <Lightbulb size={20} />; | ||
case 'task': return <Cog size={20} />; | ||
default: return <List size={20} />; | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="p-4 rounded-lg shadow-md max-w-4xl mx-auto my-8"> | ||
<h2 className="text-2xl font-bold mb-4">Idea Submission Hub</h2> | ||
<div className="mb-4 p-2 border rounded"> | ||
<h3 className="font-bold flex items-center"><Lightbulb size={16} className="mr-2" /> New Ideas Welcome!</h3> | ||
<p className="text-sm">We encourage everyone to submit new problems, solutions, or tasks. Your ideas can make a difference!</p> | ||
</div> | ||
<form onSubmit={handleSubmit} className="mb-6"> | ||
<div className="mb-4"> | ||
<label className="block mb-2 text-sm font-bold">Idea Type</label> | ||
<div className="flex space-x-2"> | ||
{(['problem', 'solution', 'task', 'other'] as IdeaType[]).map(type => ( | ||
<button | ||
key={type} | ||
type="button" | ||
onClick={() => setIdeaType(type)} | ||
className={`px-3 py-2 rounded border ${ideaType === type ? 'border-2' : 'border'}`} | ||
> | ||
{type.charAt(0).toUpperCase() + type.slice(1)} | ||
</button> | ||
))} | ||
</div> | ||
</div> | ||
<div className="mb-4"> | ||
<label htmlFor="title" className="block mb-2 text-sm font-bold">Title</label> | ||
<input | ||
type="text" | ||
id="title" | ||
value={title} | ||
onChange={(e) => setTitle(e.target.value)} | ||
className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2" | ||
required | ||
/> | ||
</div> | ||
<div className="mb-4"> | ||
<label htmlFor="description" className="block mb-2 text-sm font-bold">Description</label> | ||
<textarea | ||
id="description" | ||
value={description} | ||
onChange={(e) => setDescription(e.target.value)} | ||
className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2" | ||
rows={4} | ||
required | ||
/> | ||
</div> | ||
<button | ||
type="submit" | ||
className="px-4 py-2 font-bold rounded-full border hover:border-2 focus:outline-none focus:ring-2" | ||
> | ||
Submit Idea | ||
</button> | ||
</form> | ||
{submitted && ( | ||
<div className="mb-4 p-2 border rounded"> | ||
<p className="text-sm font-bold">Thank you for your submission! Our team will review your idea shortly.</p> | ||
</div> | ||
)} | ||
<div> | ||
<h3 className="font-bold mb-2">Recent Submissions</h3> | ||
{recentIdeas.map((idea, index) => ( | ||
<div key={index} className="mb-2 p-2 border rounded"> | ||
<div className="flex items-center"> | ||
{getIcon(idea.type)} | ||
<span className="ml-2 font-bold">{idea.title}</span> | ||
</div> | ||
<p className="text-sm mt-1">{idea.description}</p> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default IdeaSubmissionHub; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
"use client" | ||
import React, { useState, useEffect } from 'react'; | ||
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; | ||
import { TrendingUp, TrendingDown, RefreshCw, AlertTriangle } from 'lucide-react'; | ||
|
||
interface Metric { | ||
name: string; | ||
value: number; | ||
trend: 'up' | 'down' | 'stable'; | ||
impact: 'positive' | 'negative' | 'neutral'; | ||
} | ||
|
||
interface DataSource { | ||
name: string; | ||
reliability: number; | ||
} | ||
|
||
const ImpactTrackerVisualizer: React.FC = () => { | ||
const [metrics, setMetrics] = useState<Metric[]>([]); | ||
const [dataSources, setDataSources] = useState<DataSource[]>([]); | ||
const [selectedMetric, setSelectedMetric] = useState<string | null>(null); | ||
const [historicalData, setHistoricalData] = useState<any[]>([]); | ||
|
||
useEffect(() => { | ||
// Simulated initial data | ||
const initialMetrics: Metric[] = [ | ||
{ name: 'Drug candidates identified', value: 150, trend: 'up', impact: 'positive' }, | ||
{ name: 'Clinical trials initiated', value: 12, trend: 'up', impact: 'positive' }, | ||
{ name: 'Average drug development time (months)', value: 60, trend: 'down', impact: 'positive' }, | ||
{ name: 'Research collaborations', value: 45, trend: 'up', impact: 'positive' }, | ||
{ name: 'Publications cited', value: 230, trend: 'up', impact: 'positive' }, | ||
]; | ||
setMetrics(initialMetrics); | ||
|
||
const initialDataSources: DataSource[] = [ | ||
{ name: 'Clinical trial databases', reliability: 0.95 }, | ||
{ name: 'Scientific journals', reliability: 0.9 }, | ||
{ name: 'Patent offices', reliability: 0.85 }, | ||
{ name: 'Research institutions', reliability: 0.8 }, | ||
{ name: 'Industry reports', reliability: 0.75 }, | ||
]; | ||
setDataSources(initialDataSources); | ||
}, []); | ||
|
||
const generateHistoricalData = (metricName: string) => { | ||
const data = []; | ||
let value = Math.floor(Math.random() * 100); | ||
for (let i = 12; i > 0; i--) { | ||
value += Math.floor(Math.random() * 20) - 10; | ||
data.push({ | ||
month: i, | ||
[metricName]: Math.max(0, value), | ||
}); | ||
} | ||
setHistoricalData(data.reverse()); | ||
}; | ||
|
||
const handleMetricClick = (metricName: string) => { | ||
setSelectedMetric(metricName); | ||
generateHistoricalData(metricName); | ||
}; | ||
|
||
const getTrendIcon = (trend: string) => { | ||
switch (trend) { | ||
case 'up': | ||
return <TrendingUp size={16} className="text-green-500" />; | ||
case 'down': | ||
return <TrendingDown size={16} className="text-red-500" />; | ||
default: | ||
return <RefreshCw size={16} className="text-yellow-500" />; | ||
} | ||
}; | ||
|
||
const getImpactColor = (impact: string) => { | ||
switch (impact) { | ||
case 'positive': | ||
return 'text-green-500'; | ||
case 'negative': | ||
return 'text-red-500'; | ||
default: | ||
return 'text-yellow-500'; | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="p-4 bg-white dark:bg-gray-800 rounded-lg shadow-md max-w-4xl mx-auto my-8"> | ||
<h2 className="text-2xl font-bold mb-4 text-gray-800 dark:text-gray-200">AI Impact Tracker</h2> | ||
<div className="mb-4 p-2 bg-blue-100 dark:bg-blue-900 rounded"> | ||
<h3 className="font-bold flex items-center"><AlertTriangle size={16} className="mr-2" /> Real-time Impact Analysis</h3> | ||
<p className="text-sm">Our AI agents continuously analyze data from various sources to track key metrics and measure the real-world impact of our efforts.</p> | ||
</div> | ||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> | ||
<div> | ||
<h3 className="font-bold mb-2">Key Metrics</h3> | ||
{metrics.map(metric => ( | ||
<div | ||
key={metric.name} | ||
className="p-2 mb-2 bg-gray-100 dark:bg-gray-700 rounded cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600" | ||
onClick={() => handleMetricClick(metric.name)} | ||
> | ||
<div className="flex justify-between items-center"> | ||
<span>{metric.name}</span> | ||
<span className="font-bold">{metric.value}</span> | ||
</div> | ||
<div className="flex justify-between items-center mt-1"> | ||
<span className="flex items-center"> | ||
{getTrendIcon(metric.trend)} | ||
<span className="ml-1 text-sm">{metric.trend}</span> | ||
</span> | ||
<span className={`text-sm ${getImpactColor(metric.impact)}`}> | ||
Impact: {metric.impact} | ||
</span> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
<div> | ||
<h3 className="font-bold mb-2">Data Sources</h3> | ||
{dataSources.map(source => ( | ||
<div key={source.name} className="p-2 mb-2 bg-gray-100 dark:bg-gray-700 rounded"> | ||
<div className="flex justify-between items-center"> | ||
<span>{source.name}</span> | ||
<span className="text-sm">Reliability: {(source.reliability * 100).toFixed(0)}%</span> | ||
</div> | ||
<div className="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-600 mt-1"> | ||
<div className="bg-blue-600 h-2.5 rounded-full" style={{ width: `${source.reliability * 100}%` }}></div> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
{selectedMetric && ( | ||
<div> | ||
<h3 className="font-bold mb-2">Historical Data: {selectedMetric}</h3> | ||
<ResponsiveContainer width="100%" height={300}> | ||
<BarChart data={historicalData}> | ||
<CartesianGrid strokeDasharray="3 3" /> | ||
<XAxis dataKey="month" /> | ||
<YAxis /> | ||
<Tooltip /> | ||
<Legend /> | ||
<Bar dataKey={selectedMetric} fill="#8884d8" /> | ||
</BarChart> | ||
</ResponsiveContainer> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default ImpactTrackerVisualizer; |
Oops, something went wrong.