File size: 2,877 Bytes
debd125
 
e058582
 
debd125
 
 
 
 
e058582
4a70373
 
debd125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e058582
debd125
e058582
debd125
 
e058582
 
 
 
debd125
 
 
 
e058582
 
debd125
 
e058582
 
debd125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e058582
debd125
 
 
 
e058582
debd125
 
 
 
 
 
4a70373
 
e058582
 
debd125
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"use client";

import { useState } from "react";

type Note = {
  id: string;
  title: string;
  content: string;
  color: string;
  pinned: boolean;
  createdAt: Date;
  updatedAt: Date;
};

const COLORS: Record<string, string> = {
  "#fef08a": "bg-yellow-200/10 border-yellow-500/30",
  "#86efac": "bg-emerald-200/10 border-emerald-500/30",
  "#93c5fd": "bg-blue-200/10 border-blue-500/30",
  "#f9a8d4": "bg-pink-200/10 border-pink-500/30",
  "#c4b5fd": "bg-violet-200/10 border-violet-500/30",
};

export default function NoteCard({
  note,
  onEdit,
  onDelete,
  onPin,
}: {
  note: Note;
  onEdit: () => void;
  onDelete: () => void;
  onPin: () => void;
}) {
  const [showActions, setShowActions] = useState(false);
  const cls = COLORS[note.color] ?? "bg-zinc-800/50 border-zinc-700";
  const ago = timeAgo(note.updatedAt);

  return (
    <div
      className={`border rounded-xl p-4 ${cls} transition hover:scale-[1.02] group`}
      onClick={() => setShowActions((v) => !v)}
    >
      <div className="flex items-start justify-between mb-2">
        <h3 className="font-semibold text-sm leading-tight flex-1 mr-2">
          {note.pinned ? "πŸ“Œ " : ""}{note.title}
        </h3>
        <div className={`flex gap-1 transition ${showActions ? "opacity-100" : "opacity-0 group-hover:opacity-100"}`}>
          <Btn onClick={(e) => { e.stopPropagation(); onPin(); }} title={note.pinned ? "Unpin" : "Pin"}>
            {note.pinned ? "β—‡" : "β—†"}
          </Btn>
          <Btn onClick={(e) => { e.stopPropagation(); onEdit(); }} title="Edit">✎</Btn>
          <Btn onClick={(e) => { e.stopPropagation(); onDelete(); }} title="Delete">βœ•</Btn>
        </div>
      </div>
      {note.content && (
        <p className="text-xs text-zinc-400 leading-relaxed line-clamp-4 mb-3">{note.content}</p>
      )}
      <div className="flex items-center justify-between">
        <span
          className="w-3 h-3 rounded-full inline-block"
          style={{ backgroundColor: note.color }}
        />
        <span className="text-[10px] text-zinc-500">{ago}</span>
      </div>
    </div>
  );
}

function Btn({ onClick, title, children }: { onClick: (e: React.MouseEvent) => void; title: string; children: React.ReactNode }) {
  return (
    <button
      onClick={onClick}
      title={title}
      className="w-7 h-7 flex items-center justify-center rounded-lg text-sm text-zinc-400 hover:text-white hover:bg-zinc-700 active:bg-zinc-600 transition"
    >
      {children}
    </button>
  );
}

function timeAgo(d: Date | string): string {
  const t = new Date(d).getTime();
  if (isNaN(t)) return "";
  const diff = Date.now() - t;
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  return `${Math.floor(hrs / 24)}d ago`;
}