feat: 联调点赞功能
This commit is contained in:
parent
3ed5f603c4
commit
e6b28751bd
|
|
@ -5,7 +5,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { IconButton } from '@/components/ui/button';
|
import { IconButton } from '@/components/ui/button';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import LikedIcon from '@/components/features/LikedIcon';
|
import LikedButton from '@/components/features/LikeButton';
|
||||||
import { LikeTargetType } from '@/services/editor/type';
|
import { LikeTargetType } from '@/services/editor/type';
|
||||||
|
|
||||||
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
||||||
|
|
@ -20,11 +20,7 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
|
||||||
<Link href="/home">
|
<Link href="/home">
|
||||||
<IconButton variant="ghost" size="large" iconfont="icon-arrow-left" />
|
<IconButton variant="ghost" size="large" iconfont="icon-arrow-left" />
|
||||||
</Link>
|
</Link>
|
||||||
<LikedIcon
|
<LikedButton size="large" objectId={id} objectType={LikeTargetType.Character} />
|
||||||
iconProps={{ size: 'large' }}
|
|
||||||
objectId={id}
|
|
||||||
objectType={LikeTargetType.Character}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{/* 内容区 */}
|
{/* 内容区 */}
|
||||||
<div className="mx-auto flex-1 overflow-auto pb-4 w-full">
|
<div className="mx-auto flex-1 overflow-auto pb-4 w-full">
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import IconFont from '@/components/ui/iconFont';
|
||||||
import MaskCreate from './MaskCreate';
|
import MaskCreate from './MaskCreate';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import LikedIcon from '@/components/features/LikedIcon';
|
import LikedButton from '@/components/features/LikeButton';
|
||||||
import { LikeTargetType } from '@/services/editor/type';
|
import { LikeTargetType } from '@/services/editor/type';
|
||||||
|
|
||||||
type SettingProps = {
|
type SettingProps = {
|
||||||
|
|
@ -71,7 +71,7 @@ export default function SettingDialog({ open, onOpenChange }: SettingProps) {
|
||||||
<AlertDialogContent className="max-w-[500px]" showCloseButton={activeTab === 'profile'}>
|
<AlertDialogContent className="max-w-[500px]" showCloseButton={activeTab === 'profile'}>
|
||||||
<AlertDialogTitle className="flex justify-between">
|
<AlertDialogTitle className="flex justify-between">
|
||||||
{activeTab === 'profile' ? (
|
{activeTab === 'profile' ? (
|
||||||
<LikedIcon objectId={characterId} objectType={LikeTargetType.Character} />
|
<LikedButton objectId={characterId} objectType={LikeTargetType.Character} />
|
||||||
) : (
|
) : (
|
||||||
titleMap[activeTab]
|
titleMap[activeTab]
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,31 @@ import { LikeTargetType, LikeType } from '@/services/editor/type';
|
||||||
import { IconButton } from '../ui/button';
|
import { IconButton } from '../ui/button';
|
||||||
import { useThmubObject } from '@/hooks/services/common';
|
import { useThmubObject } from '@/hooks/services/common';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
type LikedIconProps = {
|
type LikedIconProps = {
|
||||||
objectId: string;
|
objectId: string;
|
||||||
objectType: LikeTargetType;
|
objectType: LikeTargetType;
|
||||||
iconProps?: React.ComponentProps<typeof IconButton>;
|
} & React.ComponentProps<typeof IconButton>;
|
||||||
};
|
|
||||||
|
|
||||||
const LikedIcon = React.memo((props: LikedIconProps) => {
|
const LikedButton = React.memo((props: LikedIconProps) => {
|
||||||
const { objectId, objectType, iconProps } = props;
|
const { objectId, objectType, ...iconProps } = props;
|
||||||
const { thumb, handleThumb, loading } = useThmubObject({ objectId, objectType });
|
const { thumb, handleThumb, loading } = useThmubObject({ objectId, objectType });
|
||||||
|
const isLiked = thumb === LikeType.Liked;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="tertiary"
|
variant="tertiary"
|
||||||
size="small"
|
size="small"
|
||||||
{...iconProps}
|
{...iconProps}
|
||||||
iconfont={thumb === LikeType.Liked ? 'icon-Like-fill' : 'icon-Like'}
|
iconfont={isLiked ? 'icon-Like-fill' : 'icon-Like'}
|
||||||
|
className={cn(iconProps?.className, isLiked && 'text-red-500')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
handleThumb(thumb === LikeType.Liked ? LikeType.Canceled : LikeType.Liked);
|
handleThumb(isLiked ? LikeType.Canceled : LikeType.Liked);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LikedIcon;
|
export default LikedButton;
|
||||||
|
|
@ -1,30 +1,35 @@
|
||||||
import { getLikeStatus, thmubObject } from '@/services/editor';
|
import { getLikeStatus, thmubObject } from '@/services/editor';
|
||||||
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { authKeys } from '@/lib/query-keys';
|
import { authKeys } from '@/lib/query-keys';
|
||||||
import { LikeObjectParamsType, LikeType } from '@/services/editor/type';
|
import { LikeObjectParamsType, LikeType } from '@/services/editor/type';
|
||||||
import { useAsyncFn } from '../tools';
|
import { useAsyncFn } from '../tools';
|
||||||
|
import { useCurrentUser } from '../auth';
|
||||||
|
|
||||||
export function useThmubObject(props: Pick<LikeObjectParamsType, 'objectId' | 'objectType'>) {
|
export function useThmubObject(props: Pick<LikeObjectParamsType, 'objectId' | 'objectType'>) {
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const [thumb, setThumb] = useState<LikeType>();
|
const [thumb, setThumb] = useState<LikeType>();
|
||||||
const user = queryClient.getQueryData(authKeys.currentUser()) as any;
|
const { data: user } = useCurrentUser();
|
||||||
|
|
||||||
useQuery({
|
const { data: likeStatus, refetch: refetchLikeStatus } = useQuery({
|
||||||
queryKey: ['likeStatus', props.objectId, user.userId],
|
queryKey: ['likeStatus', props.objectId, user?.userId],
|
||||||
enabled: !!props.objectId && !!user.userId,
|
enabled: !!props.objectId && !!user?.userId,
|
||||||
queryFn: () => {
|
queryFn: async () => {
|
||||||
return getLikeStatus({ objectId: props.objectId, userId: user.userId });
|
const { data } = await getLikeStatus({ objectId: props.objectId, userId: user?.userId });
|
||||||
|
return data.likeStatus;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof likeStatus === 'number') {
|
||||||
|
setThumb(likeStatus);
|
||||||
|
}
|
||||||
|
}, [likeStatus]);
|
||||||
|
|
||||||
const { run: handleThumb, loading } = useAsyncFn(async (likeType: LikeType) => {
|
const { run: handleThumb, loading } = useAsyncFn(async (likeType: LikeType) => {
|
||||||
setThumb(likeType);
|
setThumb(likeType);
|
||||||
const user = queryClient.getQueryData(authKeys.currentUser()) as any;
|
const { code } = await thmubObject({ ...props, likeType, userId: user?.userId });
|
||||||
const { data } = await thmubObject({ ...props, likeType, userId: user?.userId });
|
if (code === 200) {
|
||||||
if (data.code === 200) {
|
refetchLikeStatus();
|
||||||
} else {
|
|
||||||
setThumb(undefined);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,5 @@ export async function thmubObject(params: LikeObjectParamsType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLikeStatus(params: Pick<LikeObjectParamsType, 'objectId' | 'userId'>) {
|
export async function getLikeStatus(params: Pick<LikeObjectParamsType, 'objectId' | 'userId'>) {
|
||||||
const { data } = await editorRequest('/api/like/getLikeStatus', { method: 'POST', data: params });
|
return editorRequest('/api/like/getLikeStatus', { method: 'POST', data: params });
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue