Careeroza
Real World Example
Login Like Swiggy and Zomato
Indian consumer apps mostly use phone + OTP or Google login, keep users signed in for weeks, and lock the admin and seller panels behind roles. ShopEase uses Google + email/password for customers and roles for staff:
| Area | Check |
|---|---|
/products, / | Public |
/cart | Guest cart in a cookie; merged into the user cart on login |
/checkout, /account/* | Signed in |
/seller/* | Role seller + owns the product |
/admin/* | Role admin |
Admin Page
// app/admin/orders/page.tsx
import { requireRole } from '@/lib/authz';
import { prisma } from '@/lib/prisma';
import RefundButton from './RefundButton';
export default async function AdminOrders() {
await requireRole('admin');
const orders = await prisma.order.findMany({ orderBy: { createdAt: 'desc' }, take: 50, include: { user: true } });
return (
<table>
<tbody>
{orders.map((o) => (
<tr key={o.id}>
<td>{o.id}</td>
<td>{o.user.email}</td>
<td>₹{o.total}</td>
<td>{o.status}</td>
<td><RefundButton orderId={o.id} /></td>
</tr>
))}
</tbody>
</table>
);
}// app/admin/orders/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { requireRole } from '@/lib/authz';
export async function refundOrder(orderId: string) {
const admin = await requireRole('admin'); // checked again: actions are public endpoints
await prisma.order.update({ where: { id: orderId }, data: { status: 'REFUNDED', refundedBy: admin.id } });
revalidatePath('/admin/orders');
}