feat: share shopping lists via a public link
Mirrors the existing recipe public-share pattern (/r/[id], gated by a visibility flag, no auth required) — shopping lists previously only supported private per-user collaborator invites (email + viewer/editor role), with no way to hand someone a link who isn't already a member. - shoppingLists.isPublic (owner-only toggle, same access-control pattern already used for renaming/deleting the list). - New public /s/[id] route added to PUBLIC_PATHS — read-only aisle-grouped view with a signup CTA for logged-out visitors, styled after /r/[id]. - The existing collaborator-invite dialog (ShareShoppingListButton) now also has a "Public link" toggle + copy-link button at the top, so there's one Share entry point for both private and public sharing. Verified locally: toggling public via the real dialog UI persists correctly (confirmed via DB + a fresh curl PATCH to rule out a client race in my own test script), and the public link loads with zero auth for a logged-out browser context.
This commit is contained in:
@@ -26,6 +26,7 @@ export async function GET(_req: NextRequest, { params }: Params) {
|
||||
const PatchSchema = z.object({
|
||||
completed: z.boolean().optional(),
|
||||
name: z.string().min(1).max(100).optional(),
|
||||
isPublic: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: Params) {
|
||||
@@ -45,6 +46,11 @@ export async function PATCH(req: NextRequest, { params }: Params) {
|
||||
await db.update(shoppingLists).set({ name: body.data.name }).where(eq(shoppingLists.id, id));
|
||||
}
|
||||
|
||||
if (body.data.isPublic !== undefined) {
|
||||
if (access.role !== "owner") return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
await db.update(shoppingLists).set({ isPublic: body.data.isPublic }).where(eq(shoppingLists.id, id));
|
||||
}
|
||||
|
||||
if (body.data.completed) {
|
||||
if (!canWriteShoppingList(access.role)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
// Mark all items as checked
|
||||
|
||||
Reference in New Issue
Block a user