feat: add WatchMedium field, general review editing, configurable deploy
Some checks failed
CI / Check / Test (push) Failing after 27m0s
Some checks failed
CI / Check / Test (push) Failing after 27m0s
- WatchMedium enum (cinema/streaming/tv/physical_media/download/media_server/other) - PATCH /api/v1/reviews/:id partial update (rating, comment, watched_at, watch_medium) - edit_review use case w/ ownership + remote review guard, best-effort AP Update broadcast - SPA: icon picker, edit sheet (long-press mobile / pencil desktop), watch medium badge - shared ReviewFormFields, EditableContextMenu, parse_watched_at/format_watched_at - deploy.sh parameterized (--features, --tag), CORS allows PATCH - CONTEXT.md glossary, ADR-0001 general review editing
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import { Link } from "@tanstack/react-router"
|
||||
import { Globe } from "lucide-react"
|
||||
import { Globe, Pencil } from "lucide-react"
|
||||
import { timeAgo } from "@/lib/date"
|
||||
import { StarDisplay } from "@/components/star-display"
|
||||
import { WatchMediumBadge } from "@/components/watch-medium-badge"
|
||||
import { EditableContextMenu } from "@/components/editable-context-menu"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { posterUrl } from "@/lib/api/client"
|
||||
import type { MovieDto, ReviewDto } from "@/lib/api/common"
|
||||
@@ -13,10 +16,11 @@ type ReviewCardProps = {
|
||||
userId?: string
|
||||
isFederated?: boolean
|
||||
actorUrl?: string
|
||||
onEdit?: () => void
|
||||
}
|
||||
|
||||
export function ReviewCard({ movie, review, userName, userId, isFederated, actorUrl }: ReviewCardProps) {
|
||||
return (
|
||||
export function ReviewCard({ movie, review, userName, userId, isFederated, actorUrl, onEdit }: ReviewCardProps) {
|
||||
const card = (
|
||||
<Card size="sm">
|
||||
<CardContent className="flex gap-3">
|
||||
<Link to="/movies/$id" params={{ id: movie.id }} className="h-[84px] w-14 flex-shrink-0 overflow-hidden rounded-lg bg-muted">
|
||||
@@ -41,13 +45,27 @@ export function ReviewCard({ movie, review, userName, userId, isFederated, actor
|
||||
<span>{timeAgo(review.watched_at)}</span>
|
||||
</div>
|
||||
)}
|
||||
<Link to="/movies/$id" params={{ id: movie.id }} className="font-semibold hover:underline">
|
||||
{movie.title}
|
||||
</Link>
|
||||
<StarDisplay rating={review.rating} />
|
||||
<div className="flex items-center justify-between">
|
||||
<Link to="/movies/$id" params={{ id: movie.id }} className="font-semibold hover:underline">
|
||||
{movie.title}
|
||||
</Link>
|
||||
{onEdit && (
|
||||
<Button variant="ghost" size="icon" className="hidden size-7 md:inline-flex" onClick={onEdit}>
|
||||
<Pencil className="size-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<StarDisplay rating={review.rating} />
|
||||
{review.watch_medium && <WatchMediumBadge medium={review.watch_medium} />}
|
||||
</div>
|
||||
{review.comment && <p className="mt-1 line-clamp-2 text-xs text-muted-foreground">{review.comment}</p>}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
if (!onEdit) return card
|
||||
|
||||
return <EditableContextMenu onEdit={onEdit}>{card}</EditableContextMenu>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user