87 lines
2.6 KiB
TypeScript
87 lines
2.6 KiB
TypeScript
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
type ActionType = 'GENERATE_MASTER' | 'GENERATE_VARIANT' | 'GENERATE_MOCKUP' | 'GENERATE_PROMPT';
|
|
|
|
const DEFAULT_CREDITS: Record<ActionType, number> = {
|
|
GENERATE_PROMPT: 1,
|
|
GENERATE_MASTER: 10,
|
|
GENERATE_VARIANT: 5,
|
|
GENERATE_MOCKUP: 2
|
|
};
|
|
|
|
// Global pricing cache to avoid fetching every button render
|
|
let pricingCache: any = null;
|
|
|
|
interface CreditButtonProps {
|
|
action?: ActionType;
|
|
cost?: number; // Direct cost override (for backward compatibility)
|
|
onClick: () => void;
|
|
disabled?: boolean;
|
|
className?: string; // Additional classes for styling
|
|
children?: React.ReactNode; // Custom text if needed (e.g. "Generate")
|
|
hideCost?: boolean;
|
|
}
|
|
|
|
export const CreditButton: React.FC<CreditButtonProps> = ({
|
|
action,
|
|
cost: directCost,
|
|
onClick,
|
|
disabled = false,
|
|
className = "",
|
|
children,
|
|
hideCost = false
|
|
}) => {
|
|
const [price, setPrice] = useState<number>(directCost ?? (action ? DEFAULT_CREDITS[action] : 0));
|
|
|
|
useEffect(() => {
|
|
// If directCost is provided, use it directly
|
|
if (directCost !== undefined) {
|
|
setPrice(directCost);
|
|
return;
|
|
}
|
|
|
|
// If no action, skip fetching
|
|
if (!action) return;
|
|
|
|
const fetchPrices = async () => {
|
|
// Use cache if exists
|
|
if (pricingCache && pricingCache[`PRICE_${action}`]) {
|
|
setPrice(Number(pricingCache[`PRICE_${action}`]));
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const res = await fetch('http://localhost:3001/api/config/prices');
|
|
if (res.ok) {
|
|
const data = await res.json();
|
|
pricingCache = data;
|
|
const dynamicPrice = data[`PRICE_${action}`];
|
|
if (dynamicPrice) {
|
|
setPrice(Number(dynamicPrice));
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn("Failed to fetch dynamic prices", err);
|
|
}
|
|
};
|
|
|
|
fetchPrices();
|
|
}, [action, directCost]);
|
|
|
|
return (
|
|
<button
|
|
onClick={onClick}
|
|
disabled={disabled}
|
|
className={`flex items-center justify-center gap-2 group ${className}`}
|
|
>
|
|
{children || <span>Generate</span>}
|
|
{!hideCost && (
|
|
<span className="bg-white/20 px-2 py-0.5 rounded text-xs font-mono font-bold opacity-90 group-hover:bg-white/30 transition-colors">
|
|
{price} 🪙
|
|
</span>
|
|
)}
|
|
</button>
|
|
);
|
|
};
|