diff --git a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/HouseholderVisits.tsx b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/HouseholderVisits.tsx index e13b30c2..55c1e7a2 100644 --- a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/HouseholderVisits.tsx +++ b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/HouseholderVisits.tsx @@ -31,7 +31,7 @@ interface Props { const columns = [ visitColumnHelper.accessor('documents', { header: t.table.columns.documents, - cell: doc => , + cell: doc => , }), visitColumnHelper.accessor('date', { id: 'date', diff --git a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetail.tsx b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetail.tsx index ea0ab1c3..28e64e09 100644 --- a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetail.tsx +++ b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetail.tsx @@ -5,9 +5,10 @@ import { import { FullPageLoader, showNotification } from '@camp/design'; import type { Document } from '@camp/domain'; import { fileStorageClient } from '@camp/file-storage-client'; -import { DownloadIcon, PdfFileIcon, TrashIcon } from '@camp/icons'; +import { DownloadIcon, PdfFileIcon, TrashIcon, VideoIcon } from '@camp/icons'; import { errorMessages, messages } from '@camp/messages'; import { getFileName, getFileType } from '@camp/router'; +import { isEmpty } from '@fullstacksjs/toolbox'; import { Box, Button, @@ -15,7 +16,6 @@ import { Group, Image, SimpleGrid, - Skeleton, Stack, } from '@mantine/core'; import download from 'downloadjs'; @@ -59,17 +59,8 @@ export const VisitDetail = ({ id }: VisitDetailProps) => { ); const visit = data!.visit; - // const fileType = getFileType(selectedDocument!.url); const deleteDocument = async (d: Document): Promise => { - if (visit?.documents.length === 1) { - return showNotification({ - type: 'failure', - title: t.title, - message: messages.notification.visits.delete.cantDeleteLst, - }); - } - const deleted = await deleteOneDocument({ variables: { id: d.id }, }); @@ -87,82 +78,92 @@ export const VisitDetail = ({ id }: VisitDetailProps) => { download(file, getFileName(url)); }; - const fileType = getFileType(selectedDocument!.url); + const fileType = selectedDocument?.url + ? getFileType(selectedDocument.url) + : null; return ( - - {visit?.documents.map(doc => { - const isSelected = selectedDocument?.url === doc.url; + {isEmpty(visit?.documents ?? []) ? null : ( + <> + + {visit?.documents.map(doc => { + const isSelected = selectedDocument?.url === doc.url; - return ( - setSelectedDocument(d)} - onDelete={deleteDocument} - /> - ); - })} - - ({ - flexGrow: 1, - borderLeft: `1px solid ${theme.colors.bg[5]}`, - })} - > - {fileType === 'pdf' ? ( -
- -
- ) : ( - - )} - - - - -
+ {fileType === 'pdf' ? ( +
+ +
+ ) : fileType === 'video' ? ( +
+ +
+ ) : selectedDocument != null ? ( + + ) : null} + + + + + + + )}
); }; diff --git a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetailDocumentItem.tsx b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetailDocumentItem.tsx index 98f45369..b6045fd2 100644 --- a/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetailDocumentItem.tsx +++ b/app/Dashboard/Households/HouseholdDetail/_components/HouseholderVisits/VisitDetail/VisitDetailDocumentItem.tsx @@ -1,8 +1,7 @@ import { debug, DebugScopes } from '@camp/debug'; import type { Document } from '@camp/domain'; -import { PdfFileIcon, VerticalMenuIcon } from '@camp/icons'; +import { PdfFileIcon, VerticalMenuIcon, VideoIcon } from '@camp/icons'; import { messages } from '@camp/messages'; -import type { FileType } from '@camp/router'; import { getFileName, getFileType } from '@camp/router'; import { ActionIcon, @@ -124,10 +123,14 @@ export const VisitDetailDocumentItem = ({ sx={{ objectPosition: 'top' }} alt={document.id} /> - ) : ( + ) : fileType === 'pdf' ? (
+ ) : ( +
+ +
)} diff --git a/configs/cspell/charity.en.txt b/configs/cspell/charity.en.txt index c57bcfd8..b37b43ae 100644 --- a/configs/cspell/charity.en.txt +++ b/configs/cspell/charity.en.txt @@ -53,4 +53,5 @@ pkey alian Prray clsx -downloadjs \ No newline at end of file +downloadjs +matroska \ No newline at end of file diff --git a/libs/design/ImagePreview/ImagePreview.tsx b/libs/design/ImagePreview/ImagePreview.tsx index 277a3e0c..781ad965 100644 --- a/libs/design/ImagePreview/ImagePreview.tsx +++ b/libs/design/ImagePreview/ImagePreview.tsx @@ -1,12 +1,14 @@ import type { ImageProps } from '@mantine/core'; -import { Box, Image } from '@mantine/core'; +import { Box, Center, Image } from '@mantine/core'; + +import { CameraOffIcon } from '../../icons'; interface Props extends ImageProps { size: number; pad?: number; } -export const ImagePreview = ({ size, pad = 10, ...rest }: Props) => { +export const ImagePreview = ({ size, pad = 10, src, ...rest }: Props) => { return ( ({ @@ -16,7 +18,13 @@ export const ImagePreview = ({ size, pad = 10, ...rest }: Props) => { padding: pad, })} > - +
+ {src == null ? ( + + ) : ( + + )} +
); }; diff --git a/libs/domain/Document.ts b/libs/domain/Document.ts index 47db5bc7..e90b8868 100644 --- a/libs/domain/Document.ts +++ b/libs/domain/Document.ts @@ -13,11 +13,21 @@ export const documentSchema = { export const documentFileValidator = z .object({ name: z.string(), - type: z.enum(['image/png', 'application/pdf', 'image/jpg', 'image/jpeg'], { - errorMap: () => ({ - message: messages.notification.addDocument.unsupportedType, - }), - }), + type: z.enum( + [ + 'image/png', + 'application/pdf', + 'image/jpg', + 'image/jpeg', + 'video/mp4', + 'video/x-matroska', + ], + { + errorMap: () => ({ + message: messages.notification.addDocument.unsupportedType, + }), + }, + ), size: z .number() .lt(20000000, messages.notification.addDocument.maxSizeExceeded), diff --git a/libs/icons/index.ts b/libs/icons/index.ts index 5fe12632..6e4928cc 100644 --- a/libs/icons/index.ts +++ b/libs/icons/index.ts @@ -4,6 +4,7 @@ export { ArrowDown as ArrowDownIcon, ArrowUp as ArrowUpIcon, Calendar as CalendarIcon, + CameraOff as CameraOffIcon, Check as CheckIcon, ChevronDown as ChevronDownIcon, ChevronLeft as ChevronLeftIcon, @@ -23,4 +24,5 @@ export { Upload as UploadIcon, User as UserIcon, MoreVertical as VerticalMenuIcon, + Video as VideoIcon, } from 'react-feather'; diff --git a/libs/router/getFileType.ts b/libs/router/getFileType.ts index 35e98a7a..745bf747 100644 --- a/libs/router/getFileType.ts +++ b/libs/router/getFileType.ts @@ -1,8 +1,9 @@ import { getFileName } from './getFileName'; -export type FileType = 'image' | 'pdf'; +export type FileType = 'image' | 'pdf' | 'video'; export const getFileType = (url: string): FileType => { const type = getFileName(url).replace(/.+\./g, ''); - return type === 'pdf' ? 'pdf' : 'image'; + + return type === 'pdf' ? 'pdf' : /mp4|mkv/.exec(type) ? 'video' : 'image'; };