fix(feed): add reaction/comment/repost actions to milestone posts, fix dark-mode contrast
MilestoneCard never rendered PostCard's action row (PawButton, comment button, PawBackButton) -- reacting/commenting was already fully supported server-side (reactions.ts/comments.ts don't restrict by post type), the UI for it was just missing since MILE-02 shipped. Also widens the prop type from a narrow local MilestoneCardPost to the existing PostCardPost (PostCard.tsx already passes the full post object in, the local type just didn't reflect it) -- this both unlocks reactionCount/commentCount and lets MilestoneCard open the same PostDetailDialog PostCard uses for commenting, instead of needing a parallel implementation. Separately: the card's bg-orange-50/border-orange-200 were hardcoded light-only Tailwind classes with no dark: variant, so in Dark Mode the pet name (text-foreground, which flips to a light color) sat on a background that stayed pale and unreadable -- same failure mode as the Clerk auth pages fixed earlier. Switched to the opacity-based bg-orange-500/5 + border-orange-500/20 pattern already used elsewhere in the app (unterstuetzen page, notifications list), which adapts to either theme automatically instead of needing a manual dark: override.
This commit is contained in:
1 parent
fa3f5faa58
commit
e89ddc4d32
2 files changed
+43
-16
No files matched your search
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import type { MilestoneType } from "@prisma/client";
|
||||
import { useState } from "react";
|
||||
import { MessageCircle } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useActivePet } from "@/context/ActivePetContext";
|
||||
import { MILESTONE_META } from "@/lib/milestone-meta";
|
||||
import { getAvatarUrl } from "@/lib/avatar-url";
|
||||
import { formatPetName } from "@/lib/pet-display-name";
|
||||
@@ -9,20 +11,14 @@ import { getMediaUrl } from "@/lib/media-url";
|
||||
import { BlurImage } from "@/components/ui/blur-image";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { AiDisclosureBadge } from "@/components/content/AiDisclosureBadge";
|
||||
import type { AiDisclosureValue } from "@/components/content/AiDisclosureSelect";
|
||||
|
||||
type MilestoneCardPost = {
|
||||
id: string;
|
||||
caption: string | null;
|
||||
createdAt: Date | string;
|
||||
aiDisclosure?: AiDisclosureValue;
|
||||
pet: { id: string; name: string; avatarKey: string | null };
|
||||
images: { id: string; storageKey: string; position: number; blurhash?: string | null }[];
|
||||
milestone: { milestoneType: MilestoneType; notes: string | null } | null;
|
||||
};
|
||||
import { PawButton } from "@/components/feed/PawButton";
|
||||
import { PawBackButton } from "@/components/feed/PawBackButton";
|
||||
import { PostDetailDialog } from "@/components/feed/PostDetailDialog";
|
||||
import type { PostCardPost } from "@/components/feed/PostCard";
|
||||
|
||||
interface MilestoneCardProps {
|
||||
post: MilestoneCardPost;
|
||||
post: PostCardPost;
|
||||
onDeleted?: (postId: string) => void;
|
||||
}
|
||||
|
||||
function formatDate(date: Date | string): string {
|
||||
@@ -40,8 +36,10 @@ function formatDate(date: Date | string): string {
|
||||
* + pet name + date + optional caption/notes + optional photo.
|
||||
* Background: bg-orange-50 border border-orange-200 per UI-SPEC accent reservation #8.
|
||||
*/
|
||||
export function MilestoneCard({ post }: MilestoneCardProps) {
|
||||
export function MilestoneCard({ post, onDeleted }: MilestoneCardProps) {
|
||||
const t = useTranslations("MilestoneTypes");
|
||||
const { activePetId } = useActivePet();
|
||||
const [showDetailDialog, setShowDetailDialog] = useState(false);
|
||||
const { pet, milestone, images, caption } = post;
|
||||
|
||||
if (!milestone) return null;
|
||||
@@ -51,7 +49,7 @@ export function MilestoneCard({ post }: MilestoneCardProps) {
|
||||
const photo = images[0];
|
||||
|
||||
return (
|
||||
<article className="bg-orange-50 border border-orange-200 rounded-lg overflow-hidden">
|
||||
<article className="bg-orange-500/5 border border-orange-500/20 rounded-lg overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-3 px-4 py-3">
|
||||
<Avatar className="w-8 h-8 shrink-0">
|
||||
@@ -98,6 +96,35 @@ export function MilestoneCard({ post }: MilestoneCardProps) {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Action row — paw reaction + comment count + paw-back, same as PostCard */}
|
||||
{activePetId && (
|
||||
<div className="flex items-center gap-4 px-4 pb-3 pt-1">
|
||||
<PawButton
|
||||
postId={post.id}
|
||||
petId={activePetId}
|
||||
initialCount={post.reactionCount ?? 0}
|
||||
initialReacted={false}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="View comments"
|
||||
onClick={() => setShowDetailDialog(true)}
|
||||
className="flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<MessageCircle className="h-4 w-4" aria-hidden="true" />
|
||||
{(post.commentCount ?? 0) > 0 && <span>{post.commentCount}</span>}
|
||||
</button>
|
||||
<PawBackButton postId={post.id} petId={activePetId} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<PostDetailDialog
|
||||
post={post}
|
||||
open={showDetailDialog}
|
||||
onClose={() => setShowDetailDialog(false)}
|
||||
onDeleted={onDeleted}
|
||||
/>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
@@ -223,7 +223,7 @@ function PostCardImpl({ post, onDeleted, variant = "feed" }: PostCardProps) {
|
||||
|
||||
// Milestone posts use their own distinct card (MILE-02)
|
||||
if (post.type === "MILESTONE") {
|
||||
return <MilestoneCard post={post} />;
|
||||
return <MilestoneCard post={post} onDeleted={onDeleted} />;
|
||||
}
|
||||
|
||||
// Repost posts delegate to RepostCard
|
||||
|
||||
Reference in new issue
Block a user