SoftTraderFrontend/app/add-item/page.tsx
2026-03-20 11:10:13 -04:00

196 lines
7.0 KiB
TypeScript

'use client'
import Link from 'next/link'
import { ArrowLeft } from 'lucide-react'
import { useState } from 'react'
import { checkSymbol, addUserInterest } from '@/lib/userInterestsApi'
type ResultState = { type: 'success' | 'error' | 'loading' | null; message: string }
export default function AddItem() {
const [activeTab, setActiveTab] = useState<'symbol' | 'topic'>('symbol')
const [symbolInput, setSymbolInput] = useState('')
const [topicInput, setTopicInput] = useState('')
const [symbolResult, setSymbolResult] = useState<ResultState>({ type: null, message: '' })
const [topicResult, setTopicResult] = useState<ResultState>({ type: null, message: '' })
const handleAddSymbol = async () => {
const trimmed = symbolInput.trim()
if (!trimmed) return
setSymbolResult({ type: 'loading', message: 'Verifying symbol...' })
try {
// Step 1: Check if symbol is valid
const checkResult = await checkSymbol(trimmed)
if (!checkResult.found) {
setSymbolResult({
type: 'error',
message: checkResult.message,
})
return
}
// Step 2: Add the symbol
const addResult = await addUserInterest('symbol', trimmed)
setSymbolResult({
type: 'success',
message: `${trimmed.toUpperCase()} has been successfully added!`,
})
setSymbolInput('')
} catch (err) {
setSymbolResult({
type: 'error',
message: err instanceof Error ? err.message : 'Failed to add symbol',
})
}
}
const handleAddTopic = async () => {
const trimmed = topicInput.trim()
if (!trimmed) return
setTopicResult({ type: 'loading', message: 'Adding topic...' })
try {
await addUserInterest('topic', trimmed)
setTopicResult({
type: 'success',
message: `${trimmed} has been added to your interests list!`,
})
setTopicInput('')
} catch (err) {
setTopicResult({
type: 'error',
message: err instanceof Error ? err.message : 'Failed to add topic',
})
}
}
return (
<div className="h-full flex flex-col">
{/* Header */}
<div className="bg-background border-b border-border px-6 py-4 flex items-center gap-4">
<Link href="/interests" className="p-2 hover:bg-secondary transition-colors">
<ArrowLeft size={20} />
</Link>
<h1 className="text-2xl font-bold">Add Item</h1>
</div>
{/* Content */}
<div className="flex-1 overflow-y-auto p-6">
<div className="max-w-md space-y-6">
{/* Tabs */}
<div className="flex gap-2 border-b border-border">
<button
onClick={() => {
setActiveTab('symbol')
setSymbolResult({ type: null, message: '' })
}}
className={`px-6 py-3 border-b-2 font-medium transition-colors ${
activeTab === 'symbol'
? 'border-primary text-foreground'
: 'border-transparent text-muted-foreground hover:text-foreground'
}`}
>
Add Symbol
</button>
<button
onClick={() => {
setActiveTab('topic')
setTopicResult({ type: null, message: '' })
}}
className={`px-6 py-3 border-b-2 font-medium transition-colors ${
activeTab === 'topic'
? 'border-primary text-foreground'
: 'border-transparent text-muted-foreground hover:text-foreground'
}`}
>
Add Topic
</button>
</div>
{/* Add Symbol Tab */}
{activeTab === 'symbol' && (
<div className="space-y-4">
<div className="space-y-3">
<label className="block text-sm font-medium">Symbol:</label>
<input
type="text"
placeholder="Enter stock symbol (e.g., AAPL, MSFT)"
value={symbolInput}
onChange={(e) => setSymbolInput(e.target.value)}
disabled={symbolResult.type === 'loading'}
className="w-full border border-border bg-input text-foreground p-4 text-base disabled:opacity-60"
/>
</div>
<button
onClick={handleAddSymbol}
disabled={!symbolInput.trim() || symbolResult.type === 'loading'}
className="w-full bg-primary text-primary-foreground p-4 font-medium hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-base"
>
{symbolResult.type === 'loading' ? 'Verifying...' : 'ADD'}
</button>
{symbolResult.type && (
<div
className={`p-4 text-sm font-medium ${
symbolResult.type === 'success'
? 'bg-positive/10 text-positive border border-positive'
: symbolResult.type === 'error'
? 'bg-negative/10 text-negative border border-negative'
: 'bg-yellow-400/10 text-yellow-600 border border-yellow-400'
}`}
>
{symbolResult.message}
</div>
)}
</div>
)}
{/* Add Topic Tab */}
{activeTab === 'topic' && (
<div className="space-y-4">
<div className="space-y-3">
<label className="block text-sm font-medium">Topic:</label>
<input
type="text"
placeholder="Enter topic name (e.g., AI, Healthcare, Energy)"
value={topicInput}
onChange={(e) => setTopicInput(e.target.value)}
disabled={topicResult.type === 'loading'}
className="w-full border border-border bg-input text-foreground p-4 text-base disabled:opacity-60"
/>
</div>
<button
onClick={handleAddTopic}
disabled={!topicInput.trim() || topicResult.type === 'loading'}
className="w-full bg-primary text-primary-foreground p-4 font-medium hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-base"
>
{topicResult.type === 'loading' ? 'Adding...' : 'ADD'}
</button>
{topicResult.type && (
<div
className={`p-4 text-sm font-medium ${
topicResult.type === 'success'
? 'bg-positive/10 text-positive border border-positive'
: topicResult.type === 'error'
? 'bg-negative/10 text-negative border border-negative'
: 'bg-yellow-400/10 text-yellow-600 border border-yellow-400'
}`}
>
{topicResult.message}
</div>
)}
</div>
)}
</div>
</div>
</div>
)
}