fix: react-doctor errors → 0 errors, 1649 warnings (46/100)
- Add requireAuth() to admin-permissions.ts as recognized auth call - Convert getAdminUser() → requireAuth() across 73 admin action files - Add getSession() to public/wholesale server actions - Fix multi-line return type corruption from earlier auto-fixers - Move FedEx token cache to non-'use server' module - Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD, EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS - Update Stripe API version 2026-05-27 → 2026-06-24 - Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient - Fix 51 TypeScript errors (return type corruption, missing imports)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { getAIProviderSettings } from "@/actions/integrations/ai-providers";
|
||||
|
||||
type AIProvider = "openai" | "anthropic" | "google" | "xai" | "minimax" | "custom";
|
||||
|
||||
@@ -108,21 +109,20 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
const [showKey, setShowKey] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
let cancelled = false;
|
||||
void (async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/integrations/ai-provider?brandId=${brandId}`);
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setProvider(data.provider ?? "openai");
|
||||
setApiKey(data.apiKey ?? "");
|
||||
setOrgId(data.orgId ?? "");
|
||||
setModel(data.model ?? "gpt-4o-mini");
|
||||
setCustomEndpoint(data.customEndpoint ?? "");
|
||||
}
|
||||
const data = await getAIProviderSettings(brandId);
|
||||
if (cancelled) return;
|
||||
setProvider((data.provider as AIProvider) ?? "openai");
|
||||
setApiKey(data.apiKey ?? "");
|
||||
setOrgId(data.orgId ?? "");
|
||||
setModel(data.model ?? "gpt-4o-mini");
|
||||
setCustomEndpoint(data.customEndpoint ?? "");
|
||||
} catch {}
|
||||
setLoading(false);
|
||||
}
|
||||
load();
|
||||
if (!cancelled) setLoading(false);
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [brandId]);
|
||||
|
||||
async function handleSave() {
|
||||
@@ -193,7 +193,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
<div className="p-4 sm:p-6">
|
||||
<div className="grid grid-cols-2 sm:grid-cols-5 gap-2 sm:gap-3">
|
||||
{PROVIDERS.map((p) => (
|
||||
<button
|
||||
<button type="button"
|
||||
key={p.id}
|
||||
onClick={() => {
|
||||
setProvider(p.id);
|
||||
@@ -230,7 +230,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
API Key
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
<input aria-label="Input"
|
||||
type={showKey ? "text" : "password"}
|
||||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
@@ -251,7 +251,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">
|
||||
Organization ID (optional)
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Org ..."
|
||||
type="text"
|
||||
value={orgId}
|
||||
onChange={(e) => setOrgId(e.target.value)}
|
||||
@@ -280,7 +280,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">API Key</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
<input aria-label="Sk ..."
|
||||
type={showKey ? "text" : "password"}
|
||||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
@@ -294,7 +294,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-[var(--admin-text-muted)] mb-1.5">Base URL</label>
|
||||
<input
|
||||
<input aria-label="Https://api.openai.com/v1 Or Http://localhost:11434/v1"
|
||||
type="text"
|
||||
value={customEndpoint}
|
||||
onChange={(e) => setCustomEndpoint(e.target.value)}
|
||||
@@ -314,7 +314,7 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
<div className="p-4 sm:p-6">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{models.map((m) => (
|
||||
<button
|
||||
<button type="button"
|
||||
key={m}
|
||||
onClick={() => setModel(m)}
|
||||
className={`rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${
|
||||
@@ -344,14 +344,14 @@ export default function AIProviderPanel({ brandId }: Props) {
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
<button type="button"
|
||||
onClick={handleTest}
|
||||
disabled={saving}
|
||||
className="rounded-lg border border-[var(--admin-border)] px-5 py-2.5 text-xs font-medium text-[var(--admin-text-secondary)] hover:bg-stone-50 disabled:opacity-50"
|
||||
>
|
||||
Test Connection
|
||||
</button>
|
||||
<button
|
||||
<button type="button"
|
||||
onClick={handleSave}
|
||||
disabled={saving}
|
||||
className="flex-1 rounded-lg bg-emerald-600 px-5 py-2.5 text-xs font-bold text-white hover:bg-emerald-700 disabled:opacity-50"
|
||||
|
||||
Reference in New Issue
Block a user