Fix likes batch route order, add profile links to all usernames

This commit is contained in:
2026-05-29 14:46:18 +03:00
parent 025e52e6b1
commit 466cb97a4e
4 changed files with 38 additions and 28 deletions

View File

@@ -1,4 +1,5 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';
import { Cat } from '@/api/endpoints';
import { useAuth } from '@/hooks/useAuth';
import { useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
@@ -44,9 +45,13 @@ export default function CatCard({ cat, onOpen, likedIds }: CatCardProps) {
<article className="animate-fade-up">
<div className="card overflow-hidden cursor-pointer card-interactive" onClick={() => onOpen(cat.id)}>
<div className="flex items-center gap-3 px-5 pt-5 pb-3">
<Link to={`/profile/${cat.user_id}`} onClick={e => e.stopPropagation()}>
<UserAvatar avatarUrl={cat.user_avatar_url} username={cat.username} className="h-9 w-9" fallbackClassName="text-xs avatar-colored bg-[var(--accent)]" />
</Link>
<div className="flex-1 min-w-0">
<Link to={`/profile/${cat.user_id}`} onClick={e => e.stopPropagation()} className="hover:text-[var(--accent)] transition-colors">
<h3 className="text-sm font-semibold truncate">@{cat.username}</h3>
</Link>
<time className="text-[11px] text-[var(--fg-tertiary)]">{timeAgo}</time>
</div>
</div>

View File

@@ -1,4 +1,5 @@
import { useEffect, useState, useRef } from 'react';
import { Link } from 'react-router-dom';
import { useCat, useDeleteCat } from '@/hooks/useCats';
import { useLikeStatus, useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
import { useComments, useAddComment, useDeleteComment } from '@/hooks/useComments';
@@ -115,13 +116,13 @@ export default function CatModal({ catId, onClose }: CatModalProps) {
onClick={e => e.stopPropagation()}
>
<div className="flex items-center justify-between px-5 py-4 shrink-0">
<div className="flex items-center gap-3">
<Link to={`/profile/${cat.user_id}`} className="flex items-center gap-3 group" onClick={onClose}>
<UserAvatar avatarUrl={cat.user_avatar_url} username={cat.username} className="h-9 w-9" fallbackClassName="text-xs avatar-colored bg-[var(--accent)]" />
<div>
<span className="text-sm font-semibold">@{cat.username}</span>
<span className="text-sm font-semibold group-hover:text-[var(--accent)] transition-colors">@{cat.username}</span>
<p className="text-[11px] text-[var(--fg-tertiary)]">{dateStr}</p>
</div>
</div>
</Link>
<div className="flex items-center gap-1">
{isOwner && (
<button onClick={handleDelete} className="btn-ghost h-9 w-9 text-[var(--fg-tertiary)] hover:text-red-500 hover:bg-red-50">
@@ -153,7 +154,7 @@ export default function CatModal({ catId, onClose }: CatModalProps) {
<div className="flex items-start gap-3">
<UserAvatar avatarUrl={cat.user_avatar_url} username={cat.username} className="h-7 w-7" fallbackClassName="text-[9px] avatar-colored bg-[var(--accent)]" />
<p className="text-sm leading-[1.5]">
<span className="font-semibold mr-1">@{cat.username}</span>
<Link to={`/profile/${cat.user_id}`} onClick={onClose} className="font-semibold mr-1 hover:text-[var(--accent)] transition-colors">@{cat.username}</Link>
{cat.caption}
</p>
</div>
@@ -163,10 +164,12 @@ export default function CatModal({ catId, onClose }: CatModalProps) {
<div className="space-y-3 pt-1">
{comments.map(c => (
<div key={c.id} className="flex items-start gap-2.5 group">
<Link to={`/profile/${c.user_id}`} onClick={onClose}>
<UserAvatar avatarUrl={undefined} username={c.username} className="h-7 w-7" fallbackClassName="text-[9px] avatar-colored bg-[var(--fg-tertiary)]" />
</Link>
<div className="flex-1 min-w-0">
<p className="text-sm leading-[1.5]">
<span className="font-semibold mr-1">@{c.username}</span>
<Link to={`/profile/${c.user_id}`} onClick={onClose} className="font-semibold mr-1 hover:text-[var(--accent)] transition-colors">@{c.username}</Link>
{c.text}
</p>
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">

View File

@@ -137,7 +137,7 @@ export default function CatPage() {
{cat.caption && (
<p className="text-sm leading-[1.5]">
<span className="font-semibold mr-1">@{cat.username}</span>
<Link to={`/profile/${cat.user_id}`} className="font-semibold mr-1 hover:text-[var(--accent)] transition-colors">@{cat.username}</Link>
{cat.caption}
</p>
)}
@@ -165,10 +165,12 @@ export default function CatPage() {
</p>
{comments.map(c => (
<div key={c.id} className="flex items-start gap-2.5 group">
<Link to={`/profile/${c.user_id}`}>
<UserAvatar avatarUrl={undefined} username={c.username} className="h-7 w-7" fallbackClassName="text-[9px] avatar-colored bg-[var(--fg-tertiary)]" />
</Link>
<div className="flex-1 min-w-0">
<p className="text-sm leading-[1.5]">
<span className="font-semibold mr-1">@{c.username}</span>
<Link to={`/profile/${c.user_id}`} className="font-semibold mr-1 hover:text-[var(--accent)] transition-colors">@{c.username}</Link>
{c.text}
</p>
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">

View File

@@ -4,6 +4,23 @@ import { authMiddleware, AuthRequest } from '../middleware/auth.js';
const router = Router();
router.post('/batch/status', authMiddleware, (req: AuthRequest, res: Response) => {
const userId = req.userId!;
const { catIds } = req.body as { catIds: number[] };
if (!Array.isArray(catIds) || catIds.length === 0) {
res.json({ likedIds: [] });
return;
}
const likes = queryAll(
`SELECT cat_id FROM likes WHERE user_id = ? AND cat_id IN (${catIds.map(() => '?').join(',')})`,
[userId, ...catIds]
);
res.json({ likedIds: likes.map((l: any) => l.cat_id) });
});
router.post('/:catId', authMiddleware, (req: AuthRequest, res: Response) => {
const catId = parseInt(req.params.catId);
const userId = req.userId!;
@@ -63,21 +80,4 @@ router.get('/:catId/status', authMiddleware, (req: AuthRequest, res: Response) =
res.json({ liked: !!liked });
});
router.post('/batch/status', authMiddleware, (req: AuthRequest, res: Response) => {
const userId = req.userId!;
const { catIds } = req.body as { catIds: number[] };
if (!Array.isArray(catIds) || catIds.length === 0) {
res.json({ likedIds: [] });
return;
}
const likes = queryAll(
`SELECT cat_id FROM likes WHERE user_id = ? AND cat_id IN (${catIds.map(() => '?').join(',')})`,
[userId, ...catIds]
);
res.json({ likedIds: likes.map((l: any) => l.cat_id) });
});
export default router;