This commit is contained in:
2024-09-24 15:46:05 +05:30
parent d1a01b60fe
commit 4482aad236
11 changed files with 704 additions and 15 deletions

107
package-lock.json generated
View File

@@ -11,9 +11,12 @@
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@reduxjs/toolkit": "^2.2.7",
"framer-motion": "^11.5.6",
"js-cookie": "^3.0.5",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"react-redux": "^9.1.2"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
@@ -2297,6 +2300,30 @@
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@reduxjs/toolkit": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz",
"integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==",
"license": "MIT",
"dependencies": {
"immer": "^10.0.3",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"reselect": "^5.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
@@ -2810,6 +2837,12 @@
"@types/react": "*"
}
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==",
"license": "MIT"
},
"node_modules/@vitejs/plugin-react-swc": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.0.tgz",
@@ -4262,6 +4295,16 @@
"node": ">= 4"
}
},
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -4710,6 +4753,15 @@
"set-function-name": "^2.0.1"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5287,6 +5339,29 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/react-redux": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
"license": "MIT",
"dependencies": {
"@types/use-sync-external-store": "^0.0.3",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^18.2.25",
"react": "^18.0",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-remove-scroll": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
@@ -5357,6 +5432,21 @@
}
}
},
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT"
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
"license": "MIT",
"peerDependencies": {
"redux": "^5.0.0"
}
},
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
@@ -5404,6 +5494,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/reselect": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
"license": "MIT"
},
"node_modules/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -6000,6 +6096,15 @@
}
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/vite": {
"version": "5.4.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",

View File

@@ -13,9 +13,12 @@
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@reduxjs/toolkit": "^2.2.7",
"framer-motion": "^11.5.6",
"js-cookie": "^3.0.5",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"react-redux": "^9.1.2"
},
"devDependencies": {
"@eslint/js": "^9.9.0",

View File

@@ -1,13 +1,10 @@
import './App.css'
function App() {
import { Box } from '@chakra-ui/react'
import React from 'react'
const App = () => {
return (
<Box>
</Box>
<Box>App</Box>
)
}
export default App
export default App

View File

@@ -0,0 +1,6 @@
// GlobalStateContext.js
import { createContext } from 'react';
const GlobalStateContext = createContext();
export default GlobalStateContext;

View File

@@ -0,0 +1,20 @@
// GlobalStateContext.js
import React, { useState } from "react";
import GlobalStateContext from "./GlobalStateContext";
const GlobalStateProvider = ({ children }) => {
const [isAuthenticate, setIsAuthenticate] = useState(false);
return (
<GlobalStateContext.Provider
value={{
isAuthenticate,
setIsAuthenticate,
}}
>
{children}
</GlobalStateContext.Provider>
);
};
export default GlobalStateProvider;

View File

@@ -0,0 +1,72 @@
// io.service.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./token.serivce";
export const ioService = createApi({
reducerPath: "ioService",
baseQuery: baseQuery,
tagTypes: [
"prePopulate",
"getIO",
"getKeyMerits",
"getArtifactsVideo",
"getInvestmentDocuments",
"getIOById",
"getSponser",
"getInvestmentType",
"getInvestmentTypeID"
],
endpoints: (builder) => ({
// =====[get prepopulate data]
getIOprepopulateData: builder.query({
query: () => `/io/admin/pre-populate`,
providesTags: ["prePopulate"],
}),
getIOById: builder.query({
query: (id) => ({ url: `/io/admin/${id}` }),
providesTags: ["getIOById"],
}),
// =====[create]
createIO: builder.mutation({
query: (data) => ({
url: `/io/admin`,
method: "POST",
body: data,
}),
invalidatesTags: ["getIO"],
}),
updateIO: builder.mutation({
query: ({ data, id }) => ({
url: `/io/admin/${id}`,
method: "PATCH",
body: data,
}),
invalidatesTags: ["getIOById", "getIO", "prePopulate"],
}),
deleteKeyMerits: builder.mutation({
query: (id) => ({
url: `/io/admin/key-merits/hard-delete/${id}`,
method: "DELETE",
}),
invalidatesTags: ["getIOById"],
}),
}),
});
// Export hooks for usage in functional components
export const {
useGetIOprepopulateDataQuery,
useGetIOByIdQuery,
useCreateIOMutation,
useUpdateIOMutation,
useDeleteKeyMeritsMutation,
} = ioService;

View File

@@ -0,0 +1,224 @@
// io.service.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./token.serivce";
export const onBoard = createApi({
reducerPath: "onBoard",
baseQuery: baseQuery,
tagTypes: [
"interest",
"fetchComunities"
],
endpoints: (builder) => ({
// =====[send otp]
sendOtp: builder.mutation({
query: (data) => ({
url: `/send_otp`,
method: "POST",
body: data,
}),
}),
// =====[verifiy otp]
verifyOtp: builder.mutation({
query: (data) => ({
url: `/verify_otp`,
method: "POST",
body: data,
}),
}),
// =====[add profile]
addProfile: builder.mutation({
query: (data) => ({
url: `/add_profile`,
method: "POST",
body: data,
}),
}),
// =====[get interest]
getInterest: builder.query({
query: () => `/fetch-interests`,
providesTags: ["interest"],
}),
// =====[selected Interest]
selectedInterest: builder.mutation({
query: (data) => ({
url: `/select-interests`,
method: "POST",
body: data,
}),
}),
// =====[forgot password]
forgotPassword: builder.mutation({
query: (data) => ({
url: `/forgot-password`,
method: "POST",
body: data,
}),
}),
// =====[forgot password]
forgotPasswordVerifyOtp: builder.mutation({
query: (data) => ({
url: `/forgot-password/verify-otp`,
method: "POST",
body: data,
}),
}),
// =====[Reset password]
resetPassword: builder.mutation({
query: (data) => ({
url: `/reset-password`,
method: "POST",
body: data,
}),
}),
// =====[fetch Comunities]
fetchComunities: builder.query({
query: () => `/fetch-communities`,
providesTags: ["fetchComunities"],
}),
// =====[select Communnity]
selectCommunnity: builder.mutation({
query: (data) => ({
url: `/select-communities`,
method: "POST",
body: data,
}),
}),
// =====[ /tell-us-about-your-business ]
tellUsAboutYourBussiness: builder.mutation({
query: (data) => ({
url: `/tell-us-about-your-business`,
method: "POST",
body: data,
}),
}),
// =====[fetch Groups]
fetchGroups: builder.query({
query: () => `/fetch-groups`,
providesTags: ["fetchGroups"],
}),
// =====[select Groups]
selectGroups: builder.mutation({
query: (data) => ({
url: `/select-groups`,
method: "POST",
body: data,
}),
}),
// =====[ bussines-profile stepper form ]
updateBussinessStepperForm: builder.mutation({
query: (data) => ({
url: `/update-business-profile-step-1`,
method: "POST",
body: data,
}),
}),
searchGroups: builder.query({
query: (searchData) => `search-group?search_data=${searchData}`,
}),
searchCommunity: builder.query({
query: (searchData) => `search-community?search_data=${searchData}`,
}),
// =====[Google Login]
googleLogin: builder.mutation({
query: (data) => ({
url: `/sign-in-with-google-login`,
method: "POST",
body: data,
}),
}),
// =====[Update user Account type]
updateUserAccountType: builder.mutation({
query: (data) => ({
url: `/update-user-account-type`,
method: "POST",
body: data,
}),
}),
}),
});
// Export hooks for usage in functional components
export const {
useSendOtpMutation,
useVerifyOtpMutation,
useAddProfileMutation,
useGetInterestQuery,
useSelectedInterestMutation,
useForgotPasswordMutation,
useForgotPasswordVerifyOtpMutation,
useResetPasswordMutation,
useFetchComunitiesQuery,
useSelectCommunnityMutation,
useTellUsAboutYourBussinessMutation,
useFetchGroupsQuery,
useSelectGroupsMutation,
useUpdateBussinessStepperFormMutation,
useSearchGroupsQuery,
useSearchCommunityQuery,
useGoogleLoginMutation,
useUpdateUserAccountTypeMutation
} = onBoard;

View File

@@ -0,0 +1,50 @@
// io.service.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./token.serivce";
export const profile = createApi({
reducerPath: "profile",
baseQuery: baseQuery,
tagTypes: [
"getProfile"
],
endpoints: (builder) => ({
// =====[send otp]
sendOtp: builder.mutation({
query: (data) => ({
url: `/send_otp`,
method: "POST",
body: data,
}),
}),
// =====[get interest]
getProfile: builder.query({
query: () => `/fetch-profile`,
providesTags: ["getProfile"],
}),
}),
});
// Export hooks for usage in functional components
export const {
useSendOtpMutation,
useGetProfileQuery,
} = profile;

View File

@@ -0,0 +1,140 @@
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import Cookies from "js-cookie";
// Define a base query function with token refresh logic
console.log(import.meta.env.VITE_BASE_URL);
export const baseQuery = async (args, api, extraOptions) => {
let result = await fetchBaseQuery({
baseUrl: import.meta.env.VITE_BASE_URL,
prepareHeaders: (headers) => {
const token = localStorage.getItem("accessToken");
const username = import.meta.env.VITE_USERNAME || 'defaultUsername';
const password = import.meta.env.VITE_PASSWORD || 'defaultPassword';
// Encode credentials to Base64
const basicAuth = btoa(`${username}:${password}`);
// Set the Authorization header
headers.set('Authorization', `Basic ${basicAuth}`);
// Set the token if available
if (token) {
headers.set("access-token", token);
}
return headers;
},
})(args, api, extraOptions);
if (result.error && result.error.status === 401) {
// Handle token refresh
// const refreshToken = localStorage.getItem("refreshToken");
// if (refreshToken) {
// try {
// const refreshResult = await fetchBaseQuery({
// baseUrl: import.meta.env.VITE_BASE_URL,
// })(
// {
// url: "/auth/user/regenerate-token",
// method: "POST",
// body: { refreshToken },
// },
// api,
// extraOptions
// );
// if (refreshResult.data) {
// // Save new tokens
// localStorage.setItem("accessToken", refreshResult.data.access.token);
// localStorage.setItem("refreshToken", refreshResult.data.refresh.token);
// localStorage.setItem("refreshTokenExp", refreshResult.data.refresh.expires);
// // Retry the original request with the new token
// result = await fetchBaseQuery({
// baseUrl: import.meta.env.VITE_BASE_URL,
// prepareHeaders: (headers) => {
// const newToken = localStorage.getItem("accessToken");
// // Set the Authorization header again
// headers.set('Authorization', `Basic ${basicAuth}`);
// // Set the new token
// if (newToken) {
// headers.set("x-auth-token", newToken);
// }
// return headers;
// },
// })(args, api, extraOptions);
// }
// } catch (err) {
// console.error("Failed to refresh token:", err);
// // Handle refresh failure (e.g., redirect to login)
// }
// }
const [ logout ] = useLogoutMutation()
const res = await logout()
console.log(res);
// Remove token and authenticated status from storage and cookies
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");
Cookies.remove("isAuthenticated", { path: '/login' });
}
return result;
};
// Create an RTK Query API slice
export const apiSlice = createApi({
reducerPath: "api",
baseQuery: baseQuery,
endpoints: (builder) => ({
login: builder.mutation({
query: (credentials) => ({
url: "/login",
method: "POST",
body: credentials,
}),
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
console.log(data?.data['access-token']);
// Store tokens in local storage
localStorage.setItem("accessToken", data?.data['access-token']);
localStorage.setItem("refreshToken", data?.data?.refresh?.token);
localStorage.setItem("accessTokenExp", data?.data?.access?.expires);
} catch (error) {
console.error("Login failed:", error);
}
},
}),
logout: builder.mutation({
query: (credentials) => ({
url: "/logout",
method: "POST",
}),
}),
refreshToken: builder.mutation({
query: (refreshToken) => ({
url: "/auth/user/regenerate-token",
method: "POST",
body: { refreshToken },
}),
}),
// Add more endpoints as needed
}),
});
export const { useLoginMutation, useRefreshTokenMutation, useLogoutMutation } = apiSlice;
export default apiSlice;

