180 lines
6.5 KiB
TypeScript
180 lines
6.5 KiB
TypeScript
"use client";
|
||
|
||
import React, { useState } from "react";
|
||
import { JournalPost } from "./types";
|
||
import { X, Heart, Share2, CornerDownRight, Check, BookOpen, Volume2 } from "lucide-react";
|
||
|
||
interface PostDetailModalProps {
|
||
post: JournalPost | null;
|
||
onClose: () => void;
|
||
onTagClick: (tag: string) => void;
|
||
}
|
||
|
||
export const PostDetailModal: React.FC<PostDetailModalProps> = ({
|
||
post,
|
||
onClose,
|
||
onTagClick,
|
||
}) => {
|
||
const [likes, setLikes] = useState(post?.likes || 0);
|
||
const [hasLiked, setHasLiked] = useState(false);
|
||
const [copied, setCopied] = useState(false);
|
||
|
||
if (!post) return null;
|
||
|
||
const handleLike = () => {
|
||
if (!hasLiked) {
|
||
setLikes((prev) => prev + 1);
|
||
setHasLiked(true);
|
||
} else {
|
||
setLikes((prev) => prev - 1);
|
||
setHasLiked(false);
|
||
}
|
||
};
|
||
|
||
const handleShare = () => {
|
||
navigator.clipboard.writeText(window.location.href);
|
||
setCopied(true);
|
||
setTimeout(() => setCopied(false), 2000);
|
||
};
|
||
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-xs animate-in fade-in duration-200">
|
||
<div
|
||
className="relative w-full max-w-2xl notebook-sheet rounded-2xl p-6 sm:p-9 shadow-2xl border border-[#18181B]/15 max-h-[90vh] overflow-y-auto"
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
{/* Top binder clip */}
|
||
<div className="binder-clip absolute top-[-8px] left-10 w-12 h-5 rounded-xs" />
|
||
|
||
{/* Close Button */}
|
||
<button
|
||
onClick={onClose}
|
||
title="Kapat"
|
||
aria-label="Kapat"
|
||
className="absolute top-5 right-5 p-1.5 rounded-lg text-[#787D89] hover:text-[#18181B] hover:bg-[#18181B]/5 transition-colors cursor-pointer"
|
||
>
|
||
<X className="w-5 h-5" />
|
||
</button>
|
||
|
||
{/* Metadata Header */}
|
||
<div className="flex items-center gap-2 text-xs font-mono text-[#787D89] mb-3">
|
||
<span className="font-bold text-[#18181B]">{post.date} • {post.timestamp}</span>
|
||
<span>•</span>
|
||
<span className="px-2 py-0.5 rounded-full bg-[#18181B]/5 text-[#52525B]">
|
||
{post.moodLabel}
|
||
</span>
|
||
{post.stampedText && (
|
||
<span className="rubber-stamp text-[10px] text-[#E11D48] border-[#E11D48] ml-auto">
|
||
{post.stampedText}
|
||
</span>
|
||
)}
|
||
</div>
|
||
|
||
{/* Post Title */}
|
||
{post.title && (
|
||
<h1 className="font-heading font-black text-2xl sm:text-3xl text-[#18181B] leading-tight mb-4">
|
||
{post.title}
|
||
</h1>
|
||
)}
|
||
|
||
{/* Polaroid Image if any */}
|
||
{post.imageUrl && (
|
||
<div className="my-4 p-3 bg-white border border-[#18181B]/10 rounded shadow-sm">
|
||
<img
|
||
src={post.imageUrl}
|
||
alt={post.imageCaption || "Polaroid"}
|
||
className="w-full max-h-80 object-cover rounded-xs"
|
||
/>
|
||
{post.imageCaption && (
|
||
<div className="font-handwritten text-[#18181B] text-xl font-bold mt-2 px-1">
|
||
{post.imageCaption}
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{/* Code Snippet if any */}
|
||
{post.codeSnippet && (
|
||
<div className="my-4">
|
||
<div className="px-3 py-1.5 bg-[#1E232D] text-white/70 text-xs font-mono rounded-t-lg border border-b-0 border-white/10 flex items-center justify-between">
|
||
<span>{post.title || "snippet.rs"}</span>
|
||
<span className="uppercase text-[10px]">{post.codeLanguage || "code"}</span>
|
||
</div>
|
||
<pre className="p-4 rounded-b-lg bg-[#141820] text-emerald-400 font-mono text-xs overflow-x-auto leading-relaxed border border-white/10">
|
||
<code>{post.codeSnippet}</code>
|
||
</pre>
|
||
</div>
|
||
)}
|
||
|
||
{/* Body Content */}
|
||
<div className="font-serif text-[#18181B] text-base sm:text-lg leading-relaxed whitespace-pre-line my-4 space-y-4">
|
||
{post.content}
|
||
</div>
|
||
|
||
{/* Margin Notes */}
|
||
{post.marginNotes && post.marginNotes.length > 0 && (
|
||
<div className="my-5 p-4 rounded-xl bg-[#FAF7F2] border border-[#18181B]/10 space-y-1.5">
|
||
<div className="text-[11px] font-mono uppercase text-[#787D89] font-bold">
|
||
Yazarın El Yazısı Notları:
|
||
</div>
|
||
{post.marginNotes.map((note, idx) => (
|
||
<div key={idx} className="font-handwritten text-[#E11D48] text-xl leading-tight flex items-center gap-2">
|
||
<CornerDownRight className="w-4 h-4 shrink-0" />
|
||
<span>{note}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
|
||
{/* Tags */}
|
||
<div className="flex items-center gap-2 flex-wrap pt-4 border-t border-[#18181B]/10 mt-6">
|
||
{post.tags.map((tag) => (
|
||
<button
|
||
key={tag}
|
||
onClick={() => {
|
||
onTagClick(tag);
|
||
onClose();
|
||
}}
|
||
className="text-xs font-mono px-2.5 py-1 rounded bg-[#F3ECE2] text-[#52525B] hover:bg-[#EFE7D6] hover:text-[#18181B] transition-colors"
|
||
>
|
||
#{tag}
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
{/* Actions */}
|
||
<div className="flex items-center justify-between pt-4 mt-2">
|
||
<div className="flex items-center gap-2">
|
||
<button
|
||
onClick={handleLike}
|
||
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-xs font-mono transition-all ${
|
||
hasLiked
|
||
? "bg-[#FFE4E6] border-[#E11D48] text-[#E11D48] font-bold"
|
||
: "bg-white border-[#18181B]/15 text-[#52525B] hover:text-[#18181B]"
|
||
}`}
|
||
>
|
||
<Heart className={`w-4 h-4 ${hasLiked ? "fill-current" : ""}`} />
|
||
<span>{likes} Beğeni</span>
|
||
</button>
|
||
|
||
<button
|
||
onClick={handleShare}
|
||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white border border-[#18181B]/15 text-xs font-mono text-[#52525B] hover:text-[#18181B] transition-all"
|
||
>
|
||
{copied ? <Check className="w-4 h-4 text-[#059669]" /> : <Share2 className="w-4 h-4" />}
|
||
<span>{copied ? "Kopyalandı!" : "Paylaş"}</span>
|
||
</button>
|
||
</div>
|
||
|
||
<button
|
||
onClick={onClose}
|
||
className="px-4 py-1.5 rounded-lg bg-[#18181B] text-[#FAF7F2] text-xs font-heading font-semibold hover:bg-black transition-colors"
|
||
>
|
||
Kapat
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|