feat: Add media details sidebar and date handling features, including media grouping by date

This commit is contained in:
2025-11-16 03:32:18 +01:00
parent 94b184d3b0
commit 2003a55ff7
16 changed files with 362 additions and 52 deletions

View File

@@ -3,8 +3,10 @@ import { createFileRoute } from "@tanstack/react-router";
import { Button } from "@/components/ui/button";
import { AuthenticatedImage } from "@/components/media/authenticated-image";
import type { Media } from "@/domain/types";
import { useState } from "react";
import { useMemo, useState } from "react"; // Import useMemo
import { MediaViewer } from "@/components/media/media-viewer";
import { groupMediaByDate } from "@/lib/date-utils"; // Import our new helper
import { parseISO } from "date-fns";
export const Route = createFileRoute("/media/")({
component: MediaPage,
@@ -22,6 +24,26 @@ function MediaPage() {
const [selectedMedia, setSelectedMedia] = useState<Media | null>(null);
const allMedia = useMemo(
() =>
data?.pages
.flatMap((page) => page.data)
.sort((a, b) => {
// Sort by date (newest first)
const dateA = a.date_taken ?? a.created_at;
const dateB = b.date_taken ?? b.created_at;
return parseISO(dateB).getTime() - parseISO(dateA).getTime();
}) ?? [],
[data]
);
const groupedMedia = useMemo(() => groupMediaByDate(allMedia), [allMedia]);
const groupEntries = useMemo(
() => Array.from(groupedMedia.entries()),
[groupedMedia]
);
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
@@ -32,22 +54,28 @@ function MediaPage() {
{error && <p>Error loading photos: {error.message}</p>}
{data && (
<div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-2">
{data.pages.map((page) =>
page.data.map((media) => (
<div
key={media.id}
className="aspect-square bg-gray-200 rounded-md overflow-hidden cursor-pointer hover:opacity-80 transition-opacity"
onClick={() => setSelectedMedia(media)}
>
<AuthenticatedImage
src={media.thumbnail_url ?? media.file_url}
alt={media.original_filename}
className="w-full h-full object-cover"
/>
<div className="space-y-8">
{groupEntries.map(([title, media]) => (
<section key={title}>
<h2 className="text-xl font-semibold mb-4">{title}</h2>
<div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-2">
{media.map((media) => (
<div
key={media.id}
className="aspect-square bg-gray-200 rounded-md overflow-hidden cursor-pointer hover:opacity-80 transition-opacity"
onClick={() => setSelectedMedia(media)}
>
<AuthenticatedImage
src={media.thumbnail_url ?? media.file_url}
alt={media.original_filename}
className="w-full h-full object-cover"
/>
</div>
))}
</div>
))
)}
</section>
))}
</div>
)}