Loading bonus clients from API
This commit is contained in:
parent
efae331aaf
commit
3142023c79
@ -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(
|
||||||
|
`${validatedBody.type}__token`,
|
||||||
|
JSON.stringify({ token, card_id }),
|
||||||
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
maxAge: 2 * 60 * 60,
|
maxAge: 2 * 60 * 60,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
31
src/app/api/bonus/info/route.ts
Normal file
31
src/app/api/bonus/info/route.ts
Normal 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);
|
||||||
17
src/entities/bonus/api/bonus.api.ts
Normal file
17
src/entities/bonus/api/bonus.api.ts
Normal 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;
|
||||||
8
src/entities/bonus/model/types/bonus-client-info.type.ts
Normal file
8
src/entities/bonus/model/types/bonus-client-info.type.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface ClientInfo {
|
||||||
|
card_id: number;
|
||||||
|
fullname: string;
|
||||||
|
cardno: string;
|
||||||
|
reg_date: string;
|
||||||
|
end_date: string;
|
||||||
|
bonuses: string;
|
||||||
|
}
|
||||||
@ -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,8 +34,12 @@ 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'>
|
||||||
|
{!data || isLoading ? (
|
||||||
|
// TODO: Bunyod please add loader here
|
||||||
|
<>Loader here</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className='flex items-center gap-2'>
|
<CardTitle className='flex items-center gap-2'>
|
||||||
<CreditCard className='h-5 w-5' />
|
<CreditCard className='h-5 w-5' />
|
||||||
@ -54,9 +51,7 @@ export function CustomerDashboard() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className='text-center'>
|
<div className='text-center'>
|
||||||
<p className='mb-2 text-4xl font-bold'>
|
<p className='mb-2 text-4xl font-bold'>{data.bonuses}</p>
|
||||||
{customerData.bonusPoints}
|
|
||||||
</p>
|
|
||||||
<p className='text-white/80'>
|
<p className='text-white/80'>
|
||||||
{t('customer.bonusCard.points')}
|
{t('customer.bonusCard.points')}
|
||||||
</p>
|
</p>
|
||||||
@ -64,12 +59,19 @@ export function CustomerDashboard() {
|
|||||||
<div className='mt-6 flex items-center justify-between'>
|
<div className='mt-6 flex items-center justify-between'>
|
||||||
<div className='flex items-center gap-1 text-sm text-white/80'>
|
<div className='flex items-center gap-1 text-sm text-white/80'>
|
||||||
<Clock className='h-4 w-4' />
|
<Clock className='h-4 w-4' />
|
||||||
<span>{t('customer.bonusCard.validUntil')}</span>
|
<span>
|
||||||
|
{t('customer.bonusCard.validUntil')}{' '}
|
||||||
|
{new Date(data.end_date).toLocaleDateString('en-GB')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<ArrowUpRight className='h-5 w-5 text-white/60' />
|
<ArrowUpRight className='h-5 w-5 text-white/60' />
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</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,22 +81,24 @@ export function CustomerDashboard() {
|
|||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
{!data || isLoading ? (
|
||||||
|
// TODO: Bunyod please add loader here
|
||||||
|
<>Loader here</>
|
||||||
|
) : (
|
||||||
<div className='grid gap-6 md:grid-cols-2'>
|
<div className='grid gap-6 md:grid-cols-2'>
|
||||||
<div>
|
<div>
|
||||||
<div className='mb-4 space-y-1'>
|
<div className='mb-4 space-y-1'>
|
||||||
<p className='text-sm text-gray-500'>
|
<p className='text-sm text-gray-500'>
|
||||||
{t('customer.infoCard.regDateLabel')}
|
{t('customer.infoCard.regDateLabel')}
|
||||||
</p>
|
</p>
|
||||||
<p className='font-medium'>
|
<p className='font-medium'>{data.fullname}</p>
|
||||||
{customerData.firstName} {customerData.lastName}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='space-y-1'>
|
<div className='space-y-1'>
|
||||||
<p className='text-sm text-gray-500'>
|
<p className='text-sm text-gray-500'>
|
||||||
{t('customer.infoCard.regDateLabel')}
|
{t('customer.infoCard.regDateLabel')}
|
||||||
</p>
|
</p>
|
||||||
<p className='font-medium'>
|
<p className='font-medium'>
|
||||||
{customerData.registrationDate}
|
{new Date(data.reg_date).toLocaleDateString('en-GB')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -103,16 +107,11 @@ export function CustomerDashboard() {
|
|||||||
<p className='text-sm text-gray-500'>
|
<p className='text-sm text-gray-500'>
|
||||||
{t('customer.infoCard.cardNumberLabel')}
|
{t('customer.infoCard.cardNumberLabel')}
|
||||||
</p>
|
</p>
|
||||||
<p className='font-medium'>{customerData.cardNumber}</p>
|
<p className='font-medium'>{data.cardno}</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user