wip emoji reactions

This commit is contained in:
john 2025-05-26 22:49:15 +02:00
parent 48ea06294e
commit 72389136a7
2 changed files with 98 additions and 0 deletions

View file

@ -44,10 +44,63 @@ export default function PostItem({ post }: PostItemProps) {
))}
</div>
)}
<PostReactions post={post} />
</article>
)
}
interface PostReactionsProps {
post: Post
}
function PostReactions({ post }: PostReactionsProps) {
// State to track user's reactions
const [userReactions, setUserReactions] = useState<Set<string>>(new Set())
// Function to format reaction count
const formatCount = (count: number): string => {
if (count < 1000) return count.toString()
if (count < 10000) return `${(count / 1000).toFixed(1)}K`
return `${Math.floor(count / 1000)}K`
}
// Function to handle reaction click
const handleReactionClick = (emoji: string) => {
setUserReactions((prev) => {
const newReactions = new Set(prev)
if (newReactions.has(emoji)) {
newReactions.delete(emoji)
} else {
newReactions.add(emoji)
}
return newReactions
})
}
return (
<div className="flex flex-wrap gap-2 mt-3 justify-end">
{post.reactions.map((reaction) => {
const isSelected = userReactions.has(reaction.emoji)
return (
<button
key={reaction.emoji}
onClick={() => handleReactionClick(reaction.emoji)}
className={`flex items-center px-2 py-1 rounded-full border ${
isSelected ? 'bg-gray-100 border-gray-400' : 'bg-white border-gray-200'
} hover:bg-gray-100 transition-colors`}
>
<span className="mr-1">{reaction.emoji}</span>
<span className="text-xs text-gray-600">
{formatCount(reaction.count + (isSelected ? 1 : 0))}
</span>
</button>
)
})}
</div>
)
}
interface PostMediaProps {
media: PostMedia
}

View file

@ -1,12 +1,18 @@
import { Temporal } from '@js-temporal/polyfill'
import { components } from '../../api/schema.ts'
export interface EmojiReaction {
emoji: string
count: number
}
export class Post {
public readonly postId: string
public readonly content: string
public readonly media: PostMedia[]
public readonly createdAt: Temporal.Instant
public readonly authorName: string
public readonly reactions: EmojiReaction[]
constructor(
postId: string,
@ -14,12 +20,51 @@ export class Post {
media: PostMedia[],
createdAt: string | Temporal.Instant,
authorName: string,
reactions: EmojiReaction[] = [],
) {
this.postId = postId
this.content = content
this.media = media
this.createdAt = Temporal.Instant.from(createdAt)
this.authorName = authorName
this.reactions = reactions.length > 0 ? reactions : this.generateRandomReactions()
}
private generateRandomReactions(): EmojiReaction[] {
// List of popular emojis
const emojis = [
'👍',
'❤️',
'😂',
'🎉',
'🔥',
'👏',
'🙏',
'💯',
'🤔',
'😍',
'🥰',
'😮',
'😢',
'😡',
'🤩',
]
// Randomly select 5 unique emojis
const selectedEmojis: string[] = []
while (selectedEmojis.length < 5) {
const randomIndex = Math.floor(Math.random() * emojis.length)
const emoji = emojis[randomIndex]
if (!selectedEmojis.includes(emoji!)) {
selectedEmojis.push(emoji!)
}
}
// Create reaction objects with random counts
return selectedEmojis.map((emoji) => ({
emoji,
count: Math.floor(Math.random() * 50), // Random count between 0 and 49
}))
}
public static fromDto(dto: components['schemas']['PostDto']): Post {