527 lines
16 KiB
TypeScript
527 lines
16 KiB
TypeScript
"use client";
|
||
import { useState, useEffect } from "react";
|
||
|
||
const translations = {
|
||
uz: {
|
||
badge: "To'lov amalga oshmadi",
|
||
title: "To'lov\nQabul\nQilinmagani uchun Sayt O'chirildi",
|
||
subtitle: "Afsuski, to'lovingizni qayta ishlashda xatolik yuz berdi.",
|
||
reasons_title: "Mumkin bo'lgan sabablar:",
|
||
reasons: [
|
||
"Karta mablag'i yetarli emas",
|
||
"Bank tomonidan to'lov rad etildi",
|
||
"Karta ma'lumotlari noto'g'ri",
|
||
"Tarmoq ulanish muammosi",
|
||
],
|
||
retry: "Qayta urinish",
|
||
support: "Qo'llab-quvvatlash",
|
||
back: "Orqaga qaytish",
|
||
code: "Xato kodi",
|
||
time: "Vaqt",
|
||
},
|
||
ru: {
|
||
badge: "Платёж не выполнен",
|
||
title: "Из-за\nнеполучения\nплатежа сайт отключен",
|
||
subtitle: "К сожалению, при обработке вашего платежа произошла ошибка.",
|
||
reasons_title: "Возможные причины:",
|
||
reasons: [
|
||
"Недостаточно средств на карте",
|
||
"Платёж отклонён банком",
|
||
"Неверные данные карты",
|
||
"Проблема с сетевым подключением",
|
||
],
|
||
retry: "Повторить",
|
||
support: "Поддержка",
|
||
back: "Назад",
|
||
code: "Код ошибки",
|
||
time: "Время",
|
||
},
|
||
en: {
|
||
badge: "Payment Failed",
|
||
title: "The site\nwas disabled\ndue to non-payment",
|
||
subtitle: "Unfortunately, an error occurred while processing your payment.",
|
||
reasons_title: "Possible reasons:",
|
||
reasons: [
|
||
"Insufficient funds on card",
|
||
"Payment declined by bank",
|
||
"Incorrect card details",
|
||
"Network connection issue",
|
||
],
|
||
retry: "Try Again",
|
||
support: "Support",
|
||
back: "Go Back",
|
||
code: "Error Code",
|
||
time: "Time",
|
||
},
|
||
};
|
||
|
||
const ERROR_CODE = "ERR-4082";
|
||
|
||
export default function PaymentFailed() {
|
||
const [lang, setLang] = useState("en");
|
||
const [visible, setVisible] = useState(false);
|
||
const [shake, setShake] = useState(false);
|
||
const [time] = useState(() =>
|
||
new Date().toLocaleTimeString("en-GB", {
|
||
hour: "2-digit",
|
||
minute: "2-digit",
|
||
second: "2-digit",
|
||
})
|
||
);
|
||
|
||
const t = translations[lang as "uz" | "ru" | "en"];
|
||
|
||
useEffect(() => {
|
||
const timer = setTimeout(() => setVisible(true), 100);
|
||
return () => clearTimeout(timer);
|
||
}, []);
|
||
|
||
const handleRetry = () => {
|
||
setShake(true);
|
||
setTimeout(() => setShake(false), 600);
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<style>{`
|
||
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap');
|
||
|
||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||
|
||
:root {
|
||
--red: #E83A3A;
|
||
--red-dark: #C02828;
|
||
--red-glow: rgba(232,58,58,0.18);
|
||
--bg: #0D0D0D;
|
||
--surface: #141414;
|
||
--surface2: #1C1C1C;
|
||
--border: rgba(255,255,255,0.07);
|
||
--text: #F0EDE8;
|
||
--muted: rgba(240,237,232,0.45);
|
||
}
|
||
|
||
body {
|
||
background: var(--bg);
|
||
font-family: 'DM Sans', sans-serif;
|
||
color: var(--text);
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.page {
|
||
min-height: 100vh;
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* Noise overlay */
|
||
.page::before {
|
||
content: '';
|
||
position: fixed;
|
||
inset: 0;
|
||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
opacity: 0.6;
|
||
}
|
||
|
||
/* Left panel */
|
||
.left {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
padding: 2.5rem;
|
||
border-right: 1px solid var(--border);
|
||
z-index: 1;
|
||
opacity: 0;
|
||
transform: translateX(-30px);
|
||
transition: opacity 0.7s ease, transform 0.7s ease;
|
||
}
|
||
.left.visible { opacity: 1; transform: translateX(0); }
|
||
|
||
.lang-switcher {
|
||
display: flex;
|
||
gap: 0.4rem;
|
||
align-self: flex-start;
|
||
}
|
||
.lang-btn {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--muted);
|
||
font-family: 'DM Sans', sans-serif;
|
||
font-size: 0.7rem;
|
||
font-weight: 500;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
padding: 0.35rem 0.7rem;
|
||
border-radius: 2rem;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
.lang-btn:hover { color: var(--text); border-color: rgba(255,255,255,0.2); }
|
||
.lang-btn.active {
|
||
background: var(--red);
|
||
border-color: var(--red);
|
||
color: #fff;
|
||
}
|
||
|
||
.title-block { flex: 1; display: flex; align-items: center; }
|
||
|
||
.main-title {
|
||
font-family: 'Bebas Neue', sans-serif;
|
||
font-size: clamp(4.5rem, 10vw, 9rem);
|
||
line-height: 0.9;
|
||
letter-spacing: 0.02em;
|
||
color: var(--text);
|
||
white-space: pre-line;
|
||
position: relative;
|
||
}
|
||
|
||
.title-accent {
|
||
display: block;
|
||
color: var(--red);
|
||
position: relative;
|
||
}
|
||
.title-accent::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -4px;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 3px;
|
||
background: var(--red);
|
||
transform: scaleX(0);
|
||
transform-origin: left;
|
||
animation: underline-grow 0.5s 0.9s ease forwards;
|
||
}
|
||
@keyframes underline-grow { to { transform: scaleX(1); } }
|
||
|
||
.meta-row {
|
||
display: flex;
|
||
gap: 2rem;
|
||
border-top: 1px solid var(--border);
|
||
padding-top: 1.5rem;
|
||
}
|
||
.meta-item { display: flex; flex-direction: column; gap: 0.25rem; }
|
||
.meta-label {
|
||
font-size: 0.65rem;
|
||
letter-spacing: 0.12em;
|
||
text-transform: uppercase;
|
||
color: var(--muted);
|
||
}
|
||
.meta-value {
|
||
font-family: 'Bebas Neue', sans-serif;
|
||
font-size: 1.1rem;
|
||
letter-spacing: 0.05em;
|
||
color: var(--red);
|
||
}
|
||
|
||
/* Right panel */
|
||
.right {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
padding: 2.5rem 3rem;
|
||
z-index: 1;
|
||
opacity: 0;
|
||
transform: translateX(30px);
|
||
transition: opacity 0.7s 0.2s ease, transform 0.7s 0.2s ease;
|
||
}
|
||
.right.visible { opacity: 1; transform: translateX(0); }
|
||
|
||
/* Glowing orb background */
|
||
.orb {
|
||
position: absolute;
|
||
width: 350px;
|
||
height: 350px;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle, rgba(232,58,58,0.12) 0%, transparent 70%);
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
pointer-events: none;
|
||
animation: pulse-orb 4s ease-in-out infinite;
|
||
}
|
||
@keyframes pulse-orb {
|
||
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.6; }
|
||
50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
|
||
}
|
||
|
||
.badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
background: var(--red-glow);
|
||
border: 1px solid rgba(232,58,58,0.3);
|
||
border-radius: 2rem;
|
||
padding: 0.4rem 1rem;
|
||
font-size: 0.75rem;
|
||
font-weight: 500;
|
||
letter-spacing: 0.06em;
|
||
color: var(--red);
|
||
margin-bottom: 2rem;
|
||
width: fit-content;
|
||
}
|
||
.badge-dot {
|
||
width: 6px; height: 6px;
|
||
border-radius: 50%;
|
||
background: var(--red);
|
||
animation: blink 1.2s ease-in-out infinite;
|
||
}
|
||
@keyframes blink {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.2; }
|
||
}
|
||
|
||
.icon-wrap {
|
||
width: 80px; height: 80px;
|
||
border-radius: 50%;
|
||
background: var(--surface2);
|
||
border: 1px solid rgba(232,58,58,0.25);
|
||
display: flex; align-items: center; justify-content: center;
|
||
margin-bottom: 2rem;
|
||
position: relative;
|
||
animation: shake-anim 0s ease;
|
||
}
|
||
.icon-wrap.shake { animation: shake-anim 0.5s ease; }
|
||
@keyframes shake-anim {
|
||
0%, 100% { transform: translateX(0) rotate(0); }
|
||
15% { transform: translateX(-6px) rotate(-3deg); }
|
||
30% { transform: translateX(6px) rotate(3deg); }
|
||
45% { transform: translateX(-4px) rotate(-2deg); }
|
||
60% { transform: translateX(4px) rotate(2deg); }
|
||
75% { transform: translateX(-2px) rotate(-1deg); }
|
||
}
|
||
.icon-ring {
|
||
position: absolute;
|
||
inset: -8px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(232,58,58,0.15);
|
||
animation: ring-pulse 2s ease-in-out infinite;
|
||
}
|
||
@keyframes ring-pulse {
|
||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||
50% { transform: scale(1.08); opacity: 1; }
|
||
}
|
||
|
||
.subtitle {
|
||
font-size: 1rem;
|
||
font-weight: 300;
|
||
color: var(--muted);
|
||
line-height: 1.7;
|
||
margin-bottom: 2.5rem;
|
||
max-width: 340px;
|
||
}
|
||
|
||
.reasons-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 1.5rem;
|
||
margin-bottom: 2.5rem;
|
||
}
|
||
.reasons-title {
|
||
font-size: 0.7rem;
|
||
font-weight: 500;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
color: var(--muted);
|
||
margin-bottom: 1rem;
|
||
}
|
||
.reason-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.6rem 0;
|
||
border-bottom: 1px solid var(--border);
|
||
font-size: 0.875rem;
|
||
font-weight: 300;
|
||
color: var(--text);
|
||
opacity: 0;
|
||
transform: translateX(10px);
|
||
transition: opacity 0.4s ease, transform 0.4s ease;
|
||
}
|
||
.reason-item.visible { opacity: 1; transform: translateX(0); }
|
||
.reason-item:last-child { border-bottom: none; }
|
||
.reason-dot {
|
||
width: 4px; height: 4px;
|
||
border-radius: 50%;
|
||
background: var(--red);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.75rem;
|
||
}
|
||
.btn-primary {
|
||
background: var(--red);
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 8px;
|
||
padding: 1rem 1.5rem;
|
||
font-family: 'DM Sans', sans-serif;
|
||
font-size: 0.9rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.2s, transform 0.1s;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.btn-primary::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: white;
|
||
opacity: 0;
|
||
transition: opacity 0.2s;
|
||
}
|
||
.btn-primary:hover { background: var(--red-dark); }
|
||
.btn-primary:hover::after { opacity: 0.05; }
|
||
.btn-primary:active { transform: scale(0.98); }
|
||
|
||
.btn-row { display: flex; gap: 0.75rem; }
|
||
.btn-secondary {
|
||
flex: 1;
|
||
background: var(--surface2);
|
||
color: var(--text);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 0.85rem 1rem;
|
||
font-family: 'DM Sans', sans-serif;
|
||
font-size: 0.85rem;
|
||
font-weight: 400;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
.btn-secondary:hover {
|
||
background: var(--surface);
|
||
border-color: rgba(255,255,255,0.15);
|
||
}
|
||
|
||
/* Diagonal stripe decoration */
|
||
.stripe {
|
||
position: absolute;
|
||
top: 0; right: 0;
|
||
width: 1px;
|
||
height: 100%;
|
||
background: linear-gradient(to bottom, transparent, var(--red), transparent);
|
||
opacity: 0.2;
|
||
}
|
||
|
||
/* Responsive */
|
||
@media (max-width: 768px) {
|
||
.page { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
|
||
.left {
|
||
padding: 1.5rem;
|
||
border-right: none;
|
||
border-bottom: 1px solid var(--border);
|
||
gap: 1.5rem;
|
||
}
|
||
.title-block { align-items: flex-start; }
|
||
.main-title { font-size: clamp(3.5rem, 14vw, 5.5rem); }
|
||
.right { padding: 2rem 1.5rem; }
|
||
.orb { width: 250px; height: 250px; }
|
||
.meta-row { gap: 1.5rem; }
|
||
}
|
||
|
||
@media (max-width: 400px) {
|
||
.left { padding: 1.25rem; }
|
||
.right { padding: 1.5rem 1.25rem; }
|
||
.btn-row { flex-direction: column; }
|
||
.reasons-card { padding: 1.25rem; }
|
||
}
|
||
`}</style>
|
||
|
||
<div className="page">
|
||
{/* LEFT */}
|
||
<div className={`left ${visible ? "visible" : ""}`}>
|
||
<div className="lang-switcher">
|
||
{["uz", "ru", "en"].map((l) => (
|
||
<button
|
||
key={l}
|
||
className={`lang-btn ${lang === l ? "active" : ""}`}
|
||
onClick={() => setLang(l)}
|
||
>
|
||
{l.toUpperCase()}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<div className="title-block">
|
||
<h1 className="main-title">
|
||
{t.title.split("\n").map((line:any, i:number) =>
|
||
i === 1 ? (
|
||
<span key={i} className="title-accent">{line}</span>
|
||
) : (
|
||
<span key={i} style={{ display: "block" }}>{line}</span>
|
||
)
|
||
)}
|
||
</h1>
|
||
</div>
|
||
|
||
<div className="meta-row">
|
||
<div className="meta-item">
|
||
<span className="meta-label">{t.code}</span>
|
||
<span className="meta-value">{ERROR_CODE}</span>
|
||
</div>
|
||
<div className="meta-item">
|
||
<span className="meta-label">{t.time}</span>
|
||
<span className="meta-value">{time}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* RIGHT */}
|
||
<div className={`right ${visible ? "visible" : ""}`}>
|
||
<div className="orb" />
|
||
<div className="stripe" />
|
||
|
||
<div className="badge">
|
||
<span className="badge-dot" />
|
||
{t.badge}
|
||
</div>
|
||
|
||
<div className={`icon-wrap ${shake ? "shake" : ""}`}>
|
||
<div className="icon-ring" />
|
||
<svg width="34" height="34" viewBox="0 0 24 24" fill="none">
|
||
<path
|
||
d="M12 9v4M12 17h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"
|
||
stroke="#E83A3A"
|
||
strokeWidth="1.5"
|
||
strokeLinecap="round"
|
||
strokeLinejoin="round"
|
||
/>
|
||
</svg>
|
||
</div>
|
||
|
||
<p className="subtitle">{t.subtitle}</p>
|
||
|
||
<div className="reasons-card">
|
||
<p className="reasons-title">{t.reasons_title}</p>
|
||
{t.reasons.map((reason, i) => (
|
||
<div
|
||
key={`${lang}-${i}`}
|
||
className={`reason-item ${visible ? "visible" : ""}`}
|
||
style={{ transitionDelay: `${0.4 + i * 0.1}s` }}
|
||
>
|
||
<span className="reason-dot" />
|
||
{reason}
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<div className="actions">
|
||
<button className="btn-primary" onClick={handleRetry}>
|
||
+998-99-940-00-49
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
} |