styling fixes
This commit is contained in:
@@ -51,6 +51,8 @@ export default tseslint.config(
|
||||
'igny8-design-system/no-raw-textarea': 'warn',
|
||||
// Button icon positioning - icons as children cause vertical stacking, use startIcon/endIcon props
|
||||
'igny8-design-system/no-icon-children': 'warn',
|
||||
// Disallow Tailwind default color utilities (blue/pink/emerald/info, etc.)
|
||||
'igny8-design-system/no-tailwind-default-colors': 'warn',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* 3. no-raw-select - Use <Select> from components/form/Select
|
||||
* 4. no-raw-textarea - Use <TextArea> from components/form/input/TextArea
|
||||
* 5. no-icon-children - Use startIcon/endIcon props instead of icon children in Button
|
||||
* 6. no-tailwind-default-colors - Disallow Tailwind default color utilities
|
||||
*
|
||||
* USAGE: Import in eslint.config.js and enable rules
|
||||
*/
|
||||
@@ -367,5 +368,101 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Disallow Tailwind default color utilities (blue-*, red-*, green-*, etc.)
|
||||
* Only allow brand-*, gray-*, success-*, warning-*, error-*, purple-*
|
||||
*/
|
||||
'no-tailwind-default-colors': {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Disallow Tailwind default color utilities. Use brand/gray/success/warning/error/purple palettes only.',
|
||||
recommended: true,
|
||||
},
|
||||
messages: {
|
||||
noDefaultColors: 'Disallowed Tailwind color utility "{{className}}". Use brand/gray/success/warning/error/purple instead.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
create(context) {
|
||||
const allowedPalettes = new Set(['brand', 'gray', 'success', 'warning', 'error', 'purple']);
|
||||
const disallowedPalettes = new Set([
|
||||
'blue', 'red', 'green', 'emerald', 'amber', 'indigo', 'violet', 'info',
|
||||
'fuchsia', 'pink', 'rose', 'sky', 'teal', 'cyan', 'lime', 'yellow',
|
||||
'orange', 'slate', 'zinc', 'neutral', 'stone'
|
||||
]);
|
||||
|
||||
const allowedSpecial = new Set([
|
||||
'text-white', 'bg-white', 'border-white', 'fill-white', 'stroke-white',
|
||||
'text-black', 'bg-black', 'border-black', 'fill-black', 'stroke-black',
|
||||
'text-transparent', 'bg-transparent', 'border-transparent',
|
||||
]);
|
||||
|
||||
const classRegex = /^(?:bg|text|border|ring|stroke|fill|from|to|via|outline|decoration|placeholder|caret|divide)-([a-z]+)-(?:\d{2,3})$/;
|
||||
|
||||
function extractClassStrings(attrValue) {
|
||||
const results = [];
|
||||
if (!attrValue) return results;
|
||||
|
||||
if (attrValue.type === 'Literal' && typeof attrValue.value === 'string') {
|
||||
results.push(attrValue.value);
|
||||
}
|
||||
|
||||
if (attrValue.type === 'JSXExpressionContainer') {
|
||||
const expr = attrValue.expression;
|
||||
if (expr.type === 'Literal' && typeof expr.value === 'string') {
|
||||
results.push(expr.value);
|
||||
}
|
||||
if (expr.type === 'TemplateLiteral') {
|
||||
for (const quasi of expr.quasis) {
|
||||
if (typeof quasi.value.cooked === 'string') {
|
||||
results.push(quasi.value.cooked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function normalizeToken(token) {
|
||||
const base = token.split(':').pop() || token;
|
||||
return base.replace(/\/[0-9]+$/, '');
|
||||
}
|
||||
|
||||
return {
|
||||
JSXAttribute(node) {
|
||||
if (node.name.type !== 'JSXIdentifier' || node.name.name !== 'className') {
|
||||
return;
|
||||
}
|
||||
|
||||
const classStrings = extractClassStrings(node.value);
|
||||
if (!classStrings.length) return;
|
||||
|
||||
for (const classString of classStrings) {
|
||||
const tokens = classString.split(/\s+/).filter(Boolean);
|
||||
for (const token of tokens) {
|
||||
const normalized = normalizeToken(token);
|
||||
if (allowedSpecial.has(normalized)) continue;
|
||||
|
||||
const match = normalized.match(classRegex);
|
||||
if (!match) continue;
|
||||
|
||||
const palette = match[1];
|
||||
if (allowedPalettes.has(palette)) continue;
|
||||
if (disallowedPalettes.has(palette)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noDefaultColors',
|
||||
data: { className: token },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -101,8 +101,8 @@ const ProductionSummary: React.FC<ProductionSummaryProps> = ({
|
||||
{
|
||||
label: 'Images',
|
||||
value: counts.images,
|
||||
color: 'text-info-600 dark:text-info-400',
|
||||
bgColor: 'bg-info-50 dark:bg-info-900/20',
|
||||
color: 'text-brand-600 dark:text-brand-400',
|
||||
bgColor: 'bg-brand-50 dark:bg-brand-900/20',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ export default function CreditCostBreakdownPanel() {
|
||||
const operationColors = [
|
||||
{ bg: 'bg-brand-50 dark:bg-brand-900/20', text: 'text-brand-600 dark:text-brand-400', border: 'border-brand-500 dark:border-brand-400' },
|
||||
{ bg: 'bg-success-50 dark:bg-success-900/20', text: 'text-success-600 dark:text-success-400', border: 'border-success-500 dark:border-success-400' },
|
||||
{ bg: 'bg-info-50 dark:bg-info-900/20', text: 'text-info-600 dark:text-info-400', border: 'border-info-500 dark:border-info-400' },
|
||||
{ bg: 'bg-brand-50 dark:bg-brand-900/20', text: 'text-brand-600 dark:text-brand-400', border: 'border-brand-500 dark:border-brand-400' },
|
||||
{ bg: 'bg-purple-50 dark:bg-purple-900/20', text: 'text-purple-600 dark:text-purple-400', border: 'border-purple-500 dark:border-purple-400' },
|
||||
{ bg: 'bg-warning-50 dark:bg-warning-900/20', text: 'text-warning-600 dark:text-warning-400', border: 'border-warning-500 dark:border-warning-400' },
|
||||
{ bg: 'bg-purple-50 dark:bg-purple-900/20', text: 'text-purple-600 dark:text-purple-400', border: 'border-purple-500 dark:border-purple-400' },
|
||||
@@ -156,10 +156,10 @@ export default function CreditCostBreakdownPanel() {
|
||||
<div className="text-xs text-gray-500 mt-1">API calls</div>
|
||||
</Card>
|
||||
|
||||
<Card className="p-6 border-l-4 border-info-500 dark:border-info-400">
|
||||
<Card className="p-6 border-l-4 border-brand-500 dark:border-brand-400">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="p-2 bg-info-50 dark:bg-info-900/20 rounded-lg">
|
||||
<DollarSignIcon className="w-5 h-5 text-info-500 dark:text-info-400" />
|
||||
<div className="p-2 bg-brand-50 dark:bg-brand-900/20 rounded-lg">
|
||||
<DollarSignIcon className="w-5 h-5 text-brand-500 dark:text-brand-400" />
|
||||
</div>
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">Total Credits</div>
|
||||
</div>
|
||||
|
||||
@@ -345,14 +345,14 @@ export default function PayInvoiceModal({
|
||||
disabled={loading}
|
||||
className={`flex-1 flex items-center justify-center gap-2 px-4 py-3 rounded-lg border-2 transition-all ${
|
||||
selectedOption === 'paypal'
|
||||
? 'border-[#0070ba] bg-blue-50 dark:bg-blue-900/20 text-[#0070ba] dark:text-blue-300'
|
||||
? 'border-brand-500 bg-brand-50 dark:bg-brand-900/20 text-brand-700 dark:text-brand-300'
|
||||
: 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 text-gray-700 dark:text-gray-300'
|
||||
}`}
|
||||
>
|
||||
<WalletIcon className={`w-5 h-5 ${selectedOption === 'paypal' ? 'text-[#0070ba]' : 'text-gray-500'}`} />
|
||||
<WalletIcon className={`w-5 h-5 ${selectedOption === 'paypal' ? 'text-brand-600' : 'text-gray-500'}`} />
|
||||
<span className="font-medium">PayPal</span>
|
||||
{isDefaultMethod('paypal') && (
|
||||
<span className="ml-1 px-1.5 py-0.5 text-xs font-medium rounded bg-blue-100 dark:bg-blue-800 text-blue-700 dark:text-blue-200">
|
||||
<span className="ml-1 px-1.5 py-0.5 text-xs font-medium rounded bg-brand-100 dark:bg-brand-800 text-brand-700 dark:text-brand-200">
|
||||
Default
|
||||
</span>
|
||||
)}
|
||||
@@ -429,12 +429,12 @@ export default function PayInvoiceModal({
|
||||
{selectedOption === 'bank_transfer' && isPakistan && (
|
||||
<form onSubmit={handleBankSubmit} className="space-y-4">
|
||||
{/* Bank Details */}
|
||||
<div className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
|
||||
<h4 className="font-medium text-blue-900 dark:text-blue-100 mb-2 flex items-center gap-2">
|
||||
<div className="p-4 bg-brand-50 dark:bg-brand-900/20 rounded-lg border border-brand-200 dark:border-brand-800">
|
||||
<h4 className="font-medium text-brand-900 dark:text-brand-100 mb-2 flex items-center gap-2">
|
||||
<Building2Icon className="w-5 h-5" />
|
||||
Bank Transfer Details
|
||||
</h4>
|
||||
<div className="text-sm text-blue-800 dark:text-blue-200 space-y-1">
|
||||
<div className="text-sm text-brand-800 dark:text-brand-200 space-y-1">
|
||||
<p><span className="font-medium">Bank:</span> Standard Chartered Bank Pakistan</p>
|
||||
<p><span className="font-medium">Account Title:</span> IGNY8 Technologies</p>
|
||||
<p><span className="font-medium">Account #:</span> 01-2345678-01</p>
|
||||
|
||||
@@ -345,9 +345,9 @@ export default function PendingPaymentView({
|
||||
</Card>
|
||||
|
||||
{/* Time Estimate Badge */}
|
||||
<div className="flex items-center justify-center gap-2 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-xl border border-blue-200 dark:border-blue-800">
|
||||
<AlertCircleIcon className="w-5 h-5 text-blue-600 dark:text-blue-400" />
|
||||
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||
<div className="flex items-center justify-center gap-2 p-4 bg-brand-50 dark:bg-brand-900/20 rounded-xl border border-brand-200 dark:border-brand-800">
|
||||
<AlertCircleIcon className="w-5 h-5 text-brand-600 dark:text-brand-400" />
|
||||
<p className="text-sm text-brand-800 dark:text-brand-200">
|
||||
<strong>Expected approval time:</strong> Within 24 hours (usually faster)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -140,8 +140,8 @@ const BulkScheduleModal: React.FC<BulkScheduleModalProps> = ({
|
||||
|
||||
{/* Preview */}
|
||||
{selectedDate && selectedTime && (
|
||||
<div className="bg-blue-50 border-l-4 border-blue-500 p-4 rounded">
|
||||
<p className="text-sm font-medium text-blue-900">
|
||||
<div className="bg-brand-50 border-l-4 border-brand-500 p-4 rounded">
|
||||
<p className="text-sm font-medium text-brand-900">
|
||||
Preview: {formatPreviewDate()} ({getAccountTimezone()})
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -104,9 +104,9 @@ const BulkSchedulePreviewModal: React.FC<BulkSchedulePreviewModalProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Site Settings Summary */}
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
||||
<p className="text-sm font-semibold text-blue-900 mb-2">Using site default schedule:</p>
|
||||
<ul className="space-y-1 text-sm text-blue-800">
|
||||
<div className="bg-brand-50 border border-brand-200 rounded-lg p-4 mb-4">
|
||||
<p className="text-sm font-semibold text-brand-900 mb-2">Using site default schedule:</p>
|
||||
<ul className="space-y-1 text-sm text-brand-800">
|
||||
<li>• First slot: {previewData.site_settings.base_time} ({accountTimezone})</li>
|
||||
<li>• First publish: {formatFullDate(firstPublish.scheduled_at)}</li>
|
||||
<li>• Last publish: {formatFullDate(lastPublish.scheduled_at)}</li>
|
||||
|
||||
@@ -140,16 +140,16 @@ const ErrorDetailsModal: React.FC<ErrorDetailsModalProps> = ({
|
||||
|
||||
{/* Suggestion */}
|
||||
{suggestion && (
|
||||
<div className="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6">
|
||||
<div className="bg-brand-50 border-l-4 border-brand-500 p-4 mb-6">
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="flex-shrink-0">
|
||||
<svg className="w-5 h-5 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<svg className="w-5 h-5 text-brand-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-blue-900">Suggestion:</p>
|
||||
<p className="text-sm text-blue-800 mt-1">{suggestion}</p>
|
||||
<p className="text-sm font-medium text-brand-900">Suggestion:</p>
|
||||
<p className="text-sm text-brand-800 mt-1">{suggestion}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function PublishLimitModal({
|
||||
</p>
|
||||
|
||||
{/* Options Box */}
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 border-l-4 border-blue-500 p-4 mb-6 text-left">
|
||||
<div className="bg-brand-50 dark:bg-brand-900/20 border-l-4 border-brand-500 p-4 mb-6 text-left">
|
||||
<p className="font-semibold text-gray-900 dark:text-white mb-3">Options:</p>
|
||||
<ul className="list-disc list-inside space-y-2 text-sm text-gray-700 dark:text-gray-300">
|
||||
<li>Deselect items to publish 5 or fewer</li>
|
||||
@@ -52,7 +52,7 @@ export default function PublishLimitModal({
|
||||
|
||||
{/* Tip */}
|
||||
<div className="flex items-start gap-2 mt-4 p-3 bg-white dark:bg-gray-800 rounded">
|
||||
<InfoIcon className="w-5 h-5 text-blue-500 flex-shrink-0 mt-0.5" />
|
||||
<InfoIcon className="w-5 h-5 text-brand-500 flex-shrink-0 mt-0.5" />
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||
<strong>Tip:</strong> Scheduling has no limit and uses your site's default publishing schedule.
|
||||
</p>
|
||||
|
||||
@@ -154,8 +154,8 @@ const ScheduleContentModal: React.FC<ScheduleContentModalProps> = ({
|
||||
|
||||
{/* Preview */}
|
||||
{selectedDate && selectedTime && (
|
||||
<div className="bg-blue-50 border-l-4 border-blue-500 p-4 rounded">
|
||||
<p className="text-sm font-medium text-blue-900">
|
||||
<div className="bg-brand-50 border-l-4 border-brand-500 p-4 rounded">
|
||||
<p className="text-sm font-medium text-brand-900">
|
||||
Preview: {formatPreviewDate()} ({getAccountTimezone()})
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -841,7 +841,7 @@ export default function SearchModal({ isOpen, onClose }: SearchModalProps) {
|
||||
|
||||
{/* Context Snippet - show matched text with surrounding context */}
|
||||
{query && result.contextSnippet && (
|
||||
<div className="mb-2 text-xs px-2 py-1 rounded bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 text-gray-700 dark:text-gray-300 italic">
|
||||
<div className="mb-2 text-xs px-2 py-1 rounded bg-brand-50 dark:bg-brand-900/20 border border-brand-200 dark:border-brand-800 text-gray-700 dark:text-gray-300 italic">
|
||||
<span dangerouslySetInnerHTML={{ __html: highlightMatch(result.contextSnippet, query) }} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -114,12 +114,12 @@ const STAT_CONFIG: Record<StatType, {
|
||||
label: 'Quick Wins',
|
||||
description: 'Low difficulty, good volume',
|
||||
icon: <BoltIcon className="w-5 h-5" />,
|
||||
accentColor: 'bg-emerald-500',
|
||||
borderColor: 'border-emerald-500',
|
||||
ringColor: 'ring-emerald-500/20',
|
||||
dotColor: 'bg-emerald-500',
|
||||
textColor: 'text-emerald-600 dark:text-emerald-400',
|
||||
badgeColor: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300',
|
||||
accentColor: 'bg-success-500',
|
||||
borderColor: 'border-success-500',
|
||||
ringColor: 'ring-success-500/20',
|
||||
dotColor: 'bg-success-500',
|
||||
textColor: 'text-success-600 dark:text-success-400',
|
||||
badgeColor: 'bg-success-100 text-success-700 dark:bg-success-900/40 dark:text-success-300',
|
||||
showThreshold: true,
|
||||
thresholdPrefix: 'Vol >',
|
||||
},
|
||||
|
||||
@@ -502,14 +502,14 @@ export default function WordPressIntegrationForm({
|
||||
</div>
|
||||
|
||||
{/* Requirements & Instructions */}
|
||||
<div className="mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
|
||||
<div className="mt-4 p-3 bg-brand-50 dark:bg-brand-900/20 border border-brand-200 dark:border-brand-800 rounded-lg">
|
||||
<div className="flex items-start gap-2">
|
||||
<InfoIcon className="w-4 h-4 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0" />
|
||||
<InfoIcon className="w-4 h-4 text-brand-600 dark:text-brand-400 mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-blue-900 dark:text-blue-300 mb-1">
|
||||
<p className="text-xs font-medium text-brand-900 dark:text-brand-300 mb-1">
|
||||
Installation Steps
|
||||
</p>
|
||||
<ol className="text-xs text-blue-800 dark:text-blue-400 space-y-1 list-decimal list-inside">
|
||||
<ol className="text-xs text-brand-800 dark:text-brand-400 space-y-1 list-decimal list-inside">
|
||||
<li>Download the plugin ZIP file</li>
|
||||
<li>Go to your WordPress admin → Plugins → Add New</li>
|
||||
<li>Click "Upload Plugin" and select the ZIP file</li>
|
||||
|
||||
@@ -176,12 +176,12 @@ export function createApprovedPageConfig(params: {
|
||||
const failedAt = row.site_status_updated_at || row.updated_at;
|
||||
if (failedAt) {
|
||||
return (
|
||||
<span className="text-red-600 dark:text-red-400 font-medium">
|
||||
<span className="text-error-600 dark:text-error-400 font-medium">
|
||||
{formatRelativeDate(failedAt)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span className="text-red-600 dark:text-red-400 text-[11px]">Failed</span>;
|
||||
return <span className="text-error-600 dark:text-error-400 text-[11px]">Failed</span>;
|
||||
}
|
||||
|
||||
// For scheduled items: show when it will be published
|
||||
@@ -191,12 +191,12 @@ export function createApprovedPageConfig(params: {
|
||||
const now = new Date();
|
||||
const isFuture = publishDate > now;
|
||||
return (
|
||||
<span className={isFuture ? "text-blue-600 dark:text-blue-400 font-medium" : "text-amber-600 dark:text-amber-400 font-medium"}>
|
||||
<span className={isFuture ? "text-brand-600 dark:text-brand-400 font-medium" : "text-warning-600 dark:text-warning-400 font-medium"}>
|
||||
{formatRelativeDate(value)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span className="text-amber-600 dark:text-amber-400 text-[11px]">Pending</span>;
|
||||
return <span className="text-warning-600 dark:text-warning-400 text-[11px]">Pending</span>;
|
||||
}
|
||||
|
||||
// For not_published items: show scheduled date if available
|
||||
@@ -205,7 +205,7 @@ export function createApprovedPageConfig(params: {
|
||||
const now = new Date();
|
||||
const isFuture = publishDate > now;
|
||||
return (
|
||||
<span className={isFuture ? "text-blue-600 dark:text-blue-400 font-medium" : "text-amber-600 dark:text-amber-400 font-medium"}>
|
||||
<span className={isFuture ? "text-brand-600 dark:text-brand-400 font-medium" : "text-warning-600 dark:text-warning-400 font-medium"}>
|
||||
{formatRelativeDate(value)}
|
||||
</span>
|
||||
);
|
||||
@@ -226,7 +226,7 @@ export function createApprovedPageConfig(params: {
|
||||
const label = TYPE_LABELS[value] || value || '-';
|
||||
const properCase = label.charAt(0).toUpperCase() + label.slice(1);
|
||||
return (
|
||||
<Badge color="blue" size="xs" variant="soft">
|
||||
<Badge color="brand" size="xs" variant="soft">
|
||||
<span className="text-[11px] font-normal">{properCase}</span>
|
||||
</Badge>
|
||||
);
|
||||
|
||||
@@ -739,8 +739,8 @@ export default function Integration() {
|
||||
</div>
|
||||
|
||||
{/* Row 2: Image Size Info */}
|
||||
<div className="p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
|
||||
<div className="text-sm text-blue-700 dark:text-blue-300">
|
||||
<div className="p-3 rounded-lg bg-brand-50 dark:bg-brand-900/20 border border-brand-200 dark:border-brand-800">
|
||||
<div className="text-sm text-brand-700 dark:text-brand-300">
|
||||
<strong>Image Sizes (auto-determined):</strong>
|
||||
<ul className="mt-1 list-disc list-inside text-xs space-y-1">
|
||||
<li>Featured image: Landscape ({getImageSizes(service, service === 'openai' ? (integrations[selectedIntegration]?.model || 'dall-e-3') : (integrations[selectedIntegration]?.runwareModel || 'runware:97@1'))[0]?.label.split(' - ')[0] || 'model-specific'})</li>
|
||||
|
||||
@@ -560,10 +560,10 @@ export default function AIAutomationSettings({ siteId }: AIAutomationSettingsPro
|
||||
</div>
|
||||
|
||||
{/* Info Banner */}
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3 mb-4">
|
||||
<div className="bg-brand-50 dark:bg-brand-900/20 border border-brand-200 dark:border-brand-800 rounded-lg p-3 mb-4">
|
||||
<div className="flex items-start gap-2">
|
||||
<InfoIcon className="w-4 h-4 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0" />
|
||||
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||
<InfoIcon className="w-4 h-4 text-brand-600 dark:text-brand-400 mt-0.5 flex-shrink-0" />
|
||||
<p className="text-sm text-brand-800 dark:text-brand-200">
|
||||
<span className="font-medium">Limit:</span> max items per run (0=all).
|
||||
<span className="font-medium ml-2">Budget:</span> credit allocation across AI stages.
|
||||
</p>
|
||||
@@ -705,10 +705,10 @@ export default function AIAutomationSettings({ siteId }: AIAutomationSettingsPro
|
||||
{/* Right: Schedule + Capacity stacked */}
|
||||
<div className="space-y-6">
|
||||
{/* Schedule Card */}
|
||||
<Card className="p-5 border-l-4 border-l-pink-500">
|
||||
<Card className="p-5 border-l-4 border-l-purple-500">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2 bg-pink-100 dark:bg-pink-900/30 rounded-lg">
|
||||
<CalendarIcon className="w-5 h-5 text-pink-600 dark:text-pink-400" />
|
||||
<div className="p-2 bg-purple-100 dark:bg-purple-900/30 rounded-lg">
|
||||
<CalendarIcon className="w-5 h-5 text-purple-600 dark:text-purple-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Schedule</h3>
|
||||
@@ -877,12 +877,12 @@ export default function AIAutomationSettings({ siteId }: AIAutomationSettingsPro
|
||||
</Card>
|
||||
|
||||
{/* Schedule & Capacity Explanation */}
|
||||
<Card className="p-4 bg-pink-50 dark:bg-pink-900/20 border-pink-200 dark:border-pink-800">
|
||||
<Card className="p-4 bg-purple-50 dark:bg-purple-900/20 border-purple-200 dark:border-purple-800">
|
||||
<div className="flex items-start gap-3">
|
||||
<CalendarIcon className="w-5 h-5 text-pink-600 dark:text-pink-400 mt-0.5 flex-shrink-0" />
|
||||
<div className="text-sm text-pink-800 dark:text-pink-200">
|
||||
<CalendarIcon className="w-5 h-5 text-purple-600 dark:text-purple-400 mt-0.5 flex-shrink-0" />
|
||||
<div className="text-sm text-purple-800 dark:text-purple-200">
|
||||
<p className="font-medium mb-2">Schedule & Capacity</p>
|
||||
<ul className="list-disc list-inside space-y-1 text-pink-700 dark:text-pink-300">
|
||||
<ul className="list-disc list-inside space-y-1 text-purple-700 dark:text-purple-300">
|
||||
<li>Select days content can be published</li>
|
||||
<li>Add time slots for publishing</li>
|
||||
<li>Capacity = Days × Time Slots</li>
|
||||
|
||||
@@ -323,10 +323,10 @@ export default function SiteDashboard() {
|
||||
{/* Deploy Site */}
|
||||
<button
|
||||
onClick={() => navigate(`/sites/${siteId}/deploy`)}
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 hover:border-info-300 hover:bg-info-50 dark:hover:bg-info-900/10 transition-all group"
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 hover:border-brand-300 hover:bg-brand-50 dark:hover:bg-brand-900/10 transition-all group"
|
||||
>
|
||||
<div className="size-8 rounded-lg bg-info-100 dark:bg-info-900/30 flex items-center justify-center flex-shrink-0">
|
||||
<ArrowUpIcon className="h-4 w-4 text-info-600 dark:text-info-400" />
|
||||
<div className="size-8 rounded-lg bg-brand-100 dark:bg-brand-900/30 flex items-center justify-center flex-shrink-0">
|
||||
<ArrowUpIcon className="h-4 w-4 text-brand-600 dark:text-brand-400" />
|
||||
</div>
|
||||
<span className="flex-1 text-sm font-medium text-gray-700 dark:text-gray-300 text-left">Deploy Site</span>
|
||||
</button>
|
||||
|
||||
@@ -696,9 +696,9 @@ export default function SiteSettings() {
|
||||
</Card>
|
||||
|
||||
{/* Card 2: Industry & Sectors Configuration */}
|
||||
<Card className="p-6 border-l-4 border-l-info-500">
|
||||
<Card className="p-6 border-l-4 border-l-brand-500">
|
||||
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<LayersIcon className="w-5 h-5 text-info-500" />
|
||||
<LayersIcon className="w-5 h-5 text-brand-500" />
|
||||
Industry & Sectors
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
|
||||
@@ -729,7 +729,7 @@ export default function AccountSettingsPage() {
|
||||
<li>✗ Cannot manage billing</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="p-4 border-l-4 border-info-500 bg-info-50/50 dark:bg-info-900/10 rounded-r-lg">
|
||||
<div className="p-4 border-l-4 border-purple-500 bg-purple-50/50 dark:bg-purple-900/10 rounded-r-lg">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-white">Member</h4>
|
||||
<Badge variant="light" color="info">Standard Access</Badge>
|
||||
|
||||
@@ -683,10 +683,10 @@ export default function PlansAndBillingPage() {
|
||||
// PAYMENT PROCESSING OVERLAY - Beautiful full-page loading with breathing badge
|
||||
if (paymentProcessing?.active) {
|
||||
const stageConfig = {
|
||||
verifying: { color: 'bg-blue-600', label: 'Verifying Payment' },
|
||||
processing: { color: 'bg-amber-600', label: 'Processing Payment' },
|
||||
verifying: { color: 'bg-brand-600', label: 'Verifying Payment' },
|
||||
processing: { color: 'bg-warning-600', label: 'Processing Payment' },
|
||||
finalizing: { color: 'bg-purple-600', label: 'Finalizing' },
|
||||
activating: { color: 'bg-green-600', label: 'Activating Subscription' },
|
||||
activating: { color: 'bg-success-600', label: 'Activating Subscription' },
|
||||
};
|
||||
const config = stageConfig[paymentProcessing.stage];
|
||||
|
||||
@@ -815,11 +815,11 @@ export default function PlansAndBillingPage() {
|
||||
</div>
|
||||
)}
|
||||
{hasPendingPayment && (
|
||||
<div className="mb-6 p-4 rounded-xl border border-info-200 bg-info-50 dark:border-info-800 dark:bg-info-900/20 flex items-start gap-3">
|
||||
<Loader2Icon className="w-5 h-5 text-info-600 dark:text-info-400 mt-0.5 shrink-0 animate-spin" />
|
||||
<div className="mb-6 p-4 rounded-xl border border-brand-200 bg-brand-50 dark:border-brand-800 dark:bg-brand-900/20 flex items-start gap-3">
|
||||
<Loader2Icon className="w-5 h-5 text-brand-600 dark:text-brand-400 mt-0.5 shrink-0 animate-spin" />
|
||||
<div>
|
||||
<p className="font-medium text-info-800 dark:text-info-200">Payment Pending Review</p>
|
||||
<p className="text-sm text-info-700 dark:text-info-300 mt-1">Your payment is being processed. Credits will be added once approved.</p>
|
||||
<p className="font-medium text-brand-800 dark:text-brand-200">Payment Pending Review</p>
|
||||
<p className="text-sm text-brand-700 dark:text-brand-300 mt-1">Your payment is being processed. Credits will be added once approved.</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -1065,11 +1065,11 @@ export default function PlansAndBillingPage() {
|
||||
onClick={() => setSelectedGateway('paypal')}
|
||||
className={`flex-1 flex items-center justify-center gap-2 px-4 py-2 rounded-lg border-2 transition-all ${
|
||||
selectedGateway === 'paypal'
|
||||
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
|
||||
? 'border-brand-500 bg-brand-50 dark:bg-brand-900/20 text-brand-700 dark:text-brand-300'
|
||||
: 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
|
||||
}`}
|
||||
>
|
||||
<WalletIcon className={`w-5 h-5 ${selectedGateway === 'paypal' ? 'text-blue-600' : 'text-gray-500'}`} />
|
||||
<WalletIcon className={`w-5 h-5 ${selectedGateway === 'paypal' ? 'text-brand-600' : 'text-gray-500'}`} />
|
||||
<span className="text-sm font-medium">PayPal</span>
|
||||
</button>
|
||||
)}
|
||||
@@ -1269,8 +1269,8 @@ export default function PlansAndBillingPage() {
|
||||
<Card className="p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 bg-info-100 dark:bg-info-900/30 rounded-lg">
|
||||
<CreditCardIcon className="w-5 h-5 text-info-600 dark:text-info-400" />
|
||||
<div className="p-2 bg-brand-100 dark:bg-brand-900/30 rounded-lg">
|
||||
<CreditCardIcon className="w-5 h-5 text-brand-600 dark:text-brand-400" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 dark:text-white">Payment Methods</h3>
|
||||
@@ -1301,7 +1301,7 @@ export default function PlansAndBillingPage() {
|
||||
{method.type === 'bank_transfer' || method.type === 'local_wallet' ? (
|
||||
<Building2Icon className="w-6 h-6 text-gray-500" />
|
||||
) : method.type === 'paypal' ? (
|
||||
<WalletIcon className="w-6 h-6 text-blue-500" />
|
||||
<WalletIcon className="w-6 h-6 text-brand-500" />
|
||||
) : (
|
||||
<CreditCardIcon className="w-6 h-6 text-brand-500" />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user