diff --git a/src/modules/details/components/ImageTag.tsx b/src/modules/details/components/ImageTag.tsx
index 931cc56..2b04306 100644
--- a/src/modules/details/components/ImageTag.tsx
+++ b/src/modules/details/components/ImageTag.tsx
@@ -1,27 +1,54 @@
+import axios from 'axios';
+import { useQuery } from 'react-query';
import { CircularProgress } from '@mui/material';
-import { isLabelWithInternallyDisabledControl } from '@testing-library/user-event/dist/utils';
-import { s3GetPresignedUrl} from 'apis/utils/mediaUpload/awsmedia';
-import Loader from 'modules/Auth/components/Loader';
-import { useEffect, useState } from 'react';
+import VisibilityIcon from '@mui/icons-material/Visibility';
+import DownloadIcon from '@mui/icons-material/Download';
+import { s3GetPresignedUrl } from 'apis/utils/mediaUpload/awsmedia';
+import MediaButton from './MediaButton';
+import { MediaS3Tagparams } from '../type';
-export const ImageS3Tag = ({ path }) => {
- const [srcImg, setSrcImg] = useState();
- const [isLoading, setIsLoading] = useState(false);
- useEffect(() => {
- setIsLoading(true);
- s3GetPresignedUrl(path)
- .then((img) => {
- setIsLoading(false);
- setSrcImg(img);
- })
- .catch((e) => {
- console.log('unable to fetch', e);
- setIsLoading(false);
- });
- }, []);
- return isLoading ? (
-
- ) : (
-
+export const MediaS3Tag = ({ path }: MediaS3Tagparams) => {
+ const { data: srcFile, isLoading, error } = useQuery(['presignedUrl', path], () => s3GetPresignedUrl(path), {
+ enabled: !!path,
+ });
+
+ const handleDownload = async () => {
+ if (srcFile) {
+ try {
+ const response = await axios.get(srcFile, { responseType: 'blob' });
+ const blob = new Blob([response.data]);
+ const downloadUrl = window.URL.createObjectURL(blob);
+ const link = document.createElement('a');
+ link.href = downloadUrl;
+ link.download = path.split('/').pop() || 'download';
+ link.click();
+ window.URL.revokeObjectURL(downloadUrl);
+ } catch (error) {
+ console.error('Download failed:', error);
+ }
+ }
+ };
+
+ const handleView = () => {
+ if (srcFile) {
+ window.open(srcFile, '_blank');
+ }
+ };
+
+ if (isLoading) {
+ return ;
+ }
+
+ return (
+
+ {srcFile ? (
+
+ } />
+ } />
+
+ ) : (
+
Unable to load file
+ )}
+
);
};
diff --git a/src/modules/details/components/MediaButton.tsx b/src/modules/details/components/MediaButton.tsx
new file mode 100644
index 0000000..0751906
--- /dev/null
+++ b/src/modules/details/components/MediaButton.tsx
@@ -0,0 +1,23 @@
+import { Button } from '@mui/material';
+import { ReactNode } from 'react';
+import './styles.scss';
+
+interface MediaButtonProps {
+ handleFunction: () => void;
+ children: ReactNode;
+ icon: React.ReactNode;
+}
+
+const MediaButton = ({ handleFunction, children, icon }: MediaButtonProps) => {
+ return (
+
+ );
+};
+export default MediaButton;
diff --git a/src/modules/details/components/Timeline.tsx b/src/modules/details/components/Timeline.tsx
index 07c968e..be7c5f8 100644
--- a/src/modules/details/components/Timeline.tsx
+++ b/src/modules/details/components/Timeline.tsx
@@ -11,7 +11,7 @@ import { Box, Chip, Paper, Typography } from '@mui/material';
import { DateFormate, getLastDaysFrom } from 'apis/utils/date.utils';
import { ticketStatusColours } from '../constants';
import { ITicketActivity } from '../type';
-import { ImageS3Tag } from './ImageTag';
+import { MediaS3Tag } from './ImageTag';
export const TimelineComponent = ({ activities }: any) => {
return (
@@ -76,7 +76,7 @@ const TimeLineDescription = ({ activity }: { activity: ITicketActivity }) => {
)}
{activity?.asset_url?.map((item) => (
-
+
))}
diff --git a/src/modules/details/components/styles.scss b/src/modules/details/components/styles.scss
new file mode 100644
index 0000000..6c02205
--- /dev/null
+++ b/src/modules/details/components/styles.scss
@@ -0,0 +1,10 @@
+.custom-button{
+ background-color: rgb(211, 211, 211) !important;
+ color: #000;
+ margin: 5px;
+ border-radius: 16px;
+}
+
+.custom-button:hover {
+ background-color: rgb(169, 169, 169) !important;
+}
diff --git a/src/modules/details/index.tsx b/src/modules/details/index.tsx
index 18c383c..4dbde9d 100644
--- a/src/modules/details/index.tsx
+++ b/src/modules/details/index.tsx
@@ -25,7 +25,7 @@ import EditIcon from '@mui/icons-material/Edit';
import { ticketStatusColours } from './constants';
-import { ImageS3Tag } from './components/ImageTag';
+import { MediaS3Tag } from './components/ImageTag';
import { UserContext } from 'App';
import { ROLES } from 'routes/roleConstants';
@@ -133,14 +133,14 @@ function Details() {
- Image
+ Attachment
{ticket?.asset_url?.map((item) => (
-
+
))}
diff --git a/src/modules/details/type.ts b/src/modules/details/type.ts
index 4c2f4df..13a3fe9 100644
--- a/src/modules/details/type.ts
+++ b/src/modules/details/type.ts
@@ -93,3 +93,7 @@ export interface IProgressTicketParams {
id: number;
setOpenEdit: (value: React.SetStateAction) => void;
}
+
+export interface MediaS3Tagparams {
+ path: string;
+}
diff --git a/src/modules/shared/UploadBucket.tsx b/src/modules/shared/UploadBucket.tsx
index f5c4e44..9d3d53f 100644
--- a/src/modules/shared/UploadBucket.tsx
+++ b/src/modules/shared/UploadBucket.tsx
@@ -4,7 +4,7 @@ import { Box } from '@mui/system';
import { IconButton, Typography } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import { useState } from 'react';
-import { ALLOWED_TYPES } from './constants';
+import { ALLOWED_TYPES, MAX_FILE_SIZE } from './constants';
export const UploadBucket = ({
isLoading,
@@ -32,11 +32,20 @@ export const UploadBucket = ({
if (invalidFile) {
setErrorMessage(`Invalid file type: ${invalidFile.name}`);
- } else {
- setErrorMessage(null);
- handleChange(selectedFiles);
+ return;
}
+
+ const oversizedFile = selectedFiles.find((file) => file.size > MAX_FILE_SIZE);
+
+ if (oversizedFile) {
+ setErrorMessage(`File exceeds size limit: ${oversizedFile.name}`);
+ return;
+ }
+
+ setErrorMessage(null);
+ handleChange(selectedFiles);
};
+
return (