fix: improve StockTable save behavior, accessibility, and structure

This commit is contained in:
2026-05-16 21:09:11 +02:00
parent bf628f67b6
commit d83620c493
+15 -17
View File
@@ -1,4 +1,4 @@
import React, { useState, useMemo } from "react"; import { useState, useMemo, type ReactNode } from "react";
interface Stock { interface Stock {
id: string; id: string;
@@ -45,6 +45,7 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
const paged = filtered.slice(page * pageSize, (page + 1) * pageSize); const paged = filtered.slice(page * pageSize, (page + 1) * pageSize);
const handleSort = (field: SortField) => { const handleSort = (field: SortField) => {
setPage(0);
if (sortField === field) { if (sortField === field) {
setSortDirection((d) => (d === "asc" ? "desc" : "asc")); setSortDirection((d) => (d === "asc" ? "desc" : "asc"));
} else { } else {
@@ -63,15 +64,15 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
setSavingNotes(editingTicker); setSavingNotes(editingTicker);
try { try {
await onNotesSave(editingTicker, editingNotes); await onNotesSave(editingTicker, editingNotes);
setEditingTicker(null);
} catch (e) { } catch (e) {
console.error("Failed to save notes:", e); console.error("Failed to save notes:", e);
} finally { } finally {
setSavingNotes(null); setSavingNotes(null);
setEditingTicker(null);
} }
}; };
const SortHeader = ({ field, children }: { field: SortField; children: React.ReactNode }) => ( const SortHeader = ({ field, children }: { field: SortField; children: ReactNode }) => (
<th <th
className="text-left py-2 px-3 font-medium text-gray-700 cursor-pointer hover:text-gray-900 select-none" className="text-left py-2 px-3 font-medium text-gray-700 cursor-pointer hover:text-gray-900 select-none"
onClick={() => handleSort(field)} onClick={() => handleSort(field)}
@@ -83,23 +84,12 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
if (stocks.length === 0) { if (stocks.length === 0) {
return ( 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> <p className="text-gray-500 py-8">No stocks tracked yet. Visit the stocks page to add some.</p>
</div>
); );
} }
return ( return (
<div className="space-y-6"> <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 && ( {saveError && (
<div className="bg-red-50 text-red-700 px-4 py-2 rounded-lg text-sm">{saveError}</div> <div className="bg-red-50 text-red-700 px-4 py-2 rounded-lg text-sm">{saveError}</div>
)} )}
@@ -129,19 +119,27 @@ export default function StockTable({ stocks, onNotesSave, saveError }: StockTabl
</thead> </thead>
<tbody> <tbody>
{paged.map((stock) => ( {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 font-medium text-gray-900">{stock.ticker}</td>
<td className="py-2 px-3"> <td className="py-2 px-3">
{editingTicker === stock.ticker ? ( {editingTicker === stock.ticker ? (
<div className="flex items-center gap-2">
<input <input
type="text" type="text"
value={editingNotes} value={editingNotes}
onChange={(e) => setEditingNotes(e.target.value)} onChange={(e) => setEditingNotes(e.target.value)}
onBlur={saveNotes}
onKeyDown={(e) => { if (e.key === "Enter") saveNotes(); if (e.key === "Escape") setEditingTicker(null); }} 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" className="flex-1 border border-blue-300 rounded px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500"
autoFocus 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 <span
className="text-gray-600 cursor-pointer hover:text-gray-900 block py-1" className="text-gray-600 cursor-pointer hover:text-gray-900 block py-1"