Fix likes batch route order, add profile links to all usernames
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import { Cat } from '@/api/endpoints';
|
import { Cat } from '@/api/endpoints';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
|
import { useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
|
||||||
@@ -44,9 +45,13 @@ export default function CatCard({ cat, onOpen, likedIds }: CatCardProps) {
|
|||||||
<article className="animate-fade-up">
|
<article className="animate-fade-up">
|
||||||
<div className="card overflow-hidden cursor-pointer card-interactive" onClick={() => onOpen(cat.id)}>
|
<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">
|
<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)]" />
|
<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">
|
<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>
|
<h3 className="text-sm font-semibold truncate">@{cat.username}</h3>
|
||||||
|
</Link>
|
||||||
<time className="text-[11px] text-[var(--fg-tertiary)]">{timeAgo}</time>
|
<time className="text-[11px] text-[var(--fg-tertiary)]">{timeAgo}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useState, useRef } from 'react';
|
import { useEffect, useState, useRef } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import { useCat, useDeleteCat } from '@/hooks/useCats';
|
import { useCat, useDeleteCat } from '@/hooks/useCats';
|
||||||
import { useLikeStatus, useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
|
import { useLikeStatus, useLikeCat, useUnlikeCat } from '@/hooks/useLikes';
|
||||||
import { useComments, useAddComment, useDeleteComment } from '@/hooks/useComments';
|
import { useComments, useAddComment, useDeleteComment } from '@/hooks/useComments';
|
||||||
@@ -115,13 +116,13 @@ export default function CatModal({ catId, onClose }: CatModalProps) {
|
|||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-5 py-4 shrink-0">
|
<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)]" />
|
<UserAvatar avatarUrl={cat.user_avatar_url} username={cat.username} className="h-9 w-9" fallbackClassName="text-xs avatar-colored bg-[var(--accent)]" />
|
||||||
<div>
|
<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>
|
<p className="text-[11px] text-[var(--fg-tertiary)]">{dateStr}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
{isOwner && (
|
{isOwner && (
|
||||||
<button onClick={handleDelete} className="btn-ghost h-9 w-9 text-[var(--fg-tertiary)] hover:text-red-500 hover:bg-red-50">
|
<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">
|
<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)]" />
|
<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]">
|
<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}
|
{cat.caption}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -163,10 +164,12 @@ export default function CatModal({ catId, onClose }: CatModalProps) {
|
|||||||
<div className="space-y-3 pt-1">
|
<div className="space-y-3 pt-1">
|
||||||
{comments.map(c => (
|
{comments.map(c => (
|
||||||
<div key={c.id} className="flex items-start gap-2.5 group">
|
<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)]" />
|
<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">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm leading-[1.5]">
|
<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}
|
{c.text}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">
|
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export default function CatPage() {
|
|||||||
|
|
||||||
{cat.caption && (
|
{cat.caption && (
|
||||||
<p className="text-sm leading-[1.5]">
|
<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}
|
{cat.caption}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@@ -165,10 +165,12 @@ export default function CatPage() {
|
|||||||
</p>
|
</p>
|
||||||
{comments.map(c => (
|
{comments.map(c => (
|
||||||
<div key={c.id} className="flex items-start gap-2.5 group">
|
<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)]" />
|
<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">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm leading-[1.5]">
|
<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}
|
{c.text}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">
|
<p className="text-[10px] text-[var(--fg-tertiary)] mt-0.5">
|
||||||
|
|||||||
@@ -4,6 +4,23 @@ import { authMiddleware, AuthRequest } from '../middleware/auth.js';
|
|||||||
|
|
||||||
const router = Router();
|
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) => {
|
router.post('/:catId', authMiddleware, (req: AuthRequest, res: Response) => {
|
||||||
const catId = parseInt(req.params.catId);
|
const catId = parseInt(req.params.catId);
|
||||||
const userId = req.userId!;
|
const userId = req.userId!;
|
||||||
@@ -63,21 +80,4 @@ router.get('/:catId/status', authMiddleware, (req: AuthRequest, res: Response) =
|
|||||||
res.json({ liked: !!liked });
|
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;
|
export default router;
|
||||||
Reference in New Issue
Block a user