Loading bonus clients from API

This commit is contained in:
Umar Adilov 2025-05-01 01:45:12 +05:00
parent efae331aaf
commit 3142023c79
5 changed files with 133 additions and 74 deletions

View File

@ -23,7 +23,7 @@ const routeHandler = async (req: NextRequest) => {
}, },
}); });
const { token } = JSON.parse(oriyoResponse.data); const { token, card_id } = JSON.parse(oriyoResponse.data);
if (!token) { if (!token) {
return NextResponse.json({ error: 'Credentials error' }, { status: 401 }); return NextResponse.json({ error: 'Credentials error' }, { status: 401 });
@ -31,10 +31,14 @@ const routeHandler = async (req: NextRequest) => {
const response = NextResponse.json({ success: true }); const response = NextResponse.json({ success: true });
response.cookies.set(`${validatedBody.type}__token`, token, { response.cookies.set(
path: '/', `${validatedBody.type}__token`,
maxAge: 2 * 60 * 60, JSON.stringify({ token, card_id }),
}); {
path: '/',
maxAge: 2 * 60 * 60,
},
);
return response; return response;
} catch (error) { } catch (error) {

View File

@ -0,0 +1,31 @@
import { NextRequest, NextResponse } from 'next/server';
import oriyoClient from '@/app/api-utlities/utilities/oriyo.client';
import { validationErrorHandler } from '../../middlewares/error-handler.middleware';
export const routeHandler = async (req: NextRequest) => {
const bonusTokenData = req.cookies.get('bonus__token');
if (!bonusTokenData) {
return NextResponse.json(
{ error: 'User does not have access' },
{ status: 401 },
);
}
const { card_id, token } = JSON.parse(bonusTokenData.value);
const oriyoResponse = await oriyoClient.get('/client/info', {
params: {
card_id,
token,
},
});
return new Response(oriyoResponse.data, {
headers: { 'Content-Type': 'application/json' },
});
};
export const GET = validationErrorHandler(routeHandler);

View File

@ -0,0 +1,17 @@
import { baseAPI } from '@/shared/api/base-api';
import { ClientInfo } from '../model/types/bonus-client-info.type';
export const bonusApi = baseAPI.injectEndpoints({
endpoints: (builder) => ({
fetchMyBonusInfo: builder.query<ClientInfo, any>({
query: () => {
return {
url: '/bonus/info',
};
},
}),
}),
});
export const { useFetchMyBonusInfoQuery } = bonusApi;

View File

@ -0,0 +1,8 @@
export interface ClientInfo {
card_id: number;
fullname: string;
cardno: string;
reg_date: string;
end_date: string;
bonuses: string;
}

View File

@ -2,6 +2,8 @@
import { ArrowUpRight, Clock, CreditCard, LogOut, User } from 'lucide-react'; import { ArrowUpRight, Clock, CreditCard, LogOut, User } from 'lucide-react';
import { useFetchMyBonusInfoQuery } from '@/entities/bonus/api/bonus.api';
import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { useTextController } from '@/shared/language/hooks/use-text-controller';
import { Button } from '@/shared/shadcn-ui/button'; import { Button } from '@/shared/shadcn-ui/button';
import { import {
@ -14,20 +16,11 @@ import {
import { TransactionsTable } from '@/widgets/transactions-table'; import { TransactionsTable } from '@/widgets/transactions-table';
// Sample customer data
const customerData = {
firstName: 'Алишер',
lastName: 'Рахмонов',
passportNumber: 'A12345678',
bonusPoints: 1250,
cardNumber: '5678-9012-3456-7890',
expiryDate: '12/2025',
registrationDate: '15.06.2020',
};
export function CustomerDashboard() { export function CustomerDashboard() {
const { t } = useTextController(); const { t } = useTextController();
const { data, isLoading } = useFetchMyBonusInfoQuery({});
return ( return (
<div className='flex min-h-screen flex-col'> <div className='flex min-h-screen flex-col'>
<main className='flex-1 py-10'> <main className='flex-1 py-10'>
@ -41,35 +34,44 @@ export function CustomerDashboard() {
</div> </div>
<div className='mb-10 grid gap-3 md:grid-cols-3 md:gap-6'> <div className='mb-10 grid gap-3 md:grid-cols-3 md:gap-6'>
{/* Bonus Card */}
<Card className='bg-gradient-to-br from-red-600 to-red-800 text-white'> <Card className='bg-gradient-to-br from-red-600 to-red-800 text-white'>
<CardHeader> {!data || isLoading ? (
<CardTitle className='flex items-center gap-2'> // TODO: Bunyod please add loader here
<CreditCard className='h-5 w-5' /> <>Loader here</>
{t('customer.bonusCard.title')} ) : (
</CardTitle> <>
<CardDescription className='text-white/80'> <CardHeader>
{t('customer.bonusCard.description')} <CardTitle className='flex items-center gap-2'>
</CardDescription> <CreditCard className='h-5 w-5' />
</CardHeader> {t('customer.bonusCard.title')}
<CardContent> </CardTitle>
<div className='text-center'> <CardDescription className='text-white/80'>
<p className='mb-2 text-4xl font-bold'> {t('customer.bonusCard.description')}
{customerData.bonusPoints} </CardDescription>
</p> </CardHeader>
<p className='text-white/80'> <CardContent>
{t('customer.bonusCard.points')} <div className='text-center'>
</p> <p className='mb-2 text-4xl font-bold'>{data.bonuses}</p>
</div> <p className='text-white/80'>
<div className='mt-6 flex items-center justify-between'> {t('customer.bonusCard.points')}
<div className='flex items-center gap-1 text-sm text-white/80'> </p>
<Clock className='h-4 w-4' /> </div>
<span>{t('customer.bonusCard.validUntil')}</span> <div className='mt-6 flex items-center justify-between'>
</div> <div className='flex items-center gap-1 text-sm text-white/80'>
<ArrowUpRight className='h-5 w-5 text-white/60' /> <Clock className='h-4 w-4' />
</div> <span>
</CardContent> {t('customer.bonusCard.validUntil')}{' '}
{new Date(data.end_date).toLocaleDateString('en-GB')}
</span>
</div>
<ArrowUpRight className='h-5 w-5 text-white/60' />
</div>
</CardContent>
</>
)}
</Card> </Card>
{/* Bonus Card */}
{/* Customer Card */} {/* Customer Card */}
<Card className='md:col-span-2'> <Card className='md:col-span-2'>
<CardHeader className='pb-2'> <CardHeader className='pb-2'>
@ -79,40 +81,37 @@ export function CustomerDashboard() {
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className='grid gap-6 md:grid-cols-2'> {!data || isLoading ? (
<div> // TODO: Bunyod please add loader here
<div className='mb-4 space-y-1'> <>Loader here</>
<p className='text-sm text-gray-500'> ) : (
{t('customer.infoCard.regDateLabel')} <div className='grid gap-6 md:grid-cols-2'>
</p> <div>
<p className='font-medium'> <div className='mb-4 space-y-1'>
{customerData.firstName} {customerData.lastName} <p className='text-sm text-gray-500'>
</p> {t('customer.infoCard.regDateLabel')}
</p>
<p className='font-medium'>{data.fullname}</p>
</div>
<div className='space-y-1'>
<p className='text-sm text-gray-500'>
{t('customer.infoCard.regDateLabel')}
</p>
<p className='font-medium'>
{new Date(data.reg_date).toLocaleDateString('en-GB')}
</p>
</div>
</div> </div>
<div className='space-y-1'> <div>
<p className='text-sm text-gray-500'> <div className='mb-4 space-y-1'>
{t('customer.infoCard.regDateLabel')} <p className='text-sm text-gray-500'>
</p> {t('customer.infoCard.cardNumberLabel')}
<p className='font-medium'> </p>
{customerData.registrationDate} <p className='font-medium'>{data.cardno}</p>
</p> </div>
</div> </div>
</div> </div>
<div> )}
<div className='mb-4 space-y-1'>
<p className='text-sm text-gray-500'>
{t('customer.infoCard.cardNumberLabel')}
</p>
<p className='font-medium'>{customerData.cardNumber}</p>
</div>
<div className='mb-4 space-y-1'>
<p className='text-sm text-gray-500'>
{t('customer.infoCard.expiryDateLabel')}
</p>
<p className='font-medium'>{customerData.expiryDate}</p>
</div>
</div>
</div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>