Inline items on lists page and interactive dashboard widget
- Lists page: show up to 10 open items per list in collapsible cards; items can be checked off directly without opening the list - Dashboard widget: replace static span-checkboxes with a real client component using useOptimistic so items can be toggled from the dashboard - listWidgetItems now returns listId for navigation links - New listListsWithItems query fetches counts + top 10 open items per list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
734268cb75
commit
8fda3e47dd
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { listLists, listWidgetItems, searchItems, searchLists } from "./server/queries";
|
||||
import { loadListForShare, type ListShareData } from "./server/share-queries";
|
||||
import { ListSharedView } from "./components/shared-view";
|
||||
import { ListWidget } from "./components/list-widget";
|
||||
|
||||
const listIdsSchema = z.union([z.literal("all"), z.array(z.string().uuid())]);
|
||||
|
||||
@@ -12,37 +13,14 @@ const listWidgetConfigSchema = z.object({
|
||||
limit: z.number().int().min(1).max(50).optional(),
|
||||
});
|
||||
|
||||
async function ListWidget({ config }: { config: unknown; ctx: WidgetContext }) {
|
||||
async function ListWidgetServer({ config }: { config: unknown; ctx: WidgetContext }) {
|
||||
const parsed = listWidgetConfigSchema.parse(config);
|
||||
const items = await listWidgetItems({
|
||||
listIds: parsed.listIds,
|
||||
showCompleted: parsed.showCompleted,
|
||||
limit: parsed.limit ?? 10,
|
||||
});
|
||||
|
||||
if (items.length === 0) {
|
||||
return (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{parsed.showCompleted ? "No items" : "No open items"}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="space-y-1">
|
||||
{items.map((item) => (
|
||||
<li key={item.id} className="flex items-center gap-2 text-sm">
|
||||
<span
|
||||
className={`h-4 w-4 shrink-0 rounded-sm border border-border ${item.done ? "bg-muted" : ""}`}
|
||||
/>
|
||||
<span className={`truncate ${item.done ? "text-muted-foreground line-through" : ""}`}>
|
||||
{item.text}
|
||||
</span>
|
||||
<span className="ml-auto shrink-0 text-xs text-muted-foreground">{item.listName}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
return <ListWidget initialItems={items} />;
|
||||
}
|
||||
|
||||
const manifest: ModuleManifest = {
|
||||
@@ -109,7 +87,7 @@ const manifest: ModuleManifest = {
|
||||
name: list.name,
|
||||
})),
|
||||
}),
|
||||
render: (props) => <ListWidget {...props} />,
|
||||
render: (props) => <ListWidgetServer {...props} />,
|
||||
},
|
||||
],
|
||||
quickAdds: [
|
||||
|
||||
Reference in New Issue
Block a user