Initial Falah Mobile rebuild — all 7 blocks complete
- Auth system (login/register/profile) - Nur AI chat with persona system - Souq marketplace with FLH economy - Forum community with Shariah moderation - Wallet & FLH top-up - Premium/Pro tier upgrade with Polar.sh - Halal Monitor with map & bookmarks - Home dashboard with daily verse & streaks - Health endpoints Next.js 16.2.7, Prisma v5 SQLite, JWT auth, Tailwind CSS v4
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { requireAuth } from "@/lib/auth";
|
||||
import { getUserTier, HALAL_LIMITS } from "@/lib/tiers";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const auth = await requireAuth(request);
|
||||
if (!auth) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: auth.userId },
|
||||
include: { halalUsage: true },
|
||||
});
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const tier = getUserTier(user.isPremium, user.isPro);
|
||||
const limits = HALAL_LIMITS[tier];
|
||||
|
||||
// If no usage record exists yet, return defaults
|
||||
const usage = user.halalUsage;
|
||||
const queriesUsed = usage?.queriesUsed ?? 0;
|
||||
const queriesLimit = usage?.queriesLimit ?? limits.queriesPerDay;
|
||||
const periodEnd = usage?.periodEnd?.toISOString() ?? null;
|
||||
|
||||
const remaining = Math.max(0, queriesLimit - queriesUsed);
|
||||
|
||||
return NextResponse.json({
|
||||
queriesUsed,
|
||||
queriesLimit,
|
||||
remaining,
|
||||
periodEnd,
|
||||
tier,
|
||||
scope: limits.scope,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("GET /api/halal/usage error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Internal server error" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const auth = await requireAuth(request);
|
||||
if (!auth) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: auth.userId },
|
||||
include: { halalUsage: true },
|
||||
});
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const tier = getUserTier(user.isPremium, user.isPro);
|
||||
const limits = HALAL_LIMITS[tier];
|
||||
|
||||
// Get or create usage record
|
||||
let usage = user.halalUsage;
|
||||
|
||||
// Check if period has expired — reset if so
|
||||
const now = new Date();
|
||||
if (usage && usage.periodEnd && new Date(usage.periodEnd) < now) {
|
||||
usage = await prisma.halalUsage.update({
|
||||
where: { userId: user.id },
|
||||
data: {
|
||||
queriesUsed: 0,
|
||||
queriesLimit: limits.queriesPerDay,
|
||||
periodEnd: new Date(now.getTime() + 24 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!usage) {
|
||||
usage = await prisma.halalUsage.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
queriesUsed: 0,
|
||||
queriesLimit: limits.queriesPerDay,
|
||||
periodEnd: new Date(now.getTime() + 24 * 60 * 60 * 1000),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Check if allowed
|
||||
if (usage.queriesUsed >= usage.queriesLimit && limits.queriesPerDay !== Infinity) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
allowed: false,
|
||||
remaining: 0,
|
||||
queriesUsed: usage.queriesUsed,
|
||||
queriesLimit: usage.queriesLimit,
|
||||
error: "Daily query limit reached. Upgrade to Premium for unlimited queries.",
|
||||
},
|
||||
{ status: 429 }
|
||||
);
|
||||
}
|
||||
|
||||
// Increment usage
|
||||
const updated = await prisma.halalUsage.update({
|
||||
where: { userId: user.id },
|
||||
data: { queriesUsed: { increment: 1 } },
|
||||
});
|
||||
|
||||
const remaining = Math.max(0, updated.queriesLimit - updated.queriesUsed);
|
||||
|
||||
return NextResponse.json({
|
||||
allowed: true,
|
||||
remaining,
|
||||
queriesUsed: updated.queriesUsed,
|
||||
queriesLimit: updated.queriesLimit,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("POST /api/halal/usage error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Internal server error" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user