crush-level-web/src/app/(main)/crushcoin/components/CheckInGrid.tsx

141 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-12-17 10:13:47 +00:00
'use client';
2025-11-13 08:38:25 +00:00
2025-12-18 10:59:55 +00:00
import { useGetSevenDaysSignList, useSignIn } from '@/hooks/useHome';
import { SignInListOutput } from '@/services/home/types';
2025-12-17 10:13:47 +00:00
import { useQueryClient } from '@tanstack/react-query';
import { homeKeys } from '@/lib/query-keys';
import { CheckInCard } from './CheckInCard';
import { useEffect, useRef } from 'react';
import { toast } from 'sonner';
2025-11-13 08:38:25 +00:00
export function CheckInGrid() {
2025-12-17 10:13:47 +00:00
const queryClient = useQueryClient();
2025-12-18 10:59:55 +00:00
const { data: signListData, isLoading } = useGetSevenDaysSignList();
const signInMutation = useSignIn();
2025-12-17 10:13:47 +00:00
const hasSignRef = useRef(false);
2025-11-13 08:38:25 +00:00
useEffect(() => {
const initializeCheckIn = async () => {
2025-12-17 10:13:47 +00:00
if (hasSignRef.current) return;
hasSignRef.current = true;
2025-11-13 08:38:25 +00:00
try {
// 先进行签到
2025-12-17 10:13:47 +00:00
const resp = await signInMutation.mutateAsync();
2025-11-13 08:38:25 +00:00
if (resp) {
2025-12-17 10:13:47 +00:00
toast.success('Check-in Successful');
2025-11-13 08:38:25 +00:00
}
// 签到成功后再获取列表数据
await queryClient.invalidateQueries({
2025-11-28 06:31:36 +00:00
queryKey: homeKeys.getSevenDaysSignList(),
2025-12-17 10:13:47 +00:00
});
2025-11-13 08:38:25 +00:00
await queryClient.invalidateQueries({
2025-11-28 06:31:36 +00:00
queryKey: ['wallet'],
2025-12-17 10:13:47 +00:00
});
2025-11-13 08:38:25 +00:00
} catch (error) {
2025-12-17 10:13:47 +00:00
console.error('初始化签到失败:', error);
2025-11-13 08:38:25 +00:00
// 即使签到失败,也要获取列表数据显示界面
queryClient.invalidateQueries({
2025-11-28 06:31:36 +00:00
queryKey: homeKeys.getSevenDaysSignList(),
2025-12-17 10:13:47 +00:00
});
2025-11-13 08:38:25 +00:00
queryClient.invalidateQueries({
2025-11-28 06:31:36 +00:00
queryKey: ['wallet'],
2025-12-17 10:13:47 +00:00
});
2025-11-13 08:38:25 +00:00
}
2025-12-17 10:13:47 +00:00
};
2025-11-28 06:31:36 +00:00
2025-11-13 08:38:25 +00:00
if (signListData) {
2025-12-17 10:13:47 +00:00
initializeCheckIn();
2025-11-13 08:38:25 +00:00
}
2025-12-17 10:13:47 +00:00
}, [signListData]);
2025-11-13 08:38:25 +00:00
if (isLoading) {
return (
2025-11-28 06:31:36 +00:00
<div className="grid h-[328px] grid-cols-3 grid-rows-2 gap-4">
2025-11-13 08:38:25 +00:00
{Array.from({ length: 6 }).map((_, index) => (
2025-11-28 06:31:36 +00:00
<div
2025-11-13 08:38:25 +00:00
key={index}
2025-11-28 06:31:36 +00:00
className="animate-pulse rounded-[16px] border border-[rgba(251,222,255,0.2)] bg-[#282233]"
2025-11-13 08:38:25 +00:00
/>
))}
</div>
2025-12-17 10:13:47 +00:00
);
2025-11-13 08:38:25 +00:00
}
2025-12-17 10:13:47 +00:00
const signList = signListData?.list || [];
const today = new Date();
const todayStr = today.toISOString().split('T')[0]; // yyyy-MM-dd 格式
2025-11-13 08:38:25 +00:00
// 确保有7天的数据如果不足则补充默认数据
2025-11-28 06:31:36 +00:00
const fullSignList: (SignInListOutput & { day: number })[] = Array.from(
{ length: 7 },
(_, index) => {
2025-12-17 10:13:47 +00:00
const day = index + 1;
const existingData = signList.find((item, itemIndex) => itemIndex === index);
2025-11-28 06:31:36 +00:00
return {
day,
coinNum: existingData?.coinNum || [5, 10, 15, 20, 30, 50, 80][index],
dayStr: existingData?.dayStr || '',
signIn: existingData?.signIn || false,
2025-12-17 10:13:47 +00:00
};
2025-11-13 08:38:25 +00:00
}
2025-12-17 10:13:47 +00:00
);
2025-11-13 08:38:25 +00:00
// 找到今天应该签到的是第几天
2025-11-28 06:31:36 +00:00
const todayIndex = fullSignList.findIndex((item) => {
2025-12-17 10:13:47 +00:00
if (!item.dayStr) return false;
return item.dayStr === todayStr;
});
2025-11-13 08:38:25 +00:00
// 如果没有找到今天的数据,假设是按顺序签到,找到第一个未签到的
2025-11-28 06:31:36 +00:00
const currentDayIndex =
2025-12-17 10:13:47 +00:00
todayIndex >= 0 ? todayIndex : fullSignList.findIndex((item) => !item.signIn);
2025-11-13 08:38:25 +00:00
return (
<div className="grid grid-cols-4 grid-rows-2 gap-4">
2025-11-28 06:31:36 +00:00
{fullSignList.map((item, index) => {
if (index === 3) {
return (
<CheckInCard
key={fullSignList[6].day}
day={fullSignList[6].day}
coinNum={fullSignList[6].coinNum || 0}
signIn={fullSignList[6].signIn || false}
isToday={fullSignList[6].dayStr === todayStr}
loading={signInMutation.isPending}
className="col-span-1 row-span-2"
/>
2025-12-17 10:13:47 +00:00
);
2025-11-28 06:31:36 +00:00
}
if (index < 3) {
return (
<CheckInCard
key={item.day}
day={item.day}
coinNum={item.coinNum || 0}
signIn={item.signIn || false}
isToday={index === currentDayIndex}
loading={signInMutation.isPending}
className="col-span-1 row-span-1"
/>
2025-12-17 10:13:47 +00:00
);
2025-11-28 06:31:36 +00:00
} else {
return (
<CheckInCard
key={fullSignList[index - 1].day}
day={fullSignList[index - 1].day}
coinNum={fullSignList[index - 1].coinNum || 0}
signIn={fullSignList[index - 1].signIn || false}
isToday={fullSignList[index - 1].dayStr === todayStr}
loading={signInMutation.isPending}
className="col-span-1 row-span-1"
/>
2025-12-17 10:13:47 +00:00
);
2025-11-28 06:31:36 +00:00
}
})}
2025-11-13 08:38:25 +00:00
</div>
2025-12-17 10:13:47 +00:00
);
2025-11-13 08:38:25 +00:00
}
2025-12-17 10:13:47 +00:00
export default CheckInGrid;