66
src/Store/Store.js Normal file
View File

@@ -0,0 +1,66 @@
import { configureStore } from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/query";
// import { sponserMaster } from "../Services/sponser.service";
// import { investmentType } from "../Services/investment.type.service";
// import { exchangeRate } from "../Services/exchange.rate.service";
// import { ioService } from "../Services/io.service";
// import { investorDetails } from "../Services/investor.details.service";
// import { investorTransaction } from "../Services/investor.transaction.service";
// import { api } from "../Services/api.service";
// import { keyMerits } from "../Services/Key.merits.service";
// import { bankDetails } from "../Services/bank.details.service";
// import { contact } from "../Services/contact.service";
// import { depositRequest } from "../Services/deposit.request.service";
import { apiSlice, baseQuery } from "../Services/token.serivce";
import { onBoard } from "../Services/onboard.service";
import { profile } from "../Services/profile.service";
// import { drawalRequest } from "../Services/drawal.request.service";
// import { deleteRequest } from "../Services/delete.request.service";
export const store = configureStore({
reducer: {
[apiSlice.reducerPath]: apiSlice.reducer,
[onBoard.reducerPath]: onBoard.reducer,
[profile.reducerPath]: profile.reducer,
// [sponserMaster.reducerPath]: sponserMaster.reducer,
// [investmentType.reducerPath]: investmentType.reducer,
// [exchangeRate.reducerPath]: exchangeRate.reducer,
// [ioService.reducerPath]: ioService.reducer,
// [investorDetails.reducerPath]: investorDetails.reducer,
// [investorTransaction.reducerPath]: investorTransaction.reducer,
// [bankDetails.reducerPath]: bankDetails.reducer,
// [contact.reducerPath]: contact.reducer,
// [depositRequest.reducerPath]: depositRequest.reducer,
// [drawalRequest.reducerPath]: drawalRequest.reducer,
// [deleteRequest.reducerPath]: deleteRequest.reducer,
// Add other reducers as needed
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: {
extraArgument: baseQuery, // Pass Axios instance as extra argument
},
}).concat(
onBoard.middleware,
apiSlice.middleware,
profile.middleware,
// investmentType.middleware,
// exchangeRate.middleware,
// ioService.middleware,
// investorDetails.middleware,
// investorTransaction.middleware,
// bankDetails.middleware,
// contact.middleware,
// depositRequest.middleware,
// drawalRequest.middleware,
// deleteRequest.middleware,
),
});
setupListeners(store.dispatch);
export default store;

View File

@@ -6,6 +6,10 @@ import { ChakraProvider } from "@chakra-ui/react";
import { extendTheme } from "@chakra-ui/react";
import * as ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import store from "./Store/Store.js";
import GlobalStateProvider from "./Contexts/GlobalStateProvider.jsx";
// 2. Extend the theme to include custom colors, fonts, etc
const colors = {
brand: {
@@ -15,12 +19,14 @@ const colors = {
},
};
const theme = extendTheme({ colors });
const customTheme = extendTheme({ colors });
createRoot(document.getElementById("root")).render(
<StrictMode>
<ChakraProvider theme={theme}>
<App />
<ChakraProvider theme={customTheme}>
<Provider store={store}>
<GlobalStateProvider>
<App />
</GlobalStateProvider>
</Provider>
</ChakraProvider>
</StrictMode>
);