use reactions from post
This commit is contained in:
parent
72389136a7
commit
83835d374b
3 changed files with 80 additions and 70 deletions
|
@ -26,9 +26,9 @@ export interface paths {
|
|||
[name: string]: unknown
|
||||
}
|
||||
content: {
|
||||
'text/plain': components['schemas']['GetAllPublicPostsResponse']
|
||||
'application/json': components['schemas']['GetAllPublicPostsResponse']
|
||||
'text/json': components['schemas']['GetAllPublicPostsResponse']
|
||||
'text/plain': components['schemas']['LoadPostsResponse']
|
||||
'application/json': components['schemas']['LoadPostsResponse']
|
||||
'text/json': components['schemas']['LoadPostsResponse']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,41 @@ export interface paths {
|
|||
patch?: never
|
||||
trace?: never
|
||||
}
|
||||
'/posts/{postId}': {
|
||||
parameters: {
|
||||
query?: never
|
||||
header?: never
|
||||
path?: never
|
||||
cookie?: never
|
||||
}
|
||||
get?: never
|
||||
put?: never
|
||||
post?: never
|
||||
delete: {
|
||||
parameters: {
|
||||
query?: never
|
||||
header?: never
|
||||
path: {
|
||||
postId: string
|
||||
}
|
||||
cookie?: never
|
||||
}
|
||||
requestBody?: never
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content?: never
|
||||
}
|
||||
}
|
||||
}
|
||||
options?: never
|
||||
head?: never
|
||||
patch?: never
|
||||
trace?: never
|
||||
}
|
||||
'/media': {
|
||||
parameters: {
|
||||
query?: never
|
||||
|
@ -87,7 +122,8 @@ export interface paths {
|
|||
requestBody: {
|
||||
content: {
|
||||
'multipart/form-data': {
|
||||
file?: components['schemas']['IFormFile']
|
||||
/** Format: binary */
|
||||
file?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -387,24 +423,21 @@ export interface components {
|
|||
height: number | null
|
||||
}
|
||||
CreatePostResponse: {
|
||||
/** Format: uuid */
|
||||
postId: string
|
||||
post: components['schemas']['PostDto']
|
||||
}
|
||||
CreateSignupCodeRequest: {
|
||||
code: string
|
||||
email: string
|
||||
name: string
|
||||
}
|
||||
GetAllPublicPostsResponse: {
|
||||
ListSignupCodesResult: {
|
||||
signupCodes: components['schemas']['SignupCodeDto'][]
|
||||
}
|
||||
LoadPostsResponse: {
|
||||
posts: components['schemas']['PostDto'][]
|
||||
/** Format: uuid */
|
||||
next: string | null
|
||||
}
|
||||
/** Format: binary */
|
||||
IFormFile: string
|
||||
ListSignupCodesResult: {
|
||||
signupCodes: components['schemas']['SignupCodeDto'][]
|
||||
}
|
||||
LoginRequest: {
|
||||
username: string
|
||||
password: string
|
||||
|
@ -426,8 +459,10 @@ export interface components {
|
|||
postId: string
|
||||
content: string
|
||||
media: components['schemas']['PostMediaDto'][]
|
||||
reactions: components['schemas']['PostReactionDto'][]
|
||||
/** Format: date-time */
|
||||
createdAt: string
|
||||
possibleReactions: string[]
|
||||
}
|
||||
PostMediaDto: {
|
||||
/** Format: uri */
|
||||
|
@ -437,6 +472,12 @@ export interface components {
|
|||
/** Format: int32 */
|
||||
height: number | null
|
||||
}
|
||||
PostReactionDto: {
|
||||
emoji: string
|
||||
/** Format: int32 */
|
||||
count: number
|
||||
didReact: boolean
|
||||
}
|
||||
RefreshUserResult: {
|
||||
/** Format: uuid */
|
||||
userId: string
|
||||
|
|
|
@ -55,9 +55,6 @@ interface PostReactionsProps {
|
|||
}
|
||||
|
||||
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()
|
||||
|
@ -65,34 +62,33 @@ function PostReactions({ post }: PostReactionsProps) {
|
|||
return `${Math.floor(count / 1000)}K`
|
||||
}
|
||||
|
||||
// Function to handle reaction click
|
||||
// NOOP handlers for react/unreact functionality
|
||||
const handleReactionClick = (emoji: string) => {
|
||||
setUserReactions((prev) => {
|
||||
const newReactions = new Set(prev)
|
||||
if (newReactions.has(emoji)) {
|
||||
newReactions.delete(emoji)
|
||||
} else {
|
||||
newReactions.add(emoji)
|
||||
}
|
||||
return newReactions
|
||||
})
|
||||
console.log(`Reaction clicked: ${emoji}`)
|
||||
// This would normally call an API to add/remove a reaction
|
||||
}
|
||||
|
||||
// Find existing reactions to display
|
||||
const reactionMap = new Map(post.reactions.map(r => [r.emoji, r]))
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2 mt-3 justify-end">
|
||||
{post.reactions.map((reaction) => {
|
||||
const isSelected = userReactions.has(reaction.emoji)
|
||||
{post.possibleReactions.map((emoji) => {
|
||||
const reaction = reactionMap.get(emoji)
|
||||
const count = reaction?.count || 0
|
||||
const didReact = reaction?.didReact || false
|
||||
|
||||
return (
|
||||
<button
|
||||
key={reaction.emoji}
|
||||
onClick={() => handleReactionClick(reaction.emoji)}
|
||||
key={emoji}
|
||||
onClick={() => handleReactionClick(emoji)}
|
||||
className={`flex items-center px-2 py-1 rounded-full border ${
|
||||
isSelected ? 'bg-gray-100 border-gray-400' : 'bg-white border-gray-200'
|
||||
didReact ? '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="mr-1">{emoji}</span>
|
||||
<span className="text-xs text-gray-600">
|
||||
{formatCount(reaction.count + (isSelected ? 1 : 0))}
|
||||
{formatCount(count)}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ import { components } from '../../api/schema.ts'
|
|||
export interface EmojiReaction {
|
||||
emoji: string
|
||||
count: number
|
||||
didReact: boolean
|
||||
}
|
||||
|
||||
export class Post {
|
||||
|
@ -13,6 +14,7 @@ export class Post {
|
|||
public readonly createdAt: Temporal.Instant
|
||||
public readonly authorName: string
|
||||
public readonly reactions: EmojiReaction[]
|
||||
public readonly possibleReactions: string[]
|
||||
|
||||
constructor(
|
||||
postId: string,
|
||||
|
@ -21,50 +23,15 @@ export class Post {
|
|||
createdAt: string | Temporal.Instant,
|
||||
authorName: string,
|
||||
reactions: EmojiReaction[] = [],
|
||||
possibleReactions: string[] = [],
|
||||
) {
|
||||
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
|
||||
}))
|
||||
this.reactions = reactions
|
||||
this.possibleReactions = possibleReactions
|
||||
}
|
||||
|
||||
public static fromDto(dto: components['schemas']['PostDto']): Post {
|
||||
|
@ -74,6 +41,12 @@ export class Post {
|
|||
dto.media.map((m) => new PostMediaImpl(new URL(m.url), m.width, m.height)),
|
||||
Temporal.Instant.from(dto.createdAt),
|
||||
dto.author.username,
|
||||
dto.reactions.map((r) => ({
|
||||
emoji: r.emoji,
|
||||
count: r.count,
|
||||
didReact: r.didReact
|
||||
})),
|
||||
dto.possibleReactions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue