-
Notifications
You must be signed in to change notification settings - Fork 30
Open
Description
<title>نظام تتبع إنتاج المطبعة - PrintTrack Pro</title>
<style>
:root {
--primary: #2c3e50;
--secondary: #e74c3c;
--light: #ecf0f1;
--dark: #2c3e50;
--success: #27ae60;
--warning: #f39c12;
--info: #3498db;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7f9;
color: #333;
direction: rtl;
}
.sidebar {
background-color: var(--primary);
color: white;
height: 100vh;
position: fixed;
padding-top: 60px;
box-shadow: 3px 0 10px rgba(0, 0, 0, 0.1);
z-index: 1000;
right: 0;
top: 0;
width: 250px;
}
.sidebar .nav-link {
color: rgba(255, 255, 255, 0.8);
padding: 15px 20px;
margin: 5px 0;
border-radius: 5px;
transition: all 0.3s;
}
.sidebar .nav-link:hover,
.sidebar .nav-link.active {
background-color: rgba(255, 255, 255, 0.1);
color: white;
}
.sidebar .nav-link i {
margin-left: 10px;
}
.main-content {
margin-right: 250px;
padding: 20px;
}
.header {
background-color: white;
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
.stats-card {
background-color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
text-align: center;
transition: transform 0.3s;
}
.stats-card:hover {
transform: translateY(-5px);
}
.stats-card i {
font-size: 2.5rem;
margin-bottom: 15px;
}
.stats-card .card-title {
font-size: 1.2rem;
color: var(--dark);
margin-bottom: 10px;
}
.stats-card .card-value {
font-size: 2rem;
font-weight: bold;
}
.card-orders { border-bottom: 4px solid var(--info); }
.card-orders i { color: var(--info); }
.card-progress { border-bottom: 4px solid var(--warning); }
.card-progress i { color: var(--warning); }
.card-completed { border-bottom: 4px solid var(--success); }
.card-completed i { color: var(--success); }
.card-delayed { border-bottom: 4px solid var(--secondary); }
.card-delayed i { color: var(--secondary); }
.section-title {
border-right: 4px solid var(--primary);
padding-right: 15px;
margin: 30px 0 20px;
color: var(--primary);
}
.order-card {
background-color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
border-right: 4px solid var(--info);
transition: all 0.3s;
}
.order-card.delayed { border-right: 4px solid var(--secondary); }
.order-card.urgent { border-right: 4px solid var(--warning); }
.order-card.completed { border-right: 4px solid var(--success); }
.progress-bar {
height: 10px;
border-radius: 5px;
}
.badge-status {
padding: 8px 15px;
border-radius: 20px;
font-weight: normal;
}
.table th {
background-color: var(--primary);
color: white;
}
@media (max-width: 768px) {
.sidebar {
width: 100%;
height: auto;
position: relative;
padding-top: 20px;
}
.main-content {
margin-right: 0;
margin-top: 20px;
}
}
/* Custom animations */
@keyframes pulseWarning {
0% { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(243, 156, 18, 0); }
100% { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0); }
}
.order-card.urgent {
animation: pulseWarning 2s infinite;
}
.toast-container {
position: fixed;
top: 80px;
left: 50%;
transform: translateX(-50%);
z-index: 1100;
}
.order-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.order-card-title {
margin: 0;
font-size: 1.1rem;
}
.order-card-info {
margin-bottom: 15px;
color: #666;
}
.order-card-progress {
margin-bottom: 15px;
}
.order-card-footer {
display: flex;
justify-content: space-between;
font-size: 0.9rem;
color: #666;
}
.order-card-footer i {
margin-left: 5px;
}
/* تحسينات إضافية */
.sidebar .logo {
font-weight: bold;
font-size: 1.5rem;
margin-bottom: 15px;
}
.sidebar .logo span {
color: #f1c40f;
}
.sidebar .nav-item {
margin-bottom: 5px;
}
.search-box {
position: relative;
margin-bottom: 20px;
}
.search-box i {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
color: #95a5a6;
}
.search-box input {
padding-right: 40px;
border-radius: 30px;
}
.order-priority-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
margin-left: 5px;
}
.priority-high {
background-color: var(--secondary);
}
.priority-medium {
background-color: var(--warning);
}
.priority-low {
background-color: var(--info);
}
.table-responsive {
border-radius: 10px;
overflow: hidden;
}
.table th, .table td {
vertical-align: middle;
text-align: right;
}
.action-buttons .btn {
margin: 0 2px;
}
</style>
<!-- منطقة الإشعارات -->
<div class="toast-container"></div>
<!-- الشريط الجانبي -->
<div class="sidebar">
<div class="text-center mb-4">
<div class="logo">PrintTrack <span>Pro</span></div>
<p class="text-muted">نظام تتبع الإنتاج</p>
</div>
<div class="px-3 mb-3">
<div class="input-group search-box">
<input type="text" class="form-control" placeholder="بحث...">
<i class="fas fa-search"></i>
</div>
</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#"><i class="fas fa-home"></i> لوحة التحكم</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-tasks"></i> إدارة الطلبات</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-cogs"></i> خطوط الإنتاج</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-chart-line"></i> التقارير والإحصائيات</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-users"></i> إدارة العملاء</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-box"></i> إدارة المخزون</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fas fa-cog"></i> الإعدادات</a>
</li>
<li class="nav-item mt-4">
<a class="nav-link" href="#"><i class="fas fa-sign-out-alt"></i> تسجيل الخروج</a>
</li>
</ul>
</div>
<!-- المحتوى الرئيسي -->
<div class="main-content">
<!-- الرأس -->
<div class="header d-flex justify-content-between align-items-center">
<div>
<h2>لوحة تحكم نظام PrintTrack Pro</h2>
<p class="text-muted">مرحباً بك، أحمد! آخر تسجيل دخول كان اليوم الساعة 09:45 صباحاً</p>
</div>
<div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addOrderModal">
<i class="fas fa-plus"></i> طلب جديد
</button>
</div>
</div>
<!-- إحصائيات سريعة -->
<div class="row">
<div class="col-md-3">
<div class="stats-card card-orders">
<i class="fas fa-clipboard-list"></i>
<div class="card-title">الطلبات اليوم</div>
<div id="total-orders" class="card-value">24</div>
</div>
</div>
<div class="col-md-3">
<div class="stats-card card-progress">
<i class="fas fa-spinner"></i>
<div class="card-title">قيد التنفيذ</div>
<div id="in-progress" class="card-value">18</div>
</div>
</div>
<div class="col-md-3">
<div class="stats-card card-completed">
<i class="fas fa-check-circle"></i>
<div class="card-title">مكتملة</div>
<div id="completed-orders" class="card-value">15</div>
</div>
</div>
<div class="col-md-3">
<div class="stats-card card-delayed">
<i class="fas fa-exclamation-triangle"></i>
<div class="card-title">متأخرة</div>
<div id="delayed-orders" class="card-value">3</div>
</div>
</div>
</div>
<!-- الطلبات الحديثة -->
<h3 class="section-title">الطلبات الحديثة</h3>
<div class="search-box mb-3">
<input type="text" id="ordersSearch" class="form-control" placeholder="البحث في الطلبات...">
</div>
<div id="recent-orders-container" class="row">
<!-- سيتم تعبئته ديناميكياً -->
</div>
<!-- خطوط الإنتاج -->
<h3 class="section-title">حالة خطوط الإنتاج</h3>
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>اسم الخط</th>
<th>الحالة</th>
<th>الطلب الحالي</th>
<th>معدل التشغيل</th>
<th>الإنتاج اليوم</th>
<th>الإجراءات</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="order-priority-indicator priority-high"></span> خط الطباعة الرقمية</td>
<td><span class="badge bg-success">نشط</span></td>
<td>طلب #1235</td>
<td>85%</td>
<td>1,250 نسخة</td>
<td class="action-buttons">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
<button class="btn btn-sm btn-outline-success"><i class="fas fa-play"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="fas fa-stop"></i></button>
</td>
</tr>
<tr>
<td><span class="order-priority-indicator priority-medium"></span> خط التغليف الآلي</td>
<td><span class="badge bg-warning">صيانة</span></td>
<td>طلب #1230</td>
<td>0%</td>
<td>0 نسخة</td>
<td class="action-buttons">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
<button class="btn btn-sm btn-outline-success"><i class="fas fa-play"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="fas fa-stop"></i></button>
</td>
</tr>
<tr>
<td><span class="order-priority-indicator priority-low"></span> خط القص والطي</td>
<td><span class="badge bg-success">نشط</span></td>
<td>طلب #1236</td>
<td>75%</td>
<td>850 نسخة</td>
<td class="action-buttons">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
<button class="btn btn-sm btn-outline-success"><i class="fas fa-play"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="fas fa-stop"></i></button>
</td>
</tr>
<tr>
<td><span class="order-priority-indicator priority-low"></span> خط الطباعة الأوفست</td>
<td><span class="badge bg-info">مستعد</span></td>
<td>لا يوجد</td>
<td>0%</td>
<td>3,400 نسخة</td>
<td class="action-buttons">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
<button class="btn btn-sm btn-outline-success"><i class="fas fa-play"></i></button>
<button class="btn btn-sm btn-outline-danger"><i class="fas fa-stop"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Modal: إضافة طلب جديد -->
<div class="modal fade" id="addOrderModal" tabindex="-1" aria-labelledby="addOrderModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addOrderModalLabel">إضافة طلب جديد</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="newOrderForm">
<div class="mb-3">
<label class="form-label">رقم الطلب (تلقائي)</label>
<input type="text" class="form-control" id="orderId" value="#AUTO-1237" readonly>
</div>
<div class="mb-3">
<label class="form-label">وصف الطلب</label>
<input type="text" class="form-control" id="orderDesc" required placeholder="مثال: كتيب تعريفي - 500 نسخة">
</div>
<div class="mb-3">
<label class="form-label">العميل</label>
<select class="form-select" id="clientSelect" required>
<option value="">اختر عميلاً</option>
<option value="شركة التقنية المحدودة">شركة التقنية المحدودة</option>
<option value="مؤسسة الإبداع للدعاية">مؤسسة الإبداع للدعاية</option>
<option value="مكتبة المعرفة">مكتبة المعرفة</option>
<option value="شركة النهضة العقارية">شركة النهضة العقارية</option>
<option value="عميل جديد">+ عميل جديد</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">الأولوية</label>
<select class="form-select" id="prioritySelect" required>
<option value="normal">عادي</option>
<option value="urgent">عاجل</option>
<option value="critical">طارئ</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">تاريخ التسليم المطلوب</label>
<input type="date" class="form-control" id="deliveryDate" required>
</div>
<div class="mb-3">
<label class="form-label">تقدم التنفيذ (%)</label>
<input type="number" min="0" max="100" class="form-control" id="progressInput" value="0">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
<button type="button" class="btn btn-primary" id="saveOrderBtn">حفظ الطلب</button>
</div>
</div>
</div>
</div>
<!-- Bootstrap & Custom JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// تعيين تاريخ اليوم كحد أدنى لتاريخ التسليم
const today = new Date();
const minDate = today.toISOString().split('T')[0];
document.getElementById('deliveryDate').setAttribute('min', minDate);
// دالة لحساب الفرق بالأيام بين تاريخين
function calculateDaysDifference(targetDate) {
const today = new Date();
today.setHours(0, 0, 0, 0); // تصفير الوقت للمقارنة
const target = new Date(targetDate);
target.setHours(0, 0, 0, 0);
const diffTime = target.getTime() - today.getTime();
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return diffDays;
}
// دالة لتحديد حالة الطلب بناءً على التقدم والتاريخ
function determineOrderStatus(progress, daysLeft, priority) {
if (progress >= 100) {
return { status: "مكتمل", priorityClass: "completed", badgeClass: "bg-success" };
}
if (daysLeft < 0) {
return { status: "متأخر", priorityClass: "delayed", badgeClass: "bg-danger" };
}
if (priority === "urgent" || priority === "critical") {
return { status: "عاجل", priorityClass: "urgent", badgeClass: "bg-warning" };
}
return { status: "قيد الطباعة", priorityClass: "normal", badgeClass: "bg-info" };
}
// دالة لحساب رقم الطلب التالي
function generateOrderNumber() {
const randomNum = Math.floor(Math.random() * 9000) + 1000;
return `AUTO-${randomNum}`;
}
// بيانات الطلبات الأساسية
let orders = [
{
id: "1235",
desc: "كتيب ترويجي",
client: "شركة التقنية المحدودة",
progress: 65,
delivery: "2023-11-15",
priority: "normal"
},
{
id: "1236",
desc: "بوسترات إعلانية",
client: "مؤسسة الإبداع للدعاية",
progress: 30,
delivery: "2023-11-12",
priority: "urgent"
},
{
id: "1234",
desc: "تقويمات 2024",
client: "مكتبة المعرفة",
progress: 80,
delivery: "2023-11-10",
priority: "normal"
},
{
id: "1233",
desc: "أظرف مؤسسة",
client: "شركة النهضة العقارية",
progress: 100,
delivery: "2023-11-08",
priority: "normal"
},
{
id: "1232",
desc: "كراسات مدرسية",
client: "وزارة التربية",
progress: 45,
delivery: "2023-11-20",
priority: "critical"
},
{
id: "1231",
desc: "فواتير كهرباء",
client: "الشركة الوطنية للكهرباء",
progress: 90,
delivery: "2023-11-05",
priority: "normal"
}
];
// دالة لعرض الطلبات
function renderOrders(ordersToRender) {
const container = document.getElementById('recent-orders-container');
container.innerHTML = '';
if (ordersToRender.length === 0) {
container.innerHTML = `
<div class="col-12 text-center py-5">
<i class="fas fa-box-open fa-3x text-muted mb-3"></i>
<h4>لا توجد طلبات مطابقة للبحث</h4>
<p class="text-muted">حاول تعديل مصطلح البحث أو إضافة طلب جديد</p>
</div>
`;
return;
}
ordersToRender.forEach(order => {
const daysLeft = calculateDaysDifference(order.delivery);
const statusInfo = determineOrderStatus(order.progress, daysLeft, order.priority);
container.appendChild(createOrderCard({
...order,
daysLeft: daysLeft,
status: statusInfo.status,
priorityClass: statusInfo.priorityClass,
badgeClass: statusInfo.badgeClass
}));
});
}
// دالة لإنشاء بطاقة طلب
function createOrderCard(order) {
const col = document.createElement('div');
col.className = 'col-md-6';
const deliveryDate = new Date(order.delivery);
const deliveryStr = deliveryDate.toLocaleDateString('ar-EG', {
year: 'numeric',
month: 'short',
day: 'numeric'
});
let timeInfo = "";
if (order.daysLeft > 0) {
timeInfo = `<i class="far fa-clock"></i> متبقي: ${order.daysLeft} يوم`;
} else if (order.daysLeft === 0) {
timeInfo = `<i class="fas fa-check-circle"></i> اليوم`;
} else {
timeInfo = `<i class="fas fa-exclamation-triangle text-danger"></i> متأخر: ${Math.abs(order.daysLeft)} يوم`;
}
// تحديد مؤشر الأولوية
let priorityIndicator = "";
if (order.priority === "critical") {
priorityIndicator = `<span class="order-priority-indicator priority-high" title="أولوية عالية"></span>`;
} else if (order.priority === "urgent") {
priorityIndicator = `<span class="order-priority-indicator priority-medium" title="أولوية متوسطة"></span>`;
} else {
priorityIndicator = `<span class="order-priority-indicator priority-low" title="أولوية منخفضة"></span>`;
}
col.innerHTML = `
<div class="order-card ${order.priorityClass}">
<div class="order-card-header">
<h5 class="order-card-title">${priorityIndicator} طلب #${order.id} - ${order.desc}</h5>
<span class="badge ${order.badgeClass} badge-status">${order.status}</span>
</div>
<div class="order-card-info">
<span class="text-muted">العميل: ${order.client}</span>
</div>
<div class="order-card-progress">
<div class="d-flex justify-content-between mb-1">
<span>تقدم التنفيذ</span>
<span>${order.progress}%</span>
</div>
<div class="progress">
<div class="progress-bar ${order.badgeClass}" style="width: ${order.progress}%"></div>
</div>
</div>
<div class="order-card-footer">
<span><i class="far fa-calendar"></i> تاريخ التسليم: ${deliveryStr}</span>
<span>${timeInfo}</span>
</div>
</div>
`;
return col;
}
// دالة لتحديث الإحصائيات
function updateStats() {
let total = 0;
let inProgress = 0;
let completed = 0;
let delayed = 0;
orders.forEach(order => {
const daysLeft = calculateDaysDifference(order.delivery);
const statusInfo = determineOrderStatus(order.progress, daysLeft, order.priority);
total++;
if (statusInfo.status === "مكتمل") {
completed++;
} else if (statusInfo.status === "متأخر") {
delayed++;
} else {
inProgress++;
}
});
document.getElementById('total-orders').textContent = total;
document.getElementById('in-progress').textContent = inProgress;
document.getElementById('completed-orders').textContent = completed;
document.getElementById('delayed-orders').textContent = delayed;
}
// دالة لإظهار الإشعارات
function showToast(message, type = 'success') {
const toastContainer = document.querySelector('.toast-container');
const toast = document.createElement('div');
toast.className = `toast align-items-center text-bg-${type} border-0 show`;
toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', 'assertive');
toast.setAttribute('aria-atomic', 'true');
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">${message}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
`;
toastContainer.appendChild(toast);
// إزالة تلقائية بعد 3 ثواني
setTimeout(() => {
toast.remove();
}, 3000);
}
// دالة للبحث في الطلبات
function searchOrders() {
const searchTerm = document.getElementById('ordersSearch').value.toLowerCase();
if (searchTerm.trim() === '') {
renderOrders(orders);
return;
}
const filteredOrders = orders.filter(order =>
order.id.toLowerCase().includes(searchTerm) ||
order.desc.toLowerCase().includes(searchTerm) ||
order.client.toLowerCase().includes(searchTerm)
);
renderOrders(filteredOrders);
}
// حفظ طلب جديد
document.getElementById('saveOrderBtn').addEventListener('click', function() {
const desc = document.getElementById('orderDesc').value.trim();
const client = document.getElementById('clientSelect').value;
const priority = document.getElementById('prioritySelect').value;
const deliveryDate = document.getElementById('deliveryDate').value;
const progress = parseInt(document.getElementById('progressInput').value) || 0;
// التحقق من صحة المدخلات
if (!desc || !client || !deliveryDate) {
showToast('يرجى ملء جميع الحقول المطلوبة', 'danger');
return;
}
if (progress < 0 || progress > 100) {
showToast('نسبة التقدم يجب أن تكون بين 0 و 100', 'danger');
return;
}
// إنشاء طلب جديد
const newOrder = {
id: generateOrderNumber(),
desc: desc,
client: client,
progress: progress,
delivery: deliveryDate,
priority: priority
};
// إضافة الطلب للقائمة
orders.unshift(newOrder);
// إعادة عرض الطلبات وتحديث الإحصائيات
renderOrders(orders);
updateStats();
// إغلاق المودال
const modal = bootstrap.Modal.getInstance(document.getElementById('addOrderModal'));
if (modal) {
modal.hide();
}
// تنظيف الفورم
document.getElementById('newOrderForm').reset();
document.getElementById('orderId').value = `#${generateOrderNumber()}`;
// إظهار إشعار نجاح
showToast('تم إضافة الطلب بنجاح!', 'success');
// إشعار خاص للطلبات العاجلة
if (priority === 'urgent' || priority === 'critical') {
setTimeout(() => {
showToast('تنبيه: تم إضافة طلب عاجل!', 'warning');
}, 1000);
}
});
// تهيئة رقم الطلب التلقائي
document.getElementById('orderId').value = `#${generateOrderNumber()}`;
// تفعيل البحث
document.getElementById('ordersSearch').addEventListener('input', searchOrders);
// عرض الطلبات الأولية
renderOrders(orders);
updateStats();
// تحديث الإحصائيات كل 5 دقائق
setInterval(updateStats, 300000);
});
</script>
Metadata
Metadata
Assignees
Labels
No labels