Shortcodes

This commit is contained in:
cdricms
2025-02-10 08:52:32 +01:00
parent a7ad045631
commit 8e87d834bc
20 changed files with 485 additions and 71 deletions

View File

@@ -14,6 +14,18 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import type IShortcode from "@/interfaces/IShortcode";
import Image from "next/image";
import Media from "@/interfaces/Media";
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "./ui/pagination";
import useMedia from "@/hooks/use-media";
import { Loader2 } from "lucide-react";
interface ShortcodeDialogProps {
onSave: (shortcode: IShortcode) => void;
@@ -33,6 +45,8 @@ export default function ShortcodeDialog({
);
const handleSave = () => {
if (!(_shortcode?.code && (_shortcode.media_id || _shortcode.value)))
return;
onSave(_shortcode);
setOpen();
resetForm();
@@ -92,6 +106,7 @@ export default function ShortcodeDialog({
setShortcode((p) => ({
...p,
value: e.target.value,
media_id: undefined,
}))
}
className="col-span-3"
@@ -99,27 +114,29 @@ export default function ShortcodeDialog({
</div>
</TabsContent>
<TabsContent value="media">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="mediaId" className="text-right">
Media ID
</Label>
<Input
id="mediaId"
value={_shortcode.media_id}
onChange={(e) =>
setShortcode((p) => ({
...p,
media_id: e.target.value,
}))
}
className="col-span-3"
/>
</div>
<PhotoGrid
onSelect={(photo) => {
setShortcode((p) => ({
...p,
media_id: photo.id,
value: undefined,
}));
}}
/>
</TabsContent>
</Tabs>
</div>
<DialogFooter>
<Button type="submit" onClick={handleSave}>
<Button
disabled={
!(
_shortcode?.code &&
(_shortcode.media_id || _shortcode.value)
)
}
type="submit"
onClick={handleSave}
>
Enregistrer
</Button>
</DialogFooter>
@@ -127,3 +144,144 @@ export default function ShortcodeDialog({
</Dialog>
);
}
const LazyImage = ({
photo,
onClick,
isSelected,
}: {
photo: Media;
onClick: () => void;
isSelected: boolean;
}) => {
return (
<div
className={`aspect-square ${isSelected ? "ring-4 ring-primary" : ""}`}
>
<Image
src={photo.url || "/placeholder.svg"}
alt={photo.alt}
width={300}
height={300}
className="object-cover w-full h-full cursor-pointer transition-transform hover:scale-105"
onClick={onClick}
/>
</div>
);
};
const PhotoGrid: React.FC<{ onSelect: (photo: Media) => void }> = ({
onSelect,
}) => {
const { data, error, isLoading, success, setPage, setLimit, mutate } =
useMedia(5);
const [selectedPhoto, setSelectedPhoto] = useState<Media | null>(null);
const handlePhotoClick = (photo: Media) => {
setSelectedPhoto(photo);
onSelect(photo);
};
const handleChangeSelection = () => {
setSelectedPhoto(null);
// if (!photos) return;
// const currentIndex = photos.findIndex(
// (photo) => photo.id === selectedPhoto?.id,
// );
// const nextIndex = (currentIndex + 1) % photos.length;
// setSelectedPhoto(photos[nextIndex]);
};
if (isLoading) return <Loader2 className="animate-spin" />;
return (
<div className="container mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Gallerie Photo</h1>
{selectedPhoto ? (
<div className="flex flex-col items-center">
<Image
src={selectedPhoto.url || "/placeholder.svg"}
alt={selectedPhoto.alt}
width={600}
height={600}
className="w-full max-w-2xl h-auto mb-4 rounded-lg"
/>
<div className="flex gap-4 mt-4">
<Button onClick={handleChangeSelection}>
Changer de sélection
</Button>
</div>
</div>
) : (
<>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
{data?.items?.map((photo) => {
return (
<LazyImage
photo={photo}
key={photo.id}
onClick={() => handlePhotoClick(photo)}
isSelected={false}
/>
);
})}
</div>
<Pagination className="mt-8">
<PaginationContent>
<PaginationItem>
<PaginationPrevious
href="#"
onClick={(e) => {
e.preventDefault();
setPage((prev) =>
Math.max(prev - 1, 1),
);
}}
className={
data?.page === 1
? "pointer-events-none opacity-50"
: ""
}
/>
</PaginationItem>
{[...Array(data?.totalPages)].map((_, i) => (
<PaginationItem key={i + 1}>
<PaginationLink
href="#"
onClick={(e) => {
e.preventDefault();
setPage(i + 1);
}}
isActive={data?.page === i + 1}
>
{i + 1}
</PaginationLink>
</PaginationItem>
))}
<PaginationItem>
<PaginationNext
href="#"
onClick={(e) => {
e.preventDefault();
setPage((prev) =>
Math.min(
prev + 1,
data?.totalPages ?? 1,
),
);
}}
className={
data?.page === data?.totalPages
? "pointer-events-none opacity-50"
: ""
}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
</>
)}
</div>
);
};