Skip to content

Commit

Permalink
MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
Jontes-Tech authored and lucemans committed Dec 15, 2024
1 parent 7f4b95e commit a99e0f4
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 19 deletions.
3 changes: 3 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.4",
"embla-carousel": "^8.5.1",
"embla-carousel-auto-height": "^8.5.1",
"embla-carousel-react": "^8.5.1",
"eslint-plugin-unused-imports": "^4.0.1",
"globals": "^15.8.0",
"javascript-time-ago": "^2.5.11",
Expand Down
43 changes: 43 additions & 0 deletions web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 81 additions & 0 deletions web/src/components/media/MediaCarousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import '../../embla.css';

import AutoHeight from 'embla-carousel-auto-height';
import useEmblaCarousel from 'embla-carousel-react';
import { Dispatch, FC, SetStateAction, useEffect } from 'react';
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa6';

import { MediaMetaData } from './MediaMetaData';
import { BareMediaPreview } from './MediaPreview';

export const MediaCarousel: FC<{
ids: number[];
mediaId: number;
setMediaId: Dispatch<SetStateAction<number | undefined>>;
}> = ({ ids, mediaId, setMediaId }) => {
const [emblaReference, emblaApi] = useEmblaCarousel(
{
loop: true,
},
[AutoHeight()]
);

// update mediaId based on embla state
emblaApi?.on('select', () => {
const selected = emblaApi.selectedScrollSnap();

if (selected !== undefined) {
setMediaId(ids[selected]);
}
});

useEffect(() => {
if (mediaId !== undefined) {
const index = ids.indexOf(mediaId);

// TODO: If this useEffect wasn't triggered by emblaApi.on('select'), then we should set the scrollTo(index, true) boolean to true to not animate the scroll
emblaApi?.scrollTo(index);
}
});

return (
<div className="flex flex-col md:flex-row">
<div ref={emblaReference} className="embla overflow-hidden">
<div className="embla__container">
{ids.map((id) => (
<div
key={id}
className="embla__slide rounded-lg select-none"
draggable={false}
>
<BareMediaPreview media_id={id} />
</div>
))}
</div>
</div>
<div className="p-4 min-w-64">
<code>
<MediaMetaData mediaId={mediaId} />
</code>
<div>
<button
className="bg-gray-200 rounded-lg p-2 disabled:opacity-50 text-black px-2 gap-x-2"
onClick={() => {
emblaApi?.scrollPrev();
}}
>
<FaArrowLeft />
</button>
<button
className="bg-gray-200 rounded-lg p-2 disabled:opacity-50 text-black px-2 gap-x-2"
onClick={() => {
emblaApi?.scrollNext();
}}
>
<FaArrowRight />
</button>
</div>
</div>
</div>
);
};
40 changes: 22 additions & 18 deletions web/src/components/media/MediaGallery.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
'use client';

import * as Dialog from '@radix-ui/react-dialog';
import { FC } from 'react';
import { FaArrowLeft, FaArrowRight } from 'react-icons/fa6';
import { FC, useState } from 'react';

import { BareMediaPreview, MediaPreview } from './MediaPreview';
import { useMedia } from '@/api/media';

import { MediaCarousel } from './MediaCarousel';
import { MediaPreview } from './MediaPreview';

export const MediaGallery: FC<{
media_ids: number[];
}> = ({ media_ids }) => {
const [mediaId, setMediaId] = useState<number | undefined>();

return (
<div className="card flex items-stretch">
<Dialog.Root modal={true}>
{media_ids.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 grid-flow-row w-full gap-2">
{media_ids.map((media_id) => (
<Dialog.Trigger key={media_id}>
<Dialog.Trigger
key={media_id}
onClick={() => {
setMediaId(media_id);
}}
>
<MediaPreview
media_id={media_id}
key={media_id}
Expand All @@ -30,20 +39,15 @@ export const MediaGallery: FC<{
)}
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 bg-black bg-opacity-50" />
<Dialog.Content className="fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
<Dialog.Content className="w-[80vw] max-w-xl rounded-xl">
<BareMediaPreview media_id={media_ids[1]} />
<div className="w-full bg-white p-4">
<div>
<button className="p-2 bg-neutral-800 text-white">
<FaArrowLeft />
</button>
<button className="p-2 bg-neutral-800 text-white">
<FaArrowRight />
</button>
</div>
</div>
</Dialog.Content>
<Dialog.Content className="fixed inset-0 bg-white rounded-lg shadow-lg max-w-6xl mx-auto my-8 h-min">
<Dialog.DialogTitle className="text-center font-medium text-xl overflow-hidden p-2">
{useMedia(mediaId).data?.description}
</Dialog.DialogTitle>
<MediaCarousel
ids={media_ids}
mediaId={mediaId!}
setMediaId={setMediaId}
/>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
Expand Down
17 changes: 17 additions & 0 deletions web/src/components/media/MediaMetaData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FC } from 'react';

import { useMedia } from '@/api/media';

export const MediaMetaData: FC<{
mediaId: number;
}> = ({ mediaId }) => {
const media = useMedia(mediaId).data;

return (
<>
<p>Type: {media?.kind}</p>
<p>Created: {media?.created_at}</p>
<p>Updated: {media?.updated_at}</p>
</>
);
};
2 changes: 1 addition & 1 deletion web/src/components/media/MediaPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const BareMediaPreview: FC<{
})();

return (
<div className="relative bg-neutral-100 w-full aspect-video">
<div className="relative bg-neutral-100 w-full aspect-video rounded-md">
{match(media?.kind)
.with(
'webp',
Expand Down
21 changes: 21 additions & 0 deletions web/src/embla.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.embla {
max-width: 48rem;
margin: auto;
--slide-height: 19rem;
--slide-spacing: 1rem;
--slide-size: 100%;
}
.embla__viewport {
overflow: hidden;
}
.embla__container {
display: flex;
touch-action: pan-y pinch-zoom;
margin-left: calc(var(--slide-spacing) * -1);
}
.embla__slide {
transform: translate3d(0, 0, 0);
flex: 0 0 var(--slide-size);
min-width: 0;
padding-left: var(--slide-spacing);
}

0 comments on commit a99e0f4

Please sign in to comment.