|
<!DOCTYPE html>
|
|
<html lang="ar">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>مولد مقالات AI</title>
|
|
<style>
|
|
body {
|
|
font-family: 'Cairo', sans-serif;
|
|
margin: 20px;
|
|
padding: 0;
|
|
background-color: #f9f9f9;
|
|
direction: rtl;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 28px;
|
|
color: #333;
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
input[type="text"] {
|
|
width: 100%;
|
|
padding: 12px;
|
|
font-size: 16px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
margin-bottom: 15px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.btn {
|
|
width: 100%;
|
|
padding: 12px;
|
|
font-size: 16px;
|
|
background-color: #007bff;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.article-box {
|
|
background-color: #fff;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
|
|
|
|
.article-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin: 0 0 10px 0;
|
|
}
|
|
|
|
.article-meta {
|
|
font-size: 14px;
|
|
color: #777;
|
|
margin: 0 0 10px 0;
|
|
}
|
|
|
|
|
|
.article-content {
|
|
display: none;
|
|
position: fixed;
|
|
top: 100%;
|
|
left: 50%;
|
|
width: 100%;
|
|
max-width: 600px;
|
|
height: 100%;
|
|
transform: translateX(-50%);
|
|
background-color: #fff;
|
|
border: none;
|
|
border-radius: 10px;
|
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
z-index: 1000;
|
|
overflow-y: auto;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease-in-out, top 0.3s ease-in-out;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.article-content.show {
|
|
top: 50%;
|
|
opacity: 1;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.overlay {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
z-index: 999;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease-in-out;
|
|
}
|
|
|
|
.overlay.show {
|
|
opacity: 1;
|
|
}
|
|
|
|
.close-btn {
|
|
position: sticky;
|
|
top: 10px;
|
|
right: 10px;
|
|
font-size: 24px;
|
|
cursor: pointer;
|
|
color: #333;
|
|
background-color: #fff;
|
|
border: 2px solid #ccc;
|
|
border-radius: 50%;
|
|
width: 40px;
|
|
height: 40px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 20;
|
|
transition: all 0.3s ease;
|
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.close-btn:hover {
|
|
color: #fff;
|
|
background-color: #ff4d4d;
|
|
border-color: #ff4d4d;
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.close-btn:active {
|
|
transform: scale(0.9);
|
|
}
|
|
|
|
.close-btn:hover {
|
|
color: #000;
|
|
}
|
|
|
|
.modal-header {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
text-align: center;
|
|
width: 100%;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
padding: 0 10px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.article-body {
|
|
font-size: 16px;
|
|
color: #555;
|
|
line-height: 1.6;
|
|
padding: 20px;
|
|
}
|
|
|
|
.modal-footer {
|
|
font-size: 14px;
|
|
color: #777;
|
|
margin-top: 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.skeleton {
|
|
width: 100%;
|
|
height: 200px;
|
|
background: #f0f0f0;
|
|
animation: pulse 1.5s infinite ease-in-out;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% {
|
|
background-color: #f0f0f0;
|
|
}
|
|
50% {
|
|
background-color: #e0e0e0;
|
|
}
|
|
100% {
|
|
background-color: #f0f0f0;
|
|
}
|
|
}
|
|
|
|
|
|
.search-box {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.search-box input {
|
|
width: 100%;
|
|
padding: 10px;
|
|
font-size: 16px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
code{
|
|
color: #fff;
|
|
background-color: #000;
|
|
padding: 5px;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px;
|
|
background-color: #f8f9fa;
|
|
border-top: 1px solid #e9ecef;
|
|
font-size: 14px;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.user-info {
|
|
font-weight: bold;
|
|
color: #007bff;
|
|
width: 23%;
|
|
}
|
|
|
|
.date {
|
|
font-style: italic;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.time {
|
|
font-weight: bold;
|
|
color: #28a745;
|
|
}
|
|
|
|
code{
|
|
color: #fff;
|
|
background-color: #000;
|
|
padding: 5px;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px;
|
|
background-color: #f8f9fa;
|
|
border-top: 1px solid #e9ecef;
|
|
font-size: 14px;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.user-info {
|
|
font-weight: bold;
|
|
color: #007bff;
|
|
}
|
|
|
|
.date {
|
|
font-style: italic;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.time {
|
|
font-weight: bold;
|
|
color: #28a745;
|
|
}
|
|
|
|
code{
|
|
color: #fff;
|
|
background-color: #000;
|
|
padding: 5px;
|
|
border-radius: 3px;
|
|
}
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px;
|
|
background-color: #f8f9fa;
|
|
border-top: 1px solid #e9ecef;
|
|
font-size: 14px;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.user-info {
|
|
font-weight: bold;
|
|
color: #007bff;
|
|
}
|
|
|
|
.date {
|
|
font-style: italic;
|
|
color: #6c757d;
|
|
}
|
|
|
|
.time {
|
|
font-weight: bold;
|
|
color: #28a745;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.user-photo {
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.photo_user {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
border: 2px solid #007bff;
|
|
}
|
|
|
|
.article-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin: 0 0 10px 0;
|
|
position: sticky;
|
|
top: 0;
|
|
background-color: #fff;
|
|
padding: 10px 0;
|
|
z-index: 10;
|
|
border-bottom: 1px solid #ddd;
|
|
}
|
|
|
|
.close-btn {
|
|
|
|
|
|
|
|
font-size: 30px;
|
|
cursor: pointer;
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
}
|
|
|
|
.controls{
|
|
position: sticky;
|
|
top: 0;
|
|
right: 0;
|
|
font-size: 30px;
|
|
cursor: pointer;
|
|
color: #333;
|
|
background: none;
|
|
border: none;
|
|
z-index: 20;
|
|
margin-left: auto;
|
|
padding: 5px 10px;
|
|
width: 100%;
|
|
background-color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
background-color: #007bff;
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css" rel="stylesheet"/>
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.js"></script>
|
|
|
|
<script>
|
|
let overlay = null;
|
|
|
|
function toggleContent(element) {
|
|
const content = element.querySelector('.article-content');
|
|
|
|
if (content.style.display === 'none' || content.style.display === '') {
|
|
content.style.display = 'block';
|
|
setTimeout(() => {
|
|
content.classList.add('show');
|
|
}, 10);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function closeContent(button) {
|
|
const content = button.closest('.article-content');
|
|
content.classList.remove('show');
|
|
setTimeout(() => {
|
|
content.style.display = 'none';
|
|
}, 500);
|
|
}
|
|
let isCreating = false;
|
|
|
|
|
|
async function createArticle() {
|
|
if (isCreating) {
|
|
|
|
const message = document.createElement('div');
|
|
message.id = 'creation-message';
|
|
message.textContent = 'انتظر لم ننتهي بعد';
|
|
message.style.color = 'red';
|
|
message.style.position = 'fixed';
|
|
message.style.top = '10px';
|
|
message.style.left = '50%';
|
|
message.style.transform = 'translateX(-50%)';
|
|
message.style.padding = '10px';
|
|
message.style.backgroundColor = 'white';
|
|
message.style.border = '1px solid red';
|
|
message.style.borderRadius = '5px';
|
|
message.style.zIndex = '1000';
|
|
document.body.appendChild(message);
|
|
|
|
|
|
setTimeout(() => {
|
|
document.body.removeChild(message);
|
|
}, 3000);
|
|
|
|
return;
|
|
}
|
|
|
|
const title = document.getElementById('title').value;
|
|
if (!title) {
|
|
alert('يرجى إدخال عنوان المقال.');
|
|
return;
|
|
}
|
|
|
|
isCreating = true;
|
|
document.getElementById('loading-text').style.display = 'block';
|
|
|
|
const articleSection = document.getElementById('articles');
|
|
const loadingSkeleton = document.createElement('div');
|
|
loadingSkeleton.classList.add('skeleton');
|
|
articleSection.prepend(loadingSkeleton);
|
|
|
|
try {
|
|
|
|
const response = await fetch('/create', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ title })
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('حدث خطأ أثناء إنشاء المقال.');
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
|
|
const newArticle = document.createElement('div');
|
|
newArticle.classList.add('article-box');
|
|
newArticle.setAttribute("data-idUser" , `${data.id_user}`)
|
|
newArticle.setAttribute('onclick', 'toggleContent(this)');
|
|
newArticle.innerHTML = `
|
|
<h3 class="article-title">${data.title}</h3>
|
|
<p class="article-meta">By: ${data.user} - ${new Date(data.created_at).toLocaleString()}</p>
|
|
<div class="article-content">
|
|
<div class="controls">
|
|
<button class="close-btn" onclick="closeContent(this)">×</button>
|
|
<div class="modal-header">${data.title}</div>
|
|
</div>
|
|
<div class="article-body">${data.content}</div>
|
|
<div class="modal-footer">
|
|
<img class="photo_user" src="${data.photo_user}" alt="User Photo">
|
|
<span class="user-info">By: ${data.user}</span>
|
|
<span class="date">${new Date(data.created_at).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}</span>
|
|
<span class="time">${new Date(data.created_at).toLocaleTimeString()}</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
|
|
articleSection.removeChild(loadingSkeleton);
|
|
articleSection.prepend(newArticle);
|
|
|
|
} catch (error) {
|
|
console.error(error);
|
|
alert('حدث خطأ أثناء إنشاء المقال.');
|
|
articleSection.removeChild(loadingSkeleton);
|
|
} finally {
|
|
isCreating = false;
|
|
document.getElementById('loading-text').style.display = 'none';
|
|
}
|
|
}
|
|
|
|
|
|
function searchArticles() {
|
|
const searchTerm = document.getElementById('search').value.toLowerCase();
|
|
const articles = document.querySelectorAll('.article-box');
|
|
articles.forEach(article => {
|
|
const title = article.querySelector('.article-title').textContent.toLowerCase();
|
|
if (title.includes(searchTerm)) {
|
|
article.style.display = 'block';
|
|
} else {
|
|
article.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
const showMyArticlesButton = document.getElementById('showMyArticles');
|
|
if (showMyArticlesButton) {
|
|
showMyArticlesButton.addEventListener('click', async () => {
|
|
const currentUserId = await getCurrentUserId();
|
|
|
|
if (currentUserId) {
|
|
console.log('ID المستخدم الحالي:', currentUserId);
|
|
|
|
|
|
const articles = document.querySelectorAll('.article-box');
|
|
articles.forEach(article => {
|
|
const articleUserId = article.getAttribute('data-iduser');
|
|
if (articleUserId == currentUserId) {
|
|
article.style.display = 'block';
|
|
} else {
|
|
article.style.display = 'none';
|
|
}
|
|
});
|
|
} else {
|
|
console.log('لم يتم العثور على id المستخدم.');
|
|
alert('يجب تسجيل الدخول لعرض مقالاتك.');
|
|
}
|
|
});
|
|
} else {
|
|
console.error('الزر "عرض مقالاتي" غير موجود في الصفحة.');
|
|
}
|
|
|
|
|
|
const showAllArticlesButton = document.getElementById('showAllArticles');
|
|
if (showAllArticlesButton) {
|
|
showAllArticlesButton.addEventListener('click', () => {
|
|
|
|
const articles = document.querySelectorAll('.article-box');
|
|
articles.forEach(article => {
|
|
article.style.display = 'block';
|
|
});
|
|
});
|
|
} else {
|
|
console.error('الزر "عرض كل المقالات" غير موجود في الصفحة.');
|
|
}
|
|
});
|
|
|
|
|
|
async function getCurrentUserId() {
|
|
try {
|
|
const response = await fetch('/current_user_id', {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('فشل في جلب بيانات المستخدم');
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data.id;
|
|
} catch (error) {
|
|
console.error('حدث خطأ:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="loading-text" style="text-align: center; margin-top: 20px; display: none;">
|
|
<p>جاري الإنشاء...</p>
|
|
</div>
|
|
|
|
|
|
<div class="container">
|
|
<h1>مولد مقالات AI</h1>
|
|
|
|
|
|
<div class="search-box">
|
|
<input type="text" id="search" oninput="searchArticles()" placeholder="بحث عن مقال...">
|
|
</div>
|
|
|
|
<input type="text" id="title" placeholder="أدخل عنوان المقال">
|
|
<button class="btn" onclick="createArticle()">أنشئ مقال</button>
|
|
<button id="showMyArticles">عرض مقالاتي</button>
|
|
<button id="showAllArticles">عرض كل المقالات</button>
|
|
|
|
<div id="articles">
|
|
|
|
{% for article in articles %}
|
|
<div class="article-box" data-idUser="{{ article.id_user }}" onclick="toggleContent(this)">
|
|
<h3 class="article-title">{{ article.title }}</h3>
|
|
<p class="article-meta">By: {{ article.user }} - {{ article.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</p>
|
|
<div class="article-content">
|
|
<div class="controls">
|
|
<button class="close-btn" onclick="closeContent(this)">×</button>
|
|
<div class="modal-header ">{{ article.title }}</div>
|
|
</div>
|
|
<div class="article-body">{{ article.content | safe }}</div>
|
|
<div class="modal-footer">
|
|
<img class="photo_user" src="{{ url_for('static', filename=article.photo_user) }}" alt="User Photo">
|
|
<span class="user-info">By: {{ article.user }}</span>
|
|
<span class="date">{{ article.created_at.strftime('%A, %Y-%m-%d') }}</span>
|
|
<span class="time">{{ article.created_at.strftime('%H:%M') }}</span>
|
|
<div class="user-photo">
|
|
</div> </div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|