From 5b64a420bd36c5dd1032975562c42816d89872fc Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Sat, 30 Apr 2022 21:59:08 +0200 Subject: [PATCH] selectable photos --- frontend/src/Photos/Overview.tsx | 38 ++++++++++++++++++++++++------ frontend/src/Photos/PhotoCard.scss | 5 ++++ frontend/src/Photos/PhotoCard.tsx | 14 ++++++++--- frontend/tsconfig.json | 16 ++++--------- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/frontend/src/Photos/Overview.tsx b/frontend/src/Photos/Overview.tsx index eabdf22..835c07e 100644 --- a/frontend/src/Photos/Overview.tsx +++ b/frontend/src/Photos/Overview.tsx @@ -31,15 +31,33 @@ export interface IOverviewComponentProps { fetchPhotos: () => void; } +const PhotoCardM = React.memo(PhotoCard); + export const OverviewComponent: React.FunctionComponent< IOverviewComponentProps > = (props) => { const [selectedPhoto, setSelectedPhoto] = React.useState(0); const [isOverlayOpened, setOverlayOpen] = React.useState(false); - - const onCardClick = (id: number) => { - setSelectedPhoto(id); - setOverlayOpen(true); + const [selectedPhotos, setSelectedPhotos] = React.useState>( + new Set(), + ); + const selectedPhotosRef = React.useRef>(selectedPhotos); + selectedPhotosRef.current = selectedPhotos; + const onCardClick = (e: React.MouseEvent, id: number) => { + if (e.ctrlKey) { + const newSelectedPhotos = new Set([ + ...selectedPhotosRef.current, + ]); + if (newSelectedPhotos.has(id)) { + newSelectedPhotos.delete(id); + } else { + newSelectedPhotos.add(id); + } + setSelectedPhotos(newSelectedPhotos); + } else { + setSelectedPhoto(id); + setOverlayOpen(true); + } }; if ( @@ -73,6 +91,10 @@ export const OverviewComponent: React.FunctionComponent< {}, ); + const onClick = React.useCallback((e: React.MouseEvent) => { + onCardClick(e, Number(e.currentTarget.id)); + }, []); + const photos = Object.keys(dates).reduce( (acc: JSX.Element[], year): JSX.Element[] => { const els = Object.keys(dates[year]).reduce( @@ -85,10 +107,12 @@ export const OverviewComponent: React.FunctionComponent< ); const photosEls = photos.map((photo) => { return ( - onCardClick(photo.id)} + onClick={onClick} /> ); }); diff --git a/frontend/src/Photos/PhotoCard.scss b/frontend/src/Photos/PhotoCard.scss index a7dc393..a52873b 100644 --- a/frontend/src/Photos/PhotoCard.scss +++ b/frontend/src/Photos/PhotoCard.scss @@ -2,6 +2,10 @@ img { transition: all 0.3s; } + .selected { + padding: 1rem; + border-radius: 1.5rem; + } .notLoaded { opacity: 0; @@ -10,4 +14,5 @@ .loaded { opacity: 1; } + } \ No newline at end of file diff --git a/frontend/src/Photos/PhotoCard.tsx b/frontend/src/Photos/PhotoCard.tsx index 632b3f6..b9cbc33 100644 --- a/frontend/src/Photos/PhotoCard.tsx +++ b/frontend/src/Photos/PhotoCard.tsx @@ -20,10 +20,12 @@ import { LargeSize, PreviewSize } from "./helper"; export interface IPhotoCardComponentProps extends RouteComponentProps { photo: IPhotoReqJSON; + selected: boolean; + id: string; deletePhoto: (photo: IPhotoReqJSON) => void; cancelDelete: (photo: IPhotoReqJSON) => void; - onClick: () => void; + onClick: (e: React.MouseEvent) => void; } export interface IPhotoCardComponentState { @@ -73,12 +75,18 @@ export class PhotoCardComponent extends React.PureComponent< this.props.onClick()} + id={this.props.id} + onClick={(e: React.MouseEvent) => + this.props.onClick(e) + } > {fileExists ? ( this.setLoaded(true)} /* onMouseEnter={() => diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 7abcfa1..eaaba3f 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,9 +1,6 @@ { "compilerOptions": { - "lib": [ - "es2017", - "dom" - ], + "lib": ["es2017", "dom"], "jsx": "react", "target": "es5", "module": "commonjs", @@ -17,11 +14,8 @@ "strictFunctionTypes": true, "strictNullChecks": true, "skipLibCheck": true, - "isolatedModules": true + "isolatedModules": true, + "downlevelIteration": true }, - "include": [ - "./src/**/*.ts", - "./src/**/*.tsx", - "./jest.config.js" - ] -} \ No newline at end of file + "include": ["./src/**/*.ts", "./src/**/*.tsx", "./jest.config.js"] +}