review detail sheet on diary/profile/community, wrapup period presets
This commit is contained in:
@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next"
|
||||
import { BookOpen, ChevronLeft, ChevronRight, Pencil } from "lucide-react"
|
||||
import { format, startOfMonth, subMonths } from "date-fns"
|
||||
import { ReviewSheet } from "@/components/review-sheet"
|
||||
import { ReviewDetailSheet } from "@/components/review-detail-sheet"
|
||||
import { EditableContextMenu } from "@/components/editable-context-menu"
|
||||
import { MovieCard } from "@/components/movie-card"
|
||||
import { EmptyState } from "@/components/empty-state"
|
||||
@@ -39,6 +40,7 @@ function DiaryPage() {
|
||||
useInfiniteDiary({ sort_by: "desc", user_id: auth?.user_id })
|
||||
const deleteReview = useDeleteReview()
|
||||
const [editingEntry, setEditingEntry] = useState<DiaryEntryDto | null>(null)
|
||||
const [detailEntry, setDetailEntry] = useState<DiaryEntryDto | null>(null)
|
||||
|
||||
const monthLabel = format(month, "MMMM yyyy")
|
||||
const monthStr = format(month, "yyyy-MM")
|
||||
@@ -121,6 +123,7 @@ function DiaryPage() {
|
||||
rating={item.entry.review.rating}
|
||||
comment={item.entry.review.comment}
|
||||
variant="full"
|
||||
onShowDetail={item.entry.review.comment ? () => setDetailEntry(item.entry) : undefined}
|
||||
action={
|
||||
<div className="flex items-center gap-1">
|
||||
{item.entry.review.watch_medium && (
|
||||
@@ -154,6 +157,15 @@ function DiaryPage() {
|
||||
review={editingEntry.review}
|
||||
/>
|
||||
)}
|
||||
|
||||
{detailEntry && (
|
||||
<ReviewDetailSheet
|
||||
open={!!detailEntry}
|
||||
onOpenChange={(open) => !open && setDetailEntry(null)}
|
||||
movie={detailEntry.movie}
|
||||
review={detailEntry.review}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { createFileRoute, Link } from "@tanstack/react-router"
|
||||
import { useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Bookmark, BookmarkCheck, Star, User } from "lucide-react"
|
||||
import { BackButton } from "@/components/back-button"
|
||||
import { CommunityReviews } from "@/components/community-reviews"
|
||||
import { ReviewDetailSheet } from "@/components/review-detail-sheet"
|
||||
import { ViewingHistory } from "@/components/viewing-history"
|
||||
import { RatingHistogram } from "@/components/rating-histogram"
|
||||
import { HorizontalStrip } from "@/components/horizontal-strip"
|
||||
@@ -17,7 +19,7 @@ import {
|
||||
useAddToWatchlist,
|
||||
useRemoveFromWatchlist,
|
||||
} from "@/features/watchlist"
|
||||
import type { CastMemberDto, CrewMemberDto } from "@/features/movies"
|
||||
import type { CastMemberDto, CrewMemberDto, SocialReviewDto } from "@/features/movies"
|
||||
|
||||
export const Route = createFileRoute("/_app/movies/$id")({
|
||||
component: MovieDetailPage,
|
||||
@@ -30,6 +32,7 @@ function MovieDetailPage() {
|
||||
const { data: profile } = useMovieProfile(id)
|
||||
const { data: history } = useMovieHistory(id)
|
||||
useDocumentTitle(data?.movie.title)
|
||||
const [detailReview, setDetailReview] = useState<SocialReviewDto | null>(null)
|
||||
|
||||
if (isPending) return <DetailSkeleton />
|
||||
if (!data) return null
|
||||
@@ -102,9 +105,19 @@ function MovieDetailPage() {
|
||||
</section>
|
||||
)}
|
||||
|
||||
<CommunityReviews reviews={reviews} />
|
||||
<CommunityReviews reviews={reviews} onShowDetail={setDetailReview} />
|
||||
|
||||
{history && <ViewingHistory history={history} />}
|
||||
|
||||
{detailReview && (
|
||||
<ReviewDetailSheet
|
||||
open={!!detailReview}
|
||||
onOpenChange={(open) => !open && setDetailReview(null)}
|
||||
movie={movie}
|
||||
review={{ id: "", rating: detailReview.rating, comment: detailReview.comment, watched_at: detailReview.watched_at, watch_medium: detailReview.watch_medium }}
|
||||
userName={detailReview.user_display}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createFileRoute, Link } from "@tanstack/react-router"
|
||||
import { useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { ArrowLeft, ChevronRight, Sparkles, Trash2 } from "lucide-react"
|
||||
import { format, subMonths, startOfYear, endOfYear } from "date-fns"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
@@ -125,6 +126,7 @@ function WrapupPage() {
|
||||
<DrawerTitle>{t("wrapup.generateWrapUp")}</DrawerTitle>
|
||||
</DrawerHeader>
|
||||
<div className="space-y-3 p-4 pb-8">
|
||||
<PeriodPresets onSelect={(s, e) => { setStartDate(s); setEndDate(e) }} />
|
||||
<div className="space-y-1.5">
|
||||
<Label>{t("wrapup.startDate")}</Label>
|
||||
<Input
|
||||
@@ -173,3 +175,33 @@ function WrapupPage() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PeriodPresets({ onSelect }: { onSelect: (start: string, end: string) => void }) {
|
||||
const { t } = useTranslation()
|
||||
const now = new Date()
|
||||
const fmt = (d: Date) => format(d, "yyyy-MM-dd")
|
||||
|
||||
const currentYear = now.getFullYear()
|
||||
const presets = [
|
||||
{ label: String(currentYear), start: fmt(startOfYear(now)), end: fmt(endOfYear(now)) },
|
||||
{ label: String(currentYear - 1), start: fmt(startOfYear(new Date(currentYear - 1, 0))), end: fmt(endOfYear(new Date(currentYear - 1, 0))) },
|
||||
{ label: t("wrapup.last12Months", { defaultValue: "Last 12 months" }), start: fmt(subMonths(now, 12)), end: fmt(now) },
|
||||
{ label: t("wrapup.last6Months", { defaultValue: "Last 6 months" }), start: fmt(subMonths(now, 6)), end: fmt(now) },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{presets.map((p) => (
|
||||
<Button
|
||||
key={p.label}
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onSelect(p.start, p.end)}
|
||||
>
|
||||
{p.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user