|
|
@@ -1,21 +1,20 @@
|
|
|
+import { useState } from 'react'
|
|
|
+import { type MediaFile, type Post } from '@/types/posts.types'
|
|
|
+import { ChevronLeft, ChevronRight } from 'lucide-react'
|
|
|
+import { cn } from '@/lib/utils'
|
|
|
+import { useChangeStatePost } from '@/hooks/posts/useChangeStatePost'
|
|
|
+import { usePost } from '@/hooks/posts/usePost'
|
|
|
+import { Button } from '@/components/ui/button'
|
|
|
import {
|
|
|
Dialog,
|
|
|
DialogContent,
|
|
|
DialogHeader,
|
|
|
DialogTitle,
|
|
|
} from '@/components/ui/dialog'
|
|
|
-
|
|
|
-import { Button } from '@/components/ui/button'
|
|
|
-import { Switch } from '@/components/ui/switch'
|
|
|
import { Label } from '@/components/ui/label'
|
|
|
-
|
|
|
-import { usePosts } from './posts-provider'
|
|
|
-import { usePost } from '@/hooks/posts/usePost'
|
|
|
-import { useChangeStatePost } from '@/hooks/posts/useChangeStatePost'
|
|
|
-
|
|
|
+import { Switch } from '@/components/ui/switch'
|
|
|
import VideoPlayer from '@/components/video-player'
|
|
|
-import { useState } from 'react'
|
|
|
-import { type Post } from '@/types/posts.types'
|
|
|
+import { usePosts } from './posts-provider'
|
|
|
|
|
|
export function PostsActionDialog() {
|
|
|
const { open, setOpen, currentRow } = usePosts()
|
|
|
@@ -87,7 +86,7 @@ function PostContent({
|
|
|
return (
|
|
|
<div>
|
|
|
<div className='pb-2'>
|
|
|
- <VideoPlayer src={post?.video?.url as string} />
|
|
|
+ <PostMedia post={post} />
|
|
|
</div>
|
|
|
|
|
|
<div className='py-2 text-sm'>متن پست : {post?.caption}</div>
|
|
|
@@ -120,3 +119,100 @@ function PostContent({
|
|
|
</div>
|
|
|
)
|
|
|
}
|
|
|
+
|
|
|
+function PostMedia({ post }: { post: Post }) {
|
|
|
+ const images = (post.images ?? []).filter((image) => Boolean(image?.url))
|
|
|
+
|
|
|
+ if (post.video?.url && post.type !== 'gallery') {
|
|
|
+ return <VideoPlayer src={post.video.url} />
|
|
|
+ }
|
|
|
+
|
|
|
+ if (images.length > 0) {
|
|
|
+ return <PostGallery images={images} />
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className='rounded-2xl bg-muted py-10 text-center text-sm text-muted-foreground'>
|
|
|
+ رسانهای برای نمایش وجود ندارد
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function PostGallery({ images }: { images: MediaFile[] }) {
|
|
|
+ const [index, setIndex] = useState(0)
|
|
|
+ const current = images[index] ?? images[0]
|
|
|
+ const hasMany = images.length > 1
|
|
|
+
|
|
|
+ const go = (delta: number) => {
|
|
|
+ setIndex(
|
|
|
+ (currentIndex) => (currentIndex + delta + images.length) % images.length
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!current) return null
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className='space-y-3'>
|
|
|
+ <div className='relative overflow-hidden rounded-2xl bg-muted'>
|
|
|
+ <img
|
|
|
+ src={current.url}
|
|
|
+ alt={current.name}
|
|
|
+ className='mx-auto max-h-[60vh] w-full object-contain'
|
|
|
+ />
|
|
|
+
|
|
|
+ {hasMany && (
|
|
|
+ <>
|
|
|
+ <Button
|
|
|
+ type='button'
|
|
|
+ variant='secondary'
|
|
|
+ size='icon'
|
|
|
+ className='absolute inset-s-3 top-1/2 -translate-y-1/2'
|
|
|
+ onClick={() => go(-1)}
|
|
|
+ aria-label='تصویر قبلی'
|
|
|
+ >
|
|
|
+ <ChevronRight />
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ type='button'
|
|
|
+ variant='secondary'
|
|
|
+ size='icon'
|
|
|
+ className='absolute inset-e-3 top-1/2 -translate-y-1/2'
|
|
|
+ onClick={() => go(1)}
|
|
|
+ aria-label='تصویر بعدی'
|
|
|
+ >
|
|
|
+ <ChevronLeft />
|
|
|
+ </Button>
|
|
|
+ <span className='absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full bg-black/60 px-2.5 py-0.5 text-xs text-white'>
|
|
|
+ {index + 1} / {images.length}
|
|
|
+ </span>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {hasMany && (
|
|
|
+ <div className='flex gap-2 overflow-x-auto pb-1'>
|
|
|
+ {images.map((image, imageIndex) => (
|
|
|
+ <button
|
|
|
+ key={image.hash || image.url}
|
|
|
+ type='button'
|
|
|
+ onClick={() => setIndex(imageIndex)}
|
|
|
+ className={cn(
|
|
|
+ 'size-16 shrink-0 overflow-hidden rounded-md border-2',
|
|
|
+ imageIndex === index
|
|
|
+ ? 'border-primary'
|
|
|
+ : 'border-transparent opacity-70'
|
|
|
+ )}
|
|
|
+ aria-label={image.name}
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ src={image.url}
|
|
|
+ alt={image.name}
|
|
|
+ className='size-full object-cover'
|
|
|
+ />
|
|
|
+ </button>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|