Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4989bf6de4 | |||
| 4267c34399 | |||
| 6d1697e672 | |||
| 45270f9b18 | |||
| a13687635b | |||
| c2600b6a68 | |||
| b45493f5bd | |||
| cb46430ce4 |
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
NEXT_PUBLIC_API_BASE_URL=http://battlbuilder-api:8080
|
NEXT_PUBLIC_API_BASE_URL=http://battlbuilder-api:8080
|
||||||
|
|
||||||
# Middleware to limited site to only root page
|
# Middleware to limited site to only root page
|
||||||
NEXT_PUBLIC_LAUNCH_ONLY_ROOT=true
|
LAUNCH_ONLY_ROOT=true
|
||||||
|
|
||||||
NEXT_PUBLIC_SHORTLINK_BASE_URL=https://battl.build
|
NEXT_PUBLIC_SHORTLINK_BASE_URL=https://battl.build
|
||||||
|
|
||||||
|
|||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="db-tree-configuration">
|
||||||
|
<option name="data" value="" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -417,9 +417,9 @@ export default function PrivacyPolicy() {
|
|||||||
<br />
|
<br />
|
||||||
Battl Builder, LLC.
|
Battl Builder, LLC.
|
||||||
<br />
|
<br />
|
||||||
[Your Address]
|
{/* [Your Address]
|
||||||
<br />
|
<br />
|
||||||
[City, State, ZIP]
|
[City, State, ZIP] */}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-4 text-sm">
|
<p className="mt-4 text-sm">
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Plus, Pencil, Trash2, X } from "lucide-react";
|
import { Plus, Pencil, Trash2, X } from "lucide-react";
|
||||||
import { useAuth } from "@/context/AuthContext";
|
|
||||||
import {
|
import {
|
||||||
createPlatform,
|
createPlatform,
|
||||||
deletePlatform,
|
deletePlatform,
|
||||||
@@ -15,7 +14,6 @@ import {
|
|||||||
} from "@/lib/api/platforms";
|
} from "@/lib/api/platforms";
|
||||||
|
|
||||||
export default function AdminPlatformsPage() {
|
export default function AdminPlatformsPage() {
|
||||||
const { getAuthHeaders } = useAuth();
|
|
||||||
|
|
||||||
const [platforms, setPlatforms] = useState<Platform[]>([]);
|
const [platforms, setPlatforms] = useState<Platform[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -36,7 +34,7 @@ export default function AdminPlatformsPage() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
const data = await fetchPlatforms(getAuthHeaders());
|
const data = await fetchPlatforms({});
|
||||||
setPlatforms(data);
|
setPlatforms(data);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@@ -77,7 +75,7 @@ export default function AdminPlatformsPage() {
|
|||||||
try {
|
try {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
await deletePlatform(getAuthHeaders(), p.id);
|
await deletePlatform({}, p.id);
|
||||||
await load();
|
await load();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@@ -103,7 +101,7 @@ export default function AdminPlatformsPage() {
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
if (modalMode === "create") {
|
if (modalMode === "create") {
|
||||||
await createPlatform(getAuthHeaders(), { ...form, key, label });
|
await createPlatform({}, { ...form, key, label });
|
||||||
} else if (selected) {
|
} else if (selected) {
|
||||||
const update: UpdatePlatformDto = {};
|
const update: UpdatePlatformDto = {};
|
||||||
if (key !== selected.key) update.key = key;
|
if (key !== selected.key) update.key = key;
|
||||||
@@ -111,7 +109,7 @@ export default function AdminPlatformsPage() {
|
|||||||
if ((form.isActive ?? true) !== selected.isActive)
|
if ((form.isActive ?? true) !== selected.isActive)
|
||||||
update.isActive = form.isActive;
|
update.isActive = form.isActive;
|
||||||
|
|
||||||
await updatePlatform(getAuthHeaders(), selected.id, update);
|
await updatePlatform({}, selected.id, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
setShowModal(false);
|
setShowModal(false);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { API_BASE, getToken, qs } from "./auth";
|
import { API_BASE, qs } from "./auth";
|
||||||
import type {
|
import type {
|
||||||
AdminProductRow,
|
AdminProductRow,
|
||||||
PageResponse,
|
PageResponse,
|
||||||
@@ -9,25 +9,14 @@ import type {
|
|||||||
|
|
||||||
import type { CaliberDto } from "./types";
|
import type { CaliberDto } from "./types";
|
||||||
|
|
||||||
|
export async function fetchAdminRoles(params: Record<string, any>) {
|
||||||
async function authedFetch(url: string, init?: RequestInit) {
|
const queryString = qs(params);
|
||||||
const token = getToken();
|
const res = await fetch(
|
||||||
const res = await fetch(url, {
|
`/api/admin/products/roles${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
...(init ?? {}),
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
...(init?.headers ?? {}),
|
|
||||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
||||||
} as any,
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchAdminRoles(params: Record<string, any>) {
|
|
||||||
const res = await authedFetch(
|
|
||||||
`${API_BASE}/api/v1/admin/products/roles?${qs(params)}`
|
|
||||||
);
|
);
|
||||||
if (!res.ok) throw new Error(`Failed to load roles (${res.status}): ${await res.text()}`);
|
if (!res.ok) throw new Error(`Failed to load roles (${res.status}): ${await res.text()}`);
|
||||||
return (await res.json()) as string[];
|
return (await res.json()) as string[];
|
||||||
@@ -35,8 +24,13 @@ export async function fetchAdminRoles(params: Record<string, any>) {
|
|||||||
|
|
||||||
// Facet/filtering can still use distinct values seen on products (optional)
|
// Facet/filtering can still use distinct values seen on products (optional)
|
||||||
export async function fetchProductCaliberFacet(params: Record<string, any>) {
|
export async function fetchProductCaliberFacet(params: Record<string, any>) {
|
||||||
const res = await authedFetch(
|
const queryString = qs(params);
|
||||||
`${API_BASE}/api/v1/admin/products/calibers?${qs(params)}`
|
const res = await fetch(
|
||||||
|
`/api/admin/products/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
}
|
||||||
);
|
);
|
||||||
if (!res.ok)
|
if (!res.ok)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -46,8 +40,13 @@ export async function fetchProductCaliberFacet(params: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchAdminProducts(params: Record<string, any>) {
|
export async function fetchAdminProducts(params: Record<string, any>) {
|
||||||
const res = await authedFetch(
|
const queryString = qs(params);
|
||||||
`${API_BASE}/api/v1/admin/products?${qs(params)}`
|
const res = await fetch(
|
||||||
|
`/api/admin/products${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
}
|
||||||
);
|
);
|
||||||
if (!res.ok) throw new Error(`Failed to load admin products (${res.status}): ${await res.text()}`);
|
if (!res.ok) throw new Error(`Failed to load admin products (${res.status}): ${await res.text()}`);
|
||||||
return (await res.json()) as PageResponse<AdminProductRow>;
|
return (await res.json()) as PageResponse<AdminProductRow>;
|
||||||
@@ -84,14 +83,11 @@ export async function bulkUpdate(
|
|||||||
classificationReason: "Admin bulk override";
|
classificationReason: "Admin bulk override";
|
||||||
}>
|
}>
|
||||||
) {
|
) {
|
||||||
const token = getToken();
|
const res = await fetch(`/api/admin/products/bulk`, {
|
||||||
|
|
||||||
const res = await fetch(`${API_BASE}/api/v1/admin/products/bulk`, {
|
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ productIds, ...set }),
|
body: JSON.stringify({ productIds, ...set }),
|
||||||
});
|
});
|
||||||
@@ -103,8 +99,13 @@ export async function bulkUpdate(
|
|||||||
|
|
||||||
|
|
||||||
export async function fetchAdminCalibers(params: Record<string, any>) {
|
export async function fetchAdminCalibers(params: Record<string, any>) {
|
||||||
const res = await authedFetch(
|
const queryString = qs(params);
|
||||||
`${API_BASE}/api/v1/admin/calibers?${qs(params)}`
|
const res = await fetch(
|
||||||
|
`/api/admin/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
credentials: "include",
|
||||||
|
cache: "no-store",
|
||||||
|
}
|
||||||
);
|
);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`Failed to load calibers (${res.status}): ${await res.text()}`);
|
throw new Error(`Failed to load calibers (${res.status}): ${await res.text()}`);
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ export default function AdminUsersPage() {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
async function fetchUsers() {
|
async function fetchUsers() {
|
||||||
|
console.log("in the users fetch");
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
const res = await fetch(`${API_BASE_URL}/admin/users`, {
|
const res = await fetch(`/api/admin/users`, {
|
||||||
headers: {
|
headers: {
|
||||||
...getAuthHeaders(),
|
...getAuthHeaders(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ const API_BASE_URL =
|
|||||||
|
|
||||||
// POST /api/admin/beta-invites?dryRun=true&limit=10&tokenMinutes=30
|
// POST /api/admin/beta-invites?dryRun=true&limit=10&tokenMinutes=30
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
const token = cookies().get("session_token")?.value;
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get("session_token")?.value;
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return NextResponse.json({ error: "Missing admin token" }, { status: 401 });
|
return NextResponse.json({ error: "Missing admin token" }, { status: 401 });
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const API_BASE_URL =
|
||||||
|
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||||
|
|
||||||
|
// POST /api/admin/beta-invites?dryRun=true&limit=10&tokenMinutes=30
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
const token = cookies().get("session_token")?.value;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: "Missing admin token" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const dryRun = url.searchParams.get("dryRun") ?? "true";
|
||||||
|
const limit = url.searchParams.get("limit") ?? "0";
|
||||||
|
const tokenMinutes = url.searchParams.get("tokenMinutes") ?? "30";
|
||||||
|
|
||||||
|
const upstream = `${API_BASE_URL}/api/v1/admin/beta/invites/send?dryRun=${dryRun}&limit=${limit}&tokenMinutes=${tokenMinutes}`;
|
||||||
|
|
||||||
|
const res = await fetch(upstream, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = await res.text();
|
||||||
|
return new NextResponse(text, {
|
||||||
|
status: res.status,
|
||||||
|
headers: { "Content-Type": res.headers.get("content-type") ?? "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -5,19 +5,21 @@ const API_BASE_URL =
|
|||||||
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get("session_token")?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get("session_token")?.value;
|
||||||
if (!token) throw new Error("Unauthorized");
|
if (!token) throw new Error("Unauthorized");
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(
|
||||||
_req: Request,
|
_req: Request,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/beta/requests/${params.id}/invite`,
|
`${API_BASE_URL}/api/v1/admin/beta/requests/${resolvedParams.id}/invite`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers,
|
headers,
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const API_BASE_URL =
|
||||||
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get("session_token")?.value;
|
||||||
|
if (!token) throw new Error("Unauthorized");
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
_req: Request,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/beta/requests/${params.id}/invite`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers,
|
||||||
|
cache: "no-store",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ const API_BASE_URL =
|
|||||||
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get("session_token")?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get("session_token")?.value;
|
||||||
if (!token) throw new Error("Unauthorized");
|
if (!token) throw new Error("Unauthorized");
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const API_BASE_URL =
|
||||||
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get("session_token")?.value;
|
||||||
|
if (!token) throw new Error("Unauthorized");
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(req: Request) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const search = url.searchParams.toString();
|
||||||
|
|
||||||
|
const upstream = `${API_BASE_URL}/api/v1/admin/beta/requests${
|
||||||
|
search ? `?${search}` : ""
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const res = await fetch(upstream, {
|
||||||
|
headers,
|
||||||
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/dashboard/overview`, {
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,20 +5,22 @@ const API_BASE_URL =
|
|||||||
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get("session_token")?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get("session_token")?.value;
|
||||||
if (!token) throw new Error("Unauthorized");
|
if (!token) throw new Error("Unauthorized");
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function PUT(
|
export async function PUT(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
|
|
||||||
const res = await fetch(`${API_BASE_URL}/api/email/${params.id}`, {
|
const res = await fetch(`${API_BASE_URL}/api/email/${resolvedParams.id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { ...headers, "Content-Type": "application/json" },
|
headers: { ...headers, "Content-Type": "application/json" },
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
@@ -39,12 +41,13 @@ export async function PUT(
|
|||||||
|
|
||||||
export async function DELETE(
|
export async function DELETE(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(`${API_BASE_URL}/api/email/${params.id}`, {
|
const res = await fetch(`${API_BASE_URL}/api/email/${resolvedParams.id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const API_BASE_URL =
|
||||||
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get("session_token")?.value;
|
||||||
|
if (!token) throw new Error("Unauthorized");
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/email/${params.id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: { ...headers, "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/email/${params.id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ const API_BASE_URL =
|
|||||||
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get("session_token")?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get("session_token")?.value;
|
||||||
if (!token) throw new Error("Unauthorized");
|
if (!token) throw new Error("Unauthorized");
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const API_BASE_URL =
|
||||||
|
process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get("session_token")?.value;
|
||||||
|
if (!token) throw new Error("Unauthorized");
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/email`, {
|
||||||
|
headers,
|
||||||
|
cache: "no-store",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/email`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { ...headers, "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string; action: string }> }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedParams = await params;
|
||||||
|
|
||||||
|
const { id, action } = resolvedParams;
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/${id}/${action}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string; action: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, action } = params;
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/${id}/${action}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/ai/run${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/ai/run${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { fixImageUrls } from '@/lib/server/image-utils';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/queue2${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
// Fix mixed content warnings: upgrade HTTP image URLs to HTTPS
|
||||||
|
return NextResponse.json(fixImageUrls(data));
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { fixImageUrls } from '@/lib/server/image-utils';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/queue2${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
// Fix mixed content warnings: upgrade HTTP image URLs to HTTPS
|
||||||
|
return NextResponse.json(fixImageUrls(data));
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/run${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/enrichment/run${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = res.headers.get('content-type');
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/import-status/by-merchant`, {
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/import-status/summary`, {
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/mapping/apply`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/mapping/options`, {
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/mapping/pending-buckets`, {
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/admin/mapping/raw-categories?${searchParams.toString()}`,
|
||||||
|
{
|
||||||
|
headers,
|
||||||
|
cache: 'no-store',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/admin/mapping/upsert`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,20 +4,22 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}/import`,
|
`${API_BASE_URL}/api/v1/admin/merchants/${resolvedParams.id}/import`,
|
||||||
{ method: 'POST', headers }
|
{ method: 'POST', headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}/import`,
|
||||||
|
{ method: 'POST', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,20 +4,22 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}/offer-sync`,
|
`${API_BASE_URL}/api/v1/admin/merchants/${resolvedParams.id}/offer-sync`,
|
||||||
{ method: 'POST', headers }
|
{ method: 'POST', headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}/offer-sync`,
|
||||||
|
{ method: 'POST', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,20 +4,22 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
`${API_BASE_URL}/api/v1/admin/merchants/${resolvedParams.id}`,
|
||||||
{ headers }
|
{ headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -36,14 +38,15 @@ export async function GET(
|
|||||||
|
|
||||||
export async function PUT(
|
export async function PUT(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
`${API_BASE_URL}/api/v1/admin/merchants/${resolvedParams.id}`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { ...headers, 'Content-Type': 'application/json' },
|
headers: { ...headers, 'Content-Type': 'application/json' },
|
||||||
@@ -66,13 +69,14 @@ export async function PUT(
|
|||||||
|
|
||||||
export async function DELETE(
|
export async function DELETE(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
`${API_BASE_URL}/api/v1/admin/merchants/${resolvedParams.id}`,
|
||||||
{ method: 'DELETE', headers }
|
{ method: 'DELETE', headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
||||||
|
{ headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { ...headers, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/merchants/${params.id}`,
|
||||||
|
{ method: 'DELETE', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/merchants`, {
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/merchants`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { ...headers, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${resolvedParams.id}`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${resolvedParams.id}`,
|
||||||
|
{ method: 'DELETE', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${params.id}`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${params.id}`,
|
||||||
|
{ method: 'DELETE', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/platforms`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/platforms`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function PATCH(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/bulk`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function PATCH(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/bulk`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/calibers${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/roles${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products/roles${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { fixImageUrls } from '@/lib/server/image-utils';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
return NextResponse.json(fixImageUrls(data));
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
import { fixImageUrls } from '@/lib/server/image-utils';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/products${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
return NextResponse.json(fixImageUrls(data));
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${resolvedParams.id}`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const resolvedParams = await params;
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${resolvedParams.id}`,
|
||||||
|
{ method: 'DELETE', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${params.id}`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
request: NextRequest,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/platforms/${params.id}`,
|
||||||
|
{ method: 'DELETE', headers }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ ok: true });
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/users${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const data = await res.json();
|
||||||
|
return NextResponse.json(data);
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/users`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
async function getAuthHeader() {
|
||||||
|
const token = cookies().get('session_token')?.value;
|
||||||
|
if (!token) throw new Error('Unauthorized');
|
||||||
|
return { Authorization: `Bearer ${token}` };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const searchParams = request.nextUrl.searchParams;
|
||||||
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
|
const res = await fetch(
|
||||||
|
`${API_BASE_URL}/api/v1/admin/users${queryString ? `?${queryString}` : ''}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const data = await res.json();
|
||||||
|
return NextResponse.json(data);
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const headers = await getAuthHeader();
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/v1/admin/users`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/auth/beta/signup`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,8 @@ export async function POST(request: NextRequest) {
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
// Set HTTP-only cookie instead of returning token
|
// Set HTTP-only cookie instead of returning token
|
||||||
cookies().set('session_token', data.token, {
|
const cookieStore = await cookies();
|
||||||
|
cookieStore.set('session_token', data.token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: process.env.NODE_ENV === 'production',
|
secure: process.env.NODE_ENV === 'production',
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server';
|
|||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
export async function POST() {
|
export async function POST() {
|
||||||
cookies().delete('session_token');
|
const cookieStore = await cookies();
|
||||||
|
cookieStore.delete('session_token');
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}/api/auth/magic/exchange`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: await res.text() },
|
||||||
|
{ status: res.status }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(await res.json());
|
||||||
|
} catch (err: any) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: err?.message || 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||||
@@ -16,7 +17,7 @@ export async function GET(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
cookies().delete('session_token');
|
cookieStore.delete('session_token');
|
||||||
return NextResponse.json({ error: 'Session expired' }, { status: 401 });
|
return NextResponse.json({ error: 'Session expired' }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
// Set HTTP-only cookie on successful registration
|
// Set HTTP-only cookie on successful registration
|
||||||
if (data.token) {
|
if (data.token) {
|
||||||
cookies().set('session_token', data.token, {
|
const cookieStore = await cookies();
|
||||||
|
cookieStore.set('session_token', data.token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: process.env.NODE_ENV === 'production',
|
secure: process.env.NODE_ENV === 'production',
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
|
|||||||
@@ -4,20 +4,22 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const { id } = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/gunbuilder/builds/${params.id}`,
|
`${API_BASE_URL}/api/v1/gunbuilder/builds/${id}`,
|
||||||
{ headers }
|
{ headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -36,14 +38,15 @@ export async function GET(
|
|||||||
|
|
||||||
export async function PUT(
|
export async function PUT(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const { id } = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/gunbuilder/builds/${params.id}`,
|
`${API_BASE_URL}/api/v1/gunbuilder/builds/${id}`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { ...headers, 'Content-Type': 'application/json' },
|
headers: { ...headers, 'Content-Type': 'application/json' },
|
||||||
@@ -66,13 +69,14 @@ export async function PUT(
|
|||||||
|
|
||||||
export async function DELETE(
|
export async function DELETE(
|
||||||
request: NextRequest,
|
request: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const { id } = await params;
|
||||||
const headers = await getAuthHeader();
|
const headers = await getAuthHeader();
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`${API_BASE_URL}/api/v1/gunbuilder/builds/${params.id}`,
|
`${API_BASE_URL}/api/v1/gunbuilder/builds/${id}`,
|
||||||
{ method: 'DELETE', headers }
|
{ method: 'DELETE', headers }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { cookies } from 'next/headers';
|
|||||||
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
const API_BASE_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_BASE_URL;
|
||||||
|
|
||||||
async function getAuthHeader() {
|
async function getAuthHeader() {
|
||||||
const token = cookies().get('session_token')?.value;
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get('session_token')?.value;
|
||||||
if (!token) throw new Error('Unauthorized');
|
if (!token) throw new Error('Unauthorized');
|
||||||
return { Authorization: `Bearer ${token}` };
|
return { Authorization: `Bearer ${token}` };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,13 @@ function timeAgo(iso?: string | null) {
|
|||||||
export default async function BuildBreakdownPage({
|
export default async function BuildBreakdownPage({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: { buildId: string };
|
params: Promise<{ buildId: string }>;
|
||||||
}) {
|
}) {
|
||||||
|
const { buildId } = await params;
|
||||||
|
|
||||||
// Public detail endpoint - use Next.js API route
|
// Public detail endpoint - use Next.js API route
|
||||||
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000';
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000';
|
||||||
const res = await fetch(`${baseUrl}/api/builds/public/${params.buildId}`, {
|
const res = await fetch(`${baseUrl}/api/builds/public/${buildId}`, {
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -359,7 +361,7 @@ export default async function BuildBreakdownPage({
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-zinc-500">Build ID</span>
|
<span className="text-zinc-500">Build ID</span>
|
||||||
<span className="text-zinc-300">
|
<span className="text-zinc-300">
|
||||||
{(build.uuid ?? params.buildId).slice(0, 8)}…
|
{(build.uuid ?? buildId).slice(0, 8)}…
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|||||||
@@ -2,20 +2,17 @@
|
|||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
import { AuthProvider } from "@/context/AuthContext";
|
|
||||||
import { BuilderNav } from "@/components/BuilderNav";
|
import { BuilderNav } from "@/components/BuilderNav";
|
||||||
import { TopNav } from "@/components/TopNav";
|
import { TopNav } from "@/components/TopNav";
|
||||||
|
|
||||||
export default function BuilderLayout({ children }: { children: ReactNode }) {
|
export default function BuilderLayout({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-neutral-950 text-zinc-50">
|
<div className="min-h-screen bg-neutral-950 text-zinc-50">
|
||||||
<AuthProvider>
|
|
||||||
<TopNav />
|
<TopNav />
|
||||||
<Suspense fallback={<div className="h-[52px]" />}>
|
<Suspense fallback={<div className="h-[52px]" />}>
|
||||||
<BuilderNav />
|
<BuilderNav />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<main className="min-h-screen">{children}</main>
|
<main className="min-h-screen">{children}</main>
|
||||||
</AuthProvider>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+1
-1
@@ -40,7 +40,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
|
|||||||
|
|
||||||
<body className="bg-dark text-zinc-950 dark:bg-black dark:text-zinc-50">
|
<body className="bg-dark text-zinc-950 dark:bg-black dark:text-zinc-50">
|
||||||
{" "}
|
{" "}
|
||||||
<Script src="https://umami.ash.gofwd.group/script.js" data-website-id="ad310b4a-aa5e-471a-938b-47a6c0f4108d"
|
<Script src="https://umami.ash.gofwd.group/script.js" data-website-id="15c6b9ad-4119-4981-829c-26db69c07a15"
|
||||||
strategy="lazyOnload"
|
strategy="lazyOnload"
|
||||||
/>
|
/>
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
|
|||||||
+2
-1
@@ -13,7 +13,7 @@ const API_BASE_URL =
|
|||||||
function LoginPageContent() {
|
function LoginPageContent() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const { login, loading } = useAuth();
|
const { login, refreshUser, loading } = useAuth();
|
||||||
|
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
@@ -36,6 +36,7 @@ function LoginPageContent() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await login({ email, password });
|
await login({ email, password });
|
||||||
|
await refreshUser();
|
||||||
router.push(next);
|
router.push(next);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setError(err?.message ?? "Failed to log in");
|
setError(err?.message ?? "Failed to log in");
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { useMemo } from "react";
|
|||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
|
|
||||||
import "react-quill/dist/quill.snow.css";
|
// import "react-quill/dist/quill.snow.css";
|
||||||
|
|
||||||
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
|
const ReactQuill = dynamic(() => import("react-quill-new"), { ssr: false });
|
||||||
|
|
||||||
type RichTextEditorProps = {
|
type RichTextEditorProps = {
|
||||||
value: string;
|
value: string;
|
||||||
|
|||||||
+13
-16
@@ -14,9 +14,6 @@ export type CreatePlatformDto = {
|
|||||||
|
|
||||||
export type UpdatePlatformDto = Partial<CreatePlatformDto>;
|
export type UpdatePlatformDto = Partial<CreatePlatformDto>;
|
||||||
|
|
||||||
const API_BASE =
|
|
||||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
|
||||||
|
|
||||||
function normalizePlatform(raw: any): Platform {
|
function normalizePlatform(raw: any): Platform {
|
||||||
const id = Number(raw?.id);
|
const id = Number(raw?.id);
|
||||||
const key = String(raw?.key ?? "").trim();
|
const key = String(raw?.key ?? "").trim();
|
||||||
@@ -33,9 +30,9 @@ function normalizePlatform(raw: any): Platform {
|
|||||||
return { id, key, label, isActive };
|
return { id, key, label, isActive };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPlatforms(tokenHeaders: HeadersInit): Promise<Platform[]> {
|
export async function fetchPlatforms(_tokenHeaders: HeadersInit): Promise<Platform[]> {
|
||||||
const res = await fetch(`${API_BASE}/api/platforms`, {
|
const res = await fetch('/api/admin/platforms', {
|
||||||
headers: { ...tokenHeaders },
|
credentials: 'include',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -48,15 +45,15 @@ export async function fetchPlatforms(tokenHeaders: HeadersInit): Promise<Platfor
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function createPlatform(
|
export async function createPlatform(
|
||||||
tokenHeaders: HeadersInit,
|
_tokenHeaders: HeadersInit,
|
||||||
dto: CreatePlatformDto
|
dto: CreatePlatformDto
|
||||||
): Promise<Platform> {
|
): Promise<Platform> {
|
||||||
const res = await fetch(`${API_BASE}/api/platforms`, {
|
const res = await fetch('/api/admin/platforms', {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
...tokenHeaders,
|
|
||||||
},
|
},
|
||||||
|
credentials: 'include',
|
||||||
body: JSON.stringify(dto),
|
body: JSON.stringify(dto),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -69,17 +66,17 @@ export async function createPlatform(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePlatform(
|
export async function updatePlatform(
|
||||||
tokenHeaders: HeadersInit,
|
_tokenHeaders: HeadersInit,
|
||||||
id: number,
|
id: number,
|
||||||
dto: UpdatePlatformDto
|
dto: UpdatePlatformDto
|
||||||
): Promise<Platform> {
|
): Promise<Platform> {
|
||||||
const res = await fetch(`${API_BASE}/api/platforms/${id}`, {
|
const res = await fetch(`/api/admin/platforms/${id}`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
...tokenHeaders,
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ isActive: dto.isActive }),
|
credentials: 'include',
|
||||||
|
body: JSON.stringify(dto),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -90,10 +87,10 @@ export async function updatePlatform(
|
|||||||
return normalizePlatform(await res.json());
|
return normalizePlatform(await res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deletePlatform(tokenHeaders: HeadersInit, id: number): Promise<void> {
|
export async function deletePlatform(_tokenHeaders: HeadersInit, id: number): Promise<void> {
|
||||||
const res = await fetch(`${API_BASE}/api/platforms/${id}`, {
|
const res = await fetch(`/api/admin/platforms/${id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: { ...tokenHeaders },
|
credentials: 'include',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Fix mixed content warnings by upgrading HTTP image URLs to HTTPS
|
||||||
|
* This handles image URLs stored in the database as http:// which cause
|
||||||
|
* browser warnings when loaded from HTTPS pages.
|
||||||
|
*/
|
||||||
|
export function fixImageUrl(url: string | null | undefined): string | null | undefined {
|
||||||
|
if (!url || typeof url !== 'string') return url;
|
||||||
|
return url.replace(/^http:\/\//i, 'https://');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively fix all image URL fields in an object
|
||||||
|
* Common fields: imageUrl, mainImageUrl, coverImageUrl, thumbnailUrl, etc.
|
||||||
|
*/
|
||||||
|
export function fixImageUrls(data: any): any {
|
||||||
|
if (!data) return data;
|
||||||
|
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
return data.map(item => fixImageUrls(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
const fixed: any = {};
|
||||||
|
for (const [key, value] of Object.entries(data)) {
|
||||||
|
// Fix any field that looks like an image URL
|
||||||
|
if (
|
||||||
|
(key.toLowerCase().includes('image') ||
|
||||||
|
key.toLowerCase().includes('photo') ||
|
||||||
|
key.toLowerCase().includes('picture')) &&
|
||||||
|
typeof value === 'string'
|
||||||
|
) {
|
||||||
|
fixed[key] = fixImageUrl(value);
|
||||||
|
} else if (typeof value === 'object') {
|
||||||
|
fixed[key] = fixImageUrls(value);
|
||||||
|
} else {
|
||||||
|
fixed[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
+64
-14
@@ -2,42 +2,92 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import type { NextRequest } from "next/server";
|
import type { NextRequest } from "next/server";
|
||||||
|
|
||||||
|
function redirectToLogin(req: NextRequest) {
|
||||||
|
const url = req.nextUrl.clone();
|
||||||
|
url.pathname = "/login";
|
||||||
|
url.searchParams.set("next", req.nextUrl.pathname);
|
||||||
|
return NextResponse.redirect(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPublicPath(pathname: string) {
|
||||||
|
// Public pages
|
||||||
|
if (pathname === "/") return true;
|
||||||
|
if (pathname === "/login") return true;
|
||||||
|
if (pathname === "/tos") return true;
|
||||||
|
if (pathname === "/privacy") return true;
|
||||||
|
if (pathname === "/beta") return true;
|
||||||
|
if (pathname.startsWith("/beta/")) return true;
|
||||||
|
if (pathname.startsWith("/auth")) return true;
|
||||||
|
if (pathname.startsWith("/api/auth")) return true;
|
||||||
|
|
||||||
|
// Static / framework assets
|
||||||
|
if (pathname.startsWith("/_next")) return true;
|
||||||
|
if (pathname === "/favicon.ico") return true;
|
||||||
|
if (pathname === "/robots.txt") return true;
|
||||||
|
if (pathname === "/sitemap.xml") return true;
|
||||||
|
|
||||||
|
// Health / misc APIs you may want public
|
||||||
|
if (pathname === "/api/health") return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isProtectedLaunchPath(pathname: string) {
|
||||||
|
return (
|
||||||
|
pathname === "/builder" ||
|
||||||
|
pathname.startsWith("/builder/") ||
|
||||||
|
pathname === "/builds" ||
|
||||||
|
pathname.startsWith("/builds/") ||
|
||||||
|
pathname === "/vault" ||
|
||||||
|
pathname.startsWith("/vault/")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function middleware(req: NextRequest) {
|
export function middleware(req: NextRequest) {
|
||||||
const { pathname } = req.nextUrl;
|
const { pathname } = req.nextUrl;
|
||||||
const token = req.cookies.get("session_token")?.value;
|
const token = req.cookies.get("session_token")?.value;
|
||||||
|
const isLoggedIn = Boolean(token);
|
||||||
|
console.log("is logged in: " + isLoggedIn);
|
||||||
|
console.log("MW:", req.nextUrl.pathname)
|
||||||
|
|
||||||
// Protect admin API routes
|
// IMPORTANT: Use a server-only env var for middleware behavior.
|
||||||
|
// Set LAUNCH_ONLY_ROOT=true in your Docker compose.
|
||||||
|
const launchOnlyRoot = process.env.LAUNCH_ONLY_ROOT === "true";
|
||||||
|
|
||||||
|
// In "launch only" mode, anonymous users are blocked only from gated app areas.
|
||||||
|
if (launchOnlyRoot && !isLoggedIn && isProtectedLaunchPath(pathname)) {
|
||||||
|
return redirectToLogin(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Protected API routes ---
|
||||||
if (pathname.startsWith("/api/admin")) {
|
if (pathname.startsWith("/api/admin")) {
|
||||||
if (!token) {
|
if (!isLoggedIn) {
|
||||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect builds API routes
|
|
||||||
if (pathname.startsWith("/api/builds")) {
|
if (pathname.startsWith("/api/builds")) {
|
||||||
if (!token) {
|
if (!isLoggedIn) {
|
||||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Protect admin pages
|
// --- Protected pages ---
|
||||||
if (pathname.startsWith("/admin")) {
|
if (pathname.startsWith("/admin")) {
|
||||||
if (!token) {
|
if (!isLoggedIn) return redirectToLogin(req);
|
||||||
const url = req.nextUrl.clone();
|
|
||||||
url.pathname = "/login";
|
|
||||||
url.searchParams.set("next", pathname);
|
|
||||||
return NextResponse.redirect(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protect the builder UI
|
||||||
|
if (pathname === "/builder" || pathname.startsWith("/builder/")) {
|
||||||
|
if (!isLoggedIn) return redirectToLogin(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
|
// Run middleware for all application routes, but avoid static assets.
|
||||||
matcher: [
|
matcher: [
|
||||||
"/api/admin/:path*",
|
"/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml).*)",
|
||||||
"/api/builds",
|
|
||||||
"/api/builds/:path+",
|
|
||||||
"/admin/:path*",
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
Vendored
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
/// <reference path="./.next/types/routes.d.ts" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
experimental: {
|
|
||||||
appDir: true,
|
|
||||||
},
|
|
||||||
typescript: {
|
typescript: {
|
||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+791
-371
File diff suppressed because it is too large
Load Diff
+22
-7
@@ -1,7 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "gunbuilder-prototype",
|
"name": "battl.builders",
|
||||||
"version": "0.1.0",
|
"version": "1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"author": {
|
||||||
|
"name": "Forward Group, LLC",
|
||||||
|
"email": "info@goforward.group",
|
||||||
|
"url": "https://goforward.group"
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Sean Strawsburg",
|
||||||
|
"email": "sean@goforward.group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Don Strawsburg",
|
||||||
|
"email": "don@goforward.group"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
@@ -13,12 +29,11 @@
|
|||||||
"@heroicons/react": "^2.2.0",
|
"@heroicons/react": "^2.2.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.555.0",
|
"lucide-react": "^0.555.0",
|
||||||
"next": "14.2.3",
|
"next": "15.5.11",
|
||||||
"quill": "^2.0.3",
|
|
||||||
"quill-image-resize-module": "^3.0.0",
|
"quill-image-resize-module": "^3.0.0",
|
||||||
"react": "18.3.1",
|
"react": "^19.2.4",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "^19.2.4",
|
||||||
"react-quill": "^2.0.0"
|
"react-quill-new": "^3.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.7",
|
||||||
|
|||||||
Reference in New Issue
Block a user