Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ supabase
# local env files
.env*.local
.env

.env.local
# vercel
.vercel

Expand Down
72 changes: 72 additions & 0 deletions app/api/group-carts/[cartId]/items/[itemId]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function PUT(
req: NextRequest,
{ params }: { params: { cartId: string; itemId: string } }
) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { cartId, itemId } = params;
const { quantity } = await req.json();

if (!cartId || !itemId) {
return NextResponse.json({ error: 'cartId and itemId are required' }, { status: 400 });
}

if (quantity === undefined) {
return NextResponse.json({ error: 'quantity is required' }, { status: 400 });
}

const { data, error } = await supabase
.from('group_cart_items')
.update({ quantity })
.eq('id', itemId)
.eq('user_id', session.user.id); // for security, only allow user to update their own items

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json(data);
}

export async function DELETE(
req: NextRequest,
{ params }: { params: { cartId: string; itemId: string } }
) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { cartId, itemId } = params;

if (!cartId || !itemId) {
return NextResponse.json({ error: 'cartId and itemId are required' }, { status: 400 });
}

const { data, error } = await supabase
.from('group_cart_items')
.delete()
.eq('id', itemId)
.eq('user_id', session.user.id); // for security, only allow user to delete their own items

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json(data);
}
79 changes: 79 additions & 0 deletions app/api/group-carts/[cartId]/items/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(
req: NextRequest,
{ params }: { params: { cartId: string } }
) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { cartId } = params;
const { product_id, quantity } = await req.json();

if (!cartId) {
return NextResponse.json({ error: 'cartId is required' }, { status: 400 });
}

if (!product_id || !quantity) {
return NextResponse.json({ error: 'product_id and quantity are required' }, { status: 400 });
}

// First, check if the user is a member of the group cart
const { data: memberData, error: memberError } = await supabase
.from('group_cart_members')
.select('id')
.eq('group_cart_id', cartId)
.eq('user_id', session.user.id)
.single();

if (memberError || !memberData) {
return NextResponse.json({ error: 'You are not a member of this group cart' }, { status: 403 });
}

// Check if the item already exists in the cart for the user
const { data: existingItem, error: existingError } = await supabase
.from('group_cart_items')
.select('id, quantity')
.eq('group_cart_id', cartId)
.eq('product_id', product_id)
.eq('user_id', session.user.id)
.single();

if (existingItem) {
// If it exists, update the quantity
const { data, error } = await supabase
.from('group_cart_items')
.update({ quantity: existingItem.quantity + quantity })
.eq('id', existingItem.id);

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
} else {
// If it doesn't exist, insert a new item
const { data, error } = await supabase
.from('group_cart_items')
.insert([
{
group_cart_id: cartId,
product_id,
quantity,
user_id: session.user.id,
},
]);

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
return NextResponse.json(data);
}
}
59 changes: 59 additions & 0 deletions app/api/group-carts/[cartId]/members/[userId]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function DELETE(
req: NextRequest,
{ params }: { params: { cartId: string; userId: string } }
) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { cartId, userId } = params;

if (!cartId || !userId) {
return NextResponse.json({ error: 'cartId and userId are required' }, { status: 400 });
}

// Check if the current user is the owner of the cart
const { data: cartData, error: cartError } = await supabase
.from('group_carts')
.select('owner_id')
.eq('id', cartId)
.single();

if (cartError || !cartData) {
return NextResponse.json({ error: 'Group cart not found' }, { status: 404 });
}

const isOwner = cartData.owner_id === session.user.id;
const isLeaving = session.user.id === userId;

// Only the owner can remove other users, or a user can remove themselves (leave)
if (!isOwner && !isLeaving) {
return NextResponse.json({ error: 'You do not have permission to remove this user' }, { status: 403 });
}

// A user cannot be removed by another user if they are the group owner
if(cartData.owner_id === userId && !isLeaving) {
return NextResponse.json({ error: 'The group owner cannot be removed' }, { status: 403 });
}

const { data, error } = await supabase
.from('group_cart_members')
.delete()
.eq('group_cart_id', cartId)
.eq('user_id', userId);

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json(data);
}
32 changes: 32 additions & 0 deletions app/api/group-carts/[cartId]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function GET(
req: NextRequest,
{ params }: { params: { cartId: string } }
) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { cartId } = params;

if (!cartId) {
return NextResponse.json({ error: 'cartId is required' }, { status: 400 });
}

const { data, error } = await supabase
.rpc('get_group_cart', { p_group_cart_id: cartId });

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json(data);
}
29 changes: 29 additions & 0 deletions app/api/group-carts/join/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(req: NextRequest) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { shareable_link } = await req.json();

if (!shareable_link) {
return NextResponse.json({ error: 'shareable_link is required' }, { status: 400 });
}

const { error } = await supabase
.rpc('join_group_cart', { shareable_link_param: shareable_link });

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json({ message: 'Successfully joined group cart' });
}
29 changes: 29 additions & 0 deletions app/api/group-carts/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(req: NextRequest) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

const { data: { session } } = await supabase.auth.getSession();

if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const { name } = await req.json();

if (!name) {
return NextResponse.json({ error: 'Group cart name is required' }, { status: 400 });
}

const { data, error } = await supabase
.rpc('create_group_cart', { name });

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json(data);
}
Loading