forked from amer2004/SweetHome
Added translation to payments
This commit is contained in:
@ -60,6 +60,9 @@ const resources = {
|
||||
"termsOfUse": "Terms of Use",
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"invalidCredentials": "Invalid credentials",
|
||||
"serverError": "Server error, please try again later",
|
||||
"apiNotFound": "Service temporarily unavailable",
|
||||
"tooManyRequests": "Too many requests, please wait",
|
||||
"connectionError": "A connection error occurred",
|
||||
"phoneInvalid": "Invalid phone number",
|
||||
"resendSuccess": "Verification code resent",
|
||||
@ -1488,6 +1491,16 @@ const resources = {
|
||||
"payments.cashPendingDialogDesc2": "The platform will confirm the payment after receiving the amount.",
|
||||
"payments.platformOfficeFullAddress": "Platform Office: Abu Rumaneh, Al-Malki Street, Damascus",
|
||||
"payments.closeButton": "Close",
|
||||
"payments.propertyLabel": "Property",
|
||||
|
||||
"payments.method.cash": "Cash Payment",
|
||||
"payments.method.cashDesc": "Pay now with automatic booking confirmation",
|
||||
"payments.method.office": "Cash",
|
||||
"payments.method.officeDesc": "Pay at the platform office. Confirmed later.",
|
||||
"payments.method.transfer": "Internal Transfer",
|
||||
"payments.method.transferDesc": "Transfer from internal account then send reference",
|
||||
"payments.method.electronic": "Electronic Payment",
|
||||
"payments.method.electronicDesc": "Electronic payment will be activated later",
|
||||
|
||||
/* ─── Onboarding ─── */
|
||||
"onboarding.step1.title": "Welcome to SweetHome",
|
||||
@ -1655,6 +1668,9 @@ const resources = {
|
||||
"termsOfUse": "شروط الاستخدام",
|
||||
"privacyPolicy": "سياسة الخصوصية",
|
||||
"invalidCredentials": "بيانات الدخول غير صحيحة",
|
||||
"serverError": "خطأ في الخادم، يرجى المحاولة لاحقاً",
|
||||
"apiNotFound": "الخدمة غير متاحة مؤقتاً",
|
||||
"tooManyRequests": "طلبات كثيرة جداً، يرجى الانتظار",
|
||||
"connectionError": "حدث خطأ في الاتصال",
|
||||
"phoneInvalid": "رقم الهاتف غير صالح",
|
||||
"resendSuccess": "تم إرسال رمز التحقق مجدداً",
|
||||
@ -2924,6 +2940,16 @@ const resources = {
|
||||
"payments.cashPendingDialogDesc2": "ستقوم المنصة بتأكيد الدفع بعد استلام المبلع.",
|
||||
"payments.platformOfficeFullAddress": "مكتب المنصة: أبو رمانة، شارع المالكي، دمشق",
|
||||
"payments.closeButton": "إغلاق",
|
||||
"payments.propertyLabel": "عقار",
|
||||
|
||||
"payments.method.cash": "الدفع النقدي",
|
||||
"payments.method.cashDesc": "ادفع الآن عبر شام كاش مع تأكيد تلقائي للحجز",
|
||||
"payments.method.office": "نقداً",
|
||||
"payments.method.officeDesc": "ادفع في مكتب المنصة. يتم التأكيد لاحقاً",
|
||||
"payments.method.transfer": "تحويل داخلي",
|
||||
"payments.method.transferDesc": "حول من حساب داخلي ثم أرسل المرجع",
|
||||
"payments.method.electronic": "دفع إلكتروني",
|
||||
"payments.method.electronicDesc": "سيتم تفعيل الدفع الإلكتروني لاحقاً",
|
||||
|
||||
/* ─── Onboarding ─── */
|
||||
"onboarding.step1.title": "مرحباً بك في SweetHome",
|
||||
|
||||
@ -153,8 +153,21 @@ export default function LoginPage() {
|
||||
}
|
||||
|
||||
setStep("otp");
|
||||
} else if (result.status >= 500) {
|
||||
console.error("[Login] Server error:", result.status, result.data);
|
||||
toast.error(t("serverError"), {
|
||||
style: { background: "#fee2e2", color: "#991b1b" },
|
||||
});
|
||||
} else if (result.status === 404) {
|
||||
console.error("[Login] API endpoint not found:", result.status);
|
||||
toast.error(t("apiNotFound"), {
|
||||
style: { background: "#fee2e2", color: "#991b1b" },
|
||||
});
|
||||
} else if (result.status === 429) {
|
||||
toast.error(t("tooManyRequests"), {
|
||||
style: { background: "#fee2e2", color: "#991b1b" },
|
||||
});
|
||||
} else {
|
||||
// Other error
|
||||
console.error("[Login] Unexpected status:", result.status, result.data);
|
||||
toast.error(
|
||||
result.data?.message || result.data || t("invalidCredentials"),
|
||||
|
||||
@ -30,47 +30,27 @@ import { payDeposit, getMyTransaction } from '@/app/utils/api';
|
||||
|
||||
const STATUS_MAP = ['pending', 'ownerConfirmed', 'depositPaid', 'depositConfirmed', 'completed', 'cancelled'];
|
||||
|
||||
const STATUS_CONFIG = {
|
||||
pending: { label: 'قيد الانتظار', color: 'bg-yellow-100 text-yellow-800 border-yellow-300', icon: Clock },
|
||||
ownerConfirmed: { label: 'مؤكد من المالك', color: 'bg-blue-100 text-blue-800 border-blue-300', icon: ShieldCheck },
|
||||
depositPaid: { label: 'تم دفع السلفة', color: 'bg-orange-100 text-orange-800 border-orange-300', icon: Wallet },
|
||||
depositConfirmed: { label: 'تم تأكيد الدفع', color: 'bg-green-100 text-green-800 border-green-300', icon: Check },
|
||||
completed: { label: 'منتهي', color: 'bg-teal-100 text-teal-800 border-teal-300', icon: Check },
|
||||
cancelled: { label: 'ملغي', color: 'bg-red-100 text-red-800 border-red-300', icon: X },
|
||||
};
|
||||
function getStatusConfig(t) {
|
||||
return {
|
||||
pending: { label: t('bookingStatus.pending'), color: 'bg-yellow-100 text-yellow-800 border-yellow-300', icon: Clock },
|
||||
ownerConfirmed: { label: t('bookingStatus.ownerConfirmed'), color: 'bg-blue-100 text-blue-800 border-blue-300', icon: ShieldCheck },
|
||||
depositPaid: { label: t('bookingStatus.depositPaid'), color: 'bg-orange-100 text-orange-800 border-orange-300', icon: Wallet },
|
||||
depositConfirmed: { label: t('bookingStatus.depositConfirmed'), color: 'bg-green-100 text-green-800 border-green-300', icon: Check },
|
||||
completed: { label: t('bookingStatus.completed'), color: 'bg-teal-100 text-teal-800 border-teal-300', icon: Check },
|
||||
cancelled: { label: t('bookingStatus.cancelled'), color: 'bg-red-100 text-red-800 border-red-300', icon: X },
|
||||
};
|
||||
}
|
||||
|
||||
const PAYMENT_METHODS = [
|
||||
{
|
||||
id: 'cash',
|
||||
label: 'الدفع النقدي',
|
||||
desc: 'ادفع الآن عبر شام كاش مع تأكيد تلقائي للحجز',
|
||||
icon: Banknote,
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
id: 'office',
|
||||
label: 'نقداً',
|
||||
desc: 'ادفع في مكتب المنصة. يتم التأكيد لاحقاً',
|
||||
icon: Building,
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
id: 'transfer',
|
||||
label: 'تحويل داخلي',
|
||||
desc: 'حول من حساب داخلي ثم أرسل المرجع',
|
||||
icon: ArrowLeftRight,
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
id: 'electronic',
|
||||
label: 'دفع إلكتروني',
|
||||
desc: 'سيتم تفعيل الدفع الإلكتروني والتحويل لاحقاً',
|
||||
icon: CreditCard,
|
||||
active: false,
|
||||
}
|
||||
];
|
||||
function getPaymentMethods(t) {
|
||||
return [
|
||||
{ id: 'cash', label: t('payments.method.cash'), desc: t('payments.method.cashDesc'), icon: Banknote, active: true },
|
||||
{ id: 'office', label: t('payments.method.office'), desc: t('payments.method.officeDesc'), icon: Building, active: true },
|
||||
{ id: 'transfer', label: t('payments.method.transfer'), desc: t('payments.method.transferDesc'), icon: ArrowLeftRight, active: false },
|
||||
{ id: 'electronic', label: t('payments.method.electronic'), desc: t('payments.method.electronicDesc'), icon: CreditCard, active: false },
|
||||
];
|
||||
}
|
||||
|
||||
function formatCurrency(v, sign = 'ل.س') {
|
||||
function formatCurrency(v, sign = '') {
|
||||
return `${sign} ${Number(v ?? 0).toLocaleString()}`;
|
||||
}
|
||||
|
||||
@ -82,7 +62,7 @@ function formatDate(date) {
|
||||
}
|
||||
|
||||
export default function PaymentsPage() {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const [reservations, setReservations] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [payingId, setPayingId] = useState(null);
|
||||
@ -109,10 +89,10 @@ export default function PaymentsPage() {
|
||||
endDate: reservation.endDate,
|
||||
totalPrice: reservation.totalPrice ?? transaction.amount ?? 0,
|
||||
depositAmount: transaction.amount ?? reservation.totalPrice ?? 0,
|
||||
currencySign: currency.sign || 'ل.س',
|
||||
currencySign: currency.sign || t('currency.syp'),
|
||||
currencyName: currency.name || '',
|
||||
currencyRate: currency.rate,
|
||||
propertyName: propertyInfo.name || propertyInfo.address || reservation.propertyName || `عقار #${reservation.id || ''}`,
|
||||
propertyName: propertyInfo.name || propertyInfo.address || reservation.propertyName || `${t('payments.propertyLabel')} #${reservation.id || ''}`,
|
||||
propertyAddress: propertyInfo.address || reservation.propertyAddress || '',
|
||||
propertyCity: propertyInfo.city || reservation.city || '',
|
||||
_deposit: deposit,
|
||||
@ -127,7 +107,7 @@ export default function PaymentsPage() {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
}, [t]);
|
||||
|
||||
useEffect(() => {
|
||||
if (AuthService.isGuest()) {
|
||||
@ -156,7 +136,7 @@ export default function PaymentsPage() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center" dir="rtl">
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center" dir={i18n.dir()}>
|
||||
<Loader2 className="w-12 h-12 text-amber-500 animate-spin" />
|
||||
</div>
|
||||
);
|
||||
@ -164,7 +144,7 @@ export default function PaymentsPage() {
|
||||
|
||||
if (isGuest) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-b from-amber-50/50 to-white flex items-center justify-center p-4" dir="rtl">
|
||||
<div className="min-h-screen bg-gradient-to-b from-amber-50/50 to-white flex items-center justify-center p-4" dir={i18n.dir()}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
@ -193,7 +173,7 @@ export default function PaymentsPage() {
|
||||
const others = reservations.filter((r) => !canPay(r.status));
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 py-8" dir="rtl">
|
||||
<div className="min-h-screen bg-gray-50 py-8" dir={i18n.dir()}>
|
||||
<Toaster position="top-center" reverseOrder={false} />
|
||||
<div className="container mx-auto px-4 max-w-4xl">
|
||||
<motion.div
|
||||
@ -232,7 +212,7 @@ export default function PaymentsPage() {
|
||||
</h2>
|
||||
{others.map((r, i) => {
|
||||
const statusKey = STATUS_MAP[r.status] || 'pending';
|
||||
const cfg = STATUS_CONFIG[statusKey];
|
||||
const cfg = getStatusConfig(t)[statusKey];
|
||||
const Icon = cfg.icon;
|
||||
const amount = r.depositAmount || r.totalPrice || 0;
|
||||
|
||||
@ -352,7 +332,7 @@ export default function PaymentsPage() {
|
||||
<div className="px-6 py-5 border-b border-gray-100">
|
||||
<p className="text-sm font-bold text-gray-700 mb-3">{t('payments.paymentMethodLabel')}</p>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{PAYMENT_METHODS.map((method) => {
|
||||
{getPaymentMethods(t).map((method) => {
|
||||
const isSelected = selectedPayment === method.id;
|
||||
const Icon = method.icon;
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user