diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 7b72902..778e5c7 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -7,11 +7,11 @@ import { makeStore } from '@/shared/store'; export default async function About() { const store = makeStore(); - const { data, isLoading } = await store.dispatch( + const { data } = await store.dispatch( mainPageApi.endpoints.fetchAboutUsPageContent.initiate(), ); - if (isLoading || !data) return null; + if (!data) return null; return ; } diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index 7dbe591..8772735 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -23,22 +23,18 @@ const routeHandler = async (req: NextRequest) => { }, }); - const { token, card_id } = JSON.parse(oriyoResponse.data); + const parsedResponse = JSON.parse(oriyoResponse.data); - if (!token) { + if (!parsedResponse.token) { return NextResponse.json({ error: 'Credentials error' }, { status: 401 }); } const response = NextResponse.json({ success: true }); - response.cookies.set( - `${validatedBody.type}__token`, - JSON.stringify({ token, card_id }), - { - path: '/', - maxAge: 2 * 60 * 60, - }, - ); + response.cookies.set(`${validatedBody.type}__token`, oriyoResponse.data, { + path: '/', + maxAge: 2 * 60 * 60, + }); return response; } catch (error) { diff --git a/src/app/api/bonus/info/route.ts b/src/app/api/bonus/info/route.ts index efb8011..d7a8178 100644 --- a/src/app/api/bonus/info/route.ts +++ b/src/app/api/bonus/info/route.ts @@ -4,7 +4,7 @@ import oriyoClient from '@/app/api-utlities/utilities/oriyo.client'; import { validationErrorHandler } from '../../middlewares/error-handler.middleware'; -export const routeHandler = async (req: NextRequest) => { +const routeHandler = async (req: NextRequest) => { const bonusTokenData = req.cookies.get('bonus__token'); if (!bonusTokenData) { diff --git a/src/app/api/bonus/transactions/route.ts b/src/app/api/bonus/transactions/route.ts new file mode 100644 index 0000000..310e78a --- /dev/null +++ b/src/app/api/bonus/transactions/route.ts @@ -0,0 +1,63 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { z } from 'zod'; + +import oriyoClient from '@/app/api-utlities/utilities/oriyo.client'; + +import { validationErrorHandler } from '../../middlewares/error-handler.middleware'; + +const validatedSchema = z.object({ + start_date: z.string().optional(), + end_date: z.string().optional(), + limit: z.coerce.number(), + page: z.coerce.number(), +}); + +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 params = Array.from(req.nextUrl.searchParams.entries()).reduce( + (pr, cr) => { + pr[cr[0]] = cr[1]; + + return pr; + }, + {} as Record, + ); + + const validatedRequest = validatedSchema.parse(params); + + const { card_id, token } = JSON.parse(bonusTokenData.value); + + const oriyoResponse = await oriyoClient.get('/client/transactions', { + params: { + card_id, + token, + limit: validatedRequest.limit, + page: validatedRequest.page, + type: 'bonus', + sort: 'id', + direction: 'desc', + start_date: validatedRequest.start_date, + end_date: validatedRequest.end_date, + }, + }); + + const parsedResponse = JSON.parse(oriyoResponse.data); + + if (parsedResponse.error) { + return NextResponse.json({ message: 'Fetch error' }, { status: 400 }); + } + + return new Response(oriyoResponse.data, { + headers: { 'Content-Type': 'application/json' }, + }); +}; + +export const GET = validationErrorHandler(routeHandler); diff --git a/src/app/api/corporate/info/route.ts b/src/app/api/corporate/info/route.ts new file mode 100644 index 0000000..b7e23ff --- /dev/null +++ b/src/app/api/corporate/info/route.ts @@ -0,0 +1,23 @@ +import { omit } from 'lodash'; +import { NextRequest, NextResponse } from 'next/server'; + +import { validationErrorHandler } from '../../middlewares/error-handler.middleware'; + +const routeHandler = async (req: NextRequest) => { + const bonusTokenData = req.cookies.get('corporate__token'); + + if (!bonusTokenData) { + return NextResponse.json( + { error: 'User does not have access' }, + { status: 401 }, + ); + } + + const parsedData = JSON.parse(bonusTokenData.value); + + return new Response(JSON.stringify(omit(parsedData, 'token')), { + headers: { 'Content-Type': 'application/json' }, + }); +}; + +export const GET = validationErrorHandler(routeHandler); diff --git a/src/app/api/middlewares/error-handler.middleware.ts b/src/app/api/middlewares/error-handler.middleware.ts index a3046e8..d7fa719 100644 --- a/src/app/api/middlewares/error-handler.middleware.ts +++ b/src/app/api/middlewares/error-handler.middleware.ts @@ -2,9 +2,10 @@ import { NextRequest, NextResponse } from 'next/server'; import { ZodError } from 'zod'; export const validationErrorHandler = - (handler: Function) => async (req: NextRequest, res: NextResponse) => { + (handler: Function) => + async (req: NextRequest, ...args: any[]) => { try { - return await handler(req, res); + return await handler(req, ...args); } catch (error) { if (error instanceof ZodError) return NextResponse.json({ message: error.format() }, { status: 400 }); diff --git a/src/app/api/pages/about-us/route.ts b/src/app/api/pages/about-us/route.ts deleted file mode 100644 index 31363d9..0000000 --- a/src/app/api/pages/about-us/route.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - presentHistoryItems, - presentReviews, - presentStations, - presentTeamMembers, -} from '@/app/api-utlities/presenters'; -import { aboutUsPageRequest } from '@/app/api-utlities/requests/about-us-page.request'; -import { requestTaylor } from '@/app/api-utlities/utilities/taylor.client'; - -import { validationErrorHandler } from '../../middlewares/error-handler.middleware'; - -const routeHandler = async () => { - const response = await requestTaylor(aboutUsPageRequest); - - return new Response( - JSON.stringify({ - team: presentTeamMembers(response.data._komanda), - history: presentHistoryItems(response.data._istoriya), - stations: presentStations(response.data._azs), - reviews: presentReviews(response.data._otzyvy), - }), - { - headers: { 'Content-Type': 'application/json' }, - }, - ); -}; - -export const GET = validationErrorHandler(routeHandler); diff --git a/src/app/api/pages/main/route.ts b/src/app/api/pages/main/route.ts deleted file mode 100644 index deb8f1b..0000000 --- a/src/app/api/pages/main/route.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - presentDiscounts, - presentJobs, - presentPartners, - presentStations, -} from '@/app/api-utlities/presenters'; -import { mainPageRequest } from '@/app/api-utlities/requests/main-page.request'; -import { requestTaylor } from '@/app/api-utlities/utilities/taylor.client'; - -import { validationErrorHandler } from '../../middlewares/error-handler.middleware'; - -const routeHandler = async (request: Request) => { - const response = await requestTaylor(mainPageRequest); - - return new Response( - JSON.stringify({ - partners: presentPartners(response.data._partners), - jobs: presentJobs(response.data._vacancies), - discounts: presentDiscounts(response.data._akcii), - stations: presentStations(response.data._azs), - }), - { - headers: { 'Content-Type': 'application/json' }, - }, - ); -}; - -export const GET = validationErrorHandler(routeHandler); diff --git a/src/app/api/text/route.ts b/src/app/api/text/route.ts deleted file mode 100644 index a5bf3df..0000000 --- a/src/app/api/text/route.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { presentTexts } from '@/app/api-utlities/presenters'; -import { textsRequest } from '@/app/api-utlities/requests/common'; -import { requestTaylor } from '@/app/api-utlities/utilities/taylor.client'; - -export async function GET(request: Request) { - const response = await requestTaylor(textsRequest); - - return new Response( - JSON.stringify(presentTexts(response.data._kontentSajta)), - { - headers: { 'Content-Type': 'application/json' }, - }, - ); -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6406af6..a195aa5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -37,7 +37,7 @@ export default async function RootLayout({ className='scroll-smooth' style={{ scrollBehavior: 'smooth' }} > - +
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index e66b1f8..a340dee 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -15,7 +15,7 @@ import { VacanciesSection } from '@/widgets/vacancies-section'; export default async function Home() { const store = makeStore(); - const { data, isLoading } = await store.dispatch( + const { data, isLoading, error } = await store.dispatch( mainPageApi.endpoints.fetchMainPageContent.initiate(), ); diff --git a/src/entities/bonus/api/bonus.api.ts b/src/entities/bonus/api/bonus.api.ts index b8d31bf..b83c712 100644 --- a/src/entities/bonus/api/bonus.api.ts +++ b/src/entities/bonus/api/bonus.api.ts @@ -1,6 +1,10 @@ import { baseAPI } from '@/shared/api/base-api'; -import { ClientInfo } from '../model/types/bonus-client-info.type'; +import { + ClientInfo, + TransactionRequest, + TransactionResponse, +} from '../model/types/bonus-client-info.type'; export const bonusApi = baseAPI.injectEndpoints({ endpoints: (builder) => ({ @@ -11,7 +15,19 @@ export const bonusApi = baseAPI.injectEndpoints({ }; }, }), + fetchBonusTransactions: builder.query< + TransactionResponse, + TransactionRequest + >({ + query: (request) => { + return { + url: '/bonus/transactions', + params: request, + }; + }, + }), }), }); -export const { useFetchMyBonusInfoQuery } = bonusApi; +export const { useFetchMyBonusInfoQuery, useFetchBonusTransactionsQuery } = + bonusApi; diff --git a/src/entities/bonus/model/types/bonus-client-info.type.ts b/src/entities/bonus/model/types/bonus-client-info.type.ts index dd7138f..bc50a6c 100644 --- a/src/entities/bonus/model/types/bonus-client-info.type.ts +++ b/src/entities/bonus/model/types/bonus-client-info.type.ts @@ -6,3 +6,29 @@ export interface ClientInfo { end_date: string; bonuses: string; } + +export interface TransactionResponse { + transactions: Transaction[]; + card_id: string; + current_page: number; + limit: number; + total_records: number; + total_pages: number; +} + +export interface Transaction { + id: number; + date_create: string; + station: string; + product_name: string; + amount: string; + price_real: string; + sum_real: string; +} + +export interface TransactionRequest { + start_date?: string; + end_date?: string; + page: number; + limit: number; +} diff --git a/src/entities/corporate/api/corporate.api.ts b/src/entities/corporate/api/corporate.api.ts new file mode 100644 index 0000000..32426ac --- /dev/null +++ b/src/entities/corporate/api/corporate.api.ts @@ -0,0 +1,17 @@ +import { baseAPI } from '@/shared/api/base-api'; + +import { CorporateInfoResponse } from '../model/types/corporate-client-info.type'; + +export const corporateApi = baseAPI.injectEndpoints({ + endpoints: (builder) => ({ + fetchMyCorporateInfo: builder.query({ + query: () => { + return { + url: '/corporate/info', + }; + }, + }), + }), +}); + +export const { useFetchMyCorporateInfoQuery } = corporateApi; diff --git a/src/entities/corporate/model/types/corporate-client-info.type.ts b/src/entities/corporate/model/types/corporate-client-info.type.ts new file mode 100644 index 0000000..3a069ae --- /dev/null +++ b/src/entities/corporate/model/types/corporate-client-info.type.ts @@ -0,0 +1,9 @@ +export interface CorporateInfoResponse { + created_at: string; + fund: string; + fund_total: string; + group_id: number; + group_name: string; + overdraft: string; + total_cards: number; +} diff --git a/src/features/map/ui/gas-station-map.tsx b/src/features/map/ui/gas-station-map.tsx index 76ce169..5f1357e 100644 --- a/src/features/map/ui/gas-station-map.tsx +++ b/src/features/map/ui/gas-station-map.tsx @@ -10,7 +10,7 @@ import { } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; -import { Stations } from '@/app/api-utlities/@types/main'; +import { Stations } from '@/app/api-utlities/@types'; import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { Badge } from '@/shared/shadcn-ui/badge'; diff --git a/src/features/pages/api/pages.api.ts b/src/features/pages/api/pages.api.ts index e0f4d45..6909d11 100644 --- a/src/features/pages/api/pages.api.ts +++ b/src/features/pages/api/pages.api.ts @@ -1,19 +1,59 @@ +import { jsonToGraphQLQuery } from 'json-to-graphql-query'; + import { AboutUsPageData } from '@/app/api-utlities/@types/about-us'; import { MainPageData } from '@/app/api-utlities/@types/main'; +import { + presentDiscounts, + presentHistoryItems, + presentJobs, + presentPartners, + presentReviews, + presentStations, + presentTeamMembers, +} from '@/app/api-utlities/presenters'; +import { aboutUsPageRequest } from '@/app/api-utlities/requests/about-us-page.request'; +import { mainPageRequest } from '@/app/api-utlities/requests/main-page.request'; -import { baseAPI } from '@/shared/api/base-api'; +import { taylorAPI } from '@/shared/api/taylor-api'; -export const mainPageApi = baseAPI.injectEndpoints({ +export const mainPageApi = taylorAPI.injectEndpoints({ endpoints: (builder) => ({ fetchMainPageContent: builder.query({ - query: () => '/pages/main', + query: () => ({ + url: '', + method: 'POST', + body: { + query: jsonToGraphQLQuery({ query: mainPageRequest }), + }, + }), + + transformResponse: (response: any) => { + return { + partners: presentPartners(response.data._partners), + jobs: presentJobs(response.data._vacancies), + discounts: presentDiscounts(response.data._akcii), + stations: presentStations(response.data._azs), + }; + }, }), - fetchAboutUsPageContent: builder.query({ - query: () => '/pages/about-us', + fetchAboutUsPageContent: builder.mutation({ + query: () => ({ + url: '', + method: 'POST', + body: { + query: jsonToGraphQLQuery({ query: aboutUsPageRequest }), + }, + }), + + transformResponse: (response: any) => { + return { + team: presentTeamMembers(response.data._komanda), + history: presentHistoryItems(response.data._istoriya), + stations: presentStations(response.data._azs), + reviews: presentReviews(response.data._otzyvy), + }; + }, }), }), }); - -export const { useFetchMainPageContentQuery, useFetchAboutUsPageContentQuery } = - mainPageApi; diff --git a/src/pages-templates/(dashboard)/corporate-dashboard/index.tsx b/src/pages-templates/(dashboard)/corporate-dashboard/index.tsx index badc151..2353347 100644 --- a/src/pages-templates/(dashboard)/corporate-dashboard/index.tsx +++ b/src/pages-templates/(dashboard)/corporate-dashboard/index.tsx @@ -4,6 +4,8 @@ import { subMonths } from 'date-fns'; import { Building2, LogOut, Wallet } from 'lucide-react'; import { useState } from 'react'; +import { useFetchMyCorporateInfoQuery } from '@/entities/corporate/api/corporate.api'; + import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { Button } from '@/shared/shadcn-ui/button'; import { @@ -96,6 +98,8 @@ export function CorporateDashboard() { const { t } = useTextController(); + const { data, isLoading } = useFetchMyCorporateInfoQuery({}); + return (
@@ -110,7 +114,7 @@ export function CorporateDashboard() {
{/* Company Card */} - + @@ -118,55 +122,63 @@ export function CorporateDashboard() { -
-
-
-

- {t('corporate.companyCard.companyNameLabel')} -

-

{companyData.companyName}

+ {!data ? ( + <>Loading + ) : ( +
+
+
+

+ {t('corporate.companyCard.companyNameLabel')} +

+

+ {data.group_name} +

+
+
+

+ {t('corporate.companyCard.cardsCountLabel')} +

+

{data.total_cards}

+
+
+

+ {t('corporate.companyCard.registrationDateLabel')} +

+ +

+ {new Date(data.created_at).toLocaleDateString( + 'en-GB', + )} +

+
-
-

- {t('corporate.companyCard.cardsCountLabel')} -

-

{companyData.numberOfCards}

-
-
-

- {t('corporate.companyCard.registrationDateLabel')} -

-

- {companyData.registrationDate} -

+
+
+

+ {t('corporate.companyCard.fundLabel')} +

+

+ {data.fund.toLocaleString()} {t('corporate.currency')} +

+
+
+

+ {t('corporate.companyCard.overdraftLabel')} +

+

+ {data.overdraft.toLocaleString()}{' '} + {t('corporate.currency')} +

+
-
-
-

- {t('corporate.companyCard.fundLabel')} -

-

- {companyData.fund.toLocaleString()}{' '} - {t('corporate.currency')} -

-
-
-

- {t('corporate.companyCard.overdraftLabel')} -

-

- {companyData.overdraft.toLocaleString()}{' '} - {t('corporate.currency')} -

-
-
-
+ )} {/* Fund Card */} - + @@ -177,14 +189,18 @@ export function CorporateDashboard() { -
-

- {companyData.totalFund.toLocaleString()} -

-

- {t('corporate.fundCard.currency')} -

-
+ {!data ? ( + <>Loading + ) : ( +
+

+ {data.fund_total?.toLocaleString()} +

+

+ {t('corporate.fundCard.currency')} +

+
+ )}
diff --git a/src/pages-templates/login/index.tsx b/src/pages-templates/login/index.tsx index ac51ec6..40c4bb1 100644 --- a/src/pages-templates/login/index.tsx +++ b/src/pages-templates/login/index.tsx @@ -4,6 +4,7 @@ import { deleteCookie, getCookie } from 'cookies-next'; import { Building2, Fuel, User } from 'lucide-react'; import Link from 'next/link'; import { useRouter, useSearchParams } from 'next/navigation'; +import { Suspense } from 'react'; import { LoginForm } from '@/features/auth/login-form'; @@ -16,13 +17,13 @@ import { CardHeader, CardTitle, } from '@/shared/shadcn-ui/card'; +import Container from '@/shared/shadcn-ui/conteiner'; import { Tabs, TabsContent, TabsList, TabsTrigger, } from '@/shared/shadcn-ui/tabs'; -import Container from '@/shared/shadcn-ui/conteiner'; const tabs = [ { @@ -41,16 +42,97 @@ const tabs = [ }, ]; -export default function LoginPage() { +function LoginPageTabs() { const { t } = useTextController(); const router = useRouter(); const searchParams = useSearchParams(); + const defaultTab = searchParams.get('tab') || 'bonus'; const handleTabChange = (tabType: string) => { - router.push(`?tab=${tabType}`, undefined, { shallow: true }); + router.push(`?tab=${tabType}`, undefined); }; + return ( + + + {tabs.map((tab) => { + return ( + + {t(tab.label)} + + ); + })} + + + {tabs.map((tab) => { + const tabCookieName = `${tab.type}__token`; + + const authenticationCookie = getCookie(tabCookieName); + + if (authenticationCookie) { + return ( + + + + {t(tab.title)} + + + + + + + + + + ); + } + + return ( + + + + {t(tab.title)} + {t(tab.description)} + + + + + + + ); + })} + + ); +} + +export default function LoginPage() { + const { t } = useTextController(); + return (
@@ -67,86 +149,17 @@ export default function LoginPage() {
- - - {tabs.map((tab) => { - return ( - - {t(tab.label)} - - ); - })} - - - {tabs.map((tab) => { - const tabCookieName = `${tab.type}__token`; - - const authenticationCookie = getCookie(tabCookieName); - - if (authenticationCookie) { - return ( - - - - {t(tab.title)} - - - - - - - - - - ); - } - - return ( - - - - {t(tab.title)} - {t(tab.description)} - - - - - - - ); - })} - + + +

{t('auth.loginIssues')}{' '} - + {t('auth.contactLink')}

diff --git a/src/shared/api/taylor-api.ts b/src/shared/api/taylor-api.ts new file mode 100644 index 0000000..200a98c --- /dev/null +++ b/src/shared/api/taylor-api.ts @@ -0,0 +1,14 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'; + +const baseQuery = fetchBaseQuery({ + baseUrl: process.env.TAYLOR_API_ENDPOINT, + headers: { + Authorization: process.env.TAYLOR_API_TOKEN || '', + }, +}); + +export const taylorAPI = createApi({ + reducerPath: 'taylorAPI', + baseQuery, + endpoints: () => ({}), +}); diff --git a/src/shared/language/api/text-control.api.ts b/src/shared/language/api/text-control.api.ts index 1fe2b26..dcbce86 100644 --- a/src/shared/language/api/text-control.api.ts +++ b/src/shared/language/api/text-control.api.ts @@ -1,12 +1,25 @@ -import { baseAPI } from '@/shared/api/base-api'; +import { jsonToGraphQLQuery } from 'json-to-graphql-query'; + +import { presentTexts } from '@/app/api-utlities/presenters'; +import { textsRequest } from '@/app/api-utlities/requests/common'; + +import { taylorAPI } from '@/shared/api/taylor-api'; import { TextItem } from '@/shared/types/text.types'; -export const textControlApi = baseAPI.injectEndpoints({ +export const textControlApi = taylorAPI.injectEndpoints({ endpoints: (builder) => ({ fetchText: builder.query({ - query: () => '/text', + query: () => ({ + url: '', + method: 'POST', + body: { + query: jsonToGraphQLQuery({ query: textsRequest }), + }, + }), + + transformResponse: (response: any) => { + return presentTexts(response.data._kontentSajta); + }, }), }), }); - -export const { useFetchTextQuery } = textControlApi; diff --git a/src/shared/store/index.ts b/src/shared/store/index.ts index fb9db85..599e8de 100644 --- a/src/shared/store/index.ts +++ b/src/shared/store/index.ts @@ -4,13 +4,16 @@ import { createWrapper } from 'next-redux-wrapper'; import { baseAPI } from '@/shared/api/base-api'; +import { taylorAPI } from '../api/taylor-api'; import { rootReducer } from './root-reducer'; export const makeStore = () => configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => - getDefaultMiddleware().concat(baseAPI.middleware), + getDefaultMiddleware() + .concat(baseAPI.middleware) + .concat(taylorAPI.middleware), devTools: process.env.NODE_ENV === 'development', }); diff --git a/src/shared/store/root-reducer.ts b/src/shared/store/root-reducer.ts index 1b1a8cd..080aa28 100644 --- a/src/shared/store/root-reducer.ts +++ b/src/shared/store/root-reducer.ts @@ -2,6 +2,9 @@ import { combineReducers } from '@reduxjs/toolkit'; import { baseAPI } from '@/shared/api/base-api'; +import { taylorAPI } from '../api/taylor-api'; + export const rootReducer = combineReducers({ [baseAPI.reducerPath]: baseAPI.reducer, + [taylorAPI.reducerPath]: taylorAPI.reducer, }); diff --git a/src/widgets/about-page/company-timeline.tsx b/src/widgets/about-page/company-timeline.tsx index 3142061..1dcf68b 100644 --- a/src/widgets/about-page/company-timeline.tsx +++ b/src/widgets/about-page/company-timeline.tsx @@ -3,7 +3,7 @@ import { Calendar, ChevronDown, ChevronUp } from 'lucide-react'; import { useState } from 'react'; -import { HistoryItems } from '@/app/api-utlities/@types/about-us'; +import { HistoryItems } from '@/app/api-utlities/@types'; import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { Button } from '@/shared/shadcn-ui/button'; diff --git a/src/widgets/map-section.tsx b/src/widgets/map-section.tsx index 8bfa798..dc4c187 100644 --- a/src/widgets/map-section.tsx +++ b/src/widgets/map-section.tsx @@ -2,9 +2,8 @@ import { MapPin } from 'lucide-react'; -import { Stations } from '@/app/api-utlities/@types/main'; +import { Stations } from '@/app/api-utlities/@types'; -import { GasStationMap } from '@/features/map'; import { Point } from '@/features/map/model'; import { YandexMap } from '@/features/map/ui/yandex-map'; diff --git a/src/widgets/partners-section.tsx b/src/widgets/partners-section.tsx index dd51fd9..e85119f 100644 --- a/src/widgets/partners-section.tsx +++ b/src/widgets/partners-section.tsx @@ -4,7 +4,7 @@ import { Handshake } from 'lucide-react'; import Image from 'next/image'; import Link from 'next/link'; -import { Partners } from '@/app/api-utlities/@types/main'; +import { Partners } from '@/app/api-utlities/@types'; import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { Button } from '@/shared/shadcn-ui/button'; diff --git a/src/widgets/transactions-table.tsx b/src/widgets/transactions-table.tsx index 787bce3..eae985d 100644 --- a/src/widgets/transactions-table.tsx +++ b/src/widgets/transactions-table.tsx @@ -3,7 +3,9 @@ import { format, subMonths } from 'date-fns'; import { ru } from 'date-fns/locale'; import { CalendarIcon } from 'lucide-react'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; + +import { useFetchBonusTransactionsQuery } from '@/entities/bonus/api/bonus.api'; import { useTextController } from '@/shared/language/hooks/use-text-controller'; import { Button } from '@/shared/shadcn-ui/button'; @@ -23,85 +25,30 @@ import { TableRow, } from '@/shared/shadcn-ui/table'; -// Sample customer data -const customerData = { - firstName: 'Алишер', - lastName: 'Рахмонов', - passportNumber: 'A12345678', - bonusPoints: 1250, - cardNumber: '5678-9012-3456-7890', - expiryDate: '12/2025', - registrationDate: '15.06.2020', -}; - -// Sample transaction data -const generateTransactions = () => { - const stations = [ - 'АЗС Душанбе-Центр', - 'АЗС Душанбе-Запад', - 'АЗС Душанбе-Восток', - 'АЗС Худжанд', - 'АЗС Куляб', - ]; - - const products = [ - { name: 'ДТ', price: 8.5 }, - { name: 'АИ-92', price: 9.2 }, - { name: 'АИ-95', price: 10.5 }, - { name: 'Z-100 Power', price: 11.8 }, - { name: 'Пропан', price: 6.3 }, - ]; - - const transactions = []; - - // Generate 50 random transactions over the last 6 months - for (let i = 0; i < 50; i++) { - const date = subMonths(new Date(), Math.random() * 6); - const station = stations[Math.floor(Math.random() * stations.length)]; - const product = products[Math.floor(Math.random() * products.length)]; - const quantity = Math.floor(Math.random() * 40) + 10; // 10-50 liters - const cost = product.price; - const total = quantity * cost; - - transactions.push({ - id: i + 1, - date, - station, - product: product.name, - quantity, - cost, - total, - }); - } - - // Sort by date (newest first) - return transactions.sort((a, b) => b.date.getTime() - a.date.getTime()); -}; - -const transactions = generateTransactions(); - export const TransactionsTable = () => { - const [startDate, setStartDate] = useState( - subMonths(new Date(), 1), - ); - const [endDate, setEndDate] = useState(new Date()); - const [filteredTransactions, setFilteredTransactions] = - useState(transactions); + const [startDate, setStartDate] = useState(subMonths(new Date(), 1)); + const [endDate, setEndDate] = useState(new Date()); + + const { data, refetch } = useFetchBonusTransactionsQuery({ + limit: 100, + page: 1, + start_date: format(startDate, 'yyyy-MM-dd'), + end_date: format(endDate, 'yyyy-MM-dd'), + }); // Filter transactions by date range const filterTransactions = () => { if (!startDate || !endDate) return; - const filtered = transactions.filter((transaction) => { - const transactionDate = new Date(transaction.date); - return transactionDate >= startDate && transactionDate <= endDate; - }); - - setFilteredTransactions(filtered); + refetch(); }; const { t } = useTextController(); + useEffect(() => {}, [startDate, endDate]); + + if (!data) return null; + return (
@@ -200,22 +147,22 @@ export const TransactionsTable = () => { - {filteredTransactions.length > 0 ? ( - filteredTransactions.map((transaction) => ( + {data.transactions.length > 0 ? ( + data.transactions.map((transaction) => ( - {format(transaction.date, 'dd.MM.yyyy')} + {format(new Date(transaction.date_create), 'dd.MM.yyyy')} {transaction.station} - {transaction.product} + {transaction.product_name} - {transaction.quantity} + {transaction.price_real} - {transaction.cost.toFixed(2)} {t('corporate.currency')} + {transaction.amount} {t('corporate.currency')} - {transaction.total.toFixed(2)} {t('corporate.currency')} + {transaction.sum_real} {t('corporate.currency')} ))