first commit
This commit is contained in:
@@ -0,0 +1,350 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { JournalPost, MoodType, PostType } from "./types";
|
||||
import { MOODS } from "./mockData";
|
||||
import { X, Feather, Save, StickyNote, BookOpen, Code, Camera, Volume2 } from "lucide-react";
|
||||
|
||||
interface EditPostModalProps {
|
||||
post: JournalPost | null;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onUpdatePost: (updatedPost: JournalPost) => void;
|
||||
}
|
||||
|
||||
export const EditPostModal: React.FC<EditPostModalProps> = ({
|
||||
post,
|
||||
isOpen,
|
||||
onClose,
|
||||
onUpdatePost,
|
||||
}) => {
|
||||
const [type, setType] = useState<PostType>("sticky");
|
||||
const [mood, setMood] = useState<MoodType>("spark");
|
||||
const [title, setTitle] = useState("");
|
||||
const [content, setContent] = useState("");
|
||||
const [marginNote, setMarginNote] = useState("");
|
||||
const [tagInput, setTagInput] = useState("");
|
||||
const [codeSnippet, setCodeSnippet] = useState("");
|
||||
const [stampedText, setStampedText] = useState("");
|
||||
const [imageUrl, setImageUrl] = useState("");
|
||||
const [imageCaption, setImageCaption] = useState("");
|
||||
const [likes, setLikes] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (post) {
|
||||
setType(post.type);
|
||||
setMood(post.mood);
|
||||
setTitle(post.title || "");
|
||||
setContent(post.content);
|
||||
setMarginNote(post.marginNotes ? post.marginNotes.join(", ") : "");
|
||||
setTagInput(post.tags ? post.tags.join(", ") : "");
|
||||
setCodeSnippet(post.codeSnippet || "");
|
||||
setStampedText(post.stampedText || "");
|
||||
setImageUrl(post.imageUrl || "");
|
||||
setImageCaption(post.imageCaption || "");
|
||||
setLikes(post.likes || 0);
|
||||
}
|
||||
}, [post]);
|
||||
|
||||
if (!isOpen || !post) return null;
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!content.trim()) return;
|
||||
|
||||
const moodObj = MOODS.find((m) => m.id === mood) || MOODS[0];
|
||||
const tags = tagInput
|
||||
.split(",")
|
||||
.map((t) => t.trim().replace(/^#/, ""))
|
||||
.filter((t) => t.length > 0);
|
||||
|
||||
const updated: JournalPost = {
|
||||
...post,
|
||||
type,
|
||||
mood,
|
||||
moodLabel: moodObj.label,
|
||||
title: title.trim() ? title : undefined,
|
||||
content,
|
||||
marginNotes: marginNote.trim()
|
||||
? marginNote.split(",").map((n) => n.trim())
|
||||
: undefined,
|
||||
tags: tags.length > 0 ? tags : ["genel"],
|
||||
stampedText: stampedText.trim() ? stampedText.trim() : undefined,
|
||||
codeSnippet: type === "code" && codeSnippet.trim() ? codeSnippet : undefined,
|
||||
codeLanguage: type === "code" ? "typescript" : undefined,
|
||||
imageUrl: type === "polaroid" && imageUrl.trim() ? imageUrl : undefined,
|
||||
imageCaption: type === "polaroid" && imageCaption.trim() ? imageCaption : undefined,
|
||||
likes,
|
||||
};
|
||||
|
||||
onUpdatePost(updated);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-xs animate-in fade-in duration-200">
|
||||
<div
|
||||
className="relative w-full max-w-xl notebook-sheet rounded-2xl p-6 sm:p-8 shadow-2xl border border-[#18181B]/15 max-h-[90vh] overflow-y-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Washi Tape */}
|
||||
<div className="washi-tape washi-tape-amber top-[-10px] left-1/2 -translate-x-1/2 w-40" />
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between pb-4 border-b border-[#18181B]/10 mb-5">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="w-8 h-8 rounded-full bg-[#D97706] text-white flex items-center justify-center font-bold text-sm">
|
||||
✏️
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="font-heading font-extrabold text-lg text-[#18181B]">
|
||||
Notu Düzenle (Admin)
|
||||
</h2>
|
||||
<p className="text-xs font-mono text-[#787D89]">
|
||||
ID: {post.id} • {post.date}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="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>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{/* Format Selector */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1.5">
|
||||
Not Formatı:
|
||||
</label>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType("sticky")}
|
||||
className={`flex items-center justify-center gap-1 p-2 rounded-lg text-xs font-heading font-semibold border transition-all ${
|
||||
type === "sticky"
|
||||
? "bg-[#FEF3C7] border-[#D97706] text-[#B45309] shadow-xs"
|
||||
: "bg-[#FAF7F2] border-[#18181B]/10 text-[#52525B]"
|
||||
}`}
|
||||
>
|
||||
<StickyNote className="w-3.5 h-3.5" />
|
||||
<span>Post-it</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType("notebook")}
|
||||
className={`flex items-center justify-center gap-1 p-2 rounded-lg text-xs font-heading font-semibold border transition-all ${
|
||||
type === "notebook"
|
||||
? "bg-[#FAF7F2] border-[#18181B] text-[#18181B] shadow-xs font-bold"
|
||||
: "bg-[#FAF7F2] border-[#18181B]/10 text-[#52525B]"
|
||||
}`}
|
||||
>
|
||||
<BookOpen className="w-3.5 h-3.5" />
|
||||
<span>Defter</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType("code")}
|
||||
className={`flex items-center justify-center gap-1 p-2 rounded-lg text-xs font-heading font-semibold border transition-all ${
|
||||
type === "code"
|
||||
? "bg-[#1E232D] border-[#1E232D] text-white shadow-xs"
|
||||
: "bg-[#FAF7F2] border-[#18181B]/10 text-[#52525B]"
|
||||
}`}
|
||||
>
|
||||
<Code className="w-3.5 h-3.5" />
|
||||
<span>Kod</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType("polaroid")}
|
||||
className={`flex items-center justify-center gap-1 p-2 rounded-lg text-xs font-heading font-semibold border transition-all ${
|
||||
type === "polaroid"
|
||||
? "bg-[#E0F2FE] border-[#0284C7] text-[#0369A1] shadow-xs"
|
||||
: "bg-[#FAF7F2] border-[#18181B]/10 text-[#52525B]"
|
||||
}`}
|
||||
>
|
||||
<Camera className="w-3.5 h-3.5" />
|
||||
<span>Polaroid</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mood Selector */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1.5">
|
||||
Ruh Hali (Mood):
|
||||
</label>
|
||||
<div className="flex items-center gap-2 overflow-x-auto pb-1 scrollbar-none">
|
||||
{MOODS.filter((m) => m.id !== "all").map((m) => (
|
||||
<button
|
||||
key={m.id}
|
||||
type="button"
|
||||
onClick={() => setMood(m.id)}
|
||||
className={`px-3 py-1.5 rounded-lg text-xs font-heading font-semibold shrink-0 border transition-all ${
|
||||
mood === m.id
|
||||
? "bg-[#18181B] text-[#FAF7F2] border-[#18181B]"
|
||||
: "bg-[#FAF7F2] text-[#52525B] border-[#18181B]/10 hover:bg-[#EFE7D6]"
|
||||
}`}
|
||||
>
|
||||
{m.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Başlık:
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
placeholder="Başlık..."
|
||||
className="w-full px-3 py-2 text-sm bg-white/80 border border-[#18181B]/15 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#E11D48]/30 font-serif"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
İçerik:
|
||||
</label>
|
||||
<textarea
|
||||
required
|
||||
rows={4}
|
||||
value={content}
|
||||
onChange={(e) => setContent(e.target.value)}
|
||||
className="w-full px-3.5 py-2.5 text-sm bg-white/80 border border-[#18181B]/15 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#E11D48]/30 font-serif leading-relaxed"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Stamped Text */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Damga Metni (Örn: ONAYLANDI, SUÇLU, COMPILED):
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={stampedText}
|
||||
onChange={(e) => setStampedText(e.target.value)}
|
||||
placeholder="ONAYLANDI"
|
||||
className="w-full px-3 py-1.5 text-xs font-mono bg-white/80 border border-[#18181B]/15 rounded-lg uppercase"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Code Snippet */}
|
||||
{type === "code" && (
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Kod Parçası:
|
||||
</label>
|
||||
<textarea
|
||||
rows={3}
|
||||
value={codeSnippet}
|
||||
onChange={(e) => setCodeSnippet(e.target.value)}
|
||||
className="w-full px-3.5 py-2 text-xs font-mono bg-[#1E232D] text-emerald-400 border border-white/10 rounded-lg focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Polaroid Image URL */}
|
||||
{type === "polaroid" && (
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Resim URL:
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={imageUrl}
|
||||
onChange={(e) => setImageUrl(e.target.value)}
|
||||
placeholder="https://images.unsplash.com/..."
|
||||
className="w-full px-3 py-1.5 text-xs bg-white/80 border border-[#18181B]/15 rounded-lg font-mono"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Resim Yazısı (Caption):
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={imageCaption}
|
||||
onChange={(e) => setImageCaption(e.target.value)}
|
||||
placeholder="Zirve esintisi..."
|
||||
className="w-full px-3 py-1.5 text-xs bg-white/80 border border-[#18181B]/15 rounded-lg font-handwritten text-lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Margin Notes Input */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Kenar Notları (Virgülle ayırın):
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={marginNote}
|
||||
onChange={(e) => setMarginNote(e.target.value)}
|
||||
placeholder="← tam olarak bu!, not al"
|
||||
className="w-full px-3 py-1.5 text-sm bg-white/80 border border-[#18181B]/15 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#E11D48]/30 font-handwritten text-lg text-[#E11D48]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Etiketler (Virgülle ayırın):
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={tagInput}
|
||||
onChange={(e) => setTagInput(e.target.value)}
|
||||
placeholder="felsefe, gece, kahve"
|
||||
className="w-full px-3 py-1.5 text-xs bg-white/80 border border-[#18181B]/15 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#E11D48]/30 font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Likes */}
|
||||
<div>
|
||||
<label className="block text-[11px] font-mono uppercase text-[#787D89] font-bold mb-1">
|
||||
Beğeni Sayısı:
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
value={likes}
|
||||
onChange={(e) => setLikes(parseInt(e.target.value, 10) || 0)}
|
||||
className="w-32 px-3 py-1.5 text-xs bg-white/80 border border-[#18181B]/15 rounded-lg font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center justify-end gap-2.5 pt-3 border-t border-[#18181B]/10">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 rounded-lg text-xs font-heading font-semibold text-[#52525B] hover:bg-[#18181B]/5 transition-colors"
|
||||
>
|
||||
Vazgeç
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex items-center gap-1.5 px-5 py-2 rounded-lg bg-[#059669] text-white text-xs font-heading font-bold hover:bg-[#047857] shadow-sm transition-all cursor-pointer"
|
||||
>
|
||||
<Save className="w-3.5 h-3.5" />
|
||||
<span>Günü Güncelle</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user