main
tsx 95 lines 3.6 KB
Raw
1 "use client";
2
3 import { useState } from "react";
4 import Image from "next/image";
5 import Link from "next/link";
6 import { type Post } from "@/lib/data";
7 import { Avatar } from "@/components/ui/avatar";
8 import { IconHeart, IconComment, IconBookmark, IconShare } from "@/components/ui/icons";
9
10 export default function FeedPost({ post }: { post: Post }) {
11 const [liked, setLiked] = useState(false);
12 const [saved, setSaved] = useState(false);
13 const [likeCount, setLikeCount] = useState(post.likes);
14
15 return (
16 <article className="border-b border-white/6">
17 {/* Header */}
18 <div className="flex items-center justify-between px-4 py-3">
19 <div className="flex items-center gap-3">
20 <div className="p-[2px] rounded-full bg-gradient-to-tr from-white/60 to-white/20">
21 <div className="p-[2px] rounded-full bg-nord-black">
22 <Avatar letter={post.avatar} size="sm" />
23 </div>
24 </div>
25 <div>
26 <p className="text-nord-white text-sm font-semibold leading-tight">{post.handle}</p>
27 <p className="text-nord-white/40 text-[10px] uppercase tracking-widest leading-tight mt-0.5">
28 {post.location}
29 </p>
30 </div>
31 </div>
32 <Link
33 href="/studio"
34 className="text-[10px] font-bold uppercase tracking-widest text-nord-white border border-white/20 px-3 py-1.5 hover:bg-white/5 transition-colors"
35 >
36 Book
37 </Link>
38 </div>
39
40 {/* Image */}
41 <div className="relative w-full aspect-square overflow-hidden bg-nord-gray">
42 <Image
43 src={post.image}
44 alt={post.style}
45 fill
46 className="object-cover"
47 sizes="(max-width: 768px) 100vw, 680px"
48 />
49 <div className="absolute bottom-3 left-3">
50 <span className="bg-nord-black/60 backdrop-blur-sm text-nord-white/80 text-[9px] uppercase tracking-widest px-2 py-1 border border-white/10">
51 {post.style}
52 </span>
53 </div>
54 </div>
55
56 {/* Actions */}
57 <div className="px-4 pt-3 pb-1 flex items-center justify-between">
58 <div className="flex items-center gap-4">
59 <button
60 onClick={() => {
61 setLiked((p) => !p);
62 setLikeCount((p) => (liked ? p - 1 : p + 1));
63 }}
64 className={`transition-all duration-150 active:scale-90 ${liked ? "text-white" : "text-nord-white/70"}`}
65 >
66 <IconHeart filled={liked} />
67 </button>
68 <button className="text-nord-white/70 hover:text-nord-white transition-colors">
69 <IconComment />
70 </button>
71 <button className="text-nord-white/70 hover:text-nord-white transition-colors">
72 <IconShare />
73 </button>
74 </div>
75 <button
76 onClick={() => setSaved((p) => !p)}
77 className={`transition-all duration-150 active:scale-90 ${saved ? "text-white" : "text-nord-white/70"}`}
78 >
79 <IconBookmark filled={saved} />
80 </button>
81 </div>
82
83 {/* Likes + caption */}
84 <div className="px-4 pt-1 pb-4 space-y-1">
85 <p className="text-nord-white text-sm font-semibold">{likeCount.toLocaleString()} likes</p>
86 <p className="text-sm text-nord-white/90 leading-relaxed">
87 <span className="font-semibold mr-1">{post.handle}</span>
88 {post.caption}
89 </p>
90 <p className="text-[11px] text-nord-white/35 tracking-wide">{post.tags.join(" ")}</p>
91 <p className="text-[10px] text-nord-white/25 uppercase tracking-widest pt-0.5">{post.time} ago</p>
92 </div>
93 </article>
94 );
95 }