Skip to content

Commit

Permalink
added reordering images
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedegeofroy committed Nov 23, 2024
1 parent 1aac00b commit 3597b9e
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 30 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"preview": "vite preview"
},
"dependencies": {
"@hello-pangea/dnd": "^17.0.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-scroll-area": "^1.2.0",
Expand Down
114 changes: 84 additions & 30 deletions src/modules/place.module.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useCallback, useEffect, useState } from "react";
import { DragDropContext, Droppable, Draggable, DropResult } from "@hello-pangea/dnd";

import { Place, Tag } from "@/interfaces/place.interface";
import { Plus, X } from "lucide-react";
Expand All @@ -9,7 +10,13 @@ import { TagComponent } from "@/components/tag";
import { Button } from "@/components/ui/button";
import { useDashboardStore } from "@/shared/stores/places.store";

export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave: (place: Place) => void; }) => {
export const PlaceModule = ({
inputPlace,
onSave,
}: {
inputPlace: Place;
onSave: (place: Place) => void;
}) => {
const [place, setPlace] = useState<Place>(inputPlace);

useEffect(() => {
Expand Down Expand Up @@ -54,15 +61,15 @@ export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave:
};

const toggleTag = (tag: Tag) => {
const isTagSelected = place.tags.some(t => t.id === tag.id);
const isTagSelected = place.tags.some((t) => t.id === tag.id);
const updatedTags = isTagSelected
? place.tags.filter(t => t.id !== tag.id)
? place.tags.filter((t) => t.id !== tag.id)
: [...place.tags, tag];
handleTagChange(updatedTags);
};

const handleTagChange = (updatedTags: Tag[]) => {
setPlace(prev => ({
setPlace((prev) => ({
...prev,
tags: updatedTags,
}));
Expand All @@ -72,33 +79,76 @@ export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave:
onSave(place);
}, [place, onSave]);

const handleDragEnd = (result: DropResult) => {
if (!result.destination) return;

const reorderedImages = Array.from(place.images);
const [movedImage] = reorderedImages.splice(result.source.index, 1);
reorderedImages.splice(result.destination.index, 0, movedImage);

setPlace((prev) => ({ ...prev, images: reorderedImages }));

console.log(place);
};

return place !== null ? (
<form className="flex gap-5 flex-col h-full">
<div className="w-full h-[600px]">
<div className="whitespace-nowrap h-fit space-x-5 text-gray-300">
{place.images.map((img, index) => (
<div
key={`${index}_picture`}
className="inline-block group aspect-[21/30] bg-gray-100 relative rounded-xl overflow-hidden h-[300px]"
>
<img className="h-full w-full object-cover" src={img} alt="Place" />
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable
droppableId="images"
direction="horizontal"
type="image"
>
{(provided) => (
<div
className="cursor-pointer h-6 w-6 p-1 group-hover:flex hidden justify-center items-center absolute bottom-2 right-2 bg-gray-100 rounded-full"
onClick={() => handleRemovePhoto(index)}
{...provided.droppableProps}
ref={provided.innerRef}
className="whitespace-nowrap h-fit space-x-5 text-gray-300 flex"
>
<X />
{place.images.map((img, index) => (
<Draggable
key={`${index}_picture`}
draggableId={`${index}_picture`}
index={index}
>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className="inline-block group aspect-[21/30] bg-gray-100 relative rounded-xl overflow-hidden h-[300px]"
>
<img
className="h-full w-full object-cover"
src={img}
alt="Place"
/>
<div
className="cursor-pointer h-6 w-6 p-1 group-hover:flex hidden justify-center items-center absolute bottom-2 right-2 bg-gray-100 rounded-full"
onClick={() =>
handleRemovePhoto(index)
}
>
<X />
</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
<div
className="inline-block bg-gray-100 rounded-xl overflow-hidden h-[300px] cursor-pointer"
onClick={handleAddPhoto}
>
<div className="flex items-center justify-center h-full w-full aspect-[21/30]">
<Plus />
</div>
</div>
</div>
</div>
))}
<div
className="inline-block bg-gray-100 rounded-xl overflow-hidden h-[300px] cursor-pointer"
onClick={handleAddPhoto}
>
<div className="flex items-center justify-center h-full w-full aspect-[21/30]">
<Plus />
</div>
</div>
</div>
)}
</Droppable>
</DragDropContext>
</div>
<div className="h-full pl-1 w-full space-y-4">
<div className="flex gap-5">
Expand Down Expand Up @@ -174,7 +224,7 @@ export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave:
<TagComponent
key={`${tag.id}_${index}_tag`}
onClick={() => {
toggleTag(tag)
toggleTag(tag);
}}
tag={tag}
/>
Expand All @@ -183,14 +233,16 @@ export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave:
<div className="flex flex-wrap gap-5 pl-5">
{tags
.filter(
x =>
!place.tags.flatMap(y => y.id).includes(x.id)
(x) =>
!place.tags
.flatMap((y) => y.id)
.includes(x.id)
)
.map((tag, index) => (
<TagComponent
key={`${tag.id}_${index}_tag`}
onClick={() => {
toggleTag(tag)
toggleTag(tag);
}}
tag={tag}
/>
Expand All @@ -200,7 +252,9 @@ export const PlaceModule = ({ inputPlace, onSave }: { inputPlace: Place, onSave:
</div>
</div>
<div className="flex justify-end">
<Button type="button" onClick={handleSave}>Save</Button>
<Button type="button" onClick={handleSave}>
Save
</Button>
</div>
</form>
) : (
Expand Down
75 changes: 75 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==

"@babel/runtime@^7.25.6":
version "7.26.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
dependencies:
regenerator-runtime "^0.14.0"

"@esbuild/[email protected]":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
Expand Down Expand Up @@ -207,6 +214,19 @@
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==

"@hello-pangea/dnd@^17.0.0":
version "17.0.0"
resolved "https://registry.yarnpkg.com/@hello-pangea/dnd/-/dnd-17.0.0.tgz#2dede20fd6d8a9b53144547e6894fc482da3d431"
integrity sha512-LDDPOix/5N0j5QZxubiW9T0M0+1PR0rTDWeZF5pu1Tz91UQnuVK4qQ/EjY83Qm2QeX0eM8qDXANfDh3VVqtR4Q==
dependencies:
"@babel/runtime" "^7.25.6"
css-box-model "^1.2.1"
memoize-one "^6.0.0"
raf-schd "^4.0.3"
react-redux "^9.1.2"
redux "^5.0.1"
use-memo-one "^1.1.3"

"@humanwhocodes/module-importer@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
Expand Down Expand Up @@ -765,6 +785,11 @@
"@types/prop-types" "*"
csstype "^3.0.2"

"@types/use-sync-external-store@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==

"@typescript-eslint/[email protected]":
version "8.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz#d0070f206daad26253bf00ca5b80f9b54f9e2dd0"
Expand Down Expand Up @@ -1086,6 +1111,13 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"

css-box-model@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==
dependencies:
tiny-invariant "^1.0.6"

cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
Expand Down Expand Up @@ -1635,6 +1667,11 @@ lucide-react@^0.446.0:
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.446.0.tgz#b92bd0229ad79a11fff84d47f9351797fc0b904e"
integrity sha512-BU7gy8MfBMqvEdDPH79VhOXSEgyG8TSPOKWaExWGCQVqnGH7wGgDngPbofu+KdtVjPQBWbEmnfMTq90CTiiDRg==

memoize-one@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==

merge2@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
Expand Down Expand Up @@ -1882,6 +1919,11 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==

raf-schd@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==

react-dom@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
Expand All @@ -1904,6 +1946,14 @@ react-leaflet@*, react-leaflet@^4.2.1:
dependencies:
"@react-leaflet/core" "^2.1.0"

react-redux@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.2.tgz#deba38c64c3403e9abd0c3fbeab69ffd9d8a7e4b"
integrity sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==
dependencies:
"@types/use-sync-external-store" "^0.0.3"
use-sync-external-store "^1.0.0"

react-remove-scroll-bar@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c"
Expand Down Expand Up @@ -1968,6 +2018,16 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"

redux@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b"
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==

regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==

resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
Expand Down Expand Up @@ -2188,6 +2248,11 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"

tiny-invariant@^1.0.6:
version "1.3.3"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==

to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
Expand Down Expand Up @@ -2258,6 +2323,11 @@ use-callback-ref@^1.3.0:
dependencies:
tslib "^2.0.0"

use-memo-one@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==

use-sidecar@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2"
Expand All @@ -2266,6 +2336,11 @@ use-sidecar@^1.1.2:
detect-node-es "^1.1.0"
tslib "^2.0.0"

use-sync-external-store@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9"
integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==

util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
Expand Down

0 comments on commit 3597b9e

Please sign in to comment.