Compare commits

..

14 Commits

Author SHA1 Message Date
YasinShaikh123
d7012f2692 selected css 2024-08-20 19:10:58 +05:30
YasinShaikh123
e07a92ba03 mobile downloader 2024-08-20 15:55:06 +05:30
YasinShaikh123
adb4bd5d27 Merge branch 'dev' of http://git.wdipl.com/Siddhesh.More/tanami-admin-panel into feature-dev 2024-08-20 14:53:05 +05:30
cfda3264fc [.env update] 2024-08-20 14:52:13 +05:30
YasinShaikh123
1569afe4f0 mobile height 2024-08-20 13:47:46 +05:30
YasinShaikh123
4a3072b4d3 io mobile 2024-08-20 13:00:22 +05:30
4516c70406 Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/tanami-admin-panel 2024-08-20 12:19:06 +05:30
50f87869be Edit update 2024-08-20 12:19:02 +05:30
d69e4a203f Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/tanami-admin-panel 2024-08-20 11:26:40 +05:30
6e4c794d2b update 2024-08-17 20:38:06 +05:30
dfbc1ad338 finalUp 2024-08-16 20:44:13 +05:30
aa1c0c994a updted 2024-08-16 20:30:42 +05:30
620b365437 Merge branch 'dev' of http://git.wdipl.com/Siddhesh.More/tanami-admin-panel into dev 2024-08-16 20:03:54 +05:30
2e5ecb967f update 2024-08-16 20:03:50 +05:30
32 changed files with 2022 additions and 1058 deletions

2071
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,11 @@
/* font-family: "Lato", sans-serif !important; */ /* font-family: "Lato", sans-serif !important; */
} }
::selection {
background-color: #004717; /* Change this to your desired color */
color: white; /* Optional: Change the text color */
}
.pointer { .pointer {
cursor: pointer !important; cursor: pointer !important;
} }

View File

