Spaces:
Running
Running
<html lang="ar" dir="rtl"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>منشئ العقود الذكي</title> | |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap'); | |
body { | |
font-family: 'IBM Plex Sans Arabic', sans-serif; | |
background: #ffffff; | |
min-height: 100vh; | |
} | |
.split-screen { | |
display: grid; | |
grid-template-columns: 1fr 1fr; | |
gap: 2rem; | |
max-width: 1400px; | |
margin: 2rem auto; | |
padding: 0 2rem; | |
min-height: calc(100vh - 4rem); | |
} | |
.input-group { | |
position: relative; | |
margin-bottom: 1.5rem; | |
} | |
.input-group input, .input-group textarea, .input-group select { | |
width: 100%; | |
padding: 1rem 1.25rem; | |
border: 2px solid #e5e7eb; | |
border-radius: 1rem; | |
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
background: #ffffff; | |
font-size: 1rem; | |
} | |
.input-group input:focus, .input-group textarea:focus, .input-group select:focus { | |
border-color: #2563eb; | |
box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.1); | |
outline: none; | |
transform: translateY(-2px); | |
} | |
.card { | |
background: white; | |
border-radius: 1.5rem; | |
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); | |
padding: 2.5rem; | |
height: fit-content; | |
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
border: 1px solid #f3f4f6; | |
} | |
.card:hover { | |
transform: translateY(-4px); | |
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12); | |
} | |
.contract-output { | |
background: #fafafa; | |
border-radius: 1rem; | |
padding: 2rem; | |
min-height: 300px; | |
line-height: 1.8; | |
font-size: 1.1rem; | |
border: 1px solid #f3f4f6; | |
} | |
.btn { | |
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%); | |
color: white; | |
padding: 1rem 2.5rem; | |
border-radius: 1rem; | |
font-weight: 600; | |
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
border: none; | |
cursor: pointer; | |
font-size: 1.1rem; | |
position: relative; | |
overflow: hidden; | |
} | |
.btn:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 8px 20px rgba(37, 99, 235, 0.25); | |
} | |
.btn:active { | |
transform: translateY(0); | |
} | |
.copy-btn { | |
position: absolute; | |
top: 1rem; | |
left: 1rem; | |
padding: 0.5rem 1rem; | |
background: #f3f4f6; | |
border-radius: 0.75rem; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
display: flex; | |
align-items: center; | |
gap: 0.5rem; | |
font-size: 0.9rem; | |
color: #4b5563; | |
} | |
.copy-btn:hover { | |
background: #e5e7eb; | |
} | |
.success-message { | |
position: fixed; | |
bottom: 2rem; | |
right: 2rem; | |
background: #10b981; | |
color: white; | |
padding: 1rem 2rem; | |
border-radius: 1rem; | |
animation: slideIn 0.3s ease; | |
} | |
@keyframes slideIn { | |
from { transform: translateX(100%); opacity: 0; } | |
to { transform: translateX(0); opacity: 1; } | |
} | |
.loading { | |
position: relative; | |
} | |
.loading::after { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); | |
animation: loading 1.5s infinite; | |
} | |
.section-title { | |
font-size: 1.25rem; | |
color: #1f2937; | |
margin-bottom: 1.5rem; | |
padding-bottom: 0.75rem; | |
border-bottom: 2px solid #e5e7eb; | |
font-weight: 600; | |
} | |
.contract-type-selector { | |
display: flex; | |
gap: 1rem; | |
margin-bottom: 2rem; | |
} | |
.type-option { | |
flex: 1; | |
padding: 1.5rem; | |
border: 2px solid #e5e7eb; | |
border-radius: 1rem; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
text-align: center; | |
} | |
.type-option.active { | |
border-color: #2563eb; | |
background: rgba(37, 99, 235, 0.05); | |
} | |
.type-option:hover { | |
transform: translateY(-2px); | |
} | |
@media (max-width: 768px) { | |
.split-screen { | |
grid-template-columns: 1fr; | |
padding: 1rem; | |
} | |
.card { | |
margin-bottom: 1rem; | |
padding: 1.5rem; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="split-screen"> | |
<div class="card animate__animated animate__fadeInRight"> | |
<h1 class="text-4xl font-bold mb-8 text-center text-gray-800">منشئ العقود الذكي</h1> | |
<div class="contract-type-selector"> | |
<div class="type-option active" data-type="rental"> | |
<h3 class="font-bold mb-2">عقد إيجار</h3> | |
<p class="text-sm text-gray-600">عقود الإيجار السكنية والتجارية</p> | |
</div> | |
<div class="type-option" data-type="custom"> | |
<h3 class="font-bold mb-2">عقد مخصص</h3> | |
<p class="text-sm text-gray-600">صياغة عقد حسب احتياجاتك</p> | |
</div> | |
</div> | |
<div id="rentalTemplate" class="contract-template active space-y-6"> | |
<h2 class="section-title">معلومات العقد الأساسية</h2> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">المؤجر:</label> | |
<input type="text" id="landlord" placeholder="اسم المؤجر الكامل" class="focus:ring-2 focus:ring-blue-500"> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">المستأجر:</label> | |
<input type="text" id="tenant" placeholder="اسم المستأجر الكامل"> | |
</div> | |
<h2 class="section-title">تفاصيل العقار والإيجار</h2> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">عنوان العقار:</label> | |
<input type="text" id="propertyAddress" placeholder="العنوان التفصيلي للعقار"> | |
</div> | |
<div class="grid grid-cols-2 gap-4"> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">مدة الإيجار:</label> | |
<input type="text" id="rentalPeriod" placeholder="مثال: سنة واحدة"> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">قيمة الإيجار:</label> | |
<input type="text" id="rentalAmount" placeholder="القيمة بالجنيه المصري"> | |
</div> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">شروط إضافية:</label> | |
<textarea id="additionalTerms" class="h-32" placeholder="أي شروط أو ملاحظات إضافية"></textarea> | |
</div> | |
</div> | |
<div id="customTemplate" class="contract-template hidden space-y-6"> | |
<h2 class="section-title">معلومات العقد المخصص</h2> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">عنوان العقد:</label> | |
<input type="text" id="contractTitle" placeholder="عنوان العقد"> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">الطرف الأول:</label> | |
<input type="text" id="firstParty" placeholder="اسم الطرف الأول"> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">الطرف الثاني:</label> | |
<input type="text" id="secondParty" placeholder="اسم الطرف الثاني"> | |
</div> | |
<div class="input-group"> | |
<label class="block text-gray-700 font-bold mb-2">تفاصيل العقد:</label> | |
<textarea id="contractDetails" class="h-64" placeholder="اكتب تفاصيل العقد هنا"></textarea> | |
</div> | |
</div> | |
<div class="mt-8 flex justify-center"> | |
<button id="generateButton" class="btn"> | |
إنشاء العقد | |
</button> | |
</div> | |
</div> | |
<div class="card animate__animated animate__fadeInLeft"> | |
<h2 class="text-2xl font-bold mb-6 text-gray-800">العقد المنشأ</h2> | |
<div class="relative"> | |
<button class="copy-btn" id="copyButton"> | |
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" /> | |
</svg> | |
نسخ العقد | |
</button> | |
<div id="contractOutput" class="contract-output prose"></div> | |
</div> | |
</div> | |
</div> | |
<script> | |
const API_URL = 'https://j8fp9mu44k547j-7777.proxy.runpod.net/proxy/8000/chat'; | |
let currentController = null; | |
// تحسين تجربة المستخدم للمدخلات | |
document.querySelectorAll('input, textarea').forEach(element => { | |
element.addEventListener('focus', function() { | |
this.closest('.input-group').classList.add('focused'); | |
this.style.transform = 'translateY(-2px)'; | |
}); | |
element.addEventListener('blur', function() { | |
this.closest('.input-group').classList.remove('focused'); | |
this.style.transform = 'translateY(0)'; | |
}); | |
// إضافة تأثير ripple عند النقر | |
element.addEventListener('click', function(e) { | |
const ripple = document.createElement('div'); | |
ripple.classList.add('ripple'); | |
this.appendChild(ripple); | |
setTimeout(() => ripple.remove(), 1000); | |
}); | |
}); | |
// تحسين تبديل نوع العقد | |
document.querySelectorAll('.type-option').forEach(option => { | |
option.addEventListener('click', function() { | |
// إزالة الفئة النشطة من جميع الخيارات | |
document.querySelectorAll('.type-option').forEach(opt => { | |
opt.classList.remove('active'); | |
}); | |
// إضافة الفئة النشطة للخيار المحدد | |
this.classList.add('active'); | |
// إخفاء جميع النماذج | |
document.querySelectorAll('.contract-template').forEach(template => { | |
template.classList.add('hidden'); | |
}); | |
// إظهار النموذج المحدد | |
const templateId = this.dataset.type === 'rental' ? 'rentalTemplate' : 'customTemplate'; | |
// إظهار النموذج المحدد مع تأثير حركي | |
const selectedTemplate = document.getElementById(templateId); | |
selectedTemplate.classList.remove('hidden'); | |
selectedTemplate.classList.add('animate__animated', 'animate__fadeIn'); | |
}); | |
}); | |
// نسخ العقد إلى الحافظة | |
document.getElementById('copyButton').addEventListener('click', async function() { | |
const contractText = document.getElementById('contractOutput').innerText; | |
try { | |
await navigator.clipboard.writeText(contractText); | |
// إظهار رسالة نجاح | |
const successMessage = document.createElement('div'); | |
successMessage.className = 'success-message animate__animated animate__fadeIn'; | |
successMessage.textContent = 'تم نسخ العقد بنجاح!'; | |
document.body.appendChild(successMessage); | |
// إزالة رسالة النجاح بعد ثانيتين | |
setTimeout(() => { | |
successMessage.classList.add('animate__fadeOut'); | |
setTimeout(() => successMessage.remove(), 300); | |
}, 2000); | |
} catch (err) { | |
console.error('فشل نسخ النص: ', err); | |
} | |
}); | |
// تحسين عملية إنشاء العقد | |
document.getElementById('generateButton').addEventListener('click', async function() { | |
const button = this; | |
const outputDiv = document.getElementById('contractOutput'); | |
const contractType = document.querySelector('.type-option.active').dataset.type; | |
let prompt = ''; | |
// تجميع البيانات حسب نوع العقد | |
if (contractType === 'rental') { | |
const formData = { | |
landlord: document.getElementById('landlord').value, | |
tenant: document.getElementById('tenant').value, | |
propertyAddress: document.getElementById('propertyAddress').value, | |
rentalPeriod: document.getElementById('rentalPeriod').value, | |
rentalAmount: document.getElementById('rentalAmount').value, | |
additionalTerms: document.getElementById('additionalTerms').value | |
}; | |
// التحقق من البيانات المطلوبة | |
const requiredFields = ['landlord', 'tenant', 'propertyAddress', 'rentalPeriod', 'rentalAmount']; | |
const missingFields = requiredFields.filter(field => !formData[field]); | |
if (missingFields.length > 0) { | |
outputDiv.innerHTML = ` | |
<div class="text-red-500 font-bold mb-4">يرجى ملء الحقول التالية:</div> | |
<ul class="list-disc list-inside text-red-500"> | |
${missingFields.map(field => `<li>${getFieldLabel(field)}</li>`).join('')} | |
</ul> | |
`; | |
return; | |
} | |
prompt = `أنشئ عقد إيجار رسمي باللغة العربية يتضمن البيانات التالية: | |
المؤجر: ${formData.landlord} | |
المستأجر: ${formData.tenant} | |
عنوان العقار: ${formData.propertyAddress} | |
مدة الإيجار: ${formData.rentalPeriod} | |
قيمة الإيجار: ${formData.rentalAmount} | |
${formData.additionalTerms ? `شروط إضافية: ${formData.additionalTerms}` : ''} | |
يجب أن يكون العقد شاملاً وقانونياً ويحتوي على كافة البنود الأساسية المتعارف عليها في عقود الإيجار.`; | |
} else { | |
const formData = { | |
title: document.getElementById('contractTitle').value, | |
firstParty: document.getElementById('firstParty').value, | |
secondParty: document.getElementById('secondParty').value, | |
details: document.getElementById('contractDetails').value | |
}; | |
// التحقق من البيانات المطلوبة | |
const requiredFields = ['title', 'firstParty', 'secondParty', 'details']; | |
const missingFields = requiredFields.filter(field => !formData[field]); | |
if (missingFields.length > 0) { | |
outputDiv.innerHTML = ` | |
<div class="text-red-500 font-bold mb-4">يرجى ملء الحقول التالية:</div> | |
<ul class="list-disc list-inside text-red-500"> | |
${missingFields.map(field => `<li>${getFieldLabel(field)}</li>`).join('')} | |
</ul> | |
`; | |
return; | |
} | |
prompt = `أنشئ عقداً مخصصاً باللغة العربية يتضمن البيانات التالية: | |
عنوان العقد: ${formData.title} | |
الطرف الأول: ${formData.firstParty} | |
الطرف الثاني: ${formData.secondParty} | |
تفاصيل العقد: ${formData.details} | |
يجب أن يكون العقد رسمياً وقانونياً ومنظماً بشكل احترافي.`; | |
} | |
if (currentController) { | |
currentController.abort(); | |
currentController = null; | |
button.textContent = 'إنشاء العقد'; | |
button.classList.remove('loading'); | |
return; | |
} | |
try { | |
// تحديث واجهة المستخدم لحالة التحميل | |
button.textContent = 'إيقاف الإنشاء'; | |
button.classList.add('loading'); | |
outputDiv.innerHTML = ` | |
<div class="flex items-center justify-center space-x-4 text-gray-600"> | |
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div> | |
<span>جاري إنشاء العقد...</span> | |
</div> | |
`; | |
currentController = new AbortController(); | |
const response = await fetch(API_URL, { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ | |
message: prompt, | |
history: [] | |
}), | |
signal: currentController.signal | |
}); | |
const data = await response.json(); | |
outputDiv.innerHTML = data.response.replace(/\n/g, '<br>'); | |
outputDiv.classList.add('animate__animated', 'animate__fadeIn'); | |
} catch (error) { | |
if (error.name === 'AbortError') { | |
outputDiv.innerHTML = ` | |
<div class="text-yellow-600 font-bold"> | |
تم إيقاف إنشاء العقد | |
</div> | |
`; | |
} else { | |
outputDiv.innerHTML = ` | |
<div class="text-red-600 font-bold"> | |
عذراً، حدث خطأ في إنشاء العقد. يرجى المحاولة مرة أخرى. | |
</div> | |
`; | |
} | |
} finally { | |
currentController = null; | |
button.textContent = 'إنشاء العقد'; | |
button.classList.remove('loading'); | |
} | |
}); | |
// دالة مساعدة للحصول على تسميات الحقول بالعربية | |
function getFieldLabel(field) { | |
const labels = { | |
landlord: 'المؤجر', | |
tenant: 'المستأجر', | |
propertyAddress: 'عنوان العقار', | |
rentalPeriod: 'مدة الإيجار', | |
rentalAmount: 'قيمة الإيجار', | |
title: 'عنوان العقد', | |
firstParty: 'الطرف الأول', | |
secondParty: 'الطرف الثاني', | |
details: 'تفاصيل العقد' | |
}; | |
return labels[field] || field; | |
} | |
// إضافة تأثيرات حركية عند التمرير | |
const cards = document.querySelectorAll('.card'); | |
window.addEventListener('scroll', () => { | |
cards.forEach(card => { | |
const rect = card.getBoundingClientRect(); | |
const isVisible = rect.top < window.innerHeight && rect.bottom >= 0; | |
if (isVisible) { | |
card.style.transform = 'translateY(-4px)'; | |
} else { | |
card.style.transform = 'translateY(0)'; | |
} | |
}); | |
}); | |
</script> | |
</body> | |
</html> |