@@ -23,7 +23,7 @@ import {
23
23
DropdownMenuItem ,
24
24
DropdownMenuTrigger ,
25
25
} from "../ui/dropdown-menu" ;
26
- import { useEffect , useRef , useState } from "react" ;
26
+ import { useEffect , useMemo , useRef , useState } from "react" ;
27
27
import { Variant , useAnimate , motion } from "framer-motion" ;
28
28
import { useMemory } from "@/contexts/MemoryContext" ;
29
29
import { SpaceIcon } from "@/assets/Memories" ;
@@ -42,11 +42,12 @@ import useTouchHold from "@/hooks/useTouchHold";
42
42
import { DialogTrigger } from "@radix-ui/react-dialog" ;
43
43
import { AddMemoryPage , NoteAddPage , SpaceAddPage } from "./AddMemoryDialog" ;
44
44
import { ExpandedSpace } from "./ExpandedSpace" ;
45
- import { StoredSpace } from "@/server/db/schema" ;
45
+ import { StoredContent , StoredSpace } from "@/server/db/schema" ;
46
+ import Image from "next/image"
46
47
47
48
export function MemoriesBar ( ) {
48
49
const [ parent , enableAnimations ] = useAutoAnimate ( ) ;
49
- const { spaces, deleteSpace } = useMemory ( ) ;
50
+ const { spaces, deleteSpace, freeMemories } = useMemory ( ) ;
50
51
51
52
const [ isDropdownOpen , setIsDropdownOpen ] = useState ( false ) ;
52
53
const [ addMemoryState , setAddMemoryState ] = useState <
@@ -124,12 +125,15 @@ export function MemoriesBar() {
124
125
>
125
126
{ spaces . map ( ( space ) => (
126
127
< SpaceItem
127
- onDelete = { ( ) => deleteSpace ( space . id ) }
128
+ onDelete = { ( ) => { } }
128
129
key = { space . id }
129
- onClick = { ( ) => setExpandedSpace ( space . id ) }
130
+ // onClick={() => setExpandedSpace(space.id)}
130
131
{ ...space }
131
132
/>
132
133
) ) }
134
+ { freeMemories . map ( m => (
135
+ < MemoryItem { ...m } key = { m . id } />
136
+ ) ) }
133
137
</ div >
134
138
</ div >
135
139
) ;
@@ -145,12 +149,40 @@ const SpaceExitVariant: Variant = {
145
149
} ,
146
150
} ;
147
151
152
+ export function MemoryItem ( {
153
+ id,
154
+ title,
155
+ image
156
+ } : StoredContent ) {
157
+ return (
158
+ < div
159
+
160
+ className = "hover:bg-rgray-2 has-[[data-state='true']]:bg-rgray-2 has-[[data-space-text]:focus-visible]:bg-rgray-2 has-[[data-space-text]:focus-visible]:ring-rgray-7 [&:has-[[data-space-text]:focus-visible]>[data-more-button]]:opacity-100 relative flex select-none flex-col-reverse items-center justify-center rounded-md p-2 pb-4 text-center font-normal ring-transparent transition has-[[data-space-text]:focus-visible]:outline-none has-[[data-space-text]:focus-visible]:ring-2 md:has-[[data-state='true']]:bg-transparent [&:hover>[data-more-button]]:opacity-100"
161
+ >
162
+ < button data-space-text className = "focus-visible:outline-none" >
163
+ { title }
164
+ </ button >
165
+
166
+ < div className = "w-24 h-24 flex justify-center items-center" >
167
+ < img
168
+ className = "h-16 w-16"
169
+ id = { id . toString ( ) }
170
+ src = { image ! }
171
+ />
172
+ </ div >
173
+ </ div >
174
+ )
175
+ }
176
+
148
177
export function SpaceItem ( {
149
178
name,
150
179
id,
151
180
onDelete,
152
181
onClick,
153
182
} : StoredSpace & { onDelete : ( ) => void ; onClick ?: ( ) => void } ) {
183
+
184
+ const { cachedMemories } = useMemory ( ) ;
185
+
154
186
const [ itemRef , animateItem ] = useAnimate ( ) ;
155
187
const { width } = useViewport ( ) ;
156
188
@@ -162,6 +194,10 @@ export function SpaceItem({
162
194
} ,
163
195
} ) ;
164
196
197
+ const spaceMemories = useMemo ( ( ) => {
198
+ return cachedMemories . filter ( m => m . space === id )
199
+ } , [ cachedMemories ] )
200
+
165
201
return (
166
202
< motion . div
167
203
ref = { itemRef }
@@ -176,104 +212,106 @@ export function SpaceItem({
176
212
isOpen = { moreDropdownOpen }
177
213
setIsOpen = { setMoreDropdownOpen }
178
214
onDelete = { ( ) => {
215
+ onDelete ( )
216
+ return ;
179
217
if ( ! itemRef . current || width < 768 ) {
180
218
onDelete ( ) ;
181
219
return ;
182
220
}
183
- const trash = document . querySelector ( "#trash" ) ! as HTMLDivElement ;
184
- const trashBin = document . querySelector ( "#trash-button" ) ! ;
185
- const trashRect = trashBin . getBoundingClientRect ( ) ;
186
- const scopeRect = itemRef . current . getBoundingClientRect ( ) ;
187
- const el = document . createElement ( "div" ) ;
188
- el . style . position = "fixed" ;
189
- el . style . top = "0" ;
190
- el . style . left = "0" ;
191
- el . style . width = "15px" ;
192
- el . style . height = "15px" ;
193
- el . style . backgroundColor = "var(--gray-7)" ;
194
- el . style . zIndex = "60" ;
195
- el . style . borderRadius = "50%" ;
196
- el . style . transform = "scale(5)" ;
197
- el . style . opacity = "0" ;
198
- trash . dataset [ "open" ] = "true" ;
199
- const initial = {
200
- x : scopeRect . left + scopeRect . width / 2 ,
201
- y : scopeRect . top + scopeRect . height / 2 ,
202
- } ;
203
- const delta = {
204
- x :
205
- trashRect . left +
206
- trashRect . width / 2 -
207
- scopeRect . left +
208
- scopeRect . width / 2 ,
209
- y :
210
- trashRect . top +
211
- trashRect . height / 4 -
212
- scopeRect . top +
213
- scopeRect . height / 2 ,
214
- } ;
215
- const end = {
216
- x : trashRect . left + trashRect . width / 2 ,
217
- y : trashRect . top + trashRect . height / 4 ,
218
- } ;
219
- el . style . offsetPath = `path('M ${ initial . x } ${ initial . y } Q ${ delta . x * 0.01 } ${ delta . y * 0.01 } ${ end . x } ${ end . y } ` ;
220
- animateItem ( itemRef . current , SpaceExitVariant , {
221
- duration : 0.2 ,
222
- } ) . then ( ( ) => {
223
- itemRef . current . style . scale = "0" ;
224
- onDelete ( ) ;
225
- } ) ;
226
- document . body . appendChild ( el ) ;
227
- el . animate (
228
- {
229
- transform : [ "scale(5)" , "scale(1)" ] ,
230
- opacity : [ 0 , 0.3 , 1 ] ,
231
- } ,
232
- {
233
- duration : 200 ,
234
- easing : "cubic-bezier(0.64, 0.57, 0.67, 1.53)" ,
235
- fill : "forwards" ,
236
- } ,
237
- ) ;
238
- el . animate (
239
- {
240
- offsetDistance : [ "0%" , "100%" ] ,
241
- } ,
242
- {
243
- duration : 2000 ,
244
- easing : "cubic-bezier(0.64, 0.57, 0.67, 1.53)" ,
245
- fill : "forwards" ,
246
- delay : 200 ,
247
- } ,
248
- ) . onfinish = ( ) => {
249
- el . animate (
250
- { transform : "scale(0)" , opacity : 0 } ,
251
- { duration : 200 , fill : "forwards" } ,
252
- ) . onfinish = ( ) => {
253
- el . remove ( ) ;
254
- } ;
255
- } ;
221
+ // const trash = document.querySelector("#trash")! as HTMLDivElement;
222
+ // const trashBin = document.querySelector("#trash-button")!;
223
+ // const trashRect = trashBin.getBoundingClientRect();
224
+ // const scopeRect = itemRef.current.getBoundingClientRect();
225
+ // const el = document.createElement("div");
226
+ // el.style.position = "fixed";
227
+ // el.style.top = "0";
228
+ // el.style.left = "0";
229
+ // el.style.width = "15px";
230
+ // el.style.height = "15px";
231
+ // el.style.backgroundColor = "var(--gray-7)";
232
+ // el.style.zIndex = "60";
233
+ // el.style.borderRadius = "50%";
234
+ // el.style.transform = "scale(5)";
235
+ // el.style.opacity = "0";
236
+ // trash.dataset["open"] = "true";
237
+ // const initial = {
238
+ // x: scopeRect.left + scopeRect.width / 2,
239
+ // y: scopeRect.top + scopeRect.height / 2,
240
+ // };
241
+ // const delta = {
242
+ // x:
243
+ // trashRect.left +
244
+ // trashRect.width / 2 -
245
+ // scopeRect.left +
246
+ // scopeRect.width / 2,
247
+ // y:
248
+ // trashRect.top +
249
+ // trashRect.height / 4 -
250
+ // scopeRect.top +
251
+ // scopeRect.height / 2,
252
+ // };
253
+ // const end = {
254
+ // x: trashRect.left + trashRect.width / 2,
255
+ // y: trashRect.top + trashRect.height / 4,
256
+ // };
257
+ // el.style.offsetPath = `path('M ${initial.x} ${initial.y} Q ${delta.x * 0.01} ${delta.y * 0.01} ${end.x} ${end.y}`;
258
+ // animateItem(itemRef.current, SpaceExitVariant, {
259
+ // duration: 0.2,
260
+ // }).then(() => {
261
+ // itemRef.current.style.scale = "0";
262
+ // onDelete();
263
+ // });
264
+ // document.body.appendChild(el);
265
+ // el.animate(
266
+ // {
267
+ // transform: ["scale(5)", "scale(1)"],
268
+ // opacity: [0, 0.3, 1],
269
+ // },
270
+ // {
271
+ // duration: 200,
272
+ // easing: "cubic-bezier(0.64, 0.57, 0.67, 1.53)",
273
+ // fill: "forwards",
274
+ // },
275
+ // );
276
+ // el.animate(
277
+ // {
278
+ // offsetDistance: ["0%", "100%"],
279
+ // },
280
+ // {
281
+ // duration: 2000,
282
+ // easing: "cubic-bezier(0.64, 0.57, 0.67, 1.53)",
283
+ // fill: "forwards",
284
+ // delay: 200,
285
+ // },
286
+ // ).onfinish = () => {
287
+ // el.animate(
288
+ // { transform: "scale(0)", opacity: 0 },
289
+ // { duration: 200, fill: "forwards" },
290
+ // ).onfinish = () => {
291
+ // el.remove();
292
+ // };
293
+ // };
256
294
} }
257
295
/>
258
- { /* {content .length > 2 ? (
296
+ { spaceMemories . length > 2 ? (
259
297
< MemoryWithImages3
260
298
className = "h-24 w-24"
261
299
id = { id . toString ( ) }
262
- images={content .map((c) => c.image).reverse() as string[]}
300
+ images = { spaceMemories . map ( ( c ) => c . image ) . reverse ( ) as string [ ] }
263
301
/>
264
- ) : content .length === 1 ? (
302
+ ) : spaceMemories . length === 1 ? (
265
303
< MemoryWithImage
266
304
className = "h-24 w-24"
267
305
id = { id . toString ( ) }
268
- image={content [0].image!}
306
+ image = { spaceMemories [ 0 ] . image ! }
269
307
/>
270
308
) : (
271
309
< MemoryWithImages2
272
310
className = "h-24 w-24"
273
311
id = { id . toString ( ) }
274
- images={content .map((c) => c.image).reverse() as string[]}
312
+ images = { spaceMemories . map ( ( c ) => c . image ) . reverse ( ) as string [ ] }
275
313
/>
276
- )} */ }
314
+ ) }
277
315
</ motion . div >
278
316
) ;
279
317
}
@@ -288,7 +326,7 @@ export function SpaceMoreButton({
288
326
setIsOpen ?: ( open : boolean ) => void ;
289
327
} ) {
290
328
return (
291
- < >
329
+ < Dialog >
292
330
< DropdownMenu open = { isOpen } onOpenChange = { setIsOpen } >
293
331
< DropdownMenuTrigger asChild >
294
332
< button
@@ -310,16 +348,36 @@ export function SpaceMoreButton({
310
348
< Edit3 className = "mr-2 h-4 w-4" strokeWidth = { 1.5 } />
311
349
Edit
312
350
</ DropdownMenuItem >
313
- < DropdownMenuItem
314
- onClick = { onDelete }
315
- className = "focus:bg-red-100 focus:text-red-400 dark:focus:bg-red-100/10"
316
- >
317
- < Trash2 className = "mr-2 h-4 w-4" strokeWidth = { 1.5 } />
318
- Move to Trash
319
- </ DropdownMenuItem >
351
+ < DialogTrigger asChild >
352
+ < DropdownMenuItem
353
+ onClick = { onDelete }
354
+ className = "focus:bg-red-100 focus:text-red-400 dark:focus:bg-red-100/10"
355
+ >
356
+ < Trash2 className = "mr-2 h-4 w-4" strokeWidth = { 1.5 } />
357
+ Move to Trash
358
+ </ DropdownMenuItem >
359
+ </ DialogTrigger >
320
360
</ DropdownMenuContent >
321
361
</ DropdownMenu >
322
- </ >
362
+ < DialogContent >
363
+ < DialogTitle className = 'text-xl' > Are you sure?</ DialogTitle >
364
+ < DialogDescription className = 'text-md' > You will not be able to recover this space</ DialogDescription >
365
+ < DialogFooter >
366
+ < DialogClose
367
+ type = { undefined }
368
+ onClick = { onDelete }
369
+ className = "bg-red-500/40 focus-visible:bg-red-500/60 focus-visible:ring-red-500 hover:bg-red-500/60 ml-auto flex items-center justify-center rounded-md px-3 py-2 transition focus-visible:outline-none focus-visible:ring-2"
370
+ >
371
+ Delete
372
+ </ DialogClose >
373
+ < DialogClose
374
+ className = "focus-visible:bg-rgray-4 focus-visible:ring-rgray-7 hover:bg-rgray-4 ml-auto flex items-center justify-center rounded-md px-3 py-2 transition focus-visible:outline-none focus-visible:ring-2"
375
+ >
376
+ Cancel
377
+ </ DialogClose >
378
+ </ DialogFooter >
379
+ </ DialogContent >
380
+ </ Dialog >
323
381
) ;
324
382
}
325
383
0 commit comments