mirror of
https://github.com/usatiuk/photos.git
synced 2025-10-28 23:37:48 +01:00
selectable photos
This commit is contained in:
@@ -31,15 +31,33 @@ export interface IOverviewComponentProps {
|
|||||||
fetchPhotos: () => void;
|
fetchPhotos: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PhotoCardM = React.memo(PhotoCard);
|
||||||
|
|
||||||
export const OverviewComponent: React.FunctionComponent<
|
export const OverviewComponent: React.FunctionComponent<
|
||||||
IOverviewComponentProps
|
IOverviewComponentProps
|
||||||
> = (props) => {
|
> = (props) => {
|
||||||
const [selectedPhoto, setSelectedPhoto] = React.useState<number>(0);
|
const [selectedPhoto, setSelectedPhoto] = React.useState<number>(0);
|
||||||
const [isOverlayOpened, setOverlayOpen] = React.useState<boolean>(false);
|
const [isOverlayOpened, setOverlayOpen] = React.useState<boolean>(false);
|
||||||
|
const [selectedPhotos, setSelectedPhotos] = React.useState<Set<number>>(
|
||||||
const onCardClick = (id: number) => {
|
new Set(),
|
||||||
setSelectedPhoto(id);
|
);
|
||||||
setOverlayOpen(true);
|
const selectedPhotosRef = React.useRef<Set<number>>(selectedPhotos);
|
||||||
|
selectedPhotosRef.current = selectedPhotos;
|
||||||
|
const onCardClick = (e: React.MouseEvent<HTMLElement>, id: number) => {
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
const newSelectedPhotos = new Set<number>([
|
||||||
|
...selectedPhotosRef.current,
|
||||||
|
]);
|
||||||
|
if (newSelectedPhotos.has(id)) {
|
||||||
|
newSelectedPhotos.delete(id);
|
||||||
|
} else {
|
||||||
|
newSelectedPhotos.add(id);
|
||||||
|
}
|
||||||
|
setSelectedPhotos(newSelectedPhotos);
|
||||||
|
} else {
|
||||||
|
setSelectedPhoto(id);
|
||||||
|
setOverlayOpen(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -73,6 +91,10 @@ export const OverviewComponent: React.FunctionComponent<
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onClick = React.useCallback((e: React.MouseEvent<HTMLElement>) => {
|
||||||
|
onCardClick(e, Number(e.currentTarget.id));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const photos = Object.keys(dates).reduce(
|
const photos = Object.keys(dates).reduce(
|
||||||
(acc: JSX.Element[], year): JSX.Element[] => {
|
(acc: JSX.Element[], year): JSX.Element[] => {
|
||||||
const els = Object.keys(dates[year]).reduce(
|
const els = Object.keys(dates[year]).reduce(
|
||||||
@@ -85,10 +107,12 @@ export const OverviewComponent: React.FunctionComponent<
|
|||||||
);
|
);
|
||||||
const photosEls = photos.map((photo) => {
|
const photosEls = photos.map((photo) => {
|
||||||
return (
|
return (
|
||||||
<PhotoCard
|
<PhotoCardM
|
||||||
key={photo.id}
|
selected={selectedPhotos.has(photo.id)}
|
||||||
|
key={"p" + photo.id}
|
||||||
|
id={String(photo.id)}
|
||||||
photo={photo}
|
photo={photo}
|
||||||
onClick={() => onCardClick(photo.id)}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
img {
|
img {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
.selected {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.notLoaded {
|
.notLoaded {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -10,4 +14,5 @@
|
|||||||
.loaded {
|
.loaded {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -20,10 +20,12 @@ import { LargeSize, PreviewSize } from "./helper";
|
|||||||
|
|
||||||
export interface IPhotoCardComponentProps extends RouteComponentProps {
|
export interface IPhotoCardComponentProps extends RouteComponentProps {
|
||||||
photo: IPhotoReqJSON;
|
photo: IPhotoReqJSON;
|
||||||
|
selected: boolean;
|
||||||
|
id: string;
|
||||||
|
|
||||||
deletePhoto: (photo: IPhotoReqJSON) => void;
|
deletePhoto: (photo: IPhotoReqJSON) => void;
|
||||||
cancelDelete: (photo: IPhotoReqJSON) => void;
|
cancelDelete: (photo: IPhotoReqJSON) => void;
|
||||||
onClick: () => void;
|
onClick: (e: React.MouseEvent<HTMLElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPhotoCardComponentState {
|
export interface IPhotoCardComponentState {
|
||||||
@@ -73,12 +75,18 @@ export class PhotoCardComponent extends React.PureComponent<
|
|||||||
<Card
|
<Card
|
||||||
className="photoCard"
|
className="photoCard"
|
||||||
interactive={true}
|
interactive={true}
|
||||||
onClick={() => this.props.onClick()}
|
id={this.props.id}
|
||||||
|
onClick={(e: React.MouseEvent<HTMLElement>) =>
|
||||||
|
this.props.onClick(e)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{fileExists ? (
|
{fileExists ? (
|
||||||
<img
|
<img
|
||||||
src={getPhotoThumbPath(this.props.photo, PreviewSize)}
|
src={getPhotoThumbPath(this.props.photo, PreviewSize)}
|
||||||
className={this.state.loaded ? "loaded" : "notLoaded"}
|
className={
|
||||||
|
(this.state.loaded ? "loaded " : "notLoaded ") +
|
||||||
|
(this.props.selected ? "selected " : " ")
|
||||||
|
}
|
||||||
onLoad={() => this.setLoaded(true)}
|
onLoad={() => this.setLoaded(true)}
|
||||||
/*
|
/*
|
||||||
onMouseEnter={() =>
|
onMouseEnter={() =>
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": [
|
"lib": ["es2017", "dom"],
|
||||||
"es2017",
|
|
||||||
"dom"
|
|
||||||
],
|
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
@@ -17,11 +14,8 @@
|
|||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true,
|
||||||
|
"downlevelIteration": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./jest.config.js"]
|
||||||
"./src/**/*.ts",
|
}
|
||||||
"./src/**/*.tsx",
|
|
||||||
"./jest.config.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user