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;
|