december improvements #2
@@ -1,6 +1,6 @@
|
|||||||
import type { FaceRegion, Media, MediaMetadata } from "@/domain/types";
|
import type { FaceRegion, Media, MediaMetadata } from "@/domain/types";
|
||||||
import { useGetMediaDetails } from "@/features/media/use-media";
|
import { useGetMediaDetails } from "@/features/media/use-media";
|
||||||
import { useListMediaTags } from "@/features/tags/use-tags";
|
import { useListMediaTags, useAddMediaTags, useRemoveMediaTag } from "@/features/tags/use-tags";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
@@ -13,6 +13,10 @@ import { PersonFaceBadge } from "@/components/people/person-face-badge";
|
|||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { format, parseISO } from "date-fns";
|
import { format, parseISO } from "date-fns";
|
||||||
import { Separator } from "../ui/separator";
|
import { Separator } from "../ui/separator";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Plus, X } from "lucide-react";
|
||||||
|
|
||||||
type MediaDetailsSidebarProps = {
|
type MediaDetailsSidebarProps = {
|
||||||
media: Media;
|
media: Media;
|
||||||
@@ -42,6 +46,23 @@ export function MediaDetailsSidebar({
|
|||||||
media.id
|
media.id
|
||||||
);
|
);
|
||||||
const { data: tags, isLoading: isLoadingTags } = useListMediaTags(media.id);
|
const { data: tags, isLoading: isLoadingTags } = useListMediaTags(media.id);
|
||||||
|
const addTags = useAddMediaTags(media.id);
|
||||||
|
const removeTag = useRemoveMediaTag(media.id);
|
||||||
|
const [newTag, setNewTag] = useState("");
|
||||||
|
|
||||||
|
const handleAddTag = () => {
|
||||||
|
if (!newTag.trim()) return;
|
||||||
|
addTags.mutate(
|
||||||
|
{ tags: [newTag.trim()] },
|
||||||
|
{
|
||||||
|
onSuccess: () => setNewTag(""),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveTag = (tagName: string) => {
|
||||||
|
removeTag.mutate(tagName);
|
||||||
|
};
|
||||||
|
|
||||||
const displayDate = media.date_taken
|
const displayDate = media.date_taken
|
||||||
? format(parseISO(media.date_taken), "MMMM d, yyyy 'at' h:mm a")
|
? format(parseISO(media.date_taken), "MMMM d, yyyy 'at' h:mm a")
|
||||||
@@ -102,14 +123,35 @@ export function MediaDetailsSidebar({
|
|||||||
|
|
||||||
<AccordionItem value="tags">
|
<AccordionItem value="tags">
|
||||||
<AccordionTrigger>Tags</AccordionTrigger>
|
<AccordionTrigger>Tags</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent className="space-y-4">
|
||||||
{/* TODO: Add input to add tags */}
|
<div className="flex gap-2">
|
||||||
|
<Input
|
||||||
|
placeholder="Add tag..."
|
||||||
|
value={newTag}
|
||||||
|
onChange={(e) => setNewTag(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") handleAddTag();
|
||||||
|
}}
|
||||||
|
className="h-8"
|
||||||
|
/>
|
||||||
|
<Button size="sm" variant="outline" onClick={handleAddTag} disabled={!newTag.trim() || addTags.isPending} className="h-8 w-8 p-0">
|
||||||
|
<Plus size={16} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{isLoadingTags && <Skeleton className="h-8 w-full" />}
|
{isLoadingTags && <Skeleton className="h-8 w-full" />}
|
||||||
{tags && tags.length > 0 && (
|
{tags && tags.length > 0 && (
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{tags.map((tag) => (
|
{tags.map((tag) => (
|
||||||
<Badge key={tag.id} variant="secondary">
|
<Badge key={tag.id} variant="secondary" className="pr-1 gap-1">
|
||||||
{tag.name}
|
{tag.name}
|
||||||
|
<button
|
||||||
|
onClick={() => handleRemoveTag(tag.name)}
|
||||||
|
className="hover:bg-muted rounded-full p-0.5 transition-colors"
|
||||||
|
disabled={removeTag.isPending}
|
||||||
|
>
|
||||||
|
<X size={12} />
|
||||||
|
</button>
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user