fix: improve StockTable save behavior, accessibility, and structure
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { useState, useMemo, type ReactNode } from "react";
|
||||
|
||||
interface Stock {
|
||||
id: string;
|
||||
@@ -45,6 +45,7 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
|
||||
const paged = filtered.slice(page * pageSize, (page + 1) * pageSize);
|
||||
|
||||
const handleSort = (field: SortField) => {
|
||||
setPage(0);
|
||||
if (sortField === field) {
|
||||
setSortDirection((d) => (d === "asc" ? "desc" : "asc"));
|
||||
} else {
|
||||
@@ -63,15 +64,15 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
|
||||
setSavingNotes(editingTicker);
|
||||
try {
|
||||
await onNotesSave(editingTicker, editingNotes);
|
||||
setEditingTicker(null);
|
||||
} catch (e) {
|
||||
console.error("Failed to save notes:", e);
|
||||
} finally {
|
||||
setSavingNotes(null);
|
||||
setEditingTicker(null);
|
||||
}
|
||||
};
|
||||
|
||||
const SortHeader = ({ field, children }: { field: SortField; children: React.ReactNode }) => (
|
||||
const SortHeader = ({ field, children }: { field: SortField; children: ReactNode }) => (
|
||||
<th
|
||||
className="text-left py-2 px-3 font-medium text-gray-700 cursor-pointer hover:text-gray-900 select-none"
|
||||
onClick={() => handleSort(field)}
|
||||
@@ -83,23 +84,12 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
|
||||
|
||||
if (stocks.length === 0) {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-gray-900">Stock Database</h2>
|
||||
<p className="text-sm text-gray-600 mt-1">Manage tracked stocks and their analysis notes.</p>
|
||||
</div>
|
||||
<p className="text-gray-500 py-8">No stocks tracked yet. Visit the stocks page to add some.</p>
|
||||
</div>
|
||||
<p className="text-gray-500 py-8">No stocks tracked yet. Visit the stocks page to add some.</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-gray-900">Stock Database</h2>
|
||||
<p className="text-sm text-gray-600 mt-1">Manage tracked stocks and their analysis notes.</p>
|
||||
</div>
|
||||
|
||||
{saveError && (
|
||||
<div className="bg-red-50 text-red-700 px-4 py-2 rounded-lg text-sm">{saveError}</div>
|
||||
)}
|
||||
@@ -129,20 +119,28 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
|
||||
</thead>
|
||||
<tbody>
|
||||
{paged.map((stock) => (
|
||||
<tr key={stock.ticker} className="border-b border-gray-100 hover:bg-gray-50">
|
||||
<tr key={stock.id} className="border-b border-gray-100 hover:bg-gray-50">
|
||||
<td className="py-2 px-3 font-medium text-gray-900">{stock.ticker}</td>
|
||||
<td className="py-2 px-3">
|
||||
{editingTicker === stock.ticker ? (
|
||||
<input
|
||||
type="text"
|
||||
value={editingNotes}
|
||||
onChange={(e) => setEditingNotes(e.target.value)}
|
||||
onBlur={saveNotes}
|
||||
onKeyDown={(e) => { if (e.key === "Enter") saveNotes(); if (e.key === "Escape") setEditingTicker(null); }}
|
||||
className="w-full border border-blue-300 rounded px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500"
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
{editingTicker === stock.ticker ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={editingNotes}
|
||||
onChange={(e) => setEditingNotes(e.target.value)}
|
||||
onKeyDown={(e) => { if (e.key === "Enter") saveNotes(); if (e.key === "Escape") setEditingTicker(null); }}
|
||||
className="flex-1 border border-blue-300 rounded px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500"
|
||||
autoFocus
|
||||
/>
|
||||
<button
|
||||
onClick={saveNotes}
|
||||
disabled={savingNotes === stock.ticker}
|
||||
className="text-xs bg-blue-600 text-white px-2 py-1 rounded hover:bg-blue-700 disabled:opacity-50"
|
||||
>
|
||||
{savingNotes === stock.ticker ? "Saving..." : "Save"}
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<span
|
||||
className="text-gray-600 cursor-pointer hover:text-gray-900 block py-1"
|
||||
onClick={() => startEditing(stock)}
|
||||
|
||||
Reference in New Issue
Block a user