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