feat: Allow inline editing of both name and description for decks and quizzes
All checks were successful
Automated Container Build / build-and-push (push) Successful in 52s

This commit is contained in:
Elijah 2026-06-27 20:48:19 -07:00
parent 0295101e10
commit ec8e601332
2 changed files with 113 additions and 35 deletions

View file

@ -30,6 +30,7 @@ export default function FlashcardsPage() {
const [classId, setClassId] = useState<string>("");
const [editingId, setEditingId] = useState<string | null>(null);
const [editName, setEditName] = useState("");
const [editDescription, setEditDescription] = useState("");
const fetchDecks = useCallback(async (cId: string) => {
try {
@ -77,10 +78,10 @@ export default function FlashcardsPage() {
await fetch(`/api/decks/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: editName.trim() }),
body: JSON.stringify({ name: editName.trim(), description: editDescription.trim() || null }),
});
setDecks((prev) =>
prev.map((d) => (d.id === id ? { ...d, name: editName.trim() } : d))
prev.map((d) => (d.id === id ? { ...d, name: editName.trim(), description: editDescription.trim() || null } : d))
);
setEditingId(null);
}
@ -148,38 +149,48 @@ export default function FlashcardsPage() {
className="group flex flex-col bg-bg-surface rounded-xl border border-border-light shadow-[var(--shadow-card)] hover:shadow-[var(--shadow-card-hover)] hover:border-primary/20 transition-all duration-300 h-full"
>
<div className="p-6 flex flex-col flex-1 h-full">
{/* Name (editable) */}
{/* Name and Description (editable) */}
{editingId === deck.id ? (
<div className="flex gap-2 mb-3">
<div className="flex flex-col gap-3 mb-3">
<input
type="text"
value={editName}
onChange={(e) => setEditName(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && handleRename(deck.id)}
placeholder="Deck Name"
autoFocus
className="flex-1 px-3 py-1.5 rounded-lg border border-border bg-bg-surface-alt/50 text-text-heading text-sm focus:outline-none focus:ring-2 focus:ring-primary/30"
className="w-full px-3 py-1.5 rounded-lg border border-border bg-bg-surface-alt/50 text-text-heading text-sm font-semibold focus:outline-none focus:ring-2 focus:ring-primary/30"
/>
<button
onClick={() => handleRename(deck.id)}
className="text-sm text-primary hover:text-primary-hover cursor-pointer"
>
Save
</button>
<button
onClick={() => setEditingId(null)}
className="text-sm text-text-muted hover:text-text-heading cursor-pointer"
>
Cancel
</button>
<textarea
value={editDescription}
onChange={(e) => setEditDescription(e.target.value)}
placeholder="Description (optional)"
rows={2}
className="w-full px-3 py-1.5 rounded-lg border border-border bg-bg-surface-alt/50 text-text-heading text-sm focus:outline-none focus:ring-2 focus:ring-primary/30 resize-none"
/>
<div className="flex gap-2 mt-1">
<button
onClick={() => handleRename(deck.id)}
className="px-3 py-1.5 bg-primary text-white text-xs font-medium rounded-md hover:bg-primary-hover cursor-pointer"
>
Save Changes
</button>
<button
onClick={() => setEditingId(null)}
className="px-3 py-1.5 bg-bg-surface-alt text-text-heading text-xs font-medium rounded-md hover:bg-border cursor-pointer transition-colors"
>
Cancel
</button>
</div>
</div>
) : (
<h3 className="text-lg font-semibold text-text-heading mb-1">
{deck.name}
</h3>
)}
{deck.description && (
<p className="text-sm text-text-secondary mb-3 line-clamp-2">{deck.description}</p>
<>
<h3 className="text-lg font-semibold text-text-heading mb-1">
{deck.name}
</h3>
{deck.description && (
<p className="text-sm text-text-secondary mb-3 line-clamp-2">{deck.description}</p>
)}
</>
)}
{/* Stats */}
@ -231,9 +242,10 @@ export default function FlashcardsPage() {
onClick={() => {
setEditingId(deck.id);
setEditName(deck.name);
setEditDescription(deck.description || "");
}}
className="p-2 rounded-lg text-text-muted hover:text-text-heading hover:bg-bg-surface-alt transition-all duration-200 cursor-pointer"
title="Rename"
title="Edit"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />