feat: live updates on shared shopping lists
Polls item state every 4s and merges it into the list view, guarding any item with an in-flight local edit so a poll landing mid-edit can't stomp on it. No websocket/SSE infra exists in this app yet, so this follows the same polling convention already used for notifications and message threads. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,36 @@ import { getShoppingListAccess, canWriteShoppingList } from "@/lib/shopping-list
|
||||
import { guessAisle } from "@/lib/grocery-categories";
|
||||
import { notifyShoppingListMembers } from "@/lib/shopping-list-notify";
|
||||
|
||||
// Polled by the list view (components/meal-plan/shopping-list-view.tsx) so
|
||||
// collaborators see each other's checked/added/reordered items without a
|
||||
// manual refresh — no push/websocket infra in this app, so a short poll on
|
||||
// the same shape the page's initial server-render already uses.
|
||||
export async function GET(_req: NextRequest, { params }: Params) {
|
||||
const { session, response } = await requireSession();
|
||||
if (response) return response;
|
||||
const { id } = await params;
|
||||
|
||||
const access = await getShoppingListAccess(id, session!.user.id);
|
||||
if (!access) return NextResponse.json({ error: "Not found" }, { status: 404 });
|
||||
|
||||
const items = await db.query.shoppingListItems.findMany({
|
||||
where: eq(shoppingListItems.listId, id),
|
||||
orderBy: (t, { asc }) => [asc(t.aisle), asc(t.sortOrder), asc(t.rawName)],
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
items: items.map((i) => ({
|
||||
id: i.id,
|
||||
rawName: i.rawName,
|
||||
quantity: i.quantity,
|
||||
unit: i.unit,
|
||||
aisle: i.aisle,
|
||||
checked: i.checked,
|
||||
sortOrder: i.sortOrder,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
const AddItemsSchema = z.object({
|
||||
items: z.array(z.object({
|
||||
rawName: z.string().min(1),
|
||||
|
||||
Reference in New Issue
Block a user