mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
refactor(theming): replace red-* palette with semantic error-* tokens
Sweep 30 files: text/bg/border/ring/from/to/via/fill/stroke/shadow/divide/decoration/ outline/placeholder-red-N → -error-N. All red usages were semantically error/danger (no brand red), so tokens now flow through the design-system CSS variables and respond to palette overrides.
This commit is contained in:
@@ -43,7 +43,7 @@ export const STYLE_OPTIONS = [
|
||||
{ value: 'default' as const, colorClass: 'bg-dark-500' },
|
||||
{ value: 'primary' as const, colorClass: 'bg-blue-500' },
|
||||
{ value: 'success' as const, colorClass: 'bg-success-500' },
|
||||
{ value: 'danger' as const, colorClass: 'bg-red-500' },
|
||||
{ value: 'danger' as const, colorClass: 'bg-error-500' },
|
||||
];
|
||||
|
||||
const DEFAULT_CONFIG: MenuConfig = { rows: [] };
|
||||
|
||||
@@ -235,7 +235,7 @@ export default function PromoOffersSection({ className = '' }: PromoOffersSectio
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDeactivateClick}
|
||||
className="flex items-center justify-center gap-1.5 rounded-xl border border-dark-600/50 bg-dark-900/50 px-4 py-2.5 text-sm text-dark-400 transition-colors hover:border-red-500/30 hover:bg-red-500/10 hover:text-red-400"
|
||||
className="flex items-center justify-center gap-1.5 rounded-xl border border-dark-600/50 bg-dark-900/50 px-4 py-2.5 text-sm text-dark-400 transition-colors hover:border-error-500/30 hover:bg-error-500/10 hover:text-error-400"
|
||||
>
|
||||
<XCircleIcon />
|
||||
<span>{t('promo.deactivate.button')}</span>
|
||||
|
||||
@@ -499,7 +499,7 @@ export default function TelegramLoginButton({ referralCode }: TelegramLoginButto
|
||||
</>
|
||||
) : deepLinkError ? (
|
||||
<div className="flex flex-col items-center space-y-2">
|
||||
<p className="text-xs text-red-500">{deepLinkError}</p>
|
||||
<p className="text-xs text-error-500">{deepLinkError}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={startDeepLinkAuth}
|
||||
@@ -542,7 +542,7 @@ export default function TelegramLoginButton({ referralCode }: TelegramLoginButto
|
||||
</svg>
|
||||
{oidcLoading ? t('common.loading') : t('auth.loginWithTelegram')}
|
||||
</button>
|
||||
{oidcError && <p className="text-xs text-red-500">{oidcError}</p>}
|
||||
{oidcError && <p className="text-xs text-error-500">{oidcError}</p>}
|
||||
</div>
|
||||
) : (
|
||||
<div ref={containerRef} className="flex justify-center" />
|
||||
|
||||
@@ -73,7 +73,7 @@ export function AnalyticsTab() {
|
||||
<div className="rounded-2xl border border-dark-700/50 bg-dark-800/50 p-6">
|
||||
<div className="mb-1 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-yellow-500/20 to-red-500/20">
|
||||
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-yellow-500/20 to-error-500/20">
|
||||
<svg className="h-5 w-5 text-yellow-400" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" />
|
||||
</svg>
|
||||
|
||||
@@ -19,7 +19,7 @@ const STYLE_OPTIONS: { value: StyleValue; colorClass: string }[] = [
|
||||
{ value: 'default', colorClass: 'bg-dark-500' },
|
||||
{ value: 'primary', colorClass: 'bg-blue-500' },
|
||||
{ value: 'success', colorClass: 'bg-success-500' },
|
||||
{ value: 'danger', colorClass: 'bg-red-500' },
|
||||
{ value: 'danger', colorClass: 'bg-error-500' },
|
||||
];
|
||||
|
||||
function labelsEqual(a: Record<string, string>, b: Record<string, string>): boolean {
|
||||
@@ -226,7 +226,7 @@ export function ButtonsTab() {
|
||||
: cfg.style === 'success'
|
||||
? 'bg-success-500 text-white'
|
||||
: cfg.style === 'danger'
|
||||
? 'bg-red-500 text-white'
|
||||
? 'bg-error-500 text-white'
|
||||
: 'bg-blue-500 text-white'
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -292,11 +292,11 @@ export function ColoredItemCombobox({
|
||||
type="button"
|
||||
onClick={(e) => handleDelete(e, item)}
|
||||
disabled={deletingId === item.id}
|
||||
className="shrink-0 rounded p-1 text-dark-600 transition-colors hover:bg-red-500/10 hover:text-red-400 disabled:opacity-50"
|
||||
className="shrink-0 rounded p-1 text-dark-600 transition-colors hover:bg-error-500/10 hover:text-error-400 disabled:opacity-50"
|
||||
aria-label={t('news.admin.combobox.delete', { name: item.name })}
|
||||
>
|
||||
{deletingId === item.id ? (
|
||||
<div className="h-3.5 w-3.5 animate-spin rounded-full border-2 border-red-400 border-t-transparent" />
|
||||
<div className="h-3.5 w-3.5 animate-spin rounded-full border-2 border-error-400 border-t-transparent" />
|
||||
) : (
|
||||
<svg className="h-3.5 w-3.5" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||
|
||||
@@ -234,7 +234,7 @@ function ButtonChip({
|
||||
{!isBuiltin && (
|
||||
<button
|
||||
onClick={onRemove}
|
||||
className="rounded-lg p-1 text-dark-500 transition-colors hover:bg-red-500/10 hover:text-red-400"
|
||||
className="rounded-lg p-1 text-dark-500 transition-colors hover:bg-error-500/10 hover:text-error-400"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
@@ -423,7 +423,7 @@ function SortableRow({
|
||||
{!allBuiltin && (
|
||||
<button
|
||||
onClick={() => onRemoveRow(row.id)}
|
||||
className="rounded-lg p-1.5 text-dark-500 transition-colors hover:bg-red-500/10 hover:text-red-400"
|
||||
className="rounded-lg p-1.5 text-dark-500 transition-colors hover:bg-error-500/10 hover:text-error-400"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
@@ -796,7 +796,7 @@ export function MenuEditorTab() {
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-400">
|
||||
<div className="rounded-xl border border-error-500/30 bg-error-500/10 px-4 py-3 text-sm text-error-400">
|
||||
{t('common.error')}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function BlacklistedScreen() {
|
||||
<div className="mb-8">
|
||||
<div className="mx-auto flex h-24 w-24 items-center justify-center rounded-full bg-dark-800">
|
||||
<svg
|
||||
className="h-12 w-12 text-red-500"
|
||||
className="h-12 w-12 text-error-500"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function ChannelSubscriptionScreen() {
|
||||
{channels.map((ch) => (
|
||||
<div
|
||||
key={ch.channel_id}
|
||||
className="flex items-center justify-between rounded-xl border border-red-500/30 bg-red-500/10 p-3"
|
||||
className="flex items-center justify-between rounded-xl border border-error-500/30 bg-error-500/10 p-3"
|
||||
>
|
||||
<span className="text-sm font-medium text-white">{ch.title || ch.channel_id}</span>
|
||||
{ch.channel_link && (
|
||||
@@ -146,8 +146,8 @@ export default function ChannelSubscriptionScreen() {
|
||||
|
||||
{/* Error message */}
|
||||
{error && (
|
||||
<div className="mb-4 rounded-xl border border-red-500/30 bg-red-500/10 p-3">
|
||||
<p className="text-sm text-red-400">{error}</p>
|
||||
<div className="mb-4 rounded-xl border border-error-500/30 bg-error-500/10 p-3">
|
||||
<p className="text-sm text-error-400">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ export default function TvQuickConnect({ subscriptionUrl, isLight }: Props) {
|
||||
{toast && (
|
||||
<div
|
||||
className={`fixed bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-xl px-5 py-3 text-sm font-medium shadow-lg transition-all ${
|
||||
toast.type === 'success' ? 'bg-emerald-500/90 text-white' : 'bg-red-500/90 text-white'
|
||||
toast.type === 'success' ? 'bg-emerald-500/90 text-white' : 'bg-error-500/90 text-white'
|
||||
}`}
|
||||
>
|
||||
{toast.text}
|
||||
|
||||
@@ -48,7 +48,7 @@ export function AddonsTab({ params }: AddonsTabProps) {
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return <div className="py-8 text-center text-red-400">{t('admin.salesStats.loadError')}</div>;
|
||||
return <div className="py-8 text-center text-error-400">{t('admin.salesStats.loadError')}</div>;
|
||||
}
|
||||
|
||||
const packageBarData = data.by_package.map((item) => ({
|
||||
|
||||
@@ -68,7 +68,7 @@ export function DepositsTab({ params }: DepositsTabProps) {
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return <div className="py-8 text-center text-red-400">{t('admin.salesStats.loadError')}</div>;
|
||||
return <div className="py-8 text-center text-error-400">{t('admin.salesStats.loadError')}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,7 +35,7 @@ export function RenewalsTab({ params }: RenewalsTabProps) {
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return <div className="py-8 text-center text-red-400">{t('admin.salesStats.loadError')}</div>;
|
||||
return <div className="py-8 text-center text-error-400">{t('admin.salesStats.loadError')}</div>;
|
||||
}
|
||||
|
||||
const dailyData = data.daily.map((item) => ({
|
||||
|
||||
@@ -45,7 +45,7 @@ export function SalesTab({ params }: SalesTabProps) {
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return <div className="py-8 text-center text-red-400">{t('admin.salesStats.loadError')}</div>;
|
||||
return <div className="py-8 text-center text-error-400">{t('admin.salesStats.loadError')}</div>;
|
||||
}
|
||||
|
||||
const tariffBarData = data.by_tariff.map((item) => ({
|
||||
|
||||
@@ -42,7 +42,7 @@ export function TrialsTab({ params }: TrialsTabProps) {
|
||||
}
|
||||
|
||||
if (isError || !data) {
|
||||
return <div className="py-8 text-center text-red-400">{t('admin.salesStats.loadError')}</div>;
|
||||
return <div className="py-8 text-center text-error-400">{t('admin.salesStats.loadError')}</div>;
|
||||
}
|
||||
|
||||
const pieData = data.by_provider.map((item) => ({
|
||||
|
||||
@@ -45,7 +45,7 @@ function StatusBadge({
|
||||
? 'bg-emerald-400/15 text-emerald-400 border-emerald-400/20'
|
||||
: isLimited
|
||||
? 'bg-amber-400/15 text-amber-400 border-amber-400/20'
|
||||
: 'bg-red-400/15 text-red-400 border-red-400/20';
|
||||
: 'bg-error-400/15 text-error-400 border-error-400/20';
|
||||
|
||||
const label = isActive
|
||||
? t('subscription.statusActive', 'Активна')
|
||||
@@ -96,7 +96,11 @@ export default function SubscriptionListCard({
|
||||
? Math.min(100, (trafficUsed / trafficLimit) * 100)
|
||||
: 0;
|
||||
const trafficColor =
|
||||
trafficPercent >= 90 ? 'bg-red-400' : trafficPercent >= 70 ? 'bg-amber-400' : 'bg-emerald-400';
|
||||
trafficPercent >= 90
|
||||
? 'bg-error-400'
|
||||
: trafficPercent >= 70
|
||||
? 'bg-amber-400'
|
||||
: 'bg-emerald-400';
|
||||
|
||||
const isLimitedStatus = subscription.status === 'limited';
|
||||
|
||||
@@ -207,7 +211,7 @@ export default function SubscriptionListCard({
|
||||
: t('subscription.autopay', 'Автопродление');
|
||||
return (
|
||||
<span
|
||||
className={`flex items-center gap-1 ${enabled ? 'text-emerald-400/70' : 'text-red-400/50'}`}
|
||||
className={`flex items-center gap-1 ${enabled ? 'text-emerald-400/70' : 'text-error-400/50'}`}
|
||||
>
|
||||
<svg
|
||||
className="h-3 w-3"
|
||||
|
||||
@@ -189,7 +189,7 @@ interface StatusBadgeProps {
|
||||
function StatusBadge({ status, label }: StatusBadgeProps) {
|
||||
const colorMap: Record<string, string> = {
|
||||
success: 'bg-success-500/20 text-success-400',
|
||||
denied: 'bg-red-500/20 text-red-400',
|
||||
denied: 'bg-error-500/20 text-error-400',
|
||||
error: 'bg-amber-500/20 text-amber-400',
|
||||
};
|
||||
|
||||
@@ -212,7 +212,7 @@ function MethodBadge({ method }: MethodBadgeProps) {
|
||||
POST: 'bg-success-500/20 text-success-400',
|
||||
PUT: 'bg-amber-500/20 text-amber-400',
|
||||
PATCH: 'bg-amber-500/20 text-amber-400',
|
||||
DELETE: 'bg-red-500/20 text-red-400',
|
||||
DELETE: 'bg-error-500/20 text-error-400',
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -50,7 +50,7 @@ function StatusBadge({ status }: StatusBadgeProps) {
|
||||
const styles: Record<string, string> = {
|
||||
paid: 'bg-green-500/20 text-green-400',
|
||||
pending: 'bg-amber-500/20 text-amber-400',
|
||||
cancelled: 'bg-red-500/20 text-red-400',
|
||||
cancelled: 'bg-error-500/20 text-error-400',
|
||||
};
|
||||
|
||||
const normalized = status.toLowerCase();
|
||||
@@ -78,7 +78,7 @@ function StatCard({ label, value, color, isActive, onClick }: StatCardProps) {
|
||||
blue: 'border-accent-500/30 bg-accent-500/20 text-accent-400',
|
||||
amber: 'border-amber-500/30 bg-amber-500/20 text-amber-400',
|
||||
green: 'border-green-500/30 bg-green-500/20 text-green-400',
|
||||
red: 'border-red-500/30 bg-red-500/20 text-red-400',
|
||||
red: 'border-error-500/30 bg-error-500/20 text-error-400',
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -597,7 +597,7 @@ export default function AdminPayments() {
|
||||
{checkPaymentMutation.isError &&
|
||||
checkPaymentMutation.variables?.paymentId === payment.id &&
|
||||
checkPaymentMutation.variables?.method === payment.method && (
|
||||
<div className="mt-3 rounded-lg border border-red-500/30 bg-red-500/10 p-2 text-sm text-red-400">
|
||||
<div className="mt-3 rounded-lg border border-error-500/30 bg-error-500/10 p-2 text-sm text-error-400">
|
||||
{t('admin.payments.checkError')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -141,7 +141,7 @@ function EffectBadge({ effect, className }: EffectBadgeProps) {
|
||||
className={`inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-semibold ${
|
||||
isAllow
|
||||
? 'border-success-500/30 bg-success-500/10 text-success-400'
|
||||
: 'border-red-500/30 bg-red-500/10 text-red-400'
|
||||
: 'border-error-500/30 bg-error-500/10 text-error-400'
|
||||
} ${className ?? ''}`}
|
||||
>
|
||||
{isAllow ? t('admin.policies.effectAllow') : t('admin.policies.effectDeny')}
|
||||
@@ -331,7 +331,7 @@ export default function AdminPolicies() {
|
||||
<div className="text-xs text-dark-400">{t('admin.policies.stats.allow')}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-dark-700 bg-dark-800 p-4">
|
||||
<div className="text-2xl font-bold text-red-400">
|
||||
<div className="text-2xl font-bold text-error-400">
|
||||
{sortedPolicies.filter((p) => p.effect === 'deny').length}
|
||||
</div>
|
||||
<div className="text-xs text-dark-400">{t('admin.policies.stats.deny')}</div>
|
||||
|
||||
@@ -455,7 +455,7 @@ export default function AdminPolicyEdit() {
|
||||
onClick={() => setFormData((prev) => ({ ...prev, effect: 'deny' }))}
|
||||
className={`flex-1 rounded-lg border px-3 py-2 text-sm font-medium transition-colors ${
|
||||
formData.effect === 'deny'
|
||||
? 'border-red-500/50 bg-red-500/10 text-red-400'
|
||||
? 'border-error-500/50 bg-error-500/10 text-error-400'
|
||||
: 'border-dark-600 bg-dark-900 text-dark-400 hover:border-dark-500'
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -595,14 +595,14 @@ export default function AdminTickets() {
|
||||
</div>
|
||||
)}
|
||||
{att.error && (
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-red-500/30">
|
||||
<span className="text-xs text-red-300">!</span>
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-error-500/30">
|
||||
<span className="text-xs text-error-300">!</span>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removeAttachment(idx)}
|
||||
className="absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-dark-600 text-dark-300 hover:bg-red-500 hover:text-white"
|
||||
className="absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-dark-600 text-dark-300 hover:bg-error-500 hover:text-white"
|
||||
>
|
||||
<svg
|
||||
className="h-3 w-3"
|
||||
@@ -633,7 +633,7 @@ export default function AdminTickets() {
|
||||
/>
|
||||
|
||||
{replyError && (
|
||||
<div className="mt-2 rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-300">
|
||||
<div className="mt-2 rounded-lg border border-error-500/30 bg-error-500/10 px-3 py-2 text-sm text-error-300">
|
||||
{replyError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -83,8 +83,8 @@ export default function Contests() {
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="card border-red-500/20 bg-red-500/10">
|
||||
<p className="text-red-400">{t('contests.error')}</p>
|
||||
<div className="card border-error-500/20 bg-error-500/10">
|
||||
<p className="text-error-400">{t('contests.error')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -125,7 +125,7 @@ export default function Contests() {
|
||||
|
||||
{result && (
|
||||
<div
|
||||
className={`mb-4 rounded-lg p-4 ${result.is_winner ? 'bg-success-500/20 text-success-400' : 'bg-red-500/20 text-red-400'}`}
|
||||
className={`mb-4 rounded-lg p-4 ${result.is_winner ? 'bg-success-500/20 text-success-400' : 'bg-error-500/20 text-error-400'}`}
|
||||
>
|
||||
<p className="font-medium">{result.message}</p>
|
||||
</div>
|
||||
|
||||
@@ -122,8 +122,8 @@ export default function Polls() {
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="card border-red-500/20 bg-red-500/10">
|
||||
<p className="text-red-400">{t('polls.error')}</p>
|
||||
<div className="card border-error-500/20 bg-error-500/10">
|
||||
<p className="text-error-400">{t('polls.error')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -600,9 +600,9 @@ function SummaryCard({
|
||||
const el = document.getElementById('contact-input');
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
el.classList.add('!border-red-500', '!ring-2', '!ring-red-500/50');
|
||||
el.classList.add('!border-error-500', '!ring-2', '!ring-error-500/50');
|
||||
setTimeout(() => {
|
||||
el.classList.remove('!border-red-500', '!ring-2', '!ring-red-500/50');
|
||||
el.classList.remove('!border-error-500', '!ring-2', '!ring-error-500/50');
|
||||
}, 2000);
|
||||
}
|
||||
return;
|
||||
@@ -643,12 +643,12 @@ function SummaryCard({
|
||||
const el = document.getElementById('contact-input');
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
el.classList.add('!border-red-500', '!ring-2', '!ring-red-500/50');
|
||||
el.classList.add('!border-error-500', '!ring-2', '!ring-error-500/50');
|
||||
setTimeout(() => {
|
||||
el.focus();
|
||||
}, 300);
|
||||
setTimeout(() => {
|
||||
el.classList.remove('!border-red-500', '!ring-2', '!ring-red-500/50');
|
||||
el.classList.remove('!border-error-500', '!ring-2', '!ring-error-500/50');
|
||||
}, 2000);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -195,7 +195,7 @@ export default function RenewSubscription() {
|
||||
</div>
|
||||
</div>
|
||||
{!canAfford && (
|
||||
<div className="mt-1 text-[11px] text-red-400">
|
||||
<div className="mt-1 text-[11px] text-error-400">
|
||||
{t(
|
||||
'subscription.insufficientBalanceAmount',
|
||||
'Недостаточно средств. Не хватает {{missing}}',
|
||||
@@ -216,7 +216,9 @@ export default function RenewSubscription() {
|
||||
|
||||
{/* Error */}
|
||||
{error && !missingAmount && (
|
||||
<div className="rounded-xl bg-red-400/10 p-3 text-center text-sm text-red-400">{error}</div>
|
||||
<div className="rounded-xl bg-error-400/10 p-3 text-center text-sm text-error-400">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Renew button */}
|
||||
|
||||
@@ -1428,7 +1428,7 @@ export default function Subscription() {
|
||||
}
|
||||
}}
|
||||
disabled={deleteLoading}
|
||||
className="flex w-full items-center justify-center gap-2 rounded-2xl border border-red-400/20 bg-red-400/5 p-3.5 text-sm font-medium text-red-400 transition-colors hover:bg-red-400/10 disabled:opacity-50"
|
||||
className="flex w-full items-center justify-center gap-2 rounded-2xl border border-error-400/20 bg-error-400/5 p-3.5 text-sm font-medium text-error-400 transition-colors hover:bg-error-400/10 disabled:opacity-50"
|
||||
>
|
||||
<svg
|
||||
className="h-4 w-4"
|
||||
@@ -1447,10 +1447,10 @@ export default function Subscription() {
|
||||
</button>
|
||||
) : (
|
||||
<div
|
||||
className="rounded-2xl border border-red-400/20 p-4"
|
||||
className="rounded-2xl border border-error-400/20 p-4"
|
||||
style={{ background: 'rgba(255,59,92,0.04)' }}
|
||||
>
|
||||
<div className="mb-3 text-sm font-semibold text-red-400">
|
||||
<div className="mb-3 text-sm font-semibold text-error-400">
|
||||
{t('subscription.deleteTitle', 'Удалить подписку?')}
|
||||
</div>
|
||||
<div className="mb-4 text-xs" style={{ color: g.textSecondary }}>
|
||||
@@ -1473,7 +1473,7 @@ export default function Subscription() {
|
||||
}
|
||||
}}
|
||||
disabled={deleteLoading}
|
||||
className="flex-1 rounded-xl bg-red-500 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-red-600 disabled:opacity-50"
|
||||
className="flex-1 rounded-xl bg-error-500 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-error-600 disabled:opacity-50"
|
||||
>
|
||||
{deleteLoading
|
||||
? t('common.processing', 'Удаление...')
|
||||
@@ -2382,7 +2382,7 @@ export default function Subscription() {
|
||||
</div>
|
||||
</button>
|
||||
{revokeMutation.error && (
|
||||
<p className="mt-2 text-sm text-red-400">{getErrorMessage(revokeMutation.error)}</p>
|
||||
<p className="mt-2 text-sm text-error-400">{getErrorMessage(revokeMutation.error)}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -350,14 +350,14 @@ export default function Support() {
|
||||
</div>
|
||||
)}
|
||||
{att.error && (
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-red-500/30">
|
||||
<span className="text-xs text-red-300">!</span>
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-error-500/30">
|
||||
<span className="text-xs text-error-300">!</span>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onRemove(idx)}
|
||||
className="absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-dark-600 text-dark-300 hover:bg-red-500 hover:text-white"
|
||||
className="absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-dark-600 text-dark-300 hover:bg-error-500 hover:text-white"
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
|
||||
@@ -66,7 +66,7 @@ export default function TelegramCallback() {
|
||||
return (
|
||||
<div className="min-h-viewport flex items-center justify-center bg-gray-50 px-4 py-8">
|
||||
<div className="w-full max-w-md text-center">
|
||||
<div className="mb-4 text-5xl text-red-500">✗</div>
|
||||
<div className="mb-4 text-5xl text-error-500">✗</div>
|
||||
<h2 className="mb-2 text-lg font-semibold text-gray-900">{t('auth.loginFailed')}</h2>
|
||||
<p className="mb-6 text-sm text-gray-500">{error}</p>
|
||||
<button onClick={() => navigate('/login')} className="btn-primary">
|
||||
|
||||
@@ -102,7 +102,7 @@ export default function VerifyEmail() {
|
||||
|
||||
{status === 'error' && (
|
||||
<div>
|
||||
<div className="mb-4 text-5xl text-red-500 sm:text-6xl">✗</div>
|
||||
<div className="mb-4 text-5xl text-error-500 sm:text-6xl">✗</div>
|
||||
<h2 className="text-lg font-semibold text-gray-900 sm:text-xl">
|
||||
{t('emailVerification.failed')}
|
||||
</h2>
|
||||
|
||||
@@ -487,7 +487,7 @@ export default function Wheel() {
|
||||
if (error || !config) {
|
||||
return (
|
||||
<div className="flex min-h-[60vh] flex-col items-center justify-center gap-4">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-red-500/10">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-error-500/10">
|
||||
<span className="text-4xl">😔</span>
|
||||
</div>
|
||||
<p className="text-lg text-dark-400">{t('wheel.errors.loadFailed')}</p>
|
||||
@@ -709,7 +709,7 @@ export default function Wheel() {
|
||||
className={`animate-fade-in rounded-linear border p-4 ${
|
||||
spinResult.success
|
||||
? 'border-accent-500/30 bg-accent-500/10'
|
||||
: 'border-red-500/30 bg-red-500/10'
|
||||
: 'border-error-500/30 bg-error-500/10'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
Reference in New Issue
Block a user