data-str / templates /admin_generate.html
CORVO-AI's picture
Upload 135 files
b83571a verified
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>لوحة تحكم الأدمن - توليد الكروت</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@700;800;900&family=Tajawal:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{
--clay-canvas:#F4F1FA;
--clay-foreground:#332F3A;
--clay-muted:#635F69;
--clay-primary:#7C3AED;
--clay-primary-light:#A78BFA;
--clay-accent-pink:#DB2777;
--clay-input-bg:#EFEBF5;
--clay-success:#10B981;
--shadow-clay-card:
16px 16px 32px rgba(160,150,180,0.2),
-10px -10px 24px rgba(255,255,255,0.9),
inset 6px 6px 12px rgba(139,92,246,0.03),
inset -6px -6px 12px rgba(255,255,255,1);
--shadow-clay-btn:
12px 12px 24px rgba(139,92,246,0.3),
-8px -8px 16px rgba(255,255,255,0.4),
inset 4px 4px 8px rgba(255,255,255,0.4),
inset -4px -4px 8px rgba(0,0,0,0.1);
--shadow-clay-pressed:
inset 6px 6px 12px #d9d4e3,
inset -6px -6px 12px #ffffff;
--shadow-clay-secondary:
6px 6px 12px rgba(160,150,180,0.15),
-4px -4px 10px rgba(255,255,255,0.8),
inset 2px 2px 4px rgba(255,255,255,0.4),
inset -2px -2px 4px rgba(0,0,0,0.05);
--radius-card:32px;
--radius-input:16px;
--radius-btn:20px;
}
*{margin:0;padding:0;box-sizing:border-box;}
body{
font-family:'Tajawal',sans-serif;
background:var(--clay-canvas);
color:var(--clay-foreground);
min-height:100vh;
display:flex;
justify-content:center;
align-items:center;
padding:20px;
}
h1{
font-family:'Cairo',sans-serif;
font-size:32px;
font-weight:900;
margin-bottom:24px;
text-align:center;
color: var(--clay-primary);
text-shadow: 2px 2px 4px rgba(124, 58, 237, 0.1);
}
.clay-card{
background:rgba(255,255,255,0.65);
backdrop-filter:blur(20px);
-webkit-backdrop-filter:blur(20px);
padding:40px;
border-radius:var(--radius-card);
box-shadow:var(--shadow-clay-card);
width:100%;
max-width:520px;
border: 1px solid rgba(255,255,255,0.5);
}
.form-group{
margin-bottom:20px;
}
label{
display:block;
margin-bottom:8px;
font-weight:700;
color: var(--clay-muted);
}
input,select{
width:100%;
padding:16px;
border:none;
border-radius:var(--radius-input);
background:var(--clay-input-bg);
font-size:16px;
box-shadow:var(--shadow-clay-pressed);
outline:none;
font-family:'Tajawal',sans-serif;
color: var(--clay-foreground);
transition: all 0.3s ease;
}
input:focus, select:focus{
box-shadow:
inset 4px 4px 8px #d9d4e3,
inset -4px -4px 8px #ffffff,
0 0 0 3px rgba(124, 58, 237, 0.1);
}
.btn-primary{
width:100%;
padding:18px;
margin-top:10px;
background:linear-gradient(135deg,var(--clay-primary-light),var(--clay-primary));
color:white;
border:none;
border-radius:var(--radius-btn);
font-size:18px;
font-weight:800;
font-family:'Cairo',sans-serif;
cursor:pointer;
box-shadow:var(--shadow-clay-btn);
transition:0.2s;
position: relative;
overflow: hidden;
}
.btn-primary:hover{
transform:translateY(-3px);
filter: brightness(1.05);
}
.btn-primary:active{
transform:translateY(1px);
box-shadow: var(--shadow-clay-pressed);
}
.btn-group {
display: flex;
gap: 10px;
margin-top: 15px;
}
.btn-secondary {
flex: 1;
padding: 12px;
background: var(--clay-input-bg);
color: var(--clay-foreground);
border: none;
border-radius: var(--radius-btn);
font-weight: 700;
font-family: 'Tajawal', sans-serif;
cursor: pointer;
box-shadow: var(--shadow-clay-secondary);
transition: 0.2s;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
.btn-secondary:hover {
transform: translateY(-2px);
color: var(--clay-primary);
}
.btn-secondary:active {
transform: translateY(1px);
box-shadow: var(--shadow-clay-pressed);
}
.result-box{
margin-top:25px;
background:var(--clay-input-bg);
border-radius:var(--radius-input);
padding:20px;
box-shadow:var(--shadow-clay-pressed);
white-space:pre-line;
font-size:14px;
line-height:1.8;
min-height: 100px;
max-height: 300px;
overflow-y: auto;
border: 2px dashed rgba(124, 58, 237, 0.1);
position: relative;
direction: ltr; /* لعرض السيريل والكود بشكل صحيح */
text-align: left;
}
.background-blobs{
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
z-index:-1;
overflow:hidden;
pointer-events: none;
}
.blob{
position:absolute;
border-radius:50%;
filter:blur(80px);
opacity:0.6;
animation:float 10s infinite ease-in-out;
}
.blob-1{
width:60vh;
height:60vh;
background:var(--clay-primary);
top:-10%;
right:-10%;
opacity:0.15;
}
.blob-2{
width:50vh;
height:50vh;
background:var(--clay-accent-pink);
bottom:-10%;
left:-10%;
opacity:0.15;
}
.blob-3{
width:40vh;
height:40vh;
background:#0EA5E9;
top:40%;
right:40%;
opacity:0.1;
}
@keyframes float{
0%,100%{transform:translateY(0)}
50%{transform:translateY(-30px)}
}
.toast {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%) translateY(100px);
background: var(--clay-foreground);
color: white;
padding: 12px 24px;
border-radius: 50px;
box-shadow: 0 10px 20px rgba(0,0,0,0.2);
opacity: 0;
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
z-index: 1000;
font-weight: 500;
display: flex;
align-items: center;
gap: 10px;
}
.toast.show {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
.loader {
display: none;
width: 20px;
height: 20px;
border: 3px solid rgba(255,255,255,0.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
margin-right: 10px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="background-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
</div>
<div class="clay-card">
<h1>🎫 توليد الكروت</h1>
<div class="form-group">
<label>الفئة</label>
<select id="class">
<option value="10">10</option>
<option value="20">20</option>
<option value="35">35 (علمي)</option>
<option value="45">45 (أدبي)</option>
</select>
</div>
<div class="form-group">
<label>العدد</label>
<input type="number" id="qty" value="1" min="1" max="100">
</div>
<button class="btn-primary" onclick="generate()" id="genBtn">
<span class="loader" id="btnLoader"></span>
<span id="btnText">توليد الكروت</span>
</button>
<div class="result-box" id="result">
<span style="color: var(--clay-muted); font-size: 14px; opacity: 0.7; direction: rtl; text-align: right;">
سيظهر السيريل والكود هنا...
</span>
</div>
<div class="btn-group">
<button class="btn-secondary" onclick="copyResult()" id="copyBtn" style="display:none;">
📋 نسخ النص
</button>
<button class="btn-secondary" onclick="clearResult()" id="clearBtn" style="display:none;">
🗑️ مسح
</button>
</div>
</div>
<div class="toast" id="toast">✅ تم النسخ بنجاح</div>
<script>
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
toast.innerText = message;
toast.style.background = type === 'error' ? '#EF4444' : 'var(--clay-foreground)';
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
}
function generate(){
const cls=document.getElementById('class').value;
const qty=document.getElementById('qty').value;
const resultBox = document.getElementById('result');
const btn = document.getElementById('genBtn');
const loader = document.getElementById('btnLoader');
const btnText = document.getElementById('btnText');
if(!qty || qty <= 0) {
showToast("الرجاء إدخال رقم صحيح للعدد", "error");
return;
}
// UI Loading State
btn.disabled = true;
btn.style.opacity = "0.8";
loader.style.display = "inline-block";
btnText.innerText = "جاري التوليد...";
// تجهيز البيانات لإرسالها للسيرفر
// السيرفر يتطلب request.form لذلك نستخدم URLSearchParams
const formData = new URLSearchParams();
formData.append('class', cls);
formData.append('quantity', qty);
fetch('/admin/generate_cards', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData
})
.then(response => response.json())
.then(data => {
if(data.success){
let txt = "";
data.cards.forEach(c => {
// تنسيق النص ليكون مقروءاً
txt += `Serial: ${c.serial} | Code: ${c.code} | Class: ${c.class}\n`;
});
resultBox.innerText = txt;
document.getElementById('copyBtn').style.display = 'flex';
document.getElementById('clearBtn').style.display = 'flex';
showToast(`تم توليد ${data.cards.length} كرت بنجاح`);
} else {
showToast("فشل التوليد", "error");
resultBox.innerText = "حدث خطأ غير معروف من السيرفر.";
}
})
.catch(error => {
console.error('Error:', error);
showToast("خطأ في الاتصال بالسيرفر", "error");
resultBox.innerText = "تأكد من أن السيرفر يعمل وأنك فتحت الصفحة من خلاله.";
})
.finally(() => {
// إعادة زر التوليد لحالته الطبيعية
btn.disabled = false;
btn.style.opacity = "1";
loader.style.display = "none";
btnText.innerText = "توليد الكروت";
});
}
function copyResult() {
const resultText = document.getElementById('result').innerText;
if (!resultText || resultText.includes("سيظهر السيريل")) return;
navigator.clipboard.writeText(resultText).then(() => {
showToast("تم نسخ جميع البيانات للحافظة");
}).catch(err => {
showToast("فشل النسخ", "error");
});
}
function clearResult() {
document.getElementById('result').innerHTML = '<span style="color: var(--clay-muted); font-size: 14px; opacity: 0.7; direction: rtl; text-align: right;">سيظهر السيريل والكود هنا...</span>';
document.getElementById('copyBtn').style.display = 'none';
document.getElementById('clearBtn').style.display = 'none';
document.getElementById('qty').value = 1;
}
</script>
</body>
</html>