@@ -9,12 +9,11 @@ import { Input } from "@chakra-ui/react";
// }; // };
export const formatCurrency = (value) => { export const formatCurrency = (value) => {
if (!value) return ''; if (value === undefined || value === null) return ''; // Handle undefined or null values
const [integer, decimal] = value?.split('.'); const [integer, decimal] = String(value).split('.'); // Convert value to string before splitting
const formattedInteger = integer?.replace(/\B(?=(\d{3})+(?!\d))/g, ','); const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger; return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
}; };
const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => { const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {

View File

@@ -404,7 +404,7 @@ const FormField = ({
w={6} w={6}
h={6} h={6}
src={ src={
" https://tanami.betadelivery.com/" + import.meta.env.VITE_IMAGE_URL +
item?.logo item?.logo
} }
/> />

View File

@@ -26,7 +26,7 @@ const ImageViewer = ({ src, isOpen, onClose }) => {
rounded={6} rounded={6}
w={"100%"} w={"100%"}
h={"100%"} h={"100%"}
src={"https://tanami.betadelivery.com/" + src} src={import.meta.env.VITE_IMAGE_URL + src}
/> />
</ModalBody> </ModalBody>
</ModalContent> </ModalContent>

View File

@@ -10,6 +10,7 @@ import {
ModalHeader, ModalHeader,
ModalOverlay, ModalOverlay,
Progress, Progress,
Spinner,
Stack, Stack,
Text, Text,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
@@ -25,20 +26,26 @@ import { IoBatteryHalf } from "react-icons/io5";
import { BiWifi } from "react-icons/bi"; import { BiWifi } from "react-icons/bi";
import { useGetIOByIdQuery } from "../Services/io.service"; import { useGetIOByIdQuery } from "../Services/io.service";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import FullscreenLoaders from "./Loaders/FullscreenLoaders";
import { formatDate } from "../Constants/Constants";
import { BsFileText } from "react-icons/bs";
const MobileView = ({ isOpen, onClose, finalRef }) => { const MobileView = ({ isOpen, onClose, finalRef, actionId }) => {
const [time, setTime] = useState(new Date()); const [time, setTime] = useState(new Date());
const navigate = useNavigate(); const navigate = useNavigate();
const params = useParams(); const params = useParams();
const id = params?.id; const id = actionId;
const { const {
data, data: IObyID,
isLoading: IObyIDisLoading, isLoading: IObyIDisLoading,
error: IObyIDerror, error: IObyIDerror,
} = useGetIOByIdQuery(id, { skip: !id }); } = useGetIOByIdQuery(id, { skip: !id });
console.log(data); console.log(IObyID);
const keyMerits = IObyID?.data?.keyMerits || [];
const artifactsImage = IObyID?.data?.artifactsImage || [];
useEffect(() => { useEffect(() => {
const timer = setInterval(() => { const timer = setInterval(() => {
@@ -52,7 +59,7 @@ const MobileView = ({ isOpen, onClose, finalRef }) => {
return date.toLocaleTimeString([], { return date.toLocaleTimeString([], {
hour: "2-digit", hour: "2-digit",
minute: "2-digit", minute: "2-digit",
hour12: false, hour12: true,
}); });
}; };
@@ -79,7 +86,17 @@ const MobileView = ({ isOpen, onClose, finalRef }) => {
display={"flex"} display={"flex"}
justifyContent={"center"} justifyContent={"center"}
h={"600px"} h={"600px"}
w={"330px"} w={"320px"}
sx={{
"@media (max-width: 2024px)": {
height:"695px",
width:"360px",
},
"@media (max-width: 1440px)": {
height:"600px",
width:"320px",
},
}}
> >
<Image <Image
h={"100%"} h={"100%"}
@@ -98,278 +115,340 @@ const MobileView = ({ isOpen, onClose, finalRef }) => {
pt={"36px"} pt={"36px"}
px={"15px"} px={"15px"}
> >
<Box> {IObyIDisLoading ? (
<Box <Box
display={"flex"} display={"flex"}
alignItems={"center"} justifyContent={"center"}
position={"absolute"} alignItems={"center"}
left={"30px"} h={"100%"}
top={"18px"}
> >
<Text ml={1} mb={0}> <Spinner
<GiNetworkBars fontSize={"10px"} /> thickness='3px'
</Text> color='purple.900'
<Text ml={1} mb={0} fontSize={"10px"}> size='lg'
{formatTime(time)} />
</Text>
<Text ml={"5px"} mb={0}>
<GrLinkedinOption fontSize={"10px"} />
</Text>
{/* <Text ml={1} mb={0}><FiInstagram fontSize={"10px"} /></Text> */}
</Box> </Box>
<Box ) : (
display={"flex"} <>
alignItems={"center"} <Box>
position={"absolute"} <Box
right={"36px"}
top={"17px"}
>
<Text mb={0}>
<BiWifi fontSize={"14px"} />
</Text>
<Text ml={1} mb={0}>
<IoBatteryHalf fontSize={"15px"} />
</Text>
</Box>
</Box>
<Box
p={"10px"}
overflowY={"scroll"}
h={"483px"}
zIndex={"99"}
position={"relative"}
borderBottomLeftRadius={"23px"}
borderBottomRightRadius={"23px"}
>
<Box
mb={4}
bg={"#f5f8f6"}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Box position={"relative"}>
<Text
position={"absolute"}
top={"12px"}
left={"10px"}
backgroundColor={"#e4f6ea"}
fontSize={"10px"}
fontWeight={500}
color="green"
p={"7px 12px"}
borderRadius={"20px"}
>
Stock
</Text>
<Text
position={"absolute"}
top={"12px"}
right={"10px"}
fontSize={"10px"}
display={"flex"} display={"flex"}
alignItems={"center"} alignItems={"center"}
fontWeight={500} position={"absolute"}
backgroundColor={"#fff"} left={"30px"}
p={"7px 12px"} top={"18px"}
borderRadius={"20px"}
> >
<LuClock color="#d8804e" />{" "} <Text ml={1} mb={0}>
<Text mb={0} ml={1}> <GiNetworkBars fontSize={"10px"} />
Closing Date Aug 23 2024
</Text> </Text>
</Text> <Text ml={1} mb={0} fontSize={"10px"}>
<Image {formatTime(time)}
borderTopLeftRadius={"20px"}
borderTopRightRadius={"20px"}
h={"130px"}
w={"100%"}
src={mobileBanner}
/>
</Box>
<Stack mt="3" bg={"#fff"} py={4} px={4}>
<Text
fontSize={"sm"}
fontWeight={"500"}
color={"#000"}
mb={0}
>
Guinevere Gates
</Text>
<Heading fontSize="16px" color={"#004717"}>
BHD 46,258
</Heading>
<Progress
colorScheme="green"
size="sm"
value={20}
borderRadius={"3px"}
/>
<Text
color={"#4e4e4e"}
fontSize={"xs"}
fontWeight={600}
mb={0}
>
0.0% funded
</Text>
<Text
fontSize={"xs"}
fontWeight={500}
mb={0}
color={"#9d9d9d"}
>
fugit eligendi dolore dolore et
</Text>
</Stack>
<Box py={4} px={4}>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"10px"}
mb={1}
fontWeight={600}
color={"#616161"}
>
Sponsor name:
</Text> </Text>
<Text fontSize={"10px"} mb={1} fontWeight={600}> <Text ml={"5px"} mb={0}>
Scott Simon <GrLinkedinOption fontSize={"10px"} />
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"10px"}
mb={1}
fontWeight={600}
color={"#616161"}
>
Estimated return:
</Text>
<Text fontSize={"10px"} mb={1} fontWeight={600}>
A provident veniam
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"10px"}
mb={1}
fontWeight={600}
color={"#616161"}
>
Hoiding period:
</Text>
<Text fontSize={"10px"} mb={1} fontWeight={600}>
Eius eiusmod exericit
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"10px"}
mb={1}
fontWeight={600}
color={"#616161"}
>
Minimum investment:
</Text>
<Text fontSize={"10px"} mb={1} fontWeight={600}>
BHD 1
</Text>
</Box>
</Box>
</Box>
<Box
mb={4}
p={5}
bg={"#f5f8f6"}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Heading fontSize="14px" fontWeight={600}>
Key Merits
</Heading>
<Box display={"flex"} alignItems={"center"}>
<Image
width={"30px"}
me={2}
src="https://tanami.betadelivery.com/public/icons/icon3.svg"
/>
<Text fontSize={"xs"} mb={0}>
Sit sunt consequunt Dolores minim suscip
</Text>
</Box>
</Box>
<Box
mb={4}
p={5}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Heading fontSize="14px" fontWeight={600}>
Investment Documents
</Heading>
<Box bg={"#f5f8f6"} w={"150px"} p={3} borderRadius={"10px"}>
<Box display={"flex"} alignItems={"center"} mb={2}>
<Image
me={1}
src="https://tanami.betadelivery.com/public/icons/icon8.svg"
/>
<Text fontSize={"xs"} mb={0}>
Merrill Rocha
</Text> </Text>
{/* <Text ml={1} mb={0}><FiInstagram fontSize={"10px"} /></Text> */}
</Box> </Box>
<Box <Box
display={"flex"} display={"flex"}
alignItems={"center"} alignItems={"center"}
justifyContent={"space-between"} position={"absolute"}
right={"36px"}
top={"17px"}
> >
<Text mb={0} fontSize={"sm"}> <Text mb={0}>
0.03 mb <BiWifi fontSize={"14px"} />
</Text>
<Text ml={1} mb={0}>
<IoBatteryHalf fontSize={"15px"} />
</Text> </Text>
<GrDownload fontSize={"15px"} />
</Box> </Box>
</Box> </Box>
</Box> <Box
<Box p={"10px"}
mb={4} overflowY={"scroll"}
p={4} h={"483px"}
borderRadius={"20px"} zIndex={"99"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"} position={"relative"}
> borderBottomLeftRadius={"23px"}
<Heading fontSize="14px" fontWeight={600}> borderBottomRightRadius={"23px"}
Videos sx={{
</Heading> "@media (max-width: 2024px)": {
<video autoPlay style={{ borderRadius: "18px" }}> height:"575px",
<source },
src="https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4" "@media (max-width: 1440px)": {
type="video/mp4" height:"483px",
style={{ height: "200px" }} },
/> }}
</video> >
</Box> <Box
</Box> mb={4}
bg={"#f5f8f6"}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Box position={"relative"}>
<Text
position={"absolute"}
top={"12px"}
left={"10px"}
backgroundColor={"#e4f6ea"}
fontSize={"10px"}
fontWeight={500}
color="green"
p={"7px 12px"}
borderRadius={"20px"}
>
Stock
</Text>
<Text
position={"absolute"}
top={"12px"}
right={"10px"}
fontSize={"10px"}
display={"flex"}
alignItems={"center"}
fontWeight={500}
backgroundColor={"#fff"}
p={"7px 12px"}
borderRadius={"20px"}
>
<LuClock color="#d8804e" />{" "}
<Text mb={0} ml={1}>
Closing Date {formatDate(IObyID?.data?.closingDate)}
</Text>
</Text>
{artifactsImage?.[0]?.artifactPathName && (
<Image
borderTopLeftRadius={"20px"}
borderTopRightRadius={"20px"}
h={"130px"}
w={"100%"}
src={
"https://tanami.betadelivery.com/" +
artifactsImage[0]?.artifactPathName
}
/>
)}
</Box>
<Stack mt="3" bg={"#fff"} py={4} px={4}>
<Text
fontSize={"sm"}
fontWeight={"500"}
color={"#000"}
mb={0}
>
{IObyID?.data?.investmentType?.investmentTypeName}
</Text>
<Heading fontSize="16px" color={"#004717"}>
BHD {IObyID?.data?.goalAmount}
</Heading>
<Progress
colorScheme="green"
size="sm"
value={20}
borderRadius={"3px"}
/>
<Text
color={"#4e4e4e"}
fontSize={"xs"}
fontWeight={600}
mb={0}
>
0.0% funded
</Text>
<Text
fontSize={"xs"}
fontWeight={500}
mb={0}
color={"#9d9d9d"}
>
{IObyID?.data?.descriptionEnglish}
</Text>
</Stack>
<Box py={4} px={4}>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"xs"}
mb={1}
fontWeight={500}
color={"#616161"}
>
Sponsor name:
</Text>
<Text fontSize={"xs"} mb={1} fontWeight={500}>
{IObyID?.data?.sponsor?.sponsorName}
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"xs"}
mb={1}
fontWeight={500}
color={"#616161"}
>
Estimated return:
</Text>
<Text fontSize={"xs"} mb={1} fontWeight={500}>
{IObyID?.data?.expectedReturn}
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"xs"}
mb={1}
fontWeight={500}
color={"#616161"}
>
Hoiding period:
</Text>
<Text fontSize={"xs"} mb={1} fontWeight={500}>
{IObyID?.data?.holdingPeriod}
</Text>
</Box>
<Box display={"flex"} justifyContent={"space-between"}>
<Text
fontSize={"xs"}
mb={1}
fontWeight={500}
color={"#616161"}
>
Minimum investment:
</Text>
<Text fontSize={"xs"} mb={1} fontWeight={500}>
{
IObyID?.data?.minInvestmentAmt?.[0]?.country
?.minInvestmentAmt
}
</Text>
</Box>
</Box>
</Box>
<Box
mb={4}
p={5}
bg={"#f5f8f6"}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Heading fontSize="14px" fontWeight={600}>
Key Merits
</Heading>
<Box display={"flex"} alignItems={"center"}>
{keyMerits?.[0]?.icon?.iconFilePath && (
<Image
rounded={"md"}
display={"flex"}
p={1}
justifyContent={"center"}
alignItems={"center"}
src={
"https://tanami.betadelivery.com/" +
keyMerits[0].icon.iconFilePath
}
w={8}
h={8}
/>
)}
<Text fontSize={"xs"} mb={0}>
{IObyID?.data?.keyMerits[0]?.meritsDescription}
</Text>
</Box>
</Box>
<Box
mb={4}
p={5}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Heading fontSize="14px" fontWeight={600}>
Investment Documents
</Heading>
<Box
bg={"#f5f8f6"}
w={"150px"}
p={3}
borderRadius={"10px"}
>
<Box display={"flex"} alignItems={"center"} mb={2}>
{/* <Image
me={1}
src="https://tanami.betadelivery.com/public/icons/icon8.svg"
/> */}
<BsFileText color="forestGreen" fontSize="18px" />
<Text fontSize={"xs"} mb={0} ml={2}>
{IObyID?.data?.documents?.[0]?.documentName}
</Text>
</Box>
<Box
display={"flex"}
alignItems={"center"}
justifyContent={"space-between"}
>
<Text mb={0} fontSize={"sm"}>
{IObyID?.data?.documents?.[0]?.documentSize}
</Text>
<GrDownload fontSize={"15px"} />
</Box>
</Box>
</Box>
<Box
mb={4}
p={4}
borderRadius={"20px"}
boxShadow={"rgba(0, 0, 0, 0.15) 0px 2px 8px"}
>
<Heading fontSize="14px" fontWeight={600}>
Videos
</Heading>
<video
autoPlay
loop
controls
style={{
borderRadius: "18px",
width: "100%",
height: "auto",
}}
>
<source
src={
IObyID?.data?.artifactsVideo?.[0]
?.artifactStreamingURL
}
type="video/mp4"
style={{ height: "200px" }}
/>
Your browser does not support the video tag.
</video>
</Box>
</Box>
<Box <Box
position={"relative"} position={"relative"}
p={4} p={4}
background={"#fff"} background={"#fff"}
padding={"24px"} padding={"24px"}
paddingBottom={"3px"} paddingBottom={"3px"}
borderBottomLeftRadius={"30px"} borderBottomLeftRadius={"30px"}
borderBottomRightRadius="30px" borderBottomRightRadius="30px"
> >
<Button <Button
margin={"auto"} margin={"auto"}
width={"85%"} width={"85%"}
bottom="10px" bottom="10px"
left="0" left="0"
colorScheme="forestGreen" colorScheme="forestGreen"
mr={3} mr={3}
w={"100%"} w={"100%"}
fontWeight={500} fontWeight={500}
borderRadius={"20px"} borderRadius={"20px"}
> >
Invest Invest
</Button> </Button>
</Box> </Box>
</>
)}
</Box> </Box>
</Box> </Box>
</HStack> </HStack>

View File

@@ -130,3 +130,10 @@ export function formatTimestampInGulfTimezone(timestamp) {
}; };
return date.toLocaleDateString('en-GB', options); return date.toLocaleDateString('en-GB', options);
} }
export function formatDate(dateString) {
const options = { year: 'numeric', month: 'short', day: 'numeric' };
const date = new Date(dateString);
return date.toLocaleDateString('en-US', options);
}

View File

@@ -36,7 +36,6 @@ import { useGetDepositRequestQuery } from "../../../Services/deposit.request.ser
import { current } from "@reduxjs/toolkit"; import { current } from "@reduxjs/toolkit";
import { TABLE_PAGINATION } from "../../../Constants/Paginations"; import { TABLE_PAGINATION } from "../../../Constants/Paginations";
import { removeTrailingZeros } from "../../../Constants/Constants"; import { removeTrailingZeros } from "../../../Constants/Constants";
import { formatCurrency } from "../../../Components/CurrencyInput";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
@@ -179,7 +178,9 @@ const DepositRequest = () => {
"Amount in Investor currency": ( "Amount in Investor currency": (
<Box display={'flex'} justifyContent={'end'} w={"100px"} isTruncated={true}> <Box display={'flex'} justifyContent={'end'} w={"100px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}> <Text as={"span"} color={"teal.900"}>
{formatCurrency(removeTrailingZeros(item?.investorAmount))} <Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge> {/* {formatCurrency(removeTrailingZeros(item?.investorAmount))} */}
{parseFloat(item?.investorAmount||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
<Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
</Text> </Text>
</Box> </Box>
), ),

View File

@@ -1,4 +1,5 @@
import { import {
Badge,
Box, Box,
Button, Button,
FormControl, FormControl,
@@ -137,7 +138,7 @@ const DepositRequestApprove = ({ isOpen, onClose, firstField, id, data:requestDa
<Box as="form" onSubmit={handleSubmit(onSubmit)}> <Box as="form" onSubmit={handleSubmit(onSubmit)}>
<ModalBody> <ModalBody>
<FormControl mb={4} isRequired> <FormControl mb={4} isRequired>
<FormLabel fontSize="sm">Deposit Amount (SAR)</FormLabel> <FormLabel fontSize="sm">Deposit Amount <Badge colorScheme="green">{fileredData?.currencyCode}</Badge></FormLabel>
<Input <Input
focusBorderColor="green.400" focusBorderColor="green.400"
name="investorAmount" name="investorAmount"

View File

@@ -229,7 +229,7 @@ const filteredData = data?.data?.rows
colorScheme={"forestGreen"} colorScheme={"forestGreen"}
> >
<Link <Link
href={"https://tanami.betadelivery.com/" + item?.supporting_FileName} href={import.meta.env.VITE_IMAGE_URL + item?.supporting_FileName}
isExternal isExternal
> >
<Box <Box

View File

@@ -113,7 +113,9 @@ const AddCashDetails = ({ isOpen, onClose, firstField, actionId, setActionId, da
const handleClose = () => { const handleClose = () => {
setAlert(false) setAlert(false)
onClose() onClose()
reset() reset({
transactionAmount:""
})
} }
return ( return (

View File

@@ -180,7 +180,7 @@ const IOArtifacts = ({ enableNextTab, index, data }) => {
colorScheme={"forestGreen"} colorScheme={"forestGreen"}
> >
<Link <Link
href={"https://tanami.betadelivery.com/" + item?.artifactPathName} href={import.meta.env.VITE_IMAGE_URL + item?.artifactPathName}
isExternal isExternal
> >
<Box <Box

View File

@@ -81,7 +81,7 @@ const IOCashDetails = () => {
const searchLower = searchTerm.toLowerCase(); const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower); const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches; return nameMatches;
}); }).sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
const extractedArray = filteredData?.map((item, index) => ({ const extractedArray = filteredData?.map((item, index) => ({

View File

@@ -54,7 +54,7 @@ const IONAVDetails = () => {
const searchLower = searchTerm.toLowerCase(); const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower); const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches; return nameMatches;
}); }).sort((b, a) => new Date(a.transactionDate) - new Date(b.transactionDate));
const extractedArray=filteredData?.map((item, index) => ({ const extractedArray=filteredData?.map((item, index) => ({
id: item?.id, id: item?.id,

View File

@@ -37,7 +37,7 @@ import SetDisplayOrder from "./SetDisplayOrder";
const downloadFile = (filePath, fileName) => { const downloadFile = (filePath, fileName) => {
fetch("https://tanami.betadelivery.com/" + filePath) fetch(import.meta.env.VITE_IMAGE_URL+filePath)
.then((response) => { .then((response) => {
if (!response.ok) { if (!response.ok) {
throw new Error("Network response was not ok"); throw new Error("Network response was not ok");

View File

@@ -57,6 +57,7 @@ const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
const [isBtnLoading, setIsBtnLoading] = useState(false); const [isBtnLoading, setIsBtnLoading] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState(""); const [mouseEnteredId, setMouseEnteredId] = useState("");
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const { const {
isOpen: isEditOpen, isOpen: isEditOpen,
onOpen: onEditOpen, onOpen: onEditOpen,
@@ -128,14 +129,14 @@ const KeyMerits = ({ enableNextTab, index, data: prepopData }) => {
</Box> </Box>
), ),
Icon: item?.icon?.iconFilePath && ( Icon: item?.icon?.iconFilePath && (
<Image <Image
rounded={"md"} rounded={"md"}
// bg={"#003B14"} // bg={"#003B14"}
display={"flex"} display={"flex"}
p={1} p={1}
justifyContent={"center"} justifyContent={"center"}
alignItems={"center"} alignItems={"center"}
src={" https://tanami.betadelivery.com/" + item?.icon?.iconFilePath} src={import.meta.env.VITE_IMAGE_URL+ item?.icon?.iconFilePath}
w={8} w={8}
h={8} h={8}
/> />

View File

@@ -63,7 +63,7 @@ const SetDisplayOrder = ({ data }) => {
p={1} p={1}
justifyContent={"center"} justifyContent={"center"}
alignItems={"center"} alignItems={"center"}
src={"https://tanami.betadelivery.com/" + item?.icon?.iconFilePath} src={import.meta.env.VITE_IMAGE_URL + item?.icon?.iconFilePath}
w={8} w={8}
h={8} h={8}
/> />

View File

@@ -260,7 +260,7 @@ const IOArtifactsAdd = ({
<Image <Image
rounded={"md"} rounded={"md"}
src={ src={
"https://tanami.betadelivery.com/" + import.meta.env.VITE_IMAGE_URL +
watch()?.artifactPathName watch()?.artifactPathName
} }
alt="Image Preview" alt="Image Preview"

View File

@@ -285,7 +285,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
> >
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
{selectedImageIcon && <Image {selectedImageIcon && <Image
src={`https://tanami.betadelivery.com/${selectedImageIcon}`} src={`${import.meta.env.VITE_IMAGE_URL}${selectedImageIcon}`}
alt={selectedImageIcon} alt={selectedImageIcon}
boxSize="1rem" boxSize="1rem"
mr="12px" mr="12px"
@@ -305,7 +305,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
> >
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
<Image <Image
src={`https://tanami.betadelivery.com/${iconFilePath}`} src={`${import.meta.env.VITE_IMAGE_URL}${iconFilePath}`}
alt={iconName} alt={iconName}
boxSize="1rem" boxSize="1rem"
mr="12px" mr="12px"

View File

@@ -284,7 +284,7 @@ const KeyMeritsEdit = ({
> >
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
{selectedImageIcon&&<Image {selectedImageIcon&&<Image
src={`https://tanami.betadelivery.com/${selectedImageIcon}`} src={`${import.meta.env.VITE_IMAGE_URL}${selectedImageIcon}`}
alt={selectedImageIcon} alt={selectedImageIcon}
boxSize="1rem" boxSize="1rem"
mr="12px" mr="12px"
@@ -304,7 +304,7 @@ const KeyMeritsEdit = ({
> >
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
<Image <Image
src={`https://tanami.betadelivery.com/${iconFilePath}`} src={`${import.meta.env.VITE_IMAGE_URL}${iconFilePath}`}
alt={iconName} alt={iconName}
boxSize="1rem" boxSize="1rem"
mr="12px" mr="12px"

View File

@@ -2,6 +2,7 @@ import {
Box, Box,
Button, Button,
FormControl, FormControl,
FormErrorMessage,
FormLabel, FormLabel,
HStack, HStack,
Input, Input,
@@ -23,8 +24,61 @@ import {
import DataTable from "../../../../Components/DataTable/DataTable"; import DataTable from "../../../../Components/DataTable/DataTable";
import { useState } from "react"; import { useState } from "react";
import { AddIcon } from "@chakra-ui/icons"; import { AddIcon } from "@chakra-ui/icons";
import { useGetDistributionInvestorMutation } from "../../../../Services/io.service";
import { useParams } from "react-router-dom";
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
export const investor = yup.object().shape({
amount: yup.string().required("Amount is required"),
});
const DistributionInvestor = ({ isOpen, onClose, }) => {
const params = useParams()
const id = params?.id
// const {
// data:IObyID,
// error,
// isLoading,
// } = useGetDistributionInvestorMutation(id);
const [ getDistributionInvestment ] = useGetDistributionInvestorMutation()
const {
control,
handleSubmit,
formState: { errors },
reset,
} = useForm({
resolver: yupResolver(investor),
});
// useEffect(()=>{
// try {
// const res = getDistributionInvestment({id,data})
// console.log(res);
// } catch (error) {
// }
// },[])
// console.log(IObyID);
const DistributionInvestor = ({ isOpen, onClose }) => {
// ====================================================[Table Setup]================================================================ // ====================================================[Table Setup]================================================================
const tableHeadRow = [ const tableHeadRow = [
"Sr No.", "Sr No.",
@@ -205,22 +259,48 @@ const DistributionInvestor = ({ isOpen, onClose }) => {
); );
}; };
const onSubmit = (data) =>{
console.log( data );
}
return ( return (
<Modal size={"xl"} isOpen={isOpen} onClose={onClose}> <Modal size={"xl"} isOpen={isOpen} onClose={onClose}>
<ModalOverlay /> <ModalOverlay />
<ModalContent maxW={1000}> <ModalContent maxW={1000}>
<ModalHeader fontSize={"md"}>Distribution To Investor Transaction</ModalHeader> <ModalHeader fontSize={"md"}>
Distribution To Investor Transaction
</ModalHeader>
<ModalCloseButton /> <ModalCloseButton />
<ModalBody> <ModalBody>
<Text as="label" mb='5px' fontSize='sm' fontWeight={500}>Amount to Distribute</Text> {/* <Text as="label" mb="5px" fontSize="sm" fontWeight={500}>
<HStack mb={4}> Amount to Distribute
<Input placeholder="$00.00" size={"sm"} className="col" /> </Text> */}
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4}>
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */} {/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
<FormControl isInvalid={errors.amount}>
<FormLabel fontSize={"sm"}> Amount to Distribute</FormLabel>
<Controller
name="amount"
control={control}
render={({ field }) => (
<Input {...field} fontSize={"sm"} type="number" size={"sm"} textAlign={"right"} />
)}
/>
<FormErrorMessage fontSize={"xs"} fontWeight={500}>
{errors.amount?.message}
</FormErrorMessage>
</FormControl>
<Button <Button
// leftIcon={<AddIcon />} // leftIcon={<AddIcon />}
size={"sm"} size={"sm"}
rounded={"sm"} rounded={"sm"}
colorScheme="forestGreen" colorScheme="forestGreen"
type="submit"
> >
Calculate Calculate
</Button> </Button>
@@ -243,14 +323,12 @@ const DistributionInvestor = ({ isOpen, onClose }) => {
_hover={{ _hover={{
bg: "hsl(139deg 98.99% 26.59%)", bg: "hsl(139deg 98.99% 26.59%)",
}} }}
size={'sm'} size={"sm"}
rounded={"sm"} rounded={"sm"}
> >
Save Save
</Button> </Button>
<Button <Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
size={'sm'}
rounded={"sm"} mr={3} onClick={onClose}>
Close Close
</Button> </Button>
</ModalFooter> </ModalFooter>

View File

@@ -68,7 +68,7 @@ const ViewIOTable = () => {
// ===============================[ RTK Api calls ] // ===============================[ RTK Api calls ]
const { data, isLoading, error } = useGetIOsQuery({ const { data, isLoading, error } = useGetIOsQuery({
page: currentPage, page: currentPage,
size: pageSize, size: pageSize,
}); });
@@ -81,7 +81,7 @@ const ViewIOTable = () => {
"Goal Amount", "Goal Amount",
"Holding Period", "Holding Period",
"IO Status", "IO Status",
// "Preview", "Preview",
"Action", "Action",
]; ];
@@ -189,18 +189,22 @@ const ViewIOTable = () => {
), ),
Preview: ( Preview: (
<Box display={"flex"} justifyContent={"start"}> <Box display={"flex"} justifyContent={"start"}>
<Button <Badge
// _hover={{ color: "green.500" }} display={"flex"} px={2} py={1} alignItems={"center"}
color={"#000"}
fontWeight={500}
bg="purple.200" bg="purple.200"
// transition={"0.5s all"} onClick={() =>{
onClick={onOpen} setActionId(item.id)
// color="green.300" onOpen();
rounded={"md"} }}
rounded={"sm"}
size={"xs"} size={"xs"}
variant={"ghost"} variant={"ghost"}
cursor={"pointer"}
> >
<ImMobile className="me-1" /> View <ImMobile className="me-1" /> View
</Button> </Badge>
</Box> </Box>
), ),
Action: ( Action: (
@@ -363,7 +367,7 @@ const ViewIOTable = () => {
setMouseEntered={setMouseEntered} setMouseEntered={setMouseEntered}
/> />
<MobileView isOpen={isOpen} onClose={onClose} /> <MobileView isOpen={isOpen} onClose={onClose} actionId={actionId} />
<CustomAlertDialog <CustomAlertDialog
onClose={() => setDeleteAlert(false)} onClose={() => setDeleteAlert(false)}

View File

@@ -39,7 +39,7 @@ import UnderConstruction from "../../UnderConstruction";
const ViewIOdata = () => { const ViewIOdata = () => {
const params = useParams() const params = useParams()
const id = params?.id const id = params?.id
const { data, error, isLoading } = useGetIOprepopulateDataQuery(); const { data, error, isLoading } = useGetIOprepopulateDataQuery();
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();

View File

@@ -41,8 +41,8 @@ import Cancle from "./HeaderModal/Cancle";
import { AddIcon } from "@chakra-ui/icons"; import { AddIcon } from "@chakra-ui/icons";
import { GrGallery } from "react-icons/gr"; import { GrGallery } from "react-icons/gr";
import Loader01 from "../../../Components/Loaders/Loader01"; import Loader01 from "../../../Components/Loaders/Loader01";
import { formatCurrency } from "../../../Components/CurrencyInput"; // import { formatCurrency } from "../../../Components/CurrencyInput";
import { removeTrailingZeros } from "../../../Constants/Constants"; // import { removeTrailingZeros } from "../../../Constants/Constants";
const ViewIOdataHeader = ({data, isLoading}) => { const ViewIOdataHeader = ({data, isLoading}) => {
const params = useParams(); const params = useParams();
@@ -51,6 +51,7 @@ const ViewIOdataHeader = ({data, isLoading}) => {
const btnRef = useRef(); const btnRef = useRef();
const { IODetails, isIOloading } = useContext(GlobalStateContext); const { IODetails, isIOloading } = useContext(GlobalStateContext);
const { const {
isOpen: isInvestmentOpen, isOpen: isInvestmentOpen,
onOpen: onInvestmentOpen, onOpen: onInvestmentOpen,
@@ -104,6 +105,10 @@ const ViewIOdataHeader = ({data, isLoading}) => {
}; };
console.log(import.meta.env.VITE_IMAGE_URL +
IODetails?.artifactsImage?.[0]?.artifactPathName);
const menu = [ const menu = [
{ {
@@ -208,7 +213,7 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
w={"100%"} w={"100%"}
objectFit={"cover"} objectFit={"cover"}
src={ src={
" https://tanami.betadelivery.com/" + import.meta.env.VITE_IMAGE_URL +
IODetails?.artifactsImage?.[0]?.artifactPathName IODetails?.artifactsImage?.[0]?.artifactPathName
} }
alt={IODetails?.ioName} alt={IODetails?.ioName}
@@ -294,7 +299,8 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
IO MV IO MV
</Text> </Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}> <Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioNAV)) : "00.00"} {/* {IODetails?.ioNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioNAV)) : "00.00"} */}
{parseFloat(IODetails?.ioNAV||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</Text> </Text>
</Box> </Box>
@@ -303,7 +309,8 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
IO cash IO cash
</Text> </Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}> <Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} {/* {IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} */}
{parseFloat(IODetails?.ioCash||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</Text> </Text>
</Box> </Box>
@@ -312,7 +319,8 @@ const filteredMenu = menu?.filter(item => apiTransactionTitles?.includes(item.id
IO NAV IO NAV
</Text> </Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}> <Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioMVNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioMVNAV)) : "00.00"} {/* {IODetails?.ioMVNAV ? formatCurrency(removeTrailingZeros(IODetails?.ioMVNAV)) : "00.00"} */}
{parseFloat(IODetails?.ioMVNAV||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</Text> </Text>
</Box> </Box>

View File

@@ -263,7 +263,8 @@ const ViewIOdetails = () => {
{ {
label: "Goal Amount", label: "Goal Amount",
placeHolder: "$00.00", placeHolder: "$00.00",
value: IObyID?.data?.goalAmount ? formatCurrency(removeTrailingZeros(IObyID?.data?.goalAmount)) : "---", value: IObyID?.data?.goalAmount?parseFloat(IObyID?.data?.goalAmount||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : "---",
name: "goalAmount", name: "goalAmount",
type: "number", type: "number",
isRequired: true, isRequired: true,

View File

@@ -174,7 +174,7 @@ const ProfileView = () => {
as="span" as="span"
boxShadow={"lg"} boxShadow={"lg"}
rounded={"md"} rounded={"md"}
bg={"#EAF2EC"} bg={"#EAF2EC"}
> >
<Icon color={"#004717"} boxSize={8} as={LuWallet} /> <Icon color={"#004717"} boxSize={8} as={LuWallet} />
@@ -257,7 +257,7 @@ const ProfileView = () => {
Transaction Transaction
</Tab> </Tab>
<Tab <Tab
isDisabled={true} isDisabled={true}
fontSize={"sm"} fontSize={"sm"}
_selected={{ _selected={{
color: "#004118", color: "#004118",

View File

@@ -3,7 +3,7 @@ import axios from "axios";
// Create an Axios instance for API calls // Create an Axios instance for API calls
export const api = axios.create({ export const api = axios.create({
// baseURL: `https://tanami.betadelivery.com/api/v1`, // baseURL: `https://tanami.betadelivery.com/api/v1`,
baseURL: `https://admin.tanami.betadelivery.com/api/v1`, // Replace with your API base URL baseURL: import.meta.env.VITE_BAS_URL, // Replace with your API base URL
timeout: 10000, // Adjust timeout as needed timeout: 10000, // Adjust timeout as needed
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@@ -0,0 +1,101 @@
//sponser.service
// Need to use the React-specific entry point to import createApi
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { api } from "./api.service";
const baseUrl = api?.defaults.baseURL;
// const baseUrl = `${import.meta.env.VITE_API_BASE_URL}/${import.meta.env.VITE_API_VERSION}`
// Define a service using a base URL and expected endpoints
export const deposite = createApi({
reducerPath: "deposite",
baseQuery: fetchBaseQuery({ baseUrl: baseUrl }),
tagTypes: ["gtDeposite"],
endpoints: (builder) => ({
// ======[Get All]=====
getSponserMaster: builder.query({
query: ({ page, size }) => `/sponsor/admin?page=${page}&size=${size}`,
providesTags: ["getSponser"],
}),
// ========[Get Active]========
getActiveSponserMaster: builder.query({
query: () => `/sponsor/admin/active`,
providesTags: ["getSponser"],
}),
getSponserMasterActive: builder.query({
query: () => "/sponsor/admin/active",
}),
// ======[Get ID]=====
getSponserById: builder.query({
query: (id) => `/sponsor/admin/${id}`,
providesTags: ["getSponser"],
}),
// ========[Toggle Status]========
toggleStatus: builder.mutation({
query: ({ id }) => ({
url: `/sponsor/admin/toggle-status/${id}`,
method: "PATCH",
}),
invalidatesTags: ["getSponser"],
}),
// ========[Create Sponser]========
createSponser: builder.mutation({
query: (data) => ({
url: `/sponsor/admin`,
method: "POST",
body: data,
}),
invalidatesTags: ["getSponser"],
}),
// ========[Update Sponser]========
updateSponser: builder.mutation({
query: ({ data, id }) => ({
url: `/sponsor/admin/${id}`,
method: "PATCH",
body: data,
}),
invalidatesTags: ["getSponser"],
}),
// ========[Delete Sponser]========
deleteSponser: builder.mutation({
query: (id) => ({
url: `/sponsor/admin/delete/${id}`,
method: "DELETE",
}),
invalidatesTags: ["getSponser"],
}),
}),
});
// Export hooks for usage in functional components
export const {
useGetSponserMasterQuery,
useGetSponserMasterActiveQuery,
useToggleStatusMutation,
useCreateSponserMutation,
useUpdateSponserMutation,
useGetSponserByIdQuery,
useDeleteSponserMutation,
useGetActiveSponserMasterQuery
} = sponserMaster;

View File

@@ -22,7 +22,7 @@ export const exchangeRate = createApi({
query: (id) => `/currencyExchange/admin/${id}`, query: (id) => `/currencyExchange/admin/${id}`,
providesTags: ["getAllExchangeRate"], providesTags: ["getAllExchangeRate"],
}), }),
updateExchangeRate: builder.mutation({ updateExchangeRate: builder.mutation({
query: ({ data, id }) => ({ query: ({ data, id }) => ({
url: `/currencyExchange/admin/${id}`, url: `/currencyExchange/admin/${id}`,

View File

@@ -24,7 +24,7 @@ export const ioService = createApi({
// =====[create] // =====[create]
createInvestmentDocuments: builder.mutation({ createInvestmentDocuments: builder.mutation({
query: ({data, id}) => ({ query: ({data, id}) => ({
url: `/io/admin/document/${id}`, url: `/io/admin/document/${id}`,

View File

@@ -231,7 +231,7 @@ export const ioService = createApi({
// =====[ Amount Investment ] // =====[ Amount Investment ] ======
amountIvestment : builder.mutation({ amountIvestment : builder.mutation({
query: ({ data, id }) => ({ query: ({ data, id }) => ({
url: `/io/admin/amount-invested/${id}`, url: `/io/admin/amount-invested/${id}`,
@@ -242,11 +242,19 @@ export const ioService = createApi({
}), }),
// ======== [ Distribution Transaction ] ========
getDistributionInvestor : builder.mutation({
query: ({id,data}) => ({
url: `/io/admin/io-distribution/pre-populate/${id}`,
method: "POST",
body: data,
}),
invalidatesTags: ["getIOById"],
}),
@@ -296,8 +304,8 @@ export const {
useUpdateStatusIoMutation, useUpdateStatusIoMutation,
useAmountIvestmentMutation, useAmountIvestmentMutation,
useGetDistributionInvestorMutation,
} = ioService; } = ioService;

View File

@@ -1,8 +1,8 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
// Define a base query function with RTK Query // Define a base query function with RTK Query
// export const baseQuery = fetchBaseQuery({ // export const baseQuery = fetchBaseQuery({
// baseUrl: 'https://admin.tanami.betadelivery.com/api/v1', // baseUrl: 'https://sprint4.tanami.betadelivery.com/api/v1',
// prepareHeaders: (headers) => { // prepareHeaders: (headers) => {
// const token = localStorage.getItem('accessToken'); // const token = localStorage.getItem('accessToken');
// if (token) { // if (token) {
@@ -12,17 +12,14 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
// }, // },
// }); // });
// Define a base query function with token refresh logic // Define a base query function with token refresh logic
export const baseQuery = async (args, api, extraOptions) => { export const baseQuery = async (args, api, extraOptions) => {
let result = await fetchBaseQuery({ let result = await fetchBaseQuery({
baseUrl: 'https://admin.tanami.betadelivery.com/api/v1', baseUrl: import.meta.env.VITE_BAS_URL,
prepareHeaders: (headers) => { prepareHeaders: (headers) => {
const token = localStorage.getItem('accessToken'); const token = localStorage.getItem("accessToken");
if (token) { if (token) {
headers.set('x-auth-token', token); headers.set("x-auth-token", token);
} }
return headers; return headers;
}, },
@@ -30,38 +27,47 @@ export const baseQuery = async (args, api, extraOptions) => {
if (result.error && result.error.status === 401) { if (result.error && result.error.status === 401) {
// Handle token refresh // Handle token refresh
const refreshToken = localStorage.getItem('refreshToken'); const refreshToken = localStorage.getItem("refreshToken");
if (refreshToken) { if (refreshToken) {
try { try {
const refreshResult = await fetchBaseQuery({ const refreshResult = await fetchBaseQuery({
baseUrl: 'https://admin.tanami.betadelivery.com/api/v1', baseUrl: import.meta.env.VITE_BAS_URL,
})({ })(
url: '/auth/user/regenerate-token', {
method: 'POST', url: "/auth/user/regenerate-token",
body: { refreshToken }, method: "POST",
}, api, extraOptions); body: { refreshToken },
},
api,
extraOptions
);
if (refreshResult.data) { if (refreshResult.data) {
// Save new tokens // Save new tokens
localStorage.setItem('accessToken', refreshResult.data.access.token); localStorage.setItem("accessToken", refreshResult.data.access.token);
localStorage.setItem('refreshToken', refreshResult.data.refresh.token); localStorage.setItem(
localStorage.setItem('refreshTokenExp', refreshResult.data.refresh.expires); "refreshToken",
refreshResult.data.refresh.token
);
localStorage.setItem(
"refreshTokenExp",
refreshResult.data.refresh.expires
);
// Retry the original request with the new token // Retry the original request with the new token
result = await fetchBaseQuery({ result = await fetchBaseQuery({
baseUrl: 'https://admin.tanami.betadelivery.com/api/v1', baseUrl: import.meta.env.VITE_BAS_URL,
prepareHeaders: (headers) => { prepareHeaders: (headers) => {
const token = localStorage.getItem('accessToken'); const token = localStorage.getItem("accessToken");
if (token) { if (token) {
headers.set('x-auth-token', token); headers.set("x-auth-token", token);
} }
return headers; return headers;
}, },
})(args, api, extraOptions); })(args, api, extraOptions);
} }
} catch (err) { } catch (err) {
console.error('Failed to refresh token:', err); console.error("Failed to refresh token:", err);
// Handle refresh failure (e.g., redirect to login) // Handle refresh failure (e.g., redirect to login)
} }
} }
@@ -72,32 +78,32 @@ export const baseQuery = async (args, api, extraOptions) => {
// Create an RTK Query API slice // Create an RTK Query API slice
export const apiSlice = createApi({ export const apiSlice = createApi({
reducerPath: 'api', reducerPath: "api",
baseQuery: baseQuery, baseQuery: baseQuery,
endpoints: (builder) => ({ endpoints: (builder) => ({
login: builder.mutation({ login: builder.mutation({
query: (credentials) => ({ query: (credentials) => ({
url: '/auth/admin', url: "/auth/admin",
method: 'POST', method: "POST",
body: credentials, body: credentials,
}), }),
async onQueryStarted(arg, { dispatch, queryFulfilled }) { async onQueryStarted(arg, { dispatch, queryFulfilled }) {
try { try {
const { data } = await queryFulfilled; const { data } = await queryFulfilled;
// Store tokens in local storage // Store tokens in local storage
localStorage.setItem('accessToken', data?.data?.access?.token) ; localStorage.setItem("accessToken", data?.data?.access?.token);
localStorage.setItem('refreshToken', data?.data?.refresh?.token); localStorage.setItem("refreshToken", data?.data?.refresh?.token);
// localStorage.setItem('refreshTokenExp', data?.data?.refresh?.expires); // localStorage.setItem('refreshTokenExp', data?.data?.refresh?.expires);
localStorage.setItem('accessTokenExp', data?.data?.access?.expires); localStorage.setItem("accessTokenExp", data?.data?.access?.expires);
} catch (error) { } catch (error) {
console.error('Login failed:', error); console.error("Login failed:", error);
} }
}, },
}), }),
refreshToken: builder.mutation({ refreshToken: builder.mutation({
query: (refreshToken) => ({ query: (refreshToken) => ({
url: '/auth/user/regenerate-token', url: "/auth/user/regenerate-token",
method: 'POST', method: "POST",
body: { refreshToken }, body: { refreshToken },
}), }),
}), }),