patment part ui complated

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-04-06 11:48:31 +05:00
parent c01f3917d2
commit e95c8e9961
5 changed files with 0 additions and 145 deletions

View File

@@ -1,22 +0,0 @@
// ─── Pricing Constants ─────────────────────────────────────────────────────────
export const PRICING = {
SERVICE_FEE: 45_000,
CERTIFICATE_FEE: 15_000,
CURRENCY: 'UZS',
// Payme works in tiyin (1 UZS = 100 tiyin)
TIYIN_MULTIPLIER: 100,
} as const;
// ─── Payme Config ──────────────────────────────────────────────────────────────
export const PAYME_CONFIG = {
MERCHANT_ID: process.env.NEXT_PUBLIC_PAYME_MERCHANT_ID ?? 'your_merchant_id',
BASE_URL: 'https://checkout.paycom.uz',
// In development, point to your own backend
API_ENDPOINT: '/api/payments/payme/create',
RETURN_URL:
typeof window !== 'undefined'
? `${window.location.origin}/payment/success`
: 'https://yourapp.uz/payment/success',
} as const;

View File

@@ -7,11 +7,6 @@ export interface PaymePaymentRequest {
returnUrl: string; returnUrl: string;
} }
export interface PaymePaymentResponse {
redirectUrl: string;
transactionId: string;
}
export type PaymentStatus = 'idle' | 'loading' | 'success' | 'error'; export type PaymentStatus = 'idle' | 'loading' | 'success' | 'error';
// ─── Component Props ─────────────────────────────────────────────────────────── // ─── Component Props ───────────────────────────────────────────────────────────
@@ -29,10 +24,3 @@ export interface PaymentModalProps {
onConfirmPayment: () => void; onConfirmPayment: () => void;
isLoading: boolean; isLoading: boolean;
} }
export interface PaymeButtonProps {
amount: number;
orderId: string;
onSuccess?: (response: PaymePaymentResponse) => void;
onError?: (error: Error) => void;
}

View File

@@ -1,71 +0,0 @@
'use client';
import { useState, useCallback } from 'react';
import { PaymentStatus, PaymePaymentResponse } from './types';
import {
calculateTotal,
createPaymePayment,
generateOrderId,
redirectToPayme,
toTiyin,
} from './utils';
import { PAYME_CONFIG } from './constant';
interface UsePaymentOptions {
hasCertificate: boolean;
onSuccess?: (response: PaymePaymentResponse) => void;
onError?: (error: Error) => void;
}
interface UsePaymentReturn {
status: PaymentStatus;
error: string | null;
totalAmount: number;
handlePaymePayment: () => Promise<void>;
resetError: () => void;
}
export const usePayment = ({
hasCertificate,
onSuccess,
onError,
}: UsePaymentOptions): UsePaymentReturn => {
const [status, setStatus] = useState<PaymentStatus>('idle');
const [error, setError] = useState<string | null>(null);
const totalAmount = calculateTotal(hasCertificate);
const handlePaymePayment = useCallback(async () => {
setStatus('loading');
setError(null);
const orderId = generateOrderId();
try {
const response = await createPaymePayment({
amount: toTiyin(totalAmount),
orderId,
description: `Service fee${hasCertificate ? ' + Certificate' : ''}`,
returnUrl: PAYME_CONFIG.RETURN_URL,
});
setStatus('success');
onSuccess?.(response);
redirectToPayme(response.redirectUrl);
} catch (err) {
const paymentError =
err instanceof Error
? err
: new Error('Payment failed. Please try again.');
setStatus('error');
setError(paymentError.message);
onError?.(paymentError);
}
}, [totalAmount, hasCertificate, onSuccess, onError]);
const resetError = useCallback(() => {
setError(null);
setStatus('idle');
}, []);
return { status, error, totalAmount, handlePaymePayment, resetError };
};

View File

@@ -2,14 +2,6 @@
export const formatPrice = (amount: number, currency: string): string => export const formatPrice = (amount: number, currency: string): string =>
`${amount.toLocaleString('uz-UZ')} ${currency}`; `${amount.toLocaleString('uz-UZ')} ${currency}`;
// ─── Order ID Generator ────────────────────────────────────────────────────────
export const generateOrderId = (): string => {
const timestamp = Date.now();
const random = Math.random().toString(36).slice(2, 8).toUpperCase();
return `ORDER-${timestamp}-${random}`;
};
// ─── Payme API ───────────────────────────────────────────────────────────────── // ─── Payme API ─────────────────────────────────────────────────────────────────
/** /**

View File

@@ -34,38 +34,6 @@ const CloseButton: React.FC<{ onClick: () => void }> = ({ onClick }) => (
</button> </button>
); );
// ─── Error Banner ──────────────────────────────────────────────────────────────
// const ErrorBanner: React.FC<{ message: string; onDismiss: () => void }> = ({
// message,
// onDismiss,
// }) => (
// <div
// role="alert"
// className="flex items-start gap-3 rounded-lg bg-red-50 border border-red-200 px-4 py-3"
// >
// <svg
// className="shrink-0 mt-0.5 text-red-500"
// width="16"
// height="16"
// viewBox="0 0 24 24"
// fill="currentColor"
// >
// <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
// </svg>
// <p className="text-sm text-red-700 flex-1">{message}</p>
// <button
// onClick={onDismiss}
// aria-label="Dismiss error"
// className="text-red-400 hover:text-red-600 transition-colors"
// >
// <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
// <line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" />
// </svg>
// </button>
// </div>
// );
// ─── Security Badge ──────────────────────────────────────────────────────────── // ─── Security Badge ────────────────────────────────────────────────────────────
const SecurityBadge: React.FC<{ securityText: string }> = ({ const SecurityBadge: React.FC<{ securityText: string }> = ({