forked from amer2004/SweetHome
Added translation to all site with edit style
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import toast, { Toaster } from 'react-hot-toast';
|
||||
import {
|
||||
FileText,
|
||||
@ -19,13 +20,8 @@ import {
|
||||
import { submitReport, submitReservationReport, submitSaleReport } from '../utils/api';
|
||||
import AuthService from '../services/AuthService';
|
||||
|
||||
const tabs = [
|
||||
{ id: 'general', label: 'تقرير عام', icon: FileText },
|
||||
{ id: 'reservation', label: 'تقرير حجز', icon: Calendar },
|
||||
{ id: 'sale', label: 'تقرير بيع', icon: DollarSign },
|
||||
];
|
||||
|
||||
export default function ReportsPage() {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const [activeTab, setActiveTab] = useState('general');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -37,6 +33,12 @@ export default function ReportsPage() {
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
const tabs = [
|
||||
{ id: 'general', label: t('reports.generalReport'), icon: FileText },
|
||||
{ id: 'reservation', label: t('reports.reservationReport'), icon: Calendar },
|
||||
{ id: 'sale', label: t('reports.saleReport'), icon: DollarSign },
|
||||
];
|
||||
|
||||
const [generalForm, setGeneralForm] = useState({ subject: '', body: '' });
|
||||
const [reservationForm, setReservationForm] = useState({ reservationId: '', message: '', reporter: 'customer' });
|
||||
const [saleForm, setSaleForm] = useState({ saleId: '', message: '', reporter: 'buyer' });
|
||||
@ -45,24 +47,24 @@ export default function ReportsPage() {
|
||||
|
||||
const validateGeneral = () => {
|
||||
const e = {};
|
||||
if (!generalForm.subject.trim()) e.subject = 'الموضوع مطلوب';
|
||||
if (!generalForm.body.trim()) e.body = 'الوصف مطلوب';
|
||||
if (!generalForm.subject.trim()) e.subject = t('reports.subjectRequired');
|
||||
if (!generalForm.body.trim()) e.body = t('reports.descriptionRequired');
|
||||
setErrors(e);
|
||||
return Object.keys(e).length === 0;
|
||||
};
|
||||
|
||||
const validateReservation = () => {
|
||||
const e = {};
|
||||
if (!reservationForm.reservationId.trim()) e.reservationId = 'رقم الحجز مطلوب';
|
||||
if (!reservationForm.message.trim()) e.message = 'الرسالة مطلوبة';
|
||||
if (!reservationForm.reservationId.trim()) e.reservationId = t('reports.reservationIdRequired');
|
||||
if (!reservationForm.message.trim()) e.message = t('reports.messageRequired');
|
||||
setErrors(e);
|
||||
return Object.keys(e).length === 0;
|
||||
};
|
||||
|
||||
const validateSale = () => {
|
||||
const e = {};
|
||||
if (!saleForm.saleId.trim()) e.saleId = 'رقم البيع مطلوب';
|
||||
if (!saleForm.message.trim()) e.message = 'الرسالة مطلوبة';
|
||||
if (!saleForm.saleId.trim()) e.saleId = t('reports.saleIdRequired');
|
||||
if (!saleForm.message.trim()) e.message = t('reports.messageRequired');
|
||||
setErrors(e);
|
||||
return Object.keys(e).length === 0;
|
||||
};
|
||||
@ -74,13 +76,13 @@ export default function ReportsPage() {
|
||||
try {
|
||||
await submitReport(generalForm.subject, generalForm.body);
|
||||
setIsSuccess(true);
|
||||
toast.success('تم إرسال التقرير بنجاح!', {
|
||||
toast.success(t('reports.generalSuccess'), {
|
||||
style: { background: '#dcfce7', color: '#166534' },
|
||||
});
|
||||
setGeneralForm({ subject: '', body: '' });
|
||||
setTimeout(() => setIsSuccess(false), 2000);
|
||||
} catch (err) {
|
||||
toast.error(err.message || 'فشل إرسال التقرير', {
|
||||
toast.error(err.message || t('reports.generalFailed'), {
|
||||
style: { background: '#fee2e2', color: '#991b1b' },
|
||||
});
|
||||
} finally {
|
||||
@ -95,13 +97,13 @@ export default function ReportsPage() {
|
||||
try {
|
||||
await submitReservationReport(reservationForm);
|
||||
setIsSuccess(true);
|
||||
toast.success('تم إرسال تقرير الحجز!', {
|
||||
toast.success(t('reports.reservationSuccess'), {
|
||||
style: { background: '#dcfce7', color: '#166534' },
|
||||
});
|
||||
setReservationForm({ reservationId: '', message: '', reporter: 'customer' });
|
||||
setTimeout(() => setIsSuccess(false), 2000);
|
||||
} catch (err) {
|
||||
toast.error(err.message || 'فشل إرسال التقرير', {
|
||||
toast.error(err.message || t('reports.reservationFailed'), {
|
||||
style: { background: '#fee2e2', color: '#991b1b' },
|
||||
});
|
||||
} finally {
|
||||
@ -116,13 +118,13 @@ export default function ReportsPage() {
|
||||
try {
|
||||
await submitSaleReport(saleForm);
|
||||
setIsSuccess(true);
|
||||
toast.success('تم إرسال تقرير البيع!', {
|
||||
toast.success(t('reports.saleSuccess'), {
|
||||
style: { background: '#dcfce7', color: '#166534' },
|
||||
});
|
||||
setSaleForm({ saleId: '', message: '', reporter: 'buyer' });
|
||||
setTimeout(() => setIsSuccess(false), 2000);
|
||||
} catch (err) {
|
||||
toast.error(err.message || 'فشل إرسال التقرير', {
|
||||
toast.error(err.message || t('reports.saleFailed'), {
|
||||
style: { background: '#fee2e2', color: '#991b1b' },
|
||||
});
|
||||
} finally {
|
||||
@ -134,7 +136,7 @@ export default function ReportsPage() {
|
||||
general: (
|
||||
<form onSubmit={handleGeneralSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">الموضوع</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.subjectLabel')}</label>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||
<FileText className={`w-5 h-5 ${errors.subject ? 'text-red-500' : 'text-gray-400 group-focus-within:text-amber-500'}`} />
|
||||
@ -144,19 +146,19 @@ export default function ReportsPage() {
|
||||
value={generalForm.subject}
|
||||
onChange={(e) => { setGeneralForm({ ...generalForm, subject: e.target.value }); if (errors.subject) setErrors({ ...errors, subject: null }); }}
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all ${errors.subject ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="أدخل موضوع التقرير"
|
||||
placeholder={t('reports.subjectPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.subject && <p className="text-red-500 text-sm mt-1">{errors.subject}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">الوصف</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.descriptionLabel')}</label>
|
||||
<textarea
|
||||
value={generalForm.body}
|
||||
onChange={(e) => { setGeneralForm({ ...generalForm, body: e.target.value }); if (errors.body) setErrors({ ...errors, body: null }); }}
|
||||
rows={5}
|
||||
className={`w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all resize-none ${errors.body ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="اشرح التفاصيل..."
|
||||
placeholder={t('reports.descriptionPlaceholder')}
|
||||
/>
|
||||
{errors.body && <p className="text-red-500 text-sm mt-1">{errors.body}</p>}
|
||||
</div>
|
||||
@ -168,11 +170,11 @@ export default function ReportsPage() {
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{isLoading ? (
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> جاري الإرسال...</>
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> {t('reports.sending')}</>
|
||||
) : isSuccess ? (
|
||||
<><CheckCircle className="w-5 h-5" /> تم الإرسال!</>
|
||||
<><CheckCircle className="w-5 h-5" /> {t('reports.sentSuccess')}</>
|
||||
) : (
|
||||
<><Send className="w-5 h-5" /> إرسال التقرير</>
|
||||
<><Send className="w-5 h-5" /> {t('reports.submitReport')}</>
|
||||
)}
|
||||
</motion.button>
|
||||
</form>
|
||||
@ -180,7 +182,7 @@ export default function ReportsPage() {
|
||||
reservation: (
|
||||
<form onSubmit={handleReservationSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">رقم الحجز</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.reservationIdLabel')}</label>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||
<Hash className={`w-5 h-5 ${errors.reservationId ? 'text-red-500' : 'text-gray-400 group-focus-within:text-amber-500'}`} />
|
||||
@ -190,24 +192,24 @@ export default function ReportsPage() {
|
||||
value={reservationForm.reservationId}
|
||||
onChange={(e) => { setReservationForm({ ...reservationForm, reservationId: e.target.value }); if (errors.reservationId) setErrors({ ...errors, reservationId: null }); }}
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all ${errors.reservationId ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="أدخل رقم الحجز"
|
||||
placeholder={t('reports.reservationIdPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.reservationId && <p className="text-red-500 text-sm mt-1">{errors.reservationId}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">الرسالة</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('message')}</label>
|
||||
<textarea
|
||||
value={reservationForm.message}
|
||||
onChange={(e) => { setReservationForm({ ...reservationForm, message: e.target.value }); if (errors.message) setErrors({ ...errors, message: null }); }}
|
||||
rows={4}
|
||||
className={`w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all resize-none ${errors.message ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="اشرح المشكلة..."
|
||||
placeholder={t('reports.messagePlaceholder')}
|
||||
/>
|
||||
{errors.message && <p className="text-red-500 text-sm mt-1">{errors.message}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المبلغ</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.reporterLabel')}</label>
|
||||
<div className="flex gap-3">
|
||||
{['customer', 'owner'].map((val) => (
|
||||
<button
|
||||
@ -221,7 +223,7 @@ export default function ReportsPage() {
|
||||
}`}
|
||||
>
|
||||
<User className="w-4 h-4" />
|
||||
{val === 'customer' ? 'مستأجر' : 'مالك'}
|
||||
{val === 'customer' ? t('customer') : t('owner')}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@ -234,11 +236,11 @@ export default function ReportsPage() {
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{isLoading ? (
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> جاري الإرسال...</>
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> {t('reports.sending')}</>
|
||||
) : isSuccess ? (
|
||||
<><CheckCircle className="w-5 h-5" /> تم الإرسال!</>
|
||||
<><CheckCircle className="w-5 h-5" /> {t('reports.sentSuccess')}</>
|
||||
) : (
|
||||
<><Send className="w-5 h-5" /> إرسال التقرير</>
|
||||
<><Send className="w-5 h-5" /> {t('reports.submitReport')}</>
|
||||
)}
|
||||
</motion.button>
|
||||
</form>
|
||||
@ -246,7 +248,7 @@ export default function ReportsPage() {
|
||||
sale: (
|
||||
<form onSubmit={handleSaleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">رقم البيع</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.saleIdLabel')}</label>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
|
||||
<Hash className={`w-5 h-5 ${errors.saleId ? 'text-red-500' : 'text-gray-400 group-focus-within:text-amber-500'}`} />
|
||||
@ -256,24 +258,24 @@ export default function ReportsPage() {
|
||||
value={saleForm.saleId}
|
||||
onChange={(e) => { setSaleForm({ ...saleForm, saleId: e.target.value }); if (errors.saleId) setErrors({ ...errors, saleId: null }); }}
|
||||
className={`w-full pr-12 pl-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all ${errors.saleId ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="أدخل رقم البيع"
|
||||
placeholder={t('reports.saleIdPlaceholder')}
|
||||
/>
|
||||
</div>
|
||||
{errors.saleId && <p className="text-red-500 text-sm mt-1">{errors.saleId}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">الرسالة</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('message')}</label>
|
||||
<textarea
|
||||
value={saleForm.message}
|
||||
onChange={(e) => { setSaleForm({ ...saleForm, message: e.target.value }); if (errors.message) setErrors({ ...errors, message: null }); }}
|
||||
rows={4}
|
||||
className={`w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-amber-500 focus:border-transparent transition-all resize-none ${errors.message ? 'border-red-500' : 'border-gray-300'}`}
|
||||
placeholder="اشرح المشكلة..."
|
||||
placeholder={t('reports.messagePlaceholder')}
|
||||
/>
|
||||
{errors.message && <p className="text-red-500 text-sm mt-1">{errors.message}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">المبلغ</label>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">{t('reports.reporterLabel')}</label>
|
||||
<div className="flex gap-3">
|
||||
{['buyer', 'seller'].map((val) => (
|
||||
<button
|
||||
@ -287,7 +289,7 @@ export default function ReportsPage() {
|
||||
}`}
|
||||
>
|
||||
<User className="w-4 h-4" />
|
||||
{val === 'buyer' ? 'مشتري' : 'بائع'}
|
||||
{val === 'buyer' ? t('buyer') : t('seller')}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@ -300,11 +302,11 @@ export default function ReportsPage() {
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{isLoading ? (
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> جاري الإرسال...</>
|
||||
<><Loader2 className="w-5 h-5 animate-spin" /> {t('reports.sending')}</>
|
||||
) : isSuccess ? (
|
||||
<><CheckCircle className="w-5 h-5" /> تم الإرسال!</>
|
||||
<><CheckCircle className="w-5 h-5" /> {t('reports.sentSuccess')}</>
|
||||
) : (
|
||||
<><Send className="w-5 h-5" /> إرسال التقرير</>
|
||||
<><Send className="w-5 h-5" /> {t('reports.submitReport')}</>
|
||||
)}
|
||||
</motion.button>
|
||||
</form>
|
||||
@ -320,8 +322,8 @@ export default function ReportsPage() {
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="mb-8"
|
||||
>
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">الإبلاغ عن مشكلة</h1>
|
||||
<p className="text-gray-600">أخبرنا عن المشكلة التي تواجهها وسنقوم بمعالجتها</p>
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">{t('reports.pageTitle')}</h1>
|
||||
<p className="text-gray-600">{t('reports.pageDescription')}</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
|
||||
|
||||
Reference in New Issue
Block a user