trial log, profile fixes

This commit is contained in:
2026-04-24 16:11:56 +07:00
parent 24e3a6de44
commit 0dc6562dd2
4 changed files with 62 additions and 67 deletions
+41 -17
View File
@@ -15,13 +15,18 @@ import {
import { activateTrial, buySubscription, fetchProfile } from "./api";
import { useNavigate } from "react-router-dom";
// 🔥 ИСПРАВЛЕНО: Полная локализация интерфейса
const DICT = {
en: {
auth_ready: "App Authorization Ready",
operative: "Operative",
balance: "Balance",
tickets: "Tickets",
uplink_status: "Uplink Status",
expires: "Expires",
offline: "OFFLINE",
no_active_sub: "No active subscription.",
run_breach: "Run Breach Protocol",
system_override: "System Override",
manage_plan: "Manage Plan",
acquire: "Acquire Tier",
@@ -63,8 +68,12 @@ const DICT = {
auth_ready: "Авторизация Успешна",
operative: "Оперативник",
balance: "Баланс",
tickets: "Билеты",
uplink_status: "Статус Узла",
expires: "Истекает",
offline: "ОТКЛЮЧЕНО",
no_active_sub: "Нет активной подписки.",
run_breach: "Запустить Протокол Взлома",
system_override: "Терминал Доступа",
manage_plan: "Управление подпиской",
acquire: "Арендовать",
@@ -100,7 +109,6 @@ const DICT = {
},
};
// Захардкодим список, чтобы Триал был виден красиво
const UI_PLANS = [
{ name: "TRIAL", price: 0, price_usd: 0, price_rub: 0 },
{ name: "GHOST", price: 5, price_usd: 5, price_rub: 500 },
@@ -166,7 +174,6 @@ export default function Profile() {
);
}
// Теперь бэкенд отдает всё как надо: { user: {...}, subscription: {...}, recruits, earned }
const user = data.user || {};
const subscription = data.subscription;
const hasSub = subscription && subscription.plan_name;
@@ -190,8 +197,9 @@ export default function Profile() {
try {
await activateTrial();
window.location.reload();
} catch (e) {
alert("Error / Уже использовано");
} catch (e: any) {
// 🔥 ИСПРАВЛЕНО: Вывод реальной ошибки с бэкенда
alert(`[ERROR] ${e.message}`);
}
};
@@ -199,8 +207,8 @@ export default function Profile() {
try {
await buySubscription(planName);
window.location.reload();
} catch (e) {
alert("Error");
} catch (e: any) {
alert(`[ERROR] ${e.message}`);
}
};
@@ -237,7 +245,7 @@ export default function Profile() {
</div>
<div className="text-right">
<p className="text-muted-foreground text-xs uppercase tracking-widest mb-1">
{t.balance} | TICKETS:{" "}
{t.balance} | {t.tickets}:{" "}
<span className="text-primary">{user.game_tickets || 0}</span>
</p>
<p className="text-3xl font-black text-secondary drop-shadow-[0_0_12px_rgba(0,229,242,0.6)]">
@@ -260,7 +268,7 @@ export default function Profile() {
</span>
) : (
<span className="px-3 py-1 rounded-full text-xs font-bold uppercase bg-white/10 text-muted-foreground">
OFFLINE
{t.offline}
</span>
)}
</div>
@@ -271,7 +279,7 @@ export default function Profile() {
</p>
) : (
<p className="text-xs text-muted-foreground mt-2">
No active subscription.
{t.no_active_sub}
</p>
)}
</div>
@@ -282,7 +290,7 @@ export default function Profile() {
>
<div className="absolute inset-0 bg-[linear-gradient(45deg,transparent_25%,rgba(139,61,255,0.2)_50%,transparent_75%)] bg-[length:250%_250%,100%_100%] animate-[shimmer_2s_infinite] opacity-0 group-hover:opacity-100" />
<Terminal className="w-5 h-5 group-hover:animate-pulse relative z-10" />
<span className="relative z-10">Run Breach Protocol</span>
<span className="relative z-10">{t.run_breach}</span>
</button>
{/* SUBSCRIPTIONS */}
@@ -313,10 +321,17 @@ export default function Profile() {
const isTrial = plan.name === "TRIAL";
const isTrialUsed = isTrial && user.has_used_trial;
// 🔥 ИСПРАВЛЕНО: Улучшенный дизайн карточек и кнопки Триала
return (
<div
key={plan.name}
className={`bg-black/50 border border-white/10 rounded-2xl p-4 flex flex-col transition-colors group relative overflow-hidden ${isTrialUsed ? "opacity-50 grayscale" : "hover:border-primary/50"}`}
className={`bg-black/50 border rounded-3xl p-5 flex flex-col transition-all duration-300 group relative overflow-hidden ${
isTrial
? isTrialUsed
? "border-white/5 opacity-50 grayscale"
: "border-secondary/50 shadow-[0_0_15px_rgba(0,229,242,0.15)] hover:shadow-[0_0_25px_rgba(0,229,242,0.3)] hover:border-secondary"
: "border-white/10 hover:border-primary/50"
}`}
>
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="flex justify-between items-start mb-2">
@@ -335,12 +350,15 @@ export default function Profile() {
)}
</p>
</div>
<p className="text-xs text-muted-foreground mb-3 relative z-10">
<p className="text-xs text-muted-foreground mb-4 relative z-10">
{planData.desc}
</p>
<ul className="text-xs text-muted-foreground space-y-1 mb-4 relative z-10">
<ul className="text-xs text-muted-foreground space-y-2 mb-6 relative z-10">
{planData.features.map((f: string, i: number) => (
<li key={i}>- {f}</li>
<li key={i} className="flex items-center gap-2">
<div className="w-1 h-1 bg-secondary rounded-full" />{" "}
{f}
</li>
))}
</ul>
<button
@@ -348,14 +366,20 @@ export default function Profile() {
isTrial ? handleTrial() : handleBuy(plan.name)
}
disabled={isTrialUsed}
className={`mt-auto w-full py-2 rounded-xl text-xs font-bold transition-colors relative z-10
${isTrialUsed ? "bg-white/5 text-muted-foreground cursor-not-allowed" : "bg-white/5 hover:bg-primary text-white"}`}
className={`mt-auto w-full py-3 rounded-2xl text-xs font-bold uppercase tracking-widest transition-colors relative z-10
${
isTrialUsed
? "bg-white/5 text-muted-foreground cursor-not-allowed"
: isTrial
? "bg-secondary/20 hover:bg-secondary/40 text-secondary border border-secondary/50"
: "bg-white/5 hover:bg-primary text-white border border-white/10 hover:border-primary"
}`}
>
{isTrial
? isTrialUsed
? t.trial_used
: t.activate_trial
: `${t.acquire}`}
: t.acquire}
</button>
</div>
);