Initial commit: Gold Trading Simulator with AI-powered analysis
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import { useState } from 'react';
|
||||
import { Settings, Check, X } from 'lucide-react';
|
||||
|
||||
interface IndicatorConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
color: string;
|
||||
params: Record<string, number>;
|
||||
}
|
||||
|
||||
interface IndicatorPanelProps {
|
||||
indicators: IndicatorConfig[];
|
||||
onChange: (indicators: IndicatorConfig[]) => void;
|
||||
}
|
||||
|
||||
export default function IndicatorPanel({ indicators, onChange }: IndicatorPanelProps) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const toggleIndicator = (id: string) => {
|
||||
const updated = indicators.map((ind) =>
|
||||
ind.id === id ? { ...ind, enabled: !ind.enabled } : ind
|
||||
);
|
||||
onChange(updated);
|
||||
};
|
||||
|
||||
const updateParam = (id: string, param: string, value: number) => {
|
||||
// Validate input
|
||||
if (isNaN(value) || value <= 0) {
|
||||
return; // Don't update with invalid values
|
||||
}
|
||||
|
||||
const updated = indicators.map((ind) =>
|
||||
ind.id === id ? { ...ind, params: { ...ind.params, [param]: value } } : ind
|
||||
);
|
||||
onChange(updated);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="flex items-center gap-2 px-3 py-2 bg-dark-surface rounded-md hover:bg-dark-hover transition-colors"
|
||||
>
|
||||
<Settings className="w-4 h-4" />
|
||||
<span className="text-sm">Indicators</span>
|
||||
<span className="text-xs bg-blue-600 px-2 py-0.5 rounded-full">
|
||||
{indicators.filter((i) => i.enabled).length}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<>
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="fixed inset-0 z-40"
|
||||
onClick={() => setIsOpen(false)}
|
||||
/>
|
||||
|
||||
{/* Panel */}
|
||||
<div className="absolute top-full mt-2 right-0 w-80 bg-dark-surface border border-dark-border rounded-lg shadow-xl z-50">
|
||||
<div className="p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-semibold">Technical Indicators</h3>
|
||||
<button
|
||||
onClick={() => setIsOpen(false)}
|
||||
className="p-1 hover:bg-dark-hover rounded"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 max-h-96 overflow-y-auto">
|
||||
{indicators.map((indicator) => (
|
||||
<div
|
||||
key={indicator.id}
|
||||
className="p-3 bg-dark-bg rounded-lg border border-dark-border"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className="w-3 h-3 rounded-full"
|
||||
style={{ backgroundColor: indicator.color }}
|
||||
/>
|
||||
<span className="font-medium text-sm">{indicator.name}</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => toggleIndicator(indicator.id)}
|
||||
className={`
|
||||
p-1 rounded transition-colors
|
||||
${
|
||||
indicator.enabled
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-700 text-gray-400'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{indicator.enabled ? (
|
||||
<Check className="w-4 h-4" />
|
||||
) : (
|
||||
<X className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{indicator.enabled && Object.keys(indicator.params).length > 0 && (
|
||||
<div className="space-y-2 mt-3 pt-3 border-t border-dark-border">
|
||||
{Object.entries(indicator.params).map(([param, value]) => (
|
||||
<div key={param}>
|
||||
<label className="block text-xs text-gray-400 mb-1">
|
||||
{param.charAt(0).toUpperCase() + param.slice(1)}
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={(e) =>
|
||||
updateParam(indicator.id, param, Number(e.target.value))
|
||||
}
|
||||
min="1"
|
||||
step="1"
|
||||
className="w-full px-2 py-1 text-sm bg-dark-bg border border-dark-border rounded focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 pt-4 border-t border-dark-border">
|
||||
<button
|
||||
onClick={() => {
|
||||
const allEnabled = indicators.map((ind) => ({ ...ind, enabled: true }));
|
||||
onChange(allEnabled);
|
||||
}}
|
||||
className="w-full px-3 py-2 bg-blue-600 hover:bg-blue-700 rounded text-sm font-medium transition-colors"
|
||||
>
|
||||
Enable All
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
const allDisabled = indicators.map((ind) => ({ ...ind, enabled: false }));
|
||||
onChange(allDisabled);
|
||||
}}
|
||||
className="w-full mt-2 px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm font-medium transition-colors"
|
||||
>
|
||||
Disable All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user