Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Update frontend/src/pages/SuperAdminPanel.jsx
Browse files
frontend/src/pages/SuperAdminPanel.jsx
CHANGED
|
@@ -9,7 +9,7 @@ const DEFAULT_BILLING_TIERS = [
|
|
| 9 |
{ id: 'quick', name: 'Quick Scan', badge: 'QUICK', monthly_price: 499, yearly_price: 4990 },
|
| 10 |
{ id: 'advanced', name: 'Advanced Scan', badge: 'ADVANCED', monthly_price: 4499, yearly_price: 44990 },
|
| 11 |
{ id: 'deep', name: 'Deep Scan', badge: 'DEEP', monthly_price: 9999, yearly_price: 99990 },
|
| 12 |
-
{ id: 'enterprise', name: 'Custom Solutions', badge: 'ENTERPRISE', monthly_price: 0, yearly_price: 0
|
| 13 |
];
|
| 14 |
|
| 15 |
const BillingTierCard = ({ tier, onSave }) => {
|
|
@@ -30,10 +30,10 @@ const BillingTierCard = ({ tier, onSave }) => {
|
|
| 30 |
|
| 31 |
const getAccentClass = (id) => {
|
| 32 |
const key = (id || '').toLowerCase();
|
| 33 |
-
if (key.includes('quick')) return 'bg-
|
| 34 |
-
if (key.includes('advanced')) return 'bg-
|
| 35 |
-
if (key.includes('deep')) return 'bg-
|
| 36 |
-
if (key.includes('enterprise') || key.includes('custom')) return 'bg-
|
| 37 |
return 'bg-primary';
|
| 38 |
};
|
| 39 |
|
|
@@ -57,78 +57,74 @@ const BillingTierCard = ({ tier, onSave }) => {
|
|
| 57 |
return tier.name || tier.id;
|
| 58 |
};
|
| 59 |
|
| 60 |
-
const isCustom = (tier.id || '').toLowerCase() === 'enterprise' || tier.isCustom;
|
| 61 |
-
|
| 62 |
return (
|
| 63 |
-
<div className="bg-surface-container-lowest border border-outline-variant/
|
| 64 |
{/* Accent Top Border */}
|
| 65 |
-
<div className={`absolute top-0 left-0 right-0 h-
|
| 66 |
-
|
| 67 |
-
<div
|
| 68 |
-
<
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
| 89 |
</div>
|
| 90 |
-
</div>
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
| 104 |
</div>
|
| 105 |
</div>
|
| 106 |
</div>
|
| 107 |
|
| 108 |
-
|
| 109 |
-
<
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
</div>
|
| 129 |
-
) : (
|
| 130 |
-
<div className="h-8"></div>
|
| 131 |
-
)}
|
| 132 |
</div>
|
| 133 |
);
|
| 134 |
};
|
|
|
|
| 9 |
{ id: 'quick', name: 'Quick Scan', badge: 'QUICK', monthly_price: 499, yearly_price: 4990 },
|
| 10 |
{ id: 'advanced', name: 'Advanced Scan', badge: 'ADVANCED', monthly_price: 4499, yearly_price: 44990 },
|
| 11 |
{ id: 'deep', name: 'Deep Scan', badge: 'DEEP', monthly_price: 9999, yearly_price: 99990 },
|
| 12 |
+
{ id: 'enterprise', name: 'Custom Solutions', badge: 'ENTERPRISE', monthly_price: 0, yearly_price: 0 }
|
| 13 |
];
|
| 14 |
|
| 15 |
const BillingTierCard = ({ tier, onSave }) => {
|
|
|
|
| 30 |
|
| 31 |
const getAccentClass = (id) => {
|
| 32 |
const key = (id || '').toLowerCase();
|
| 33 |
+
if (key.includes('quick')) return 'bg-[#4285f4]';
|
| 34 |
+
if (key.includes('advanced')) return 'bg-[#a855f7]';
|
| 35 |
+
if (key.includes('deep')) return 'bg-[#f97316]';
|
| 36 |
+
if (key.includes('enterprise') || key.includes('custom')) return 'bg-[#f97316]';
|
| 37 |
return 'bg-primary';
|
| 38 |
};
|
| 39 |
|
|
|
|
| 57 |
return tier.name || tier.id;
|
| 58 |
};
|
| 59 |
|
|
|
|
|
|
|
| 60 |
return (
|
| 61 |
+
<div className="bg-surface-container-lowest border border-outline-variant/70 rounded-2xl p-6 flex flex-col justify-between shadow-2xs relative overflow-hidden">
|
| 62 |
{/* Accent Top Border */}
|
| 63 |
+
<div className={`absolute top-0 left-0 right-0 h-[5px] ${getAccentClass(tier.id)}`}></div>
|
| 64 |
+
|
| 65 |
+
<div>
|
| 66 |
+
<div className="flex flex-col items-start gap-1 pt-1 mb-5">
|
| 67 |
+
<h3 className="font-headline-sm text-[18px] font-bold text-on-surface">
|
| 68 |
+
{getDisplayName(tier)}
|
| 69 |
+
</h3>
|
| 70 |
+
<span className="text-[11px] font-mono font-medium text-on-surface-variant uppercase tracking-wider bg-[#e5e5e5] px-2.5 py-0.5 rounded">
|
| 71 |
+
{getBadge(tier)}
|
| 72 |
+
</span>
|
| 73 |
+
</div>
|
| 74 |
|
| 75 |
+
<div className="grid grid-cols-2 gap-4">
|
| 76 |
+
<div className="flex flex-col gap-1.5">
|
| 77 |
+
<label className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider">MONTHLY PRICE</label>
|
| 78 |
+
<div className="bg-[#e5e5e5] border border-outline-variant/40 rounded-lg px-3 py-2 flex items-center gap-2">
|
| 79 |
+
<span className="font-mono font-bold text-on-surface text-sm">$</span>
|
| 80 |
+
<input
|
| 81 |
+
type="number"
|
| 82 |
+
step="0.01"
|
| 83 |
+
min="0"
|
| 84 |
+
value={monthly}
|
| 85 |
+
onChange={e => setMonthly(e.target.value)}
|
| 86 |
+
className="bg-transparent border-0 outline-none w-full font-mono font-bold text-on-surface text-sm"
|
| 87 |
+
/>
|
| 88 |
+
</div>
|
| 89 |
</div>
|
|
|
|
| 90 |
|
| 91 |
+
<div className="flex flex-col gap-1.5">
|
| 92 |
+
<label className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider">YEARLY PRICE</label>
|
| 93 |
+
<div className="bg-[#e5e5e5] border border-outline-variant/40 rounded-lg px-3 py-2 flex items-center gap-2">
|
| 94 |
+
<span className="font-mono font-bold text-on-surface text-sm">$</span>
|
| 95 |
+
<input
|
| 96 |
+
type="number"
|
| 97 |
+
step="0.01"
|
| 98 |
+
min="0"
|
| 99 |
+
value={yearly}
|
| 100 |
+
onChange={e => setYearly(e.target.value)}
|
| 101 |
+
className="bg-transparent border-0 outline-none w-full font-mono font-bold text-on-surface text-sm"
|
| 102 |
+
/>
|
| 103 |
+
</div>
|
| 104 |
</div>
|
| 105 |
</div>
|
| 106 |
</div>
|
| 107 |
|
| 108 |
+
<div className="border-t border-outline-variant/30 mt-5 pt-4 flex justify-end">
|
| 109 |
+
<button
|
| 110 |
+
onClick={handleSave}
|
| 111 |
+
disabled={saving}
|
| 112 |
+
className={`px-5 py-2 border rounded-lg font-bold text-[13px] transition-all flex items-center gap-2 cursor-pointer shadow-2xs ${
|
| 113 |
+
saved
|
| 114 |
+
? 'bg-green-500 text-white border-green-500'
|
| 115 |
+
: 'border-[#2563eb]/40 text-[#2563eb] hover:border-[#2563eb] bg-surface-container-lowest hover:bg-blue-50/20'
|
| 116 |
+
}`}
|
| 117 |
+
>
|
| 118 |
+
{saving ? (
|
| 119 |
+
<span className="material-symbols-outlined animate-spin text-[16px]">sync</span>
|
| 120 |
+
) : saved ? (
|
| 121 |
+
<span className="material-symbols-outlined text-[16px]">check_circle</span>
|
| 122 |
+
) : (
|
| 123 |
+
<span className="material-symbols-outlined text-[16px] text-[#2563eb]">save</span>
|
| 124 |
+
)}
|
| 125 |
+
<span>{saving ? 'Saving...' : saved ? 'Saved!' : 'Save Changes'}</span>
|
| 126 |
+
</button>
|
| 127 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
</div>
|
| 129 |
);
|
| 130 |
};
|