the cleanup
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
|
||||
NEXT_PUBLIC_API_BASE_URL=http://localhost:8080
|
||||
NEXT_PUBLIC_API_BASE_URL=http://battlbuilder-api:8080
|
||||
|
||||
# Middleware to limited site to only root page
|
||||
NEXT_PUBLIC_LAUNCH_ONLY_ROOT=false
|
||||
|
||||
@@ -75,7 +75,7 @@ const isUuid = (v: string) =>
|
||||
);
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const STORAGE_KEY = "gunbuilder-build-state";
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ type GunbuilderProductFromApi = {
|
||||
type BuildState = Partial<Record<BuilderSlotKey, string>>;
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const STORAGE_KEY = "gunbuilder-build-state";
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ type BuildDto = {
|
||||
};
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
// UUID validator (defensive)
|
||||
const isUuid = (v: string) =>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Button, Field, Input } from "@/components/ui/form";
|
||||
import { useAuth } from "@/context/AuthContext";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type AdminBetaRequestDto = {
|
||||
id: number;
|
||||
|
||||
@@ -38,7 +38,7 @@ const DEFAULT_PLATFORM = "AR-15";
|
||||
|
||||
// Update these if your admin mapping UI lives elsewhere.
|
||||
const MAPPING_UI_PATH = "/admin/mapping"; // <- change if needed
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const url = `${API_BASE}/admin/classification/reconcile?dryRun=true&limit=500&platform=AR-15&merchantId=4`;
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function AdminClassificationReconcilePage() {
|
||||
if (merchantId?.trim()) params.set("merchantId", merchantId.trim());
|
||||
if (includeLocked) params.set("includeLocked", "true");
|
||||
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
const url = `${API_BASE}/admin/classification/reconcile?${params.toString()}`;
|
||||
|
||||
const res = await fetch(url, {
|
||||
|
||||
@@ -29,7 +29,7 @@ type QueueItem = {
|
||||
};
|
||||
|
||||
const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function getAuthHeaders(): HeadersInit {
|
||||
if (typeof window === "undefined") return {};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const formatCount = (value: number | null | undefined) =>
|
||||
(typeof value === "number" ? value : 0).toLocaleString();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { useSearchParams, useRouter } from "next/navigation";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
/**
|
||||
* Tabs:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type MerchantAdminDto = {
|
||||
id: number;
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type AdminOverview = {
|
||||
totalProducts: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export function getCookie(name: string): string | null {
|
||||
if (typeof document === "undefined") return null;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Loader2 } from "lucide-react";
|
||||
import type { AdminUser, UserRole } from "@/types/user";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export default function AdminUsersPage() {
|
||||
const { getAuthHeaders } = useAuth();
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NextResponse } from "next/server";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
// POST /api/admin/beta-invites?dryRun=true&limit=10&tokenMinutes=30
|
||||
export async function POST(req: Request) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const TOS_VERSION = "2025-12-27";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const body = await req.text().catch(() => "");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function passthroughHeaders(req: Request) {
|
||||
const h = new Headers();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
const url = new URL(req.url);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { springProxy } from "@/lib/springProxy";
|
||||
import type {
|
||||
MerchantAdminResponse,
|
||||
MerchantAdminUpdateRequest,
|
||||
} from "@/types/merchant-admin";
|
||||
|
||||
export async function PUT(
|
||||
req: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
const body = (await req.json()) as MerchantAdminUpdateRequest;
|
||||
|
||||
return springProxy<MerchantAdminResponse, MerchantAdminUpdateRequest>(
|
||||
req,
|
||||
`/api/v1/admin/merchants/${params.id}`,
|
||||
{ method: "PUT", body }
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { springProxy } from "@/lib/springProxy";
|
||||
import type {
|
||||
MerchantAdminCreateRequest,
|
||||
MerchantAdminResponse,
|
||||
} from "@/types/merchant-admin";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
return springProxy<MerchantAdminResponse[]>(req, "/api/v1/admin/merchants");
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const body = (await req.json()) as MerchantAdminCreateRequest;
|
||||
|
||||
return springProxy<MerchantAdminResponse, MerchantAdminCreateRequest>(
|
||||
req,
|
||||
"/api/v1/admin/merchants",
|
||||
{ method: "POST", body }
|
||||
);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useAuth } from "@/context/AuthContext";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function BetaConfirmPageContent() {
|
||||
const params = useSearchParams();
|
||||
|
||||
@@ -27,7 +27,7 @@ function BetaMagicPageContent() {
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080"}/api/auth/magic/exchange`, {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://battlbuilder-api:8080"}/api/auth/magic/exchange`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ token }),
|
||||
|
||||
@@ -3,7 +3,7 @@ import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function formatMoney(n?: number | null) {
|
||||
if (n == null) return "—";
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ type BuildFeedCardDto = {
|
||||
};
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
// --- UI Filter Sets (keep; we’ll generate options from data too) ---
|
||||
const CLASS_FILTERS: (BuildClass | "all")[] = ["all", "Rifle", "Pistol", "NFA"];
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { useAuth } from "@/context/AuthContext";
|
||||
import { Button, Field, Input } from "@/components/ui/form";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function LoginPageContent() {
|
||||
const router = useRouter();
|
||||
|
||||
@@ -59,7 +59,7 @@ type GunbuilderProductFromApi = {
|
||||
};
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
const PAGE_SIZE = 24;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import Link from "next/link";
|
||||
import PlatformSwitcher from "./PlatformSwitcher";
|
||||
import Image from "next/image";
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type ProductListDto = {
|
||||
id: string; // your API returns strings sometimes; keep it flexible
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import PlatformSwitcher from "./PlatformSwitcher";
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type ProductDetailDto = {
|
||||
id: string;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "react";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type AuthUser = {
|
||||
uuid: string;
|
||||
|
||||
+3
-1
@@ -8,11 +8,13 @@ WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_PUBLIC_API_BASE_URL=http://battlbuilder-api:8080
|
||||
RUN npm run build
|
||||
|
||||
FROM node:20-alpine AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/.next ./.next
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { useMemo } from "react";
|
||||
import { useAuth } from "@/context/AuthContext";
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
type JsonValue = any;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// lib/api/adminCategoryMappings.ts
|
||||
|
||||
const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export interface AdminCategory {
|
||||
id: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_URL ?? "";
|
||||
|
||||
export interface AdminMerchantCategoryMapping {
|
||||
id: number;
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface UpdateEmailRequestDto {
|
||||
status?: string;
|
||||
}
|
||||
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8080';
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL || '';
|
||||
|
||||
export async function fetchEmailRequests(token: string): Promise<EmailRequest[]> {
|
||||
const response = await fetch(`${API_BASE}/api/email`, {
|
||||
|
||||
@@ -15,7 +15,7 @@ export type CreatePlatformDto = {
|
||||
export type UpdatePlatformDto = Partial<CreatePlatformDto>;
|
||||
|
||||
const API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
function normalizePlatform(raw: any): Platform {
|
||||
const id = Number(raw?.id);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// lib/auth-client.ts
|
||||
|
||||
const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export type AuthUser = {
|
||||
id: number;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// app/lib/catalog.ts
|
||||
export const API_BASE_URL =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export type ProductListItem = {
|
||||
id: string;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// Central place for app-wide constant values.
|
||||
|
||||
// Branding / product
|
||||
export const APP_NAME = "Ballistic Builder";
|
||||
export const APP_NAME = "Battl Builder";
|
||||
export const APP_TAGLINE = "A smarter way to explore and assemble builds.";
|
||||
|
||||
// URLs
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const SPRING_BASE =
|
||||
process.env.SPRING_BASE_URL ?? "http://battlbuilder-api:8080";
|
||||
|
||||
function forwardHeaders(req: Request) {
|
||||
const headers = new Headers();
|
||||
const auth = req.headers.get("authorization");
|
||||
const cookie = req.headers.get("cookie");
|
||||
|
||||
if (auth) headers.set("authorization", auth);
|
||||
if (cookie) headers.set("cookie", cookie);
|
||||
|
||||
headers.set("accept", "application/json");
|
||||
return headers;
|
||||
}
|
||||
|
||||
type SpringProxyOptions<TBody> = {
|
||||
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
||||
body?: TBody;
|
||||
cache?: RequestCache;
|
||||
};
|
||||
|
||||
export async function springProxy<TResponse, TBody = never>(
|
||||
req: Request,
|
||||
path: string,
|
||||
options?: SpringProxyOptions<TBody>
|
||||
) {
|
||||
const url = `${SPRING_BASE}${path}`;
|
||||
const headers = forwardHeaders(req);
|
||||
|
||||
const init: RequestInit = {
|
||||
method: options?.method ?? "GET",
|
||||
headers,
|
||||
cache: options?.cache ?? "no-store",
|
||||
};
|
||||
|
||||
if (options && "body" in options && options.body !== undefined) {
|
||||
headers.set("content-type", "application/json");
|
||||
init.body = JSON.stringify(options.body);
|
||||
}
|
||||
|
||||
const res = await fetch(url, init);
|
||||
|
||||
// If Spring returns 204 No Content, don't try to parse JSON
|
||||
if (res.status === 204) {
|
||||
return new NextResponse(null, { status: 204 });
|
||||
}
|
||||
|
||||
const contentType = res.headers.get("content-type") ?? "";
|
||||
let payload: unknown;
|
||||
|
||||
if (contentType.includes("application/json")) {
|
||||
payload = await res.json().catch(() => null);
|
||||
} else {
|
||||
payload = await res.text().catch(() => null);
|
||||
}
|
||||
|
||||
// If Spring returned JSON, we respond JSON; otherwise text
|
||||
if (typeof payload === "string") {
|
||||
return new NextResponse(payload, {
|
||||
status: res.status,
|
||||
headers: { "content-type": contentType || "text/plain" },
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json(payload as TResponse, { status: res.status });
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { useAuth } from "@/context/AuthContext";
|
||||
import { useCallback, useMemo } from "react";
|
||||
|
||||
const DEFAULT_API_BASE =
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
|
||||
|
||||
export function useApi(baseUrl: string = DEFAULT_API_BASE) {
|
||||
const { token } = useAuth();
|
||||
|
||||
+3
-3
@@ -10,14 +10,14 @@ const nextConfig = {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
|
||||
async rewrites() {
|
||||
/* async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/api/:path*",
|
||||
destination: "http://localhost:8080/api/:path*",
|
||||
destination: "http://battlbuilder-api:8080/api/:path*",
|
||||
},
|
||||
];
|
||||
},
|
||||
},*/
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
+1
-1
@@ -10,7 +10,7 @@ TAG=$(git rev-parse --short HEAD)
|
||||
FULL_IMAGE="$REGISTRY/$OWNER/$IMAGE"
|
||||
|
||||
echo "Building $FULL_IMAGE:$TAG"
|
||||
docker build -f frontend/Dockerfile -t $FULL_IMAGE:$TAG .
|
||||
docker build -f frontend/Dockerfile --no-cache -t $FULL_IMAGE:$TAG .
|
||||
|
||||
echo "Tagging latest"
|
||||
docker tag $FULL_IMAGE:$TAG $FULL_IMAGE:latest
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export type MerchantAdminResponse = {
|
||||
id: number;
|
||||
name: string;
|
||||
avantlinkMid: string | null;
|
||||
feedUrl: string | null;
|
||||
offerFeedUrl: string | null;
|
||||
isActive: boolean;
|
||||
lastFullImportAt: string | null;
|
||||
lastOfferSyncAt: string | null;
|
||||
};
|
||||
|
||||
export type MerchantAdminCreateRequest = {
|
||||
name: string;
|
||||
avantlinkMid?: string | null;
|
||||
feedUrl?: string | null;
|
||||
offerFeedUrl?: string | null;
|
||||
isActive?: boolean | null;
|
||||
};
|
||||
|
||||
export type MerchantAdminUpdateRequest = {
|
||||
feedUrl?: string | null;
|
||||
offerFeedUrl?: string | null;
|
||||
isActive?: boolean | null;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export type MerchantAdminDto = {
|
||||
id?: number; // Optional for create payloads
|
||||
name: string;
|
||||
avantlinkMid?: string | null;
|
||||
feedUrl?: string | null;
|
||||
offerFeedUrl?: string | null;
|
||||
isActive?: boolean | null;
|
||||
lastFullImportAt?: string | null; // Spring Instant/LocalDateTime serialized as string
|
||||
lastOfferSyncAt?: string | null;
|
||||
};
|
||||
Reference in New Issue
Block a user