car_mms/app/components/maintenance-visits/MaintenanceVisitDetailsView.tsx
2025-09-11 14:22:27 +03:00

304 lines
13 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Link } from "@remix-run/react";
import { useSettings } from "~/contexts/SettingsContext";
import type { MaintenanceVisitWithRelations } from "~/types/database";
interface MaintenanceVisitDetailsViewProps {
visit: MaintenanceVisitWithRelations;
}
export function MaintenanceVisitDetailsView({ visit }: MaintenanceVisitDetailsViewProps) {
const { formatCurrency, formatDate, formatNumber } = useSettings();
const getPaymentStatusColor = (status: string) => {
switch (status) {
case 'paid':
return 'bg-green-100 text-green-800 border-green-200';
case 'pending':
return 'bg-yellow-100 text-yellow-800 border-yellow-200';
case 'partial':
return 'bg-blue-100 text-blue-800 border-blue-200';
case 'cancelled':
return 'bg-red-100 text-red-800 border-red-200';
default:
return 'bg-gray-100 text-gray-800 border-gray-200';
}
};
const getPaymentStatusLabel = (status: string) => {
switch (status) {
case 'paid': return 'مدفوع';
case 'pending': return 'معلق';
case 'partial': return 'مدفوع جزئياً';
case 'cancelled': return 'ملغي';
default: return status;
}
};
const getDelayLabel = (months: number) => {
const delayOptions = [
{ value: 1, label: 'شهر واحد' },
{ value: 2, label: 'شهرين' },
{ value: 3, label: '3 أشهر' },
{ value: 4, label: '4 أشهر' },
{ value: 6, label: '6 أشهر' },
{ value: 12, label: 'سنة واحدة' },
];
const option = delayOptions.find(opt => opt.value === months);
return option ? option.label : `${months} أشهر`;
};
return (
<div className="space-y-8">
{/* Header Section */}
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl p-6 border border-blue-100">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center">
<span className="text-3xl ml-3">🔧</span>
<div>
<h2 className="text-2xl font-bold text-gray-900">
زيارة صيانة #{visit.id}
</h2>
<p className="text-gray-600 mt-1">
{formatDate(visit.visitDate)}
</p>
</div>
</div>
<div className="text-right">
<div className="text-3xl font-bold text-blue-600 mb-1">
{formatCurrency(visit.cost)}
</div>
<span className={`inline-flex px-3 py-1 text-sm font-semibold rounded-full border ${getPaymentStatusColor(visit.paymentStatus)}`}>
{getPaymentStatusLabel(visit.paymentStatus)}
</span>
</div>
</div>
</div>
{/* Main Details Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Visit Information */}
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 flex items-center">
<span className="text-gray-600 text-xl ml-2">📋</span>
تفاصيل الزيارة
</h3>
</div>
<div className="p-6 space-y-4">
<div className="bg-blue-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-3">أعمال الصيانة المنجزة</label>
<div className="space-y-3">
{(() => {
try {
const jobs = JSON.parse(visit.maintenanceJobs);
return jobs.map((job: any, index: number) => (
<div key={index} className="bg-white p-3 rounded-lg border border-blue-200">
<div className="flex items-start justify-between">
<div className="flex-1">
<p className="font-semibold text-gray-900 mb-1">{job.job}</p>
{job.notes && (
<p className="text-sm text-gray-600">{job.notes}</p>
)}
</div>
<span className="inline-flex items-center px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
#{index + 1}
</span>
</div>
</div>
));
} catch {
return (
<div className="bg-white p-3 rounded-lg border border-blue-200">
<p className="text-gray-900">لا توجد تفاصيل أعمال الصيانة</p>
</div>
);
}
})()}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="bg-gray-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">عداد الكيلومترات</label>
<p className="text-gray-900 font-mono text-lg">
{formatNumber(visit.kilometers)} كم
</p>
</div>
<div className="bg-gray-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">الزيارة التالية بعد</label>
<p className="text-gray-900 font-medium">
{getDelayLabel(visit.nextVisitDelay)}
</p>
</div>
</div>
<div className="bg-gray-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-2">وصف الأعمال المنجزة</label>
<div className="bg-white rounded-lg p-4 border">
<p className="text-gray-900 whitespace-pre-wrap leading-relaxed">
{visit.description}
</p>
</div>
</div>
</div>
</div>
{/* Vehicle & Customer Information */}
<div className="space-y-6">
{/* Vehicle Info */}
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 flex items-center">
<span className="text-gray-600 text-xl ml-2">🚗</span>
معلومات المركبة
</h3>
</div>
<div className="p-6">
<div className="grid grid-cols-2 gap-4">
<div className="bg-green-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">رقم اللوحة</label>
<p className="text-xl font-bold text-gray-900 font-mono">
{visit.vehicle.plateNumber}
</p>
</div>
<div className="bg-green-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">السنة</label>
<p className="text-lg font-semibold text-gray-900">
{visit.vehicle.year}
</p>
</div>
<div className="bg-green-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">الشركة المصنعة</label>
<p className="text-gray-900 font-medium">
{visit.vehicle.manufacturer}
</p>
</div>
<div className="bg-green-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">الموديل</label>
<p className="text-gray-900 font-medium">
{visit.vehicle.model}
</p>
</div>
</div>
</div>
</div>
{/* Customer Info */}
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 flex items-center">
<span className="text-gray-600 text-xl ml-2">👤</span>
معلومات العميل
</h3>
</div>
<div className="p-6">
<div className="space-y-4">
<div className="bg-blue-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">اسم العميل</label>
<p className="text-lg font-semibold text-gray-900">
{visit.customer.name}
</p>
</div>
{(visit.customer.phone || visit.customer.email) && (
<div className="grid grid-cols-1 gap-4">
{visit.customer.phone && (
<div className="bg-blue-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">رقم الهاتف</label>
<a
href={`tel:${visit.customer.phone}`}
className="text-blue-600 hover:text-blue-800 font-mono font-medium"
dir="ltr"
>
📞 {visit.customer.phone}
</a>
</div>
)}
{visit.customer.email && (
<div className="bg-blue-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">البريد الإلكتروني</label>
<a
href={`mailto:${visit.customer.email}`}
className="text-blue-600 hover:text-blue-800 font-medium"
dir="ltr"
>
{visit.customer.email}
</a>
</div>
)}
</div>
)}
{visit.customer.address && (
<div className="bg-blue-50 p-4 rounded-lg">
<label className="block text-sm font-medium text-gray-600 mb-1">العنوان</label>
<p className="text-gray-900">
{visit.customer.address}
</p>
</div>
)}
</div>
</div>
</div>
</div>
</div>
{/* Income Information */}
{visit.income && visit.income.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-semibold text-gray-900 flex items-center">
<span className="text-gray-600 text-xl ml-2">💰</span>
سجل الدخل
</h3>
</div>
<div className="p-6">
<div className="space-y-3">
{visit.income.map((income) => (
<div key={income.id} className="flex justify-between items-center bg-green-50 p-4 rounded-lg">
<div>
<p className="text-sm text-gray-600">تاريخ الدخل</p>
<p className="font-medium text-gray-900">
{formatDate(income.incomeDate)}
</p>
</div>
<div className="text-right">
<p className="text-sm text-gray-600">المبلغ</p>
<p className="text-xl font-bold text-green-600 font-mono">
{formatCurrency(income.amount)}
</p>
</div>
</div>
))}
</div>
</div>
</div>
)}
{/* Action Buttons */}
<div className="flex flex-wrap gap-3 pt-6 border-t border-gray-200">
<Link
to={`/vehicles?search=${encodeURIComponent(visit.vehicle.plateNumber)}`}
className="inline-flex items-center px-4 py-2 text-sm font-medium text-blue-600 bg-blue-50 border border-blue-200 rounded-lg hover:bg-blue-100 transition-colors"
>
<span className="ml-2">🚗</span>
عرض تفاصيل المركبة
</Link>
<Link
to={`/customers?search=${encodeURIComponent(visit.customer.name)}`}
className="inline-flex items-center px-4 py-2 text-sm font-medium text-green-600 bg-green-50 border border-green-200 rounded-lg hover:bg-green-100 transition-colors"
>
<span className="ml-2">👤</span>
عرض تفاصيل العميل
</Link>
<Link
to={`/maintenance-visits?vehicleId=${visit.vehicle.id}`}
className="inline-flex items-center px-4 py-2 text-sm font-medium text-purple-600 bg-purple-50 border border-purple-200 rounded-lg hover:bg-purple-100 transition-colors"
>
<span className="ml-2">📋</span>
جميع زيارات هذه المركبة
</Link>
</div>
</div>
);